OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "BlinkGCPluginConsumer.h" | 5 #include "BlinkGCPluginConsumer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <set> | 8 #include <set> |
9 | 9 |
10 #include "CheckDispatchVisitor.h" | 10 #include "CheckDispatchVisitor.h" |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 if (!err && json_) { | 318 if (!err && json_) { |
319 json_->OpenList(); | 319 json_->OpenList(); |
320 } else { | 320 } else { |
321 json_ = 0; | 321 json_ = 0; |
322 llvm::errs() | 322 llvm::errs() |
323 << "[blink-gc] " | 323 << "[blink-gc] " |
324 << "Failed to create an output file for the object graph.\n"; | 324 << "Failed to create an output file for the object graph.\n"; |
325 } | 325 } |
326 } | 326 } |
327 | 327 |
328 for (CollectVisitor::RecordVector::iterator it = | 328 for (const auto& record : visitor.record_decls()) |
329 visitor.record_decls().begin(); | 329 CheckRecord(cache_.Lookup(record)); |
330 it != visitor.record_decls().end(); | |
331 ++it) { | |
332 CheckRecord(cache_.Lookup(*it)); | |
333 } | |
334 | 330 |
335 for (CollectVisitor::MethodVector::iterator it = | 331 for (const auto& method : visitor.trace_decls()) |
336 visitor.trace_decls().begin(); | 332 CheckTracingMethod(method); |
337 it != visitor.trace_decls().end(); | |
338 ++it) { | |
339 CheckTracingMethod(*it); | |
340 } | |
341 | 333 |
342 if (json_) { | 334 if (json_) { |
343 json_->CloseList(); | 335 json_->CloseList(); |
344 delete json_; | 336 delete json_; |
345 json_ = 0; | 337 json_ = 0; |
346 } | 338 } |
347 } | 339 } |
348 | 340 |
349 void BlinkGCPluginConsumer::ParseFunctionTemplates(TranslationUnitDecl* decl) { | 341 void BlinkGCPluginConsumer::ParseFunctionTemplates(TranslationUnitDecl* decl) { |
350 if (!instance_.getLangOpts().DelayedTemplateParsing) | 342 if (!instance_.getLangOpts().DelayedTemplateParsing) |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
394 | 386 |
395 CheckClass(info); | 387 CheckClass(info); |
396 } | 388 } |
397 | 389 |
398 void BlinkGCPluginConsumer::CheckClass(RecordInfo* info) { | 390 void BlinkGCPluginConsumer::CheckClass(RecordInfo* info) { |
399 if (!info) | 391 if (!info) |
400 return; | 392 return; |
401 | 393 |
402 // Check consistency of stack-allocated hierarchies. | 394 // Check consistency of stack-allocated hierarchies. |
403 if (info->IsStackAllocated()) { | 395 if (info->IsStackAllocated()) { |
404 for (RecordInfo::Bases::iterator it = info->GetBases().begin(); | 396 for (auto& base : info->GetBases()) |
405 it != info->GetBases().end(); | 397 if (!base.second.info()->IsStackAllocated()) |
406 ++it) { | 398 ReportDerivesNonStackAllocated(info, &base.second); |
407 if (!it->second.info()->IsStackAllocated()) | |
408 ReportDerivesNonStackAllocated(info, &it->second); | |
409 } | |
410 } | 399 } |
411 | 400 |
412 if (CXXMethodDecl* trace = info->GetTraceMethod()) { | 401 if (CXXMethodDecl* trace = info->GetTraceMethod()) { |
413 if (trace->isPure()) | 402 if (trace->isPure()) |
414 ReportClassDeclaresPureVirtualTrace(info, trace); | 403 ReportClassDeclaresPureVirtualTrace(info, trace); |
415 } else if (info->RequiresTraceMethod()) { | 404 } else if (info->RequiresTraceMethod()) { |
416 ReportClassRequiresTraceMethod(info); | 405 ReportClassRequiresTraceMethod(info); |
417 } | 406 } |
418 | 407 |
419 // Check polymorphic classes that are GC-derived or have a trace method. | 408 // Check polymorphic classes that are GC-derived or have a trace method. |
420 if (info->record()->hasDefinition() && info->record()->isPolymorphic()) { | 409 if (info->record()->hasDefinition() && info->record()->isPolymorphic()) { |
421 // TODO: Check classes that inherit a trace method. | 410 // TODO: Check classes that inherit a trace method. |
422 CXXMethodDecl* trace = info->GetTraceMethod(); | 411 CXXMethodDecl* trace = info->GetTraceMethod(); |
423 if (trace || info->IsGCDerived()) | 412 if (trace || info->IsGCDerived()) |
424 CheckPolymorphicClass(info, trace); | 413 CheckPolymorphicClass(info, trace); |
425 } | 414 } |
426 | 415 |
427 { | 416 { |
428 CheckFieldsVisitor visitor(options_); | 417 CheckFieldsVisitor visitor(options_); |
429 if (visitor.ContainsInvalidFields(info)) | 418 if (visitor.ContainsInvalidFields(info)) |
430 ReportClassContainsInvalidFields(info, &visitor.invalid_fields()); | 419 ReportClassContainsInvalidFields(info, visitor.invalid_fields()); |
431 } | 420 } |
432 | 421 |
433 if (info->IsGCDerived()) { | 422 if (info->IsGCDerived()) { |
434 if (!info->IsGCMixin()) { | 423 if (!info->IsGCMixin()) { |
435 CheckLeftMostDerived(info); | 424 CheckLeftMostDerived(info); |
436 CheckDispatch(info); | 425 CheckDispatch(info); |
437 if (CXXMethodDecl* newop = info->DeclaresNewOperator()) | 426 if (CXXMethodDecl* newop = info->DeclaresNewOperator()) |
438 if (!Config::IsIgnoreAnnotated(newop)) | 427 if (!Config::IsIgnoreAnnotated(newop)) |
439 ReportClassOverridesNew(info, newop); | 428 ReportClassOverridesNew(info, newop); |
440 } | 429 } |
441 | 430 |
442 { | 431 { |
443 CheckGCRootsVisitor visitor; | 432 CheckGCRootsVisitor visitor; |
444 if (visitor.ContainsGCRoots(info)) | 433 if (visitor.ContainsGCRoots(info)) |
445 ReportClassContainsGCRoots(info, &visitor.gc_roots()); | 434 ReportClassContainsGCRoots(info, visitor.gc_roots()); |
446 } | 435 } |
447 | 436 |
448 if (info->NeedsFinalization()) | 437 if (info->NeedsFinalization()) |
449 CheckFinalization(info); | 438 CheckFinalization(info); |
450 | 439 |
451 if (options_.warn_unneeded_finalizer && info->IsGCFinalized()) | 440 if (options_.warn_unneeded_finalizer && info->IsGCFinalized()) |
452 CheckUnneededFinalization(info); | 441 CheckUnneededFinalization(info); |
453 } | 442 } |
454 | 443 |
455 DumpClass(info); | 444 DumpClass(info); |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
638 void BlinkGCPluginConsumer::CheckFinalization(RecordInfo* info) { | 627 void BlinkGCPluginConsumer::CheckFinalization(RecordInfo* info) { |
639 CXXDestructorDecl* dtor = info->record()->getDestructor(); | 628 CXXDestructorDecl* dtor = info->record()->getDestructor(); |
640 | 629 |
641 // For finalized classes, check the finalization method if possible. | 630 // For finalized classes, check the finalization method if possible. |
642 if (info->IsGCFinalized()) { | 631 if (info->IsGCFinalized()) { |
643 if (dtor && dtor->hasBody()) { | 632 if (dtor && dtor->hasBody()) { |
644 CheckFinalizerVisitor visitor(&cache_, info->IsEagerlyFinalized()); | 633 CheckFinalizerVisitor visitor(&cache_, info->IsEagerlyFinalized()); |
645 visitor.TraverseCXXMethodDecl(dtor); | 634 visitor.TraverseCXXMethodDecl(dtor); |
646 if (!visitor.finalized_fields().empty()) { | 635 if (!visitor.finalized_fields().empty()) { |
647 ReportFinalizerAccessesFinalizedFields( | 636 ReportFinalizerAccessesFinalizedFields( |
648 dtor, &visitor.finalized_fields()); | 637 dtor, visitor.finalized_fields()); |
649 } | 638 } |
650 } | 639 } |
651 return; | 640 return; |
652 } | 641 } |
653 | 642 |
654 // Don't require finalization of a mixin that has not yet been "mixed in". | 643 // Don't require finalization of a mixin that has not yet been "mixed in". |
655 if (info->IsGCMixin()) | 644 if (info->IsGCMixin()) |
656 return; | 645 return; |
657 | 646 |
658 // Report the finalization error, and proceed to print possible causes for | 647 // Report the finalization error, and proceed to print possible causes for |
659 // the finalization requirement. | 648 // the finalization requirement. |
660 ReportClassRequiresFinalization(info); | 649 ReportClassRequiresFinalization(info); |
661 | 650 |
662 if (dtor && dtor->isUserProvided()) | 651 if (dtor && dtor->isUserProvided()) |
663 NoteUserDeclaredDestructor(dtor); | 652 NoteUserDeclaredDestructor(dtor); |
664 | 653 |
665 for (RecordInfo::Bases::iterator it = info->GetBases().begin(); | 654 for (auto& base : info->GetBases()) |
666 it != info->GetBases().end(); | 655 if (base.second.info()->NeedsFinalization()) |
667 ++it) { | 656 NoteBaseRequiresFinalization(&base.second); |
668 if (it->second.info()->NeedsFinalization()) | |
669 NoteBaseRequiresFinalization(&it->second); | |
670 } | |
671 | 657 |
672 for (RecordInfo::Fields::iterator it = info->GetFields().begin(); | 658 for (auto& field : info->GetFields()) |
673 it != info->GetFields().end(); | 659 if (field.second.edge()->NeedsFinalization()) |
674 ++it) { | 660 NoteField(&field.second, diag_field_requires_finalization_note_); |
675 if (it->second.edge()->NeedsFinalization()) | |
676 NoteField(&it->second, diag_field_requires_finalization_note_); | |
677 } | |
678 } | 661 } |
679 | 662 |
680 void BlinkGCPluginConsumer::CheckUnneededFinalization(RecordInfo* info) { | 663 void BlinkGCPluginConsumer::CheckUnneededFinalization(RecordInfo* info) { |
681 if (!HasNonEmptyFinalizer(info)) | 664 if (!HasNonEmptyFinalizer(info)) |
682 ReportClassDoesNotRequireFinalization(info); | 665 ReportClassDoesNotRequireFinalization(info); |
683 } | 666 } |
684 | 667 |
685 bool BlinkGCPluginConsumer::HasNonEmptyFinalizer(RecordInfo* info) { | 668 bool BlinkGCPluginConsumer::HasNonEmptyFinalizer(RecordInfo* info) { |
686 CXXDestructorDecl* dtor = info->record()->getDestructor(); | 669 CXXDestructorDecl* dtor = info->record()->getDestructor(); |
687 if (dtor && dtor->isUserProvided()) { | 670 if (dtor && dtor->isUserProvided()) { |
688 if (!dtor->hasBody() || !EmptyStmtVisitor::isEmpty(dtor->getBody())) | 671 if (!dtor->hasBody() || !EmptyStmtVisitor::isEmpty(dtor->getBody())) |
689 return true; | 672 return true; |
690 } | 673 } |
691 for (RecordInfo::Bases::iterator it = info->GetBases().begin(); | 674 for (auto& base : info->GetBases()) |
692 it != info->GetBases().end(); | 675 if (HasNonEmptyFinalizer(base.second.info())) |
693 ++it) { | |
694 if (HasNonEmptyFinalizer(it->second.info())) | |
695 return true; | 676 return true; |
696 } | 677 |
697 for (RecordInfo::Fields::iterator it = info->GetFields().begin(); | 678 for (auto& field : info->GetFields()) |
698 it != info->GetFields().end(); | 679 if (field.second.edge()->NeedsFinalization()) |
699 ++it) { | |
700 if (it->second.edge()->NeedsFinalization()) | |
701 return true; | 680 return true; |
702 } | 681 |
703 return false; | 682 return false; |
704 } | 683 } |
705 | 684 |
706 void BlinkGCPluginConsumer::CheckTracingMethod(CXXMethodDecl* method) { | 685 void BlinkGCPluginConsumer::CheckTracingMethod(CXXMethodDecl* method) { |
707 RecordInfo* parent = cache_.Lookup(method->getParent()); | 686 RecordInfo* parent = cache_.Lookup(method->getParent()); |
708 if (IsIgnored(parent)) | 687 if (IsIgnored(parent)) |
709 return; | 688 return; |
710 | 689 |
711 // Check templated tracing methods by checking the template instantiations. | 690 // Check templated tracing methods by checking the template instantiations. |
712 // Specialized templates are handled as ordinary classes. | 691 // Specialized templates are handled as ordinary classes. |
(...skipping 23 matching lines...) Expand all Loading... |
736 } | 715 } |
737 // Dispatch methods are checked when we identify subclasses. | 716 // Dispatch methods are checked when we identify subclasses. |
738 } | 717 } |
739 | 718 |
740 void BlinkGCPluginConsumer::CheckTraceMethod( | 719 void BlinkGCPluginConsumer::CheckTraceMethod( |
741 RecordInfo* parent, | 720 RecordInfo* parent, |
742 CXXMethodDecl* trace, | 721 CXXMethodDecl* trace, |
743 Config::TraceMethodType trace_type) { | 722 Config::TraceMethodType trace_type) { |
744 // A trace method must not override any non-virtual trace methods. | 723 // A trace method must not override any non-virtual trace methods. |
745 if (trace_type == Config::TRACE_METHOD) { | 724 if (trace_type == Config::TRACE_METHOD) { |
746 for (RecordInfo::Bases::iterator it = parent->GetBases().begin(); | 725 for (auto& base : parent->GetBases()) |
747 it != parent->GetBases().end(); | 726 if (CXXMethodDecl* other = base.second.info()->InheritsNonVirtualTrace()) |
748 ++it) { | |
749 RecordInfo* base = it->second.info(); | |
750 if (CXXMethodDecl* other = base->InheritsNonVirtualTrace()) | |
751 ReportOverriddenNonVirtualTrace(parent, trace, other); | 727 ReportOverriddenNonVirtualTrace(parent, trace, other); |
752 } | |
753 } | 728 } |
754 | 729 |
755 CheckTraceVisitor visitor(trace, parent, &cache_); | 730 CheckTraceVisitor visitor(trace, parent, &cache_); |
756 visitor.TraverseCXXMethodDecl(trace); | 731 visitor.TraverseCXXMethodDecl(trace); |
757 | 732 |
758 // Skip reporting if this trace method is a just delegate to | 733 // Skip reporting if this trace method is a just delegate to |
759 // traceImpl (or traceAfterDispatchImpl) method. We will report on | 734 // traceImpl (or traceAfterDispatchImpl) method. We will report on |
760 // CheckTraceMethod on traceImpl method. | 735 // CheckTraceMethod on traceImpl method. |
761 if (visitor.delegates_to_traceimpl()) | 736 if (visitor.delegates_to_traceimpl()) |
762 return; | 737 return; |
763 | 738 |
764 for (RecordInfo::Bases::iterator it = parent->GetBases().begin(); | 739 for (auto& base : parent->GetBases()) |
765 it != parent->GetBases().end(); | 740 if (!base.second.IsProperlyTraced()) |
766 ++it) { | 741 ReportBaseRequiresTracing(parent, trace, base.first); |
767 if (!it->second.IsProperlyTraced()) | |
768 ReportBaseRequiresTracing(parent, trace, it->first); | |
769 } | |
770 | 742 |
771 for (RecordInfo::Fields::iterator it = parent->GetFields().begin(); | 743 for (auto& field : parent->GetFields()) { |
772 it != parent->GetFields().end(); | 744 if (!field.second.IsProperlyTraced()) { |
773 ++it) { | |
774 if (!it->second.IsProperlyTraced()) { | |
775 // Discontinue once an untraced-field error is found. | 745 // Discontinue once an untraced-field error is found. |
776 ReportFieldsRequireTracing(parent, trace); | 746 ReportFieldsRequireTracing(parent, trace); |
777 break; | 747 break; |
778 } | 748 } |
779 } | 749 } |
780 } | 750 } |
781 | 751 |
782 void BlinkGCPluginConsumer::DumpClass(RecordInfo* info) { | 752 void BlinkGCPluginConsumer::DumpClass(RecordInfo* info) { |
783 if (!json_) | 753 if (!json_) |
784 return; | 754 return; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
844 | 814 |
845 private: | 815 private: |
846 JsonWriter* json_; | 816 JsonWriter* json_; |
847 RecordInfo* src_; | 817 RecordInfo* src_; |
848 FieldPoint* point_; | 818 FieldPoint* point_; |
849 std::string loc_; | 819 std::string loc_; |
850 }; | 820 }; |
851 | 821 |
852 DumpEdgeVisitor visitor(json_); | 822 DumpEdgeVisitor visitor(json_); |
853 | 823 |
854 RecordInfo::Bases& bases = info->GetBases(); | 824 for (auto& base : info->GetBases()) |
855 for (RecordInfo::Bases::iterator it = bases.begin(); | |
856 it != bases.end(); | |
857 ++it) { | |
858 visitor.DumpEdge(info, | 825 visitor.DumpEdge(info, |
859 it->second.info(), | 826 base.second.info(), |
860 "<super>", | 827 "<super>", |
861 Edge::kStrong, | 828 Edge::kStrong, |
862 GetLocString(it->second.spec().getLocStart())); | 829 GetLocString(base.second.spec().getLocStart())); |
863 } | |
864 | 830 |
865 RecordInfo::Fields& fields = info->GetFields(); | 831 for (auto& field : info->GetFields()) |
866 for (RecordInfo::Fields::iterator it = fields.begin(); | |
867 it != fields.end(); | |
868 ++it) { | |
869 visitor.DumpField(info, | 832 visitor.DumpField(info, |
870 &it->second, | 833 &field.second, |
871 GetLocString(it->second.field()->getLocStart())); | 834 GetLocString(field.second.field()->getLocStart())); |
872 } | |
873 } | 835 } |
874 | 836 |
875 DiagnosticsEngine::Level BlinkGCPluginConsumer::getErrorLevel() { | 837 DiagnosticsEngine::Level BlinkGCPluginConsumer::getErrorLevel() { |
876 return diagnostic_.getWarningsAsErrors() ? DiagnosticsEngine::Error | 838 return diagnostic_.getWarningsAsErrors() ? DiagnosticsEngine::Error |
877 : DiagnosticsEngine::Warning; | 839 : DiagnosticsEngine::Warning; |
878 } | 840 } |
879 | 841 |
880 std::string BlinkGCPluginConsumer::GetLocString(SourceLocation loc) { | 842 std::string BlinkGCPluginConsumer::GetLocString(SourceLocation loc) { |
881 const SourceManager& source_manager = instance_.getSourceManager(); | 843 const SourceManager& source_manager = instance_.getSourceManager(); |
882 PresumedLoc ploc = source_manager.getPresumedLoc(loc); | 844 PresumedLoc ploc = source_manager.getPresumedLoc(loc); |
(...skipping 24 matching lines...) Expand all Loading... |
907 options_.ignored_classes.end()); | 869 options_.ignored_classes.end()); |
908 } | 870 } |
909 | 871 |
910 bool BlinkGCPluginConsumer::InIgnoredDirectory(RecordInfo* info) { | 872 bool BlinkGCPluginConsumer::InIgnoredDirectory(RecordInfo* info) { |
911 std::string filename; | 873 std::string filename; |
912 if (!GetFilename(info->record()->getLocStart(), &filename)) | 874 if (!GetFilename(info->record()->getLocStart(), &filename)) |
913 return false; // TODO: should we ignore non-existing file locations? | 875 return false; // TODO: should we ignore non-existing file locations? |
914 #if defined(LLVM_ON_WIN32) | 876 #if defined(LLVM_ON_WIN32) |
915 std::replace(filename.begin(), filename.end(), '\\', '/'); | 877 std::replace(filename.begin(), filename.end(), '\\', '/'); |
916 #endif | 878 #endif |
917 std::vector<std::string>::iterator it = options_.ignored_directories.begin(); | 879 for (const auto& dir : options_.ignored_directories) |
918 for (; it != options_.ignored_directories.end(); ++it) | 880 if (filename.find(dir) != std::string::npos) |
919 if (filename.find(*it) != std::string::npos) | |
920 return true; | 881 return true; |
921 return false; | 882 return false; |
922 } | 883 } |
923 | 884 |
924 bool BlinkGCPluginConsumer::InCheckedNamespace(RecordInfo* info) { | 885 bool BlinkGCPluginConsumer::InCheckedNamespace(RecordInfo* info) { |
925 if (!info) | 886 if (!info) |
926 return false; | 887 return false; |
927 for (DeclContext* context = info->record()->getDeclContext(); | 888 for (DeclContext* context = info->record()->getDeclContext(); |
928 !context->isTranslationUnit(); | 889 !context->isTranslationUnit(); |
929 context = context->getParent()) { | 890 context = context->getParent()) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
966 ReportDiagnostic(info->record()->getInnerLocStart(), | 927 ReportDiagnostic(info->record()->getInnerLocStart(), |
967 diag_class_must_left_mostly_derive_gc_) | 928 diag_class_must_left_mostly_derive_gc_) |
968 << info->record(); | 929 << info->record(); |
969 } | 930 } |
970 | 931 |
971 void BlinkGCPluginConsumer::ReportClassRequiresTraceMethod(RecordInfo* info) { | 932 void BlinkGCPluginConsumer::ReportClassRequiresTraceMethod(RecordInfo* info) { |
972 ReportDiagnostic(info->record()->getInnerLocStart(), | 933 ReportDiagnostic(info->record()->getInnerLocStart(), |
973 diag_class_requires_trace_method_) | 934 diag_class_requires_trace_method_) |
974 << info->record(); | 935 << info->record(); |
975 | 936 |
976 for (RecordInfo::Bases::iterator it = info->GetBases().begin(); | 937 for (auto& base : info->GetBases()) |
977 it != info->GetBases().end(); | 938 if (base.second.NeedsTracing().IsNeeded()) |
978 ++it) { | 939 NoteBaseRequiresTracing(&base.second); |
979 if (it->second.NeedsTracing().IsNeeded()) | |
980 NoteBaseRequiresTracing(&it->second); | |
981 } | |
982 | 940 |
983 for (RecordInfo::Fields::iterator it = info->GetFields().begin(); | 941 for (auto& field : info->GetFields()) |
984 it != info->GetFields().end(); | 942 if (!field.second.IsProperlyTraced()) |
985 ++it) { | 943 NoteFieldRequiresTracing(info, field.first); |
986 if (!it->second.IsProperlyTraced()) | |
987 NoteFieldRequiresTracing(info, it->first); | |
988 } | |
989 } | 944 } |
990 | 945 |
991 void BlinkGCPluginConsumer::ReportBaseRequiresTracing( | 946 void BlinkGCPluginConsumer::ReportBaseRequiresTracing( |
992 RecordInfo* derived, | 947 RecordInfo* derived, |
993 CXXMethodDecl* trace, | 948 CXXMethodDecl* trace, |
994 CXXRecordDecl* base) { | 949 CXXRecordDecl* base) { |
995 ReportDiagnostic(trace->getLocStart(), diag_base_requires_tracing_) | 950 ReportDiagnostic(trace->getLocStart(), diag_base_requires_tracing_) |
996 << base << derived->record(); | 951 << base << derived->record(); |
997 } | 952 } |
998 | 953 |
999 void BlinkGCPluginConsumer::ReportFieldsRequireTracing( | 954 void BlinkGCPluginConsumer::ReportFieldsRequireTracing( |
1000 RecordInfo* info, | 955 RecordInfo* info, |
1001 CXXMethodDecl* trace) { | 956 CXXMethodDecl* trace) { |
1002 ReportDiagnostic(trace->getLocStart(), diag_fields_require_tracing_) | 957 ReportDiagnostic(trace->getLocStart(), diag_fields_require_tracing_) |
1003 << info->record(); | 958 << info->record(); |
1004 for (RecordInfo::Fields::iterator it = info->GetFields().begin(); | 959 for (auto& field : info->GetFields()) |
1005 it != info->GetFields().end(); | 960 if (!field.second.IsProperlyTraced()) |
1006 ++it) { | 961 NoteFieldRequiresTracing(info, field.first); |
1007 if (!it->second.IsProperlyTraced()) | |
1008 NoteFieldRequiresTracing(info, it->first); | |
1009 } | |
1010 } | 962 } |
1011 | 963 |
1012 void BlinkGCPluginConsumer::ReportClassContainsInvalidFields( | 964 void BlinkGCPluginConsumer::ReportClassContainsInvalidFields( |
1013 RecordInfo* info, | 965 RecordInfo* info, |
1014 CheckFieldsVisitor::Errors* errors) { | 966 const CheckFieldsVisitor::Errors& errors) { |
1015 bool only_warnings = options_.warn_raw_ptr; | 967 bool only_warnings = options_.warn_raw_ptr; |
1016 for (CheckFieldsVisitor::Errors::iterator it = errors->begin(); | 968 for (auto& error : errors) |
1017 only_warnings && it != errors->end(); | 969 if (!CheckFieldsVisitor::IsWarning(error.second)) |
1018 ++it) { | |
1019 if (!CheckFieldsVisitor::IsWarning(it->second)) | |
1020 only_warnings = false; | 970 only_warnings = false; |
1021 } | 971 |
1022 ReportDiagnostic(info->record()->getLocStart(), | 972 ReportDiagnostic(info->record()->getLocStart(), |
1023 only_warnings ? | 973 only_warnings ? |
1024 diag_class_contains_invalid_fields_warning_ : | 974 diag_class_contains_invalid_fields_warning_ : |
1025 diag_class_contains_invalid_fields_) | 975 diag_class_contains_invalid_fields_) |
1026 << info->record(); | 976 << info->record(); |
1027 | 977 |
1028 for (CheckFieldsVisitor::Errors::iterator it = errors->begin(); | 978 for (auto& error : errors) { |
1029 it != errors->end(); | 979 unsigned note; |
1030 ++it) { | 980 if (CheckFieldsVisitor::IsRawPtrError(error.second)) { |
1031 unsigned error; | 981 note = diag_raw_ptr_to_gc_managed_class_note_; |
1032 if (CheckFieldsVisitor::IsRawPtrError(it->second)) { | 982 } else if (CheckFieldsVisitor::IsReferencePtrError(error.second)) { |
1033 error = diag_raw_ptr_to_gc_managed_class_note_; | 983 note = diag_reference_ptr_to_gc_managed_class_note_; |
1034 } else if (CheckFieldsVisitor::IsReferencePtrError(it->second)) { | 984 } else if (error.second == CheckFieldsVisitor::kRefPtrToGCManaged) { |
1035 error = diag_reference_ptr_to_gc_managed_class_note_; | 985 note = diag_ref_ptr_to_gc_managed_class_note_; |
1036 } else if (it->second == CheckFieldsVisitor::kRefPtrToGCManaged) { | 986 } else if (error.second == CheckFieldsVisitor::kOwnPtrToGCManaged) { |
1037 error = diag_ref_ptr_to_gc_managed_class_note_; | 987 note = diag_own_ptr_to_gc_managed_class_note_; |
1038 } else if (it->second == CheckFieldsVisitor::kOwnPtrToGCManaged) { | 988 } else if (error.second == CheckFieldsVisitor::kMemberToGCUnmanaged) { |
1039 error = diag_own_ptr_to_gc_managed_class_note_; | 989 note = diag_member_to_gc_unmanaged_class_note_; |
1040 } else if (it->second == CheckFieldsVisitor::kMemberToGCUnmanaged) { | 990 } else if (error.second == CheckFieldsVisitor::kMemberInUnmanaged) { |
1041 error = diag_member_to_gc_unmanaged_class_note_; | 991 note = diag_member_in_unmanaged_class_note_; |
1042 } else if (it->second == CheckFieldsVisitor::kMemberInUnmanaged) { | 992 } else if (error.second == CheckFieldsVisitor::kPtrFromHeapToStack) { |
1043 error = diag_member_in_unmanaged_class_note_; | 993 note = diag_stack_allocated_field_note_; |
1044 } else if (it->second == CheckFieldsVisitor::kPtrFromHeapToStack) { | 994 } else if (error.second == CheckFieldsVisitor::kGCDerivedPartObject) { |
1045 error = diag_stack_allocated_field_note_; | 995 note = diag_part_object_to_gc_derived_class_note_; |
1046 } else if (it->second == CheckFieldsVisitor::kGCDerivedPartObject) { | |
1047 error = diag_part_object_to_gc_derived_class_note_; | |
1048 } else { | 996 } else { |
1049 assert(false && "Unknown field error"); | 997 assert(false && "Unknown field error"); |
1050 } | 998 } |
1051 NoteField(it->first, error); | 999 NoteField(error.first, note); |
1052 } | 1000 } |
1053 } | 1001 } |
1054 | 1002 |
1055 void BlinkGCPluginConsumer::ReportClassContainsGCRoots( | 1003 void BlinkGCPluginConsumer::ReportClassContainsGCRoots( |
1056 RecordInfo* info, | 1004 RecordInfo* info, |
1057 CheckGCRootsVisitor::Errors* errors) { | 1005 const CheckGCRootsVisitor::Errors& errors) { |
1058 for (CheckGCRootsVisitor::Errors::iterator it = errors->begin(); | 1006 for (auto& error : errors) { |
1059 it != errors->end(); | 1007 FieldPoint* point = nullptr; |
1060 ++it) { | 1008 for (FieldPoint* path : error) { |
1061 CheckGCRootsVisitor::RootPath::iterator path = it->begin(); | 1009 if (!point) { |
1062 FieldPoint* point = *path; | 1010 point = path; |
1063 ReportDiagnostic(info->record()->getLocStart(), | 1011 ReportDiagnostic(info->record()->getLocStart(), |
1064 diag_class_contains_gc_root_) | 1012 diag_class_contains_gc_root_) |
1065 << info->record() << point->field(); | 1013 << info->record() << point->field(); |
1066 while (++path != it->end()) { | 1014 continue; |
| 1015 } |
1067 NotePartObjectContainsGCRoot(point); | 1016 NotePartObjectContainsGCRoot(point); |
1068 point = *path; | 1017 point = path; |
1069 } | 1018 } |
1070 NoteFieldContainsGCRoot(point); | 1019 NoteFieldContainsGCRoot(point); |
1071 } | 1020 } |
1072 } | 1021 } |
1073 | 1022 |
1074 void BlinkGCPluginConsumer::ReportFinalizerAccessesFinalizedFields( | 1023 void BlinkGCPluginConsumer::ReportFinalizerAccessesFinalizedFields( |
1075 CXXMethodDecl* dtor, | 1024 CXXMethodDecl* dtor, |
1076 CheckFinalizerVisitor::Errors* fields) { | 1025 const CheckFinalizerVisitor::Errors& errors) { |
1077 for (CheckFinalizerVisitor::Errors::iterator it = fields->begin(); | 1026 for (auto& error : errors) { |
1078 it != fields->end(); | 1027 bool as_eagerly_finalized = error.as_eagerly_finalized; |
1079 ++it) { | |
1080 bool as_eagerly_finalized = it->as_eagerly_finalized; | |
1081 unsigned diag_error = as_eagerly_finalized ? | 1028 unsigned diag_error = as_eagerly_finalized ? |
1082 diag_finalizer_eagerly_finalized_field_ : | 1029 diag_finalizer_eagerly_finalized_field_ : |
1083 diag_finalizer_accesses_finalized_field_; | 1030 diag_finalizer_accesses_finalized_field_; |
1084 unsigned diag_note = as_eagerly_finalized ? | 1031 unsigned diag_note = as_eagerly_finalized ? |
1085 diag_eagerly_finalized_field_note_ : | 1032 diag_eagerly_finalized_field_note_ : |
1086 diag_finalized_field_note_; | 1033 diag_finalized_field_note_; |
1087 ReportDiagnostic(it->member->getLocStart(), diag_error) | 1034 ReportDiagnostic(error.member->getLocStart(), diag_error) |
1088 << dtor << it->field->field(); | 1035 << dtor << error.field->field(); |
1089 NoteField(it->field, diag_note); | 1036 NoteField(error.field, diag_note); |
1090 } | 1037 } |
1091 } | 1038 } |
1092 | 1039 |
1093 void BlinkGCPluginConsumer::ReportClassRequiresFinalization(RecordInfo* info) { | 1040 void BlinkGCPluginConsumer::ReportClassRequiresFinalization(RecordInfo* info) { |
1094 ReportDiagnostic(info->record()->getInnerLocStart(), | 1041 ReportDiagnostic(info->record()->getInnerLocStart(), |
1095 diag_class_requires_finalization_) | 1042 diag_class_requires_finalization_) |
1096 << info->record(); | 1043 << info->record(); |
1097 } | 1044 } |
1098 | 1045 |
1099 void BlinkGCPluginConsumer::ReportClassDoesNotRequireFinalization( | 1046 void BlinkGCPluginConsumer::ReportClassDoesNotRequireFinalization( |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1245 void BlinkGCPluginConsumer::NoteField(FieldDecl* field, unsigned note) { | 1192 void BlinkGCPluginConsumer::NoteField(FieldDecl* field, unsigned note) { |
1246 ReportDiagnostic(field->getLocStart(), note) << field; | 1193 ReportDiagnostic(field->getLocStart(), note) << field; |
1247 } | 1194 } |
1248 | 1195 |
1249 void BlinkGCPluginConsumer::NoteOverriddenNonVirtualTrace( | 1196 void BlinkGCPluginConsumer::NoteOverriddenNonVirtualTrace( |
1250 CXXMethodDecl* overridden) { | 1197 CXXMethodDecl* overridden) { |
1251 ReportDiagnostic(overridden->getLocStart(), | 1198 ReportDiagnostic(overridden->getLocStart(), |
1252 diag_overridden_non_virtual_trace_note_) | 1199 diag_overridden_non_virtual_trace_note_) |
1253 << overridden; | 1200 << overridden; |
1254 } | 1201 } |
OLD | NEW |