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 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 " is not permitted to declare a pure-virtual trace method."; | 133 " is not permitted to declare a pure-virtual trace method."; |
134 | 134 |
135 const char kLeftMostBaseMustBePolymorphic[] = | 135 const char kLeftMostBaseMustBePolymorphic[] = |
136 "[blink-gc] Left-most base class %0 of derived class %1" | 136 "[blink-gc] Left-most base class %0 of derived class %1" |
137 " must be polymorphic."; | 137 " must be polymorphic."; |
138 | 138 |
139 const char kBaseClassMustDeclareVirtualTrace[] = | 139 const char kBaseClassMustDeclareVirtualTrace[] = |
140 "[blink-gc] Left-most base class %0 of derived class %1" | 140 "[blink-gc] Left-most base class %0 of derived class %1" |
141 " must define a virtual trace method."; | 141 " must define a virtual trace method."; |
142 | 142 |
| 143 const char kClassMustDeclareGCMixinTraceMethod[] = |
| 144 "[blink-gc] Class %0 which inherits from GarbageCollectedMixin must" |
| 145 " locally declare and override trace(Visitor*)"; |
| 146 |
143 struct BlinkGCPluginOptions { | 147 struct BlinkGCPluginOptions { |
144 BlinkGCPluginOptions() | 148 BlinkGCPluginOptions() |
145 : enable_oilpan(false) | 149 : enable_oilpan(false) |
146 , dump_graph(false) | 150 , dump_graph(false) |
147 , warn_raw_ptr(false) | 151 , warn_raw_ptr(false) |
148 , warn_unneeded_finalizer(false) {} | 152 , warn_unneeded_finalizer(false) {} |
149 bool enable_oilpan; | 153 bool enable_oilpan; |
150 bool dump_graph; | 154 bool dump_graph; |
151 bool warn_raw_ptr; | 155 bool warn_raw_ptr; |
152 bool warn_unneeded_finalizer; | 156 bool warn_unneeded_finalizer; |
(...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
840 diag_derives_non_stack_allocated_ = | 844 diag_derives_non_stack_allocated_ = |
841 diagnostic_.getCustomDiagID(getErrorLevel(), kDerivesNonStackAllocated); | 845 diagnostic_.getCustomDiagID(getErrorLevel(), kDerivesNonStackAllocated); |
842 diag_class_overrides_new_ = | 846 diag_class_overrides_new_ = |
843 diagnostic_.getCustomDiagID(getErrorLevel(), kClassOverridesNew); | 847 diagnostic_.getCustomDiagID(getErrorLevel(), kClassOverridesNew); |
844 diag_class_declares_pure_virtual_trace_ = diagnostic_.getCustomDiagID( | 848 diag_class_declares_pure_virtual_trace_ = diagnostic_.getCustomDiagID( |
845 getErrorLevel(), kClassDeclaresPureVirtualTrace); | 849 getErrorLevel(), kClassDeclaresPureVirtualTrace); |
846 diag_left_most_base_must_be_polymorphic_ = diagnostic_.getCustomDiagID( | 850 diag_left_most_base_must_be_polymorphic_ = diagnostic_.getCustomDiagID( |
847 getErrorLevel(), kLeftMostBaseMustBePolymorphic); | 851 getErrorLevel(), kLeftMostBaseMustBePolymorphic); |
848 diag_base_class_must_declare_virtual_trace_ = diagnostic_.getCustomDiagID( | 852 diag_base_class_must_declare_virtual_trace_ = diagnostic_.getCustomDiagID( |
849 getErrorLevel(), kBaseClassMustDeclareVirtualTrace); | 853 getErrorLevel(), kBaseClassMustDeclareVirtualTrace); |
| 854 diag_class_must_declare_gc_mixin_trace_method_ = |
| 855 diagnostic_.getCustomDiagID(getErrorLevel(), |
| 856 kClassMustDeclareGCMixinTraceMethod); |
850 | 857 |
851 // Register note messages. | 858 // Register note messages. |
852 diag_base_requires_tracing_note_ = diagnostic_.getCustomDiagID( | 859 diag_base_requires_tracing_note_ = diagnostic_.getCustomDiagID( |
853 DiagnosticsEngine::Note, kBaseRequiresTracingNote); | 860 DiagnosticsEngine::Note, kBaseRequiresTracingNote); |
854 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID( | 861 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID( |
855 DiagnosticsEngine::Note, kFieldRequiresTracingNote); | 862 DiagnosticsEngine::Note, kFieldRequiresTracingNote); |
856 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 863 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
857 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); | 864 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); |
858 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 865 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
859 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); | 866 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
998 ReportClassContainsInvalidFields(info, &visitor.invalid_fields()); | 1005 ReportClassContainsInvalidFields(info, &visitor.invalid_fields()); |
999 } | 1006 } |
1000 | 1007 |
1001 if (info->IsGCDerived()) { | 1008 if (info->IsGCDerived()) { |
1002 | 1009 |
1003 if (!info->IsGCMixin()) { | 1010 if (!info->IsGCMixin()) { |
1004 CheckLeftMostDerived(info); | 1011 CheckLeftMostDerived(info); |
1005 CheckDispatch(info); | 1012 CheckDispatch(info); |
1006 if (CXXMethodDecl* newop = info->DeclaresNewOperator()) | 1013 if (CXXMethodDecl* newop = info->DeclaresNewOperator()) |
1007 ReportClassOverridesNew(info, newop); | 1014 ReportClassOverridesNew(info, newop); |
| 1015 if (info->IsGCMixinInstance()) { |
| 1016 // Require that declared GCMixin implementations |
| 1017 // also provide a trace() override. |
| 1018 if (info->DeclaresGCMixinMethods() |
| 1019 && !info->DeclaresLocalTraceMethod()) |
| 1020 ReportClassMustDeclareGCMixinTraceMethod(info); |
| 1021 } |
1008 } | 1022 } |
1009 | 1023 |
1010 { | 1024 { |
1011 CheckGCRootsVisitor visitor; | 1025 CheckGCRootsVisitor visitor; |
1012 if (visitor.ContainsGCRoots(info)) | 1026 if (visitor.ContainsGCRoots(info)) |
1013 ReportClassContainsGCRoots(info, &visitor.gc_roots()); | 1027 ReportClassContainsGCRoots(info, &visitor.gc_roots()); |
1014 } | 1028 } |
1015 | 1029 |
1016 if (info->NeedsFinalization()) | 1030 if (info->NeedsFinalization()) |
1017 CheckFinalization(info); | 1031 CheckFinalization(info); |
(...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1646 } | 1660 } |
1647 | 1661 |
1648 void ReportClassDoesNotRequireFinalization(RecordInfo* info) { | 1662 void ReportClassDoesNotRequireFinalization(RecordInfo* info) { |
1649 SourceLocation loc = info->record()->getInnerLocStart(); | 1663 SourceLocation loc = info->record()->getInnerLocStart(); |
1650 SourceManager& manager = instance_.getSourceManager(); | 1664 SourceManager& manager = instance_.getSourceManager(); |
1651 FullSourceLoc full_loc(loc, manager); | 1665 FullSourceLoc full_loc(loc, manager); |
1652 diagnostic_.Report(full_loc, diag_class_does_not_require_finalization_) | 1666 diagnostic_.Report(full_loc, diag_class_does_not_require_finalization_) |
1653 << info->record(); | 1667 << info->record(); |
1654 } | 1668 } |
1655 | 1669 |
| 1670 void ReportClassMustDeclareGCMixinTraceMethod(RecordInfo* info) { |
| 1671 SourceLocation loc = info->record()->getInnerLocStart(); |
| 1672 SourceManager& manager = instance_.getSourceManager(); |
| 1673 FullSourceLoc full_loc(loc, manager); |
| 1674 diagnostic_.Report( |
| 1675 full_loc, diag_class_must_declare_gc_mixin_trace_method_) |
| 1676 << info->record(); |
| 1677 } |
| 1678 |
1656 void ReportOverriddenNonVirtualTrace(RecordInfo* info, | 1679 void ReportOverriddenNonVirtualTrace(RecordInfo* info, |
1657 CXXMethodDecl* trace, | 1680 CXXMethodDecl* trace, |
1658 CXXMethodDecl* overridden) { | 1681 CXXMethodDecl* overridden) { |
1659 SourceLocation loc = trace->getLocStart(); | 1682 SourceLocation loc = trace->getLocStart(); |
1660 SourceManager& manager = instance_.getSourceManager(); | 1683 SourceManager& manager = instance_.getSourceManager(); |
1661 FullSourceLoc full_loc(loc, manager); | 1684 FullSourceLoc full_loc(loc, manager); |
1662 diagnostic_.Report(full_loc, diag_overridden_non_virtual_trace_) | 1685 diagnostic_.Report(full_loc, diag_overridden_non_virtual_trace_) |
1663 << info->record() << overridden->getParent(); | 1686 << info->record() << overridden->getParent(); |
1664 NoteOverriddenNonVirtualTrace(overridden); | 1687 NoteOverriddenNonVirtualTrace(overridden); |
1665 } | 1688 } |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1837 unsigned diag_missing_trace_dispatch_method_; | 1860 unsigned diag_missing_trace_dispatch_method_; |
1838 unsigned diag_missing_finalize_dispatch_method_; | 1861 unsigned diag_missing_finalize_dispatch_method_; |
1839 unsigned diag_virtual_and_manual_dispatch_; | 1862 unsigned diag_virtual_and_manual_dispatch_; |
1840 unsigned diag_missing_trace_dispatch_; | 1863 unsigned diag_missing_trace_dispatch_; |
1841 unsigned diag_missing_finalize_dispatch_; | 1864 unsigned diag_missing_finalize_dispatch_; |
1842 unsigned diag_derives_non_stack_allocated_; | 1865 unsigned diag_derives_non_stack_allocated_; |
1843 unsigned diag_class_overrides_new_; | 1866 unsigned diag_class_overrides_new_; |
1844 unsigned diag_class_declares_pure_virtual_trace_; | 1867 unsigned diag_class_declares_pure_virtual_trace_; |
1845 unsigned diag_left_most_base_must_be_polymorphic_; | 1868 unsigned diag_left_most_base_must_be_polymorphic_; |
1846 unsigned diag_base_class_must_declare_virtual_trace_; | 1869 unsigned diag_base_class_must_declare_virtual_trace_; |
| 1870 unsigned diag_class_must_declare_gc_mixin_trace_method_; |
1847 | 1871 |
1848 unsigned diag_base_requires_tracing_note_; | 1872 unsigned diag_base_requires_tracing_note_; |
1849 unsigned diag_field_requires_tracing_note_; | 1873 unsigned diag_field_requires_tracing_note_; |
1850 unsigned diag_raw_ptr_to_gc_managed_class_note_; | 1874 unsigned diag_raw_ptr_to_gc_managed_class_note_; |
1851 unsigned diag_ref_ptr_to_gc_managed_class_note_; | 1875 unsigned diag_ref_ptr_to_gc_managed_class_note_; |
1852 unsigned diag_own_ptr_to_gc_managed_class_note_; | 1876 unsigned diag_own_ptr_to_gc_managed_class_note_; |
1853 unsigned diag_stack_allocated_field_note_; | 1877 unsigned diag_stack_allocated_field_note_; |
1854 unsigned diag_member_in_unmanaged_class_note_; | 1878 unsigned diag_member_in_unmanaged_class_note_; |
1855 unsigned diag_part_object_to_gc_derived_class_note_; | 1879 unsigned diag_part_object_to_gc_derived_class_note_; |
1856 unsigned diag_part_object_contains_gc_root_note_; | 1880 unsigned diag_part_object_contains_gc_root_note_; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1906 | 1930 |
1907 private: | 1931 private: |
1908 BlinkGCPluginOptions options_; | 1932 BlinkGCPluginOptions options_; |
1909 }; | 1933 }; |
1910 | 1934 |
1911 } // namespace | 1935 } // namespace |
1912 | 1936 |
1913 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( | 1937 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( |
1914 "blink-gc-plugin", | 1938 "blink-gc-plugin", |
1915 "Check Blink GC invariants"); | 1939 "Check Blink GC invariants"); |
OLD | NEW |