OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 // This clang plugin checks various invariants of the Blink garbage | 5 // This clang plugin checks various invariants of the Blink garbage |
6 // collection infrastructure. | 6 // collection infrastructure. |
7 // | 7 // |
8 // Errors are described at: | 8 // Errors are described at: |
9 // http://www.chromium.org/developers/blink-gc-plugin-errors | 9 // http://www.chromium.org/developers/blink-gc-plugin-errors |
10 | 10 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 | 43 |
44 const char kClassContainsInvalidFields[] = | 44 const char kClassContainsInvalidFields[] = |
45 "[blink-gc] Class %0 contains invalid fields."; | 45 "[blink-gc] Class %0 contains invalid fields."; |
46 | 46 |
47 const char kClassContainsGCRoot[] = | 47 const char kClassContainsGCRoot[] = |
48 "[blink-gc] Class %0 contains GC root in field %1."; | 48 "[blink-gc] Class %0 contains GC root in field %1."; |
49 | 49 |
50 const char kClassRequiresFinalization[] = | 50 const char kClassRequiresFinalization[] = |
51 "[blink-gc] Class %0 requires finalization."; | 51 "[blink-gc] Class %0 requires finalization."; |
52 | 52 |
| 53 const char kClassDoesNotRequireFinalization[] = |
| 54 "[blink-gc] Class %0 may not require finalization."; |
| 55 |
53 const char kFinalizerAccessesFinalizedField[] = | 56 const char kFinalizerAccessesFinalizedField[] = |
54 "[blink-gc] Finalizer %0 accesses potentially finalized field %1."; | 57 "[blink-gc] Finalizer %0 accesses potentially finalized field %1."; |
55 | 58 |
56 const char kRawPtrToGCManagedClassNote[] = | 59 const char kRawPtrToGCManagedClassNote[] = |
57 "[blink-gc] Raw pointer field %0 to a GC managed class declared here:"; | 60 "[blink-gc] Raw pointer field %0 to a GC managed class declared here:"; |
58 | 61 |
59 const char kRefPtrToGCManagedClassNote[] = | 62 const char kRefPtrToGCManagedClassNote[] = |
60 "[blink-gc] RefPtr field %0 to a GC managed class declared here:"; | 63 "[blink-gc] RefPtr field %0 to a GC managed class declared here:"; |
61 | 64 |
62 const char kOwnPtrToGCManagedClassNote[] = | 65 const char kOwnPtrToGCManagedClassNote[] = |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 | 134 |
132 const char kLeftMostBaseMustBePolymorphic[] = | 135 const char kLeftMostBaseMustBePolymorphic[] = |
133 "[blink-gc] Left-most base class %0 of derived class %1" | 136 "[blink-gc] Left-most base class %0 of derived class %1" |
134 " must be polymorphic."; | 137 " must be polymorphic."; |
135 | 138 |
136 const char kBaseClassMustDeclareVirtualTrace[] = | 139 const char kBaseClassMustDeclareVirtualTrace[] = |
137 "[blink-gc] Left-most base class %0 of derived class %1" | 140 "[blink-gc] Left-most base class %0 of derived class %1" |
138 " must define a virtual trace method."; | 141 " must define a virtual trace method."; |
139 | 142 |
140 struct BlinkGCPluginOptions { | 143 struct BlinkGCPluginOptions { |
141 BlinkGCPluginOptions() : enable_oilpan(false), dump_graph(false) {} | 144 BlinkGCPluginOptions() |
| 145 : enable_oilpan(false) |
| 146 , dump_graph(false) |
| 147 , warn_raw_ptr(false) |
| 148 , warn_unneeded_finalizer(false) {} |
142 bool enable_oilpan; | 149 bool enable_oilpan; |
143 bool dump_graph; | 150 bool dump_graph; |
| 151 bool warn_raw_ptr; |
| 152 bool warn_unneeded_finalizer; |
144 std::set<std::string> ignored_classes; | 153 std::set<std::string> ignored_classes; |
145 std::set<std::string> checked_namespaces; | 154 std::set<std::string> checked_namespaces; |
146 std::vector<std::string> ignored_directories; | 155 std::vector<std::string> ignored_directories; |
147 }; | 156 }; |
148 | 157 |
149 typedef std::vector<CXXRecordDecl*> RecordVector; | 158 typedef std::vector<CXXRecordDecl*> RecordVector; |
150 typedef std::vector<CXXMethodDecl*> MethodVector; | 159 typedef std::vector<CXXMethodDecl*> MethodVector; |
151 | 160 |
152 // Test if a template specialization is an instantiation. | 161 // Test if a template specialization is an instantiation. |
153 static bool IsTemplateInstantiation(CXXRecordDecl* record) { | 162 static bool IsTemplateInstantiation(CXXRecordDecl* record) { |
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
612 // This visitor checks that the fields of a class are "well formed". | 621 // This visitor checks that the fields of a class are "well formed". |
613 // - OwnPtr, RefPtr and RawPtr must not point to a GC derived types. | 622 // - OwnPtr, RefPtr and RawPtr must not point to a GC derived types. |
614 // - Part objects must not be GC derived types. | 623 // - Part objects must not be GC derived types. |
615 // - An on-heap class must never contain GC roots. | 624 // - An on-heap class must never contain GC roots. |
616 // - Only stack-allocated types may point to stack-allocated types. | 625 // - Only stack-allocated types may point to stack-allocated types. |
617 class CheckFieldsVisitor : public RecursiveEdgeVisitor { | 626 class CheckFieldsVisitor : public RecursiveEdgeVisitor { |
618 public: | 627 public: |
619 | 628 |
620 enum Error { | 629 enum Error { |
621 kRawPtrToGCManaged, | 630 kRawPtrToGCManaged, |
| 631 kRawPtrToGCManagedWarning, |
622 kRefPtrToGCManaged, | 632 kRefPtrToGCManaged, |
623 kOwnPtrToGCManaged, | 633 kOwnPtrToGCManaged, |
624 kMemberInUnmanaged, | 634 kMemberInUnmanaged, |
625 kPtrFromHeapToStack, | 635 kPtrFromHeapToStack, |
626 kGCDerivedPartObject | 636 kGCDerivedPartObject |
627 }; | 637 }; |
628 | 638 |
629 typedef std::vector<std::pair<FieldPoint*, Error> > Errors; | 639 typedef std::vector<std::pair<FieldPoint*, Error> > Errors; |
630 | 640 |
631 CheckFieldsVisitor(const BlinkGCPluginOptions& options) | 641 CheckFieldsVisitor(const BlinkGCPluginOptions& options) |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
685 // In transition mode, disallow OwnPtr<T>, RawPtr<T> to GC allocated T's, | 695 // In transition mode, disallow OwnPtr<T>, RawPtr<T> to GC allocated T's, |
686 // also disallow T* in stack-allocated types. | 696 // also disallow T* in stack-allocated types. |
687 if (options_.enable_oilpan) { | 697 if (options_.enable_oilpan) { |
688 if (Parent()->IsOwnPtr() || | 698 if (Parent()->IsOwnPtr() || |
689 Parent()->IsRawPtrClass() || | 699 Parent()->IsRawPtrClass() || |
690 (stack_allocated_host_ && Parent()->IsRawPtr())) { | 700 (stack_allocated_host_ && Parent()->IsRawPtr())) { |
691 invalid_fields_.push_back(std::make_pair( | 701 invalid_fields_.push_back(std::make_pair( |
692 current_, InvalidSmartPtr(Parent()))); | 702 current_, InvalidSmartPtr(Parent()))); |
693 return; | 703 return; |
694 } | 704 } |
695 | 705 if (options_.warn_raw_ptr && Parent()->IsRawPtr()) { |
| 706 invalid_fields_.push_back(std::make_pair( |
| 707 current_, kRawPtrToGCManagedWarning)); |
| 708 } |
696 return; | 709 return; |
697 } | 710 } |
698 | 711 |
699 if (Parent()->IsRawPtr() || Parent()->IsRefPtr() || Parent()->IsOwnPtr()) { | 712 if (Parent()->IsRawPtr() || Parent()->IsRefPtr() || Parent()->IsOwnPtr()) { |
700 invalid_fields_.push_back(std::make_pair( | 713 invalid_fields_.push_back(std::make_pair( |
701 current_, InvalidSmartPtr(Parent()))); | 714 current_, InvalidSmartPtr(Parent()))); |
702 return; | 715 return; |
703 } | 716 } |
704 } | 717 } |
705 | 718 |
(...skipping 13 matching lines...) Expand all Loading... |
719 assert(false && "Unknown smart pointer kind"); | 732 assert(false && "Unknown smart pointer kind"); |
720 } | 733 } |
721 | 734 |
722 const BlinkGCPluginOptions& options_; | 735 const BlinkGCPluginOptions& options_; |
723 FieldPoint* current_; | 736 FieldPoint* current_; |
724 bool stack_allocated_host_; | 737 bool stack_allocated_host_; |
725 bool managed_host_; | 738 bool managed_host_; |
726 Errors invalid_fields_; | 739 Errors invalid_fields_; |
727 }; | 740 }; |
728 | 741 |
| 742 class EmptyStmtVisitor |
| 743 : public RecursiveASTVisitor<EmptyStmtVisitor> { |
| 744 public: |
| 745 static bool isEmpty(Stmt* stmt) { |
| 746 EmptyStmtVisitor visitor; |
| 747 visitor.TraverseStmt(stmt); |
| 748 return visitor.empty_; |
| 749 } |
| 750 |
| 751 bool WalkUpFromCompoundStmt(CompoundStmt* stmt) { |
| 752 empty_ = stmt->body_empty(); |
| 753 return false; |
| 754 } |
| 755 bool VisitStmt(Stmt*) { |
| 756 empty_ = false; |
| 757 return false; |
| 758 } |
| 759 private: |
| 760 EmptyStmtVisitor() : empty_(true) {} |
| 761 bool empty_; |
| 762 }; |
| 763 |
729 // Main class containing checks for various invariants of the Blink | 764 // Main class containing checks for various invariants of the Blink |
730 // garbage collection infrastructure. | 765 // garbage collection infrastructure. |
731 class BlinkGCPluginConsumer : public ASTConsumer { | 766 class BlinkGCPluginConsumer : public ASTConsumer { |
732 public: | 767 public: |
733 BlinkGCPluginConsumer(CompilerInstance& instance, | 768 BlinkGCPluginConsumer(CompilerInstance& instance, |
734 const BlinkGCPluginOptions& options) | 769 const BlinkGCPluginOptions& options) |
735 : instance_(instance), | 770 : instance_(instance), |
736 diagnostic_(instance.getDiagnostics()), | 771 diagnostic_(instance.getDiagnostics()), |
737 options_(options), | 772 options_(options), |
738 json_(0) { | 773 json_(0) { |
739 | 774 |
740 // Only check structures in the blink and WebKit namespaces. | 775 // Only check structures in the blink and WebKit namespaces. |
741 options_.checked_namespaces.insert("blink"); | 776 options_.checked_namespaces.insert("blink"); |
742 options_.checked_namespaces.insert("WebKit"); | 777 options_.checked_namespaces.insert("WebKit"); |
743 | 778 |
744 // Ignore GC implementation files. | 779 // Ignore GC implementation files. |
745 options_.ignored_directories.push_back("/heap/"); | 780 options_.ignored_directories.push_back("/heap/"); |
746 | 781 |
747 // Register warning/error messages. | 782 // Register warning/error messages. |
748 diag_class_must_left_mostly_derive_gc_ = diagnostic_.getCustomDiagID( | 783 diag_class_must_left_mostly_derive_gc_ = diagnostic_.getCustomDiagID( |
749 getErrorLevel(), kClassMustLeftMostlyDeriveGC); | 784 getErrorLevel(), kClassMustLeftMostlyDeriveGC); |
750 diag_class_requires_trace_method_ = | 785 diag_class_requires_trace_method_ = |
751 diagnostic_.getCustomDiagID(getErrorLevel(), kClassRequiresTraceMethod); | 786 diagnostic_.getCustomDiagID(getErrorLevel(), kClassRequiresTraceMethod); |
752 diag_base_requires_tracing_ = | 787 diag_base_requires_tracing_ = |
753 diagnostic_.getCustomDiagID(getErrorLevel(), kBaseRequiresTracing); | 788 diagnostic_.getCustomDiagID(getErrorLevel(), kBaseRequiresTracing); |
754 diag_fields_require_tracing_ = | 789 diag_fields_require_tracing_ = |
755 diagnostic_.getCustomDiagID(getErrorLevel(), kFieldsRequireTracing); | 790 diagnostic_.getCustomDiagID(getErrorLevel(), kFieldsRequireTracing); |
756 diag_class_contains_invalid_fields_ = diagnostic_.getCustomDiagID( | 791 diag_class_contains_invalid_fields_ = diagnostic_.getCustomDiagID( |
757 getErrorLevel(), kClassContainsInvalidFields); | 792 getErrorLevel(), kClassContainsInvalidFields); |
| 793 diag_class_contains_invalid_fields_warning_ = diagnostic_.getCustomDiagID( |
| 794 DiagnosticsEngine::Warning, kClassContainsInvalidFields); |
758 diag_class_contains_gc_root_ = | 795 diag_class_contains_gc_root_ = |
759 diagnostic_.getCustomDiagID(getErrorLevel(), kClassContainsGCRoot); | 796 diagnostic_.getCustomDiagID(getErrorLevel(), kClassContainsGCRoot); |
760 diag_class_requires_finalization_ = diagnostic_.getCustomDiagID( | 797 diag_class_requires_finalization_ = diagnostic_.getCustomDiagID( |
761 getErrorLevel(), kClassRequiresFinalization); | 798 getErrorLevel(), kClassRequiresFinalization); |
| 799 diag_class_does_not_require_finalization_ = diagnostic_.getCustomDiagID( |
| 800 DiagnosticsEngine::Warning, kClassDoesNotRequireFinalization); |
762 diag_finalizer_accesses_finalized_field_ = diagnostic_.getCustomDiagID( | 801 diag_finalizer_accesses_finalized_field_ = diagnostic_.getCustomDiagID( |
763 getErrorLevel(), kFinalizerAccessesFinalizedField); | 802 getErrorLevel(), kFinalizerAccessesFinalizedField); |
764 diag_overridden_non_virtual_trace_ = diagnostic_.getCustomDiagID( | 803 diag_overridden_non_virtual_trace_ = diagnostic_.getCustomDiagID( |
765 getErrorLevel(), kOverriddenNonVirtualTrace); | 804 getErrorLevel(), kOverriddenNonVirtualTrace); |
766 diag_missing_trace_dispatch_method_ = diagnostic_.getCustomDiagID( | 805 diag_missing_trace_dispatch_method_ = diagnostic_.getCustomDiagID( |
767 getErrorLevel(), kMissingTraceDispatchMethod); | 806 getErrorLevel(), kMissingTraceDispatchMethod); |
768 diag_missing_finalize_dispatch_method_ = diagnostic_.getCustomDiagID( | 807 diag_missing_finalize_dispatch_method_ = diagnostic_.getCustomDiagID( |
769 getErrorLevel(), kMissingFinalizeDispatchMethod); | 808 getErrorLevel(), kMissingFinalizeDispatchMethod); |
770 diag_virtual_and_manual_dispatch_ = | 809 diag_virtual_and_manual_dispatch_ = |
771 diagnostic_.getCustomDiagID(getErrorLevel(), kVirtualAndManualDispatch); | 810 diagnostic_.getCustomDiagID(getErrorLevel(), kVirtualAndManualDispatch); |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
934 } | 973 } |
935 | 974 |
936 { | 975 { |
937 CheckGCRootsVisitor visitor; | 976 CheckGCRootsVisitor visitor; |
938 if (visitor.ContainsGCRoots(info)) | 977 if (visitor.ContainsGCRoots(info)) |
939 ReportClassContainsGCRoots(info, &visitor.gc_roots()); | 978 ReportClassContainsGCRoots(info, &visitor.gc_roots()); |
940 } | 979 } |
941 | 980 |
942 if (info->NeedsFinalization()) | 981 if (info->NeedsFinalization()) |
943 CheckFinalization(info); | 982 CheckFinalization(info); |
| 983 |
| 984 if (options_.warn_unneeded_finalizer && info->IsGCFinalized()) |
| 985 CheckUnneededFinalization(info); |
944 } | 986 } |
945 | 987 |
946 DumpClass(info); | 988 DumpClass(info); |
947 } | 989 } |
948 | 990 |
949 CXXRecordDecl* GetDependentTemplatedDecl(const Type& type) { | 991 CXXRecordDecl* GetDependentTemplatedDecl(const Type& type) { |
950 const TemplateSpecializationType* tmpl_type = | 992 const TemplateSpecializationType* tmpl_type = |
951 type.getAs<TemplateSpecializationType>(); | 993 type.getAs<TemplateSpecializationType>(); |
952 if (!tmpl_type) | 994 if (!tmpl_type) |
953 return 0; | 995 return 0; |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1158 } | 1200 } |
1159 | 1201 |
1160 for (RecordInfo::Fields::iterator it = info->GetFields().begin(); | 1202 for (RecordInfo::Fields::iterator it = info->GetFields().begin(); |
1161 it != info->GetFields().end(); | 1203 it != info->GetFields().end(); |
1162 ++it) { | 1204 ++it) { |
1163 if (it->second.edge()->NeedsFinalization()) | 1205 if (it->second.edge()->NeedsFinalization()) |
1164 NoteField(&it->second, diag_field_requires_finalization_note_); | 1206 NoteField(&it->second, diag_field_requires_finalization_note_); |
1165 } | 1207 } |
1166 } | 1208 } |
1167 | 1209 |
| 1210 void CheckUnneededFinalization(RecordInfo* info) { |
| 1211 if (!HasNonEmptyFinalizer(info)) |
| 1212 ReportClassDoesNotRequireFinalization(info); |
| 1213 } |
| 1214 |
| 1215 bool HasNonEmptyFinalizer(RecordInfo* info) { |
| 1216 CXXDestructorDecl* dtor = info->record()->getDestructor(); |
| 1217 if (dtor && dtor->isUserProvided()) { |
| 1218 if (!dtor->hasBody() || !EmptyStmtVisitor::isEmpty(dtor->getBody())) |
| 1219 return true; |
| 1220 } |
| 1221 for (RecordInfo::Bases::iterator it = info->GetBases().begin(); |
| 1222 it != info->GetBases().end(); |
| 1223 ++it) { |
| 1224 if (HasNonEmptyFinalizer(it->second.info())) |
| 1225 return true; |
| 1226 } |
| 1227 for (RecordInfo::Fields::iterator it = info->GetFields().begin(); |
| 1228 it != info->GetFields().end(); |
| 1229 ++it) { |
| 1230 if (it->second.edge()->NeedsFinalization()) |
| 1231 return true; |
| 1232 } |
| 1233 return false; |
| 1234 } |
| 1235 |
1168 // This is the main entry for tracing method definitions. | 1236 // This is the main entry for tracing method definitions. |
1169 void CheckTracingMethod(CXXMethodDecl* method) { | 1237 void CheckTracingMethod(CXXMethodDecl* method) { |
1170 RecordInfo* parent = cache_.Lookup(method->getParent()); | 1238 RecordInfo* parent = cache_.Lookup(method->getParent()); |
1171 if (IsIgnored(parent)) | 1239 if (IsIgnored(parent)) |
1172 return; | 1240 return; |
1173 | 1241 |
1174 // Check templated tracing methods by checking the template instantiations. | 1242 // Check templated tracing methods by checking the template instantiations. |
1175 // Specialized templates are handled as ordinary classes. | 1243 // Specialized templates are handled as ordinary classes. |
1176 if (ClassTemplateDecl* tmpl = | 1244 if (ClassTemplateDecl* tmpl = |
1177 parent->record()->getDescribedClassTemplate()) { | 1245 parent->record()->getDescribedClassTemplate()) { |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1455 if (!it->second.IsProperlyTraced()) | 1523 if (!it->second.IsProperlyTraced()) |
1456 NoteFieldRequiresTracing(info, it->first); | 1524 NoteFieldRequiresTracing(info, it->first); |
1457 } | 1525 } |
1458 } | 1526 } |
1459 | 1527 |
1460 void ReportClassContainsInvalidFields(RecordInfo* info, | 1528 void ReportClassContainsInvalidFields(RecordInfo* info, |
1461 CheckFieldsVisitor::Errors* errors) { | 1529 CheckFieldsVisitor::Errors* errors) { |
1462 SourceLocation loc = info->record()->getLocStart(); | 1530 SourceLocation loc = info->record()->getLocStart(); |
1463 SourceManager& manager = instance_.getSourceManager(); | 1531 SourceManager& manager = instance_.getSourceManager(); |
1464 FullSourceLoc full_loc(loc, manager); | 1532 FullSourceLoc full_loc(loc, manager); |
1465 diagnostic_.Report(full_loc, diag_class_contains_invalid_fields_) | 1533 bool only_warnings = options_.warn_raw_ptr; |
| 1534 for (CheckFieldsVisitor::Errors::iterator it = errors->begin(); |
| 1535 only_warnings && it != errors->end(); |
| 1536 ++it) { |
| 1537 if (it->second != CheckFieldsVisitor::kRawPtrToGCManagedWarning) |
| 1538 only_warnings = false; |
| 1539 } |
| 1540 diagnostic_.Report(full_loc, only_warnings ? |
| 1541 diag_class_contains_invalid_fields_warning_ : |
| 1542 diag_class_contains_invalid_fields_) |
1466 << info->record(); | 1543 << info->record(); |
1467 for (CheckFieldsVisitor::Errors::iterator it = errors->begin(); | 1544 for (CheckFieldsVisitor::Errors::iterator it = errors->begin(); |
1468 it != errors->end(); | 1545 it != errors->end(); |
1469 ++it) { | 1546 ++it) { |
1470 unsigned error; | 1547 unsigned error; |
1471 if (it->second == CheckFieldsVisitor::kRawPtrToGCManaged) { | 1548 if (it->second == CheckFieldsVisitor::kRawPtrToGCManaged || |
| 1549 it->second == CheckFieldsVisitor::kRawPtrToGCManagedWarning) { |
1472 error = diag_raw_ptr_to_gc_managed_class_note_; | 1550 error = diag_raw_ptr_to_gc_managed_class_note_; |
1473 } else if (it->second == CheckFieldsVisitor::kRefPtrToGCManaged) { | 1551 } else if (it->second == CheckFieldsVisitor::kRefPtrToGCManaged) { |
1474 error = diag_ref_ptr_to_gc_managed_class_note_; | 1552 error = diag_ref_ptr_to_gc_managed_class_note_; |
1475 } else if (it->second == CheckFieldsVisitor::kOwnPtrToGCManaged) { | 1553 } else if (it->second == CheckFieldsVisitor::kOwnPtrToGCManaged) { |
1476 error = diag_own_ptr_to_gc_managed_class_note_; | 1554 error = diag_own_ptr_to_gc_managed_class_note_; |
1477 } else if (it->second == CheckFieldsVisitor::kMemberInUnmanaged) { | 1555 } else if (it->second == CheckFieldsVisitor::kMemberInUnmanaged) { |
1478 error = diag_member_in_unmanaged_class_note_; | 1556 error = diag_member_in_unmanaged_class_note_; |
1479 } else if (it->second == CheckFieldsVisitor::kPtrFromHeapToStack) { | 1557 } else if (it->second == CheckFieldsVisitor::kPtrFromHeapToStack) { |
1480 error = diag_stack_allocated_field_note_; | 1558 error = diag_stack_allocated_field_note_; |
1481 } else if (it->second == CheckFieldsVisitor::kGCDerivedPartObject) { | 1559 } else if (it->second == CheckFieldsVisitor::kGCDerivedPartObject) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1523 } | 1601 } |
1524 | 1602 |
1525 void ReportClassRequiresFinalization(RecordInfo* info) { | 1603 void ReportClassRequiresFinalization(RecordInfo* info) { |
1526 SourceLocation loc = info->record()->getInnerLocStart(); | 1604 SourceLocation loc = info->record()->getInnerLocStart(); |
1527 SourceManager& manager = instance_.getSourceManager(); | 1605 SourceManager& manager = instance_.getSourceManager(); |
1528 FullSourceLoc full_loc(loc, manager); | 1606 FullSourceLoc full_loc(loc, manager); |
1529 diagnostic_.Report(full_loc, diag_class_requires_finalization_) | 1607 diagnostic_.Report(full_loc, diag_class_requires_finalization_) |
1530 << info->record(); | 1608 << info->record(); |
1531 } | 1609 } |
1532 | 1610 |
| 1611 void ReportClassDoesNotRequireFinalization(RecordInfo* info) { |
| 1612 SourceLocation loc = info->record()->getInnerLocStart(); |
| 1613 SourceManager& manager = instance_.getSourceManager(); |
| 1614 FullSourceLoc full_loc(loc, manager); |
| 1615 diagnostic_.Report(full_loc, diag_class_does_not_require_finalization_) |
| 1616 << info->record(); |
| 1617 } |
| 1618 |
1533 void ReportOverriddenNonVirtualTrace(RecordInfo* info, | 1619 void ReportOverriddenNonVirtualTrace(RecordInfo* info, |
1534 CXXMethodDecl* trace, | 1620 CXXMethodDecl* trace, |
1535 CXXMethodDecl* overridden) { | 1621 CXXMethodDecl* overridden) { |
1536 SourceLocation loc = trace->getLocStart(); | 1622 SourceLocation loc = trace->getLocStart(); |
1537 SourceManager& manager = instance_.getSourceManager(); | 1623 SourceManager& manager = instance_.getSourceManager(); |
1538 FullSourceLoc full_loc(loc, manager); | 1624 FullSourceLoc full_loc(loc, manager); |
1539 diagnostic_.Report(full_loc, diag_overridden_non_virtual_trace_) | 1625 diagnostic_.Report(full_loc, diag_overridden_non_virtual_trace_) |
1540 << info->record() << overridden->getParent(); | 1626 << info->record() << overridden->getParent(); |
1541 NoteOverriddenNonVirtualTrace(overridden); | 1627 NoteOverriddenNonVirtualTrace(overridden); |
1542 } | 1628 } |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1698 FullSourceLoc full_loc(loc, manager); | 1784 FullSourceLoc full_loc(loc, manager); |
1699 diagnostic_.Report(full_loc, diag_overridden_non_virtual_trace_note_) | 1785 diagnostic_.Report(full_loc, diag_overridden_non_virtual_trace_note_) |
1700 << overridden; | 1786 << overridden; |
1701 } | 1787 } |
1702 | 1788 |
1703 unsigned diag_class_must_left_mostly_derive_gc_; | 1789 unsigned diag_class_must_left_mostly_derive_gc_; |
1704 unsigned diag_class_requires_trace_method_; | 1790 unsigned diag_class_requires_trace_method_; |
1705 unsigned diag_base_requires_tracing_; | 1791 unsigned diag_base_requires_tracing_; |
1706 unsigned diag_fields_require_tracing_; | 1792 unsigned diag_fields_require_tracing_; |
1707 unsigned diag_class_contains_invalid_fields_; | 1793 unsigned diag_class_contains_invalid_fields_; |
| 1794 unsigned diag_class_contains_invalid_fields_warning_; |
1708 unsigned diag_class_contains_gc_root_; | 1795 unsigned diag_class_contains_gc_root_; |
1709 unsigned diag_class_requires_finalization_; | 1796 unsigned diag_class_requires_finalization_; |
| 1797 unsigned diag_class_does_not_require_finalization_; |
1710 unsigned diag_finalizer_accesses_finalized_field_; | 1798 unsigned diag_finalizer_accesses_finalized_field_; |
1711 unsigned diag_overridden_non_virtual_trace_; | 1799 unsigned diag_overridden_non_virtual_trace_; |
1712 unsigned diag_missing_trace_dispatch_method_; | 1800 unsigned diag_missing_trace_dispatch_method_; |
1713 unsigned diag_missing_finalize_dispatch_method_; | 1801 unsigned diag_missing_finalize_dispatch_method_; |
1714 unsigned diag_virtual_and_manual_dispatch_; | 1802 unsigned diag_virtual_and_manual_dispatch_; |
1715 unsigned diag_missing_trace_dispatch_; | 1803 unsigned diag_missing_trace_dispatch_; |
1716 unsigned diag_missing_finalize_dispatch_; | 1804 unsigned diag_missing_finalize_dispatch_; |
1717 unsigned diag_derives_non_stack_allocated_; | 1805 unsigned diag_derives_non_stack_allocated_; |
1718 unsigned diag_class_overrides_new_; | 1806 unsigned diag_class_overrides_new_; |
1719 unsigned diag_class_declares_pure_virtual_trace_; | 1807 unsigned diag_class_declares_pure_virtual_trace_; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1758 | 1846 |
1759 virtual bool ParseArgs(const CompilerInstance& instance, | 1847 virtual bool ParseArgs(const CompilerInstance& instance, |
1760 const std::vector<string>& args) { | 1848 const std::vector<string>& args) { |
1761 bool parsed = true; | 1849 bool parsed = true; |
1762 | 1850 |
1763 for (size_t i = 0; i < args.size() && parsed; ++i) { | 1851 for (size_t i = 0; i < args.size() && parsed; ++i) { |
1764 if (args[i] == "enable-oilpan") { | 1852 if (args[i] == "enable-oilpan") { |
1765 options_.enable_oilpan = true; | 1853 options_.enable_oilpan = true; |
1766 } else if (args[i] == "dump-graph") { | 1854 } else if (args[i] == "dump-graph") { |
1767 options_.dump_graph = true; | 1855 options_.dump_graph = true; |
| 1856 } else if (args[i] == "warn-raw-ptr") { |
| 1857 options_.warn_raw_ptr = true; |
| 1858 } else if (args[i] == "warn-unneeded-finalizer") { |
| 1859 options_.warn_unneeded_finalizer = true; |
1768 } else { | 1860 } else { |
1769 parsed = false; | 1861 parsed = false; |
1770 llvm::errs() << "Unknown blink-gc-plugin argument: " << args[i] << "\n"; | 1862 llvm::errs() << "Unknown blink-gc-plugin argument: " << args[i] << "\n"; |
1771 } | 1863 } |
1772 } | 1864 } |
1773 | 1865 |
1774 return parsed; | 1866 return parsed; |
1775 } | 1867 } |
1776 | 1868 |
1777 private: | 1869 private: |
1778 BlinkGCPluginOptions options_; | 1870 BlinkGCPluginOptions options_; |
1779 }; | 1871 }; |
1780 | 1872 |
1781 } // namespace | 1873 } // namespace |
1782 | 1874 |
1783 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( | 1875 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( |
1784 "blink-gc-plugin", | 1876 "blink-gc-plugin", |
1785 "Check Blink GC invariants"); | 1877 "Check Blink GC invariants"); |
OLD | NEW |