| 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 |