Chromium Code Reviews| 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 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 122 " which is not stack allocated."; | 122 " which is not stack allocated."; |
| 123 | 123 |
| 124 const char kClassOverridesNew[] = | 124 const char kClassOverridesNew[] = |
| 125 "[blink-gc] Garbage collected class %0" | 125 "[blink-gc] Garbage collected class %0" |
| 126 " is not permitted to override its new operator."; | 126 " is not permitted to override its new operator."; |
| 127 | 127 |
| 128 const char kClassDeclaresPureVirtualTrace[] = | 128 const char kClassDeclaresPureVirtualTrace[] = |
| 129 "[blink-gc] Garbage collected class %0" | 129 "[blink-gc] Garbage collected class %0" |
| 130 " is not permitted to declare a pure-virtual trace method."; | 130 " is not permitted to declare a pure-virtual trace method."; |
| 131 | 131 |
| 132 const char kLeftMostBaseMustBePolymorphic[] = | |
| 133 "[blink-gc] Left-most base class %0 of derived class %1" | |
| 134 " must be polymorphic."; | |
| 135 | |
| 136 const char kBaseClassMustDeclareVirtualTrace[] = | |
| 137 "[blink-gc] Left-most base class %0 of derived class %1" | |
| 138 " must define a virtual trace method."; | |
| 139 | |
| 132 struct BlinkGCPluginOptions { | 140 struct BlinkGCPluginOptions { |
| 133 BlinkGCPluginOptions() : enable_oilpan(false), dump_graph(false) {} | 141 BlinkGCPluginOptions() : enable_oilpan(false), dump_graph(false) {} |
| 134 bool enable_oilpan; | 142 bool enable_oilpan; |
| 135 bool dump_graph; | 143 bool dump_graph; |
| 136 std::set<std::string> ignored_classes; | 144 std::set<std::string> ignored_classes; |
| 137 std::set<std::string> checked_namespaces; | 145 std::set<std::string> checked_namespaces; |
| 138 std::vector<std::string> ignored_directories; | 146 std::vector<std::string> ignored_directories; |
| 139 }; | 147 }; |
| 140 | 148 |
| 141 typedef std::vector<CXXRecordDecl*> RecordVector; | 149 typedef std::vector<CXXRecordDecl*> RecordVector; |
| (...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 764 diag_missing_trace_dispatch_ = | 772 diag_missing_trace_dispatch_ = |
| 765 diagnostic_.getCustomDiagID(getErrorLevel(), kMissingTraceDispatch); | 773 diagnostic_.getCustomDiagID(getErrorLevel(), kMissingTraceDispatch); |
| 766 diag_missing_finalize_dispatch_ = | 774 diag_missing_finalize_dispatch_ = |
| 767 diagnostic_.getCustomDiagID(getErrorLevel(), kMissingFinalizeDispatch); | 775 diagnostic_.getCustomDiagID(getErrorLevel(), kMissingFinalizeDispatch); |
| 768 diag_derives_non_stack_allocated_ = | 776 diag_derives_non_stack_allocated_ = |
| 769 diagnostic_.getCustomDiagID(getErrorLevel(), kDerivesNonStackAllocated); | 777 diagnostic_.getCustomDiagID(getErrorLevel(), kDerivesNonStackAllocated); |
| 770 diag_class_overrides_new_ = | 778 diag_class_overrides_new_ = |
| 771 diagnostic_.getCustomDiagID(getErrorLevel(), kClassOverridesNew); | 779 diagnostic_.getCustomDiagID(getErrorLevel(), kClassOverridesNew); |
| 772 diag_class_declares_pure_virtual_trace_ = diagnostic_.getCustomDiagID( | 780 diag_class_declares_pure_virtual_trace_ = diagnostic_.getCustomDiagID( |
| 773 getErrorLevel(), kClassDeclaresPureVirtualTrace); | 781 getErrorLevel(), kClassDeclaresPureVirtualTrace); |
| 782 diag_left_most_base_must_be_polymorphic_ = diagnostic_.getCustomDiagID( | |
| 783 getErrorLevel(), kLeftMostBaseMustBePolymorphic); | |
| 784 diag_base_class_must_declare_virtual_trace_ = diagnostic_.getCustomDiagID( | |
| 785 getErrorLevel(), kBaseClassMustDeclareVirtualTrace); | |
| 774 | 786 |
| 775 // Register note messages. | 787 // Register note messages. |
| 776 diag_base_requires_tracing_note_ = diagnostic_.getCustomDiagID( | 788 diag_base_requires_tracing_note_ = diagnostic_.getCustomDiagID( |
| 777 DiagnosticsEngine::Note, kBaseRequiresTracingNote); | 789 DiagnosticsEngine::Note, kBaseRequiresTracingNote); |
| 778 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID( | 790 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID( |
| 779 DiagnosticsEngine::Note, kFieldRequiresTracingNote); | 791 DiagnosticsEngine::Note, kFieldRequiresTracingNote); |
| 780 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 792 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
| 781 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); | 793 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); |
| 782 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 794 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
| 783 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); | 795 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 893 it != info->GetBases().end(); | 905 it != info->GetBases().end(); |
| 894 ++it) { | 906 ++it) { |
| 895 if (!it->second.info()->IsStackAllocated()) | 907 if (!it->second.info()->IsStackAllocated()) |
| 896 ReportDerivesNonStackAllocated(info, &it->second); | 908 ReportDerivesNonStackAllocated(info, &it->second); |
| 897 } | 909 } |
| 898 } | 910 } |
| 899 | 911 |
| 900 if (CXXMethodDecl* trace = info->GetTraceMethod()) { | 912 if (CXXMethodDecl* trace = info->GetTraceMethod()) { |
| 901 if (trace->isPure()) | 913 if (trace->isPure()) |
| 902 ReportClassDeclaresPureVirtualTrace(info, trace); | 914 ReportClassDeclaresPureVirtualTrace(info, trace); |
| 915 if (info->record()->isPolymorphic()) | |
| 916 CheckPolymorphicClass(info, trace); | |
| 903 } else if (info->RequiresTraceMethod()) { | 917 } else if (info->RequiresTraceMethod()) { |
| 904 ReportClassRequiresTraceMethod(info); | 918 ReportClassRequiresTraceMethod(info); |
| 905 } | 919 } |
| 906 | 920 |
| 921 | |
|
Mads Ager (chromium)
2014/08/13 12:23:58
Remove extra empty line?
zerny-chromium
2014/08/13 12:50:35
Done.
| |
| 907 { | 922 { |
| 908 CheckFieldsVisitor visitor(options_); | 923 CheckFieldsVisitor visitor(options_); |
| 909 if (visitor.ContainsInvalidFields(info)) | 924 if (visitor.ContainsInvalidFields(info)) |
| 910 ReportClassContainsInvalidFields(info, &visitor.invalid_fields()); | 925 ReportClassContainsInvalidFields(info, &visitor.invalid_fields()); |
| 911 } | 926 } |
| 912 | 927 |
| 913 if (info->IsGCDerived()) { | 928 if (info->IsGCDerived()) { |
| 914 | 929 |
| 915 if (!info->IsGCMixin()) { | 930 if (!info->IsGCMixin()) { |
| 916 CheckLeftMostDerived(info); | 931 CheckLeftMostDerived(info); |
| 917 CheckDispatch(info); | 932 CheckDispatch(info); |
| 918 if (CXXMethodDecl* newop = info->DeclaresNewOperator()) | 933 if (CXXMethodDecl* newop = info->DeclaresNewOperator()) |
| 919 ReportClassOverridesNew(info, newop); | 934 ReportClassOverridesNew(info, newop); |
| 920 } | 935 } |
| 921 | 936 |
| 922 { | 937 { |
| 923 CheckGCRootsVisitor visitor; | 938 CheckGCRootsVisitor visitor; |
| 924 if (visitor.ContainsGCRoots(info)) | 939 if (visitor.ContainsGCRoots(info)) |
| 925 ReportClassContainsGCRoots(info, &visitor.gc_roots()); | 940 ReportClassContainsGCRoots(info, &visitor.gc_roots()); |
| 926 } | 941 } |
| 927 | 942 |
| 928 if (info->NeedsFinalization()) | 943 if (info->NeedsFinalization()) |
| 929 CheckFinalization(info); | 944 CheckFinalization(info); |
| 930 } | 945 } |
| 931 | 946 |
| 932 DumpClass(info); | 947 DumpClass(info); |
| 933 } | 948 } |
| 934 | 949 |
| 950 CXXRecordDecl* GetDependentTemplatedDecl(const Type& type) { | |
| 951 const TemplateSpecializationType* tmpl_type = | |
| 952 type.getAs<TemplateSpecializationType>(); | |
| 953 if (!tmpl_type) | |
| 954 return 0; | |
| 955 | |
| 956 TemplateDecl* tmpl_decl = tmpl_type->getTemplateName().getAsTemplateDecl(); | |
| 957 if (!tmpl_decl) | |
| 958 return 0; | |
| 959 | |
| 960 return dyn_cast<CXXRecordDecl>(tmpl_decl->getTemplatedDecl()); | |
| 961 } | |
| 962 | |
| 963 // The GC infrastructure assumes that if the vtable of a polymorphic | |
| 964 // base-class is not initialized for a given object (ie, it is partially | |
| 965 // initialized) then the object does not need to be traced. Thus, we must | |
| 966 // ensure that any polymorphic class with a trace method does not have any | |
| 967 // tractable fields that are initialized before we are sure that the vtable | |
| 968 // and the trace method are both defined. There are two cases that need to | |
| 969 // hold to satisfy that assumption: | |
| 970 // | |
| 971 // 1. If trace is virtual, then it must be defined in the left-most base. | |
| 972 // This ensures that if the vtable is initialized and it contains a pointer to | |
| 973 // the trace method. | |
| 974 // | |
| 975 // 2. If trace is non-virtual, then the trace method is defined and we must | |
| 976 // ensure that the left-most base defines a vtable. This ensures that the | |
| 977 // first thing to be initialized when constructing the object is the vtable | |
| 978 // itself. | |
| 979 void CheckPolymorphicClass(RecordInfo* info, CXXMethodDecl* trace) { | |
| 980 CXXRecordDecl* left_most = info->record(); | |
| 981 CXXRecordDecl::base_class_iterator it = left_most->bases_begin(); | |
| 982 CXXRecordDecl* left_most_base = 0; | |
| 983 while (it != left_most->bases_end()) { | |
| 984 left_most_base = it->getType()->getAsCXXRecordDecl(); | |
| 985 if (!left_most_base && it->getType()->isDependentType()) | |
| 986 left_most_base = GetDependentTemplatedDecl(*it->getType()); | |
| 987 | |
| 988 // TODO: Find a way to correctly check actual instantiations | |
| 989 // for dependent types. The escape below will be hit, eg, when | |
| 990 // we have a primary template with no definition and | |
| 991 // specializations for each case (such as SupplementBase) in | |
| 992 // which case we don't succeed in checking the required | |
| 993 // properties. | |
| 994 if (!left_most_base || !left_most_base->hasDefinition()) | |
| 995 return; | |
| 996 | |
| 997 StringRef name = left_most_base->getName(); | |
| 998 // We know GCMixin base defines virtual trace. | |
| 999 if (Config::IsGCMixinBase(name)) | |
| 1000 return; | |
| 1001 | |
| 1002 // Stop with the left-most prior to a safe polymorphic base, ie, the a | |
|
Mads Ager (chromium)
2014/08/13 12:23:58
the a -> the
zerny-chromium
2014/08/13 12:50:35
Also removed the ambiguity of "the base".
| |
| 1003 // base that is non-polymorphic and contains no fields that need tracing. | |
| 1004 if (Config::IsSafePolymorphicBase(name)) | |
| 1005 break; | |
| 1006 | |
| 1007 left_most = left_most_base; | |
| 1008 it = left_most->bases_begin(); | |
| 1009 } | |
| 1010 | |
| 1011 if (RecordInfo* left_most_info = cache_.Lookup(left_most)) { | |
| 1012 | |
| 1013 // Check condition (1): | |
| 1014 if (trace->isVirtual()) { | |
| 1015 if (CXXMethodDecl* trace = left_most_info->GetTraceMethod()) { | |
| 1016 if (trace->isVirtual()) | |
| 1017 return; | |
| 1018 } | |
| 1019 ReportBaseClassMustDeclareVirtualTrace(info, left_most); | |
| 1020 return; | |
| 1021 } | |
| 1022 | |
| 1023 // Check condition (2): | |
| 1024 if (DeclaresVirtualMethods(info->record())) | |
| 1025 return; | |
| 1026 if (left_most_base) { | |
| 1027 ++it; // Get the base next to the "safe polymorphic base" | |
| 1028 if (it != left_most->bases_end()) { | |
| 1029 if (CXXRecordDecl* next_base = it->getType()->getAsCXXRecordDecl()) { | |
| 1030 if (CXXRecordDecl* next_left_most = GetLeftMostBase(next_base)) { | |
| 1031 if (DeclaresVirtualMethods(next_left_most)) | |
| 1032 return; | |
| 1033 ReportLeftMostBaseMustBePolymorphic(info, next_left_most); | |
| 1034 return; | |
| 1035 } | |
| 1036 } | |
| 1037 } | |
| 1038 } | |
| 1039 ReportLeftMostBaseMustBePolymorphic(info, left_most); | |
| 1040 } | |
| 1041 } | |
| 1042 | |
| 1043 CXXRecordDecl* GetLeftMostBase(CXXRecordDecl* left_most) { | |
| 1044 CXXRecordDecl::base_class_iterator it = left_most->bases_begin(); | |
| 1045 while (it != left_most->bases_end()) { | |
| 1046 if (it->getType()->isDependentType()) | |
| 1047 left_most = GetDependentTemplatedDecl(*it->getType()); | |
| 1048 else | |
| 1049 left_most = it->getType()->getAsCXXRecordDecl(); | |
| 1050 if (!left_most || !left_most->hasDefinition()) | |
| 1051 return 0; | |
| 1052 it = left_most->bases_begin(); | |
| 1053 } | |
| 1054 return left_most; | |
| 1055 } | |
| 1056 | |
| 1057 bool DeclaresVirtualMethods(CXXRecordDecl* decl) { | |
| 1058 CXXRecordDecl::method_iterator it = decl->method_begin(); | |
| 1059 for (; it != decl->method_end(); ++it) | |
| 1060 if (it->isVirtual() && !it->isPure()) | |
| 1061 return true; | |
| 1062 return false; | |
| 1063 } | |
| 1064 | |
| 935 void CheckLeftMostDerived(RecordInfo* info) { | 1065 void CheckLeftMostDerived(RecordInfo* info) { |
| 936 CXXRecordDecl* left_most = info->record(); | 1066 CXXRecordDecl* left_most = info->record(); |
| 937 CXXRecordDecl::base_class_iterator it = left_most->bases_begin(); | 1067 CXXRecordDecl::base_class_iterator it = left_most->bases_begin(); |
| 938 while (it != left_most->bases_end()) { | 1068 while (it != left_most->bases_end()) { |
| 939 left_most = it->getType()->getAsCXXRecordDecl(); | 1069 left_most = it->getType()->getAsCXXRecordDecl(); |
| 940 it = left_most->bases_begin(); | 1070 it = left_most->bases_begin(); |
| 941 } | 1071 } |
| 942 if (!Config::IsGCBase(left_most->getName())) | 1072 if (!Config::IsGCBase(left_most->getName())) |
| 943 ReportClassMustLeftMostlyDeriveGC(info); | 1073 ReportClassMustLeftMostlyDeriveGC(info); |
| 944 } | 1074 } |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1067 CheckTraceMethod(parent, method, isTraceAfterDispatch); | 1197 CheckTraceMethod(parent, method, isTraceAfterDispatch); |
| 1068 } | 1198 } |
| 1069 // Dispatch methods are checked when we identify subclasses. | 1199 // Dispatch methods are checked when we identify subclasses. |
| 1070 } | 1200 } |
| 1071 } | 1201 } |
| 1072 | 1202 |
| 1073 // Check an actual trace method. | 1203 // Check an actual trace method. |
| 1074 void CheckTraceMethod(RecordInfo* parent, | 1204 void CheckTraceMethod(RecordInfo* parent, |
| 1075 CXXMethodDecl* trace, | 1205 CXXMethodDecl* trace, |
| 1076 bool isTraceAfterDispatch) { | 1206 bool isTraceAfterDispatch) { |
| 1077 // A non-virtual trace method must not override another trace. | 1207 // A trace method must not override any non-virtual trace methods. |
| 1078 if (!isTraceAfterDispatch && !trace->isVirtual()) { | 1208 if (!isTraceAfterDispatch) { |
| 1079 for (RecordInfo::Bases::iterator it = parent->GetBases().begin(); | 1209 for (RecordInfo::Bases::iterator it = parent->GetBases().begin(); |
| 1080 it != parent->GetBases().end(); | 1210 it != parent->GetBases().end(); |
| 1081 ++it) { | 1211 ++it) { |
| 1082 RecordInfo* base = it->second.info(); | 1212 RecordInfo* base = it->second.info(); |
| 1083 // We allow mixin bases to contain a non-virtual trace since it will | |
| 1084 // never be used for dispatching. | |
| 1085 if (base->IsGCMixin()) | |
| 1086 continue; | |
| 1087 if (CXXMethodDecl* other = base->InheritsNonVirtualTrace()) | 1213 if (CXXMethodDecl* other = base->InheritsNonVirtualTrace()) |
| 1088 ReportOverriddenNonVirtualTrace(parent, trace, other); | 1214 ReportOverriddenNonVirtualTrace(parent, trace, other); |
| 1089 } | 1215 } |
| 1090 } | 1216 } |
| 1091 | 1217 |
| 1092 CheckTraceVisitor visitor(trace, parent); | 1218 CheckTraceVisitor visitor(trace, parent); |
| 1093 visitor.TraverseCXXMethodDecl(trace); | 1219 visitor.TraverseCXXMethodDecl(trace); |
| 1094 | 1220 |
| 1095 for (RecordInfo::Bases::iterator it = parent->GetBases().begin(); | 1221 for (RecordInfo::Bases::iterator it = parent->GetBases().begin(); |
| 1096 it != parent->GetBases().end(); | 1222 it != parent->GetBases().end(); |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1477 | 1603 |
| 1478 void ReportClassDeclaresPureVirtualTrace(RecordInfo* info, | 1604 void ReportClassDeclaresPureVirtualTrace(RecordInfo* info, |
| 1479 CXXMethodDecl* trace) { | 1605 CXXMethodDecl* trace) { |
| 1480 SourceLocation loc = trace->getLocStart(); | 1606 SourceLocation loc = trace->getLocStart(); |
| 1481 SourceManager& manager = instance_.getSourceManager(); | 1607 SourceManager& manager = instance_.getSourceManager(); |
| 1482 FullSourceLoc full_loc(loc, manager); | 1608 FullSourceLoc full_loc(loc, manager); |
| 1483 diagnostic_.Report(full_loc, diag_class_declares_pure_virtual_trace_) | 1609 diagnostic_.Report(full_loc, diag_class_declares_pure_virtual_trace_) |
| 1484 << info->record(); | 1610 << info->record(); |
| 1485 } | 1611 } |
| 1486 | 1612 |
| 1613 void ReportLeftMostBaseMustBePolymorphic(RecordInfo* derived, | |
| 1614 CXXRecordDecl* base) { | |
| 1615 SourceLocation loc = base->getLocStart(); | |
| 1616 SourceManager& manager = instance_.getSourceManager(); | |
| 1617 FullSourceLoc full_loc(loc, manager); | |
| 1618 diagnostic_.Report(full_loc, diag_left_most_base_must_be_polymorphic_) | |
| 1619 << base << derived->record(); | |
| 1620 } | |
| 1621 | |
| 1622 void ReportBaseClassMustDeclareVirtualTrace(RecordInfo* derived, | |
| 1623 CXXRecordDecl* base) { | |
| 1624 SourceLocation loc = base->getLocStart(); | |
| 1625 SourceManager& manager = instance_.getSourceManager(); | |
| 1626 FullSourceLoc full_loc(loc, manager); | |
| 1627 diagnostic_.Report(full_loc, diag_base_class_must_declare_virtual_trace_) | |
| 1628 << base << derived->record(); | |
| 1629 } | |
| 1630 | |
| 1487 void NoteManualDispatchMethod(CXXMethodDecl* dispatch) { | 1631 void NoteManualDispatchMethod(CXXMethodDecl* dispatch) { |
| 1488 SourceLocation loc = dispatch->getLocStart(); | 1632 SourceLocation loc = dispatch->getLocStart(); |
| 1489 SourceManager& manager = instance_.getSourceManager(); | 1633 SourceManager& manager = instance_.getSourceManager(); |
| 1490 FullSourceLoc full_loc(loc, manager); | 1634 FullSourceLoc full_loc(loc, manager); |
| 1491 diagnostic_.Report(full_loc, diag_manual_dispatch_method_note_) << dispatch; | 1635 diagnostic_.Report(full_loc, diag_manual_dispatch_method_note_) << dispatch; |
| 1492 } | 1636 } |
| 1493 | 1637 |
| 1494 void NoteBaseRequiresTracing(BasePoint* base) { | 1638 void NoteBaseRequiresTracing(BasePoint* base) { |
| 1495 SourceLocation loc = base->spec().getLocStart(); | 1639 SourceLocation loc = base->spec().getLocStart(); |
| 1496 SourceManager& manager = instance_.getSourceManager(); | 1640 SourceManager& manager = instance_.getSourceManager(); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1567 unsigned diag_finalizer_accesses_finalized_field_; | 1711 unsigned diag_finalizer_accesses_finalized_field_; |
| 1568 unsigned diag_overridden_non_virtual_trace_; | 1712 unsigned diag_overridden_non_virtual_trace_; |
| 1569 unsigned diag_missing_trace_dispatch_method_; | 1713 unsigned diag_missing_trace_dispatch_method_; |
| 1570 unsigned diag_missing_finalize_dispatch_method_; | 1714 unsigned diag_missing_finalize_dispatch_method_; |
| 1571 unsigned diag_virtual_and_manual_dispatch_; | 1715 unsigned diag_virtual_and_manual_dispatch_; |
| 1572 unsigned diag_missing_trace_dispatch_; | 1716 unsigned diag_missing_trace_dispatch_; |
| 1573 unsigned diag_missing_finalize_dispatch_; | 1717 unsigned diag_missing_finalize_dispatch_; |
| 1574 unsigned diag_derives_non_stack_allocated_; | 1718 unsigned diag_derives_non_stack_allocated_; |
| 1575 unsigned diag_class_overrides_new_; | 1719 unsigned diag_class_overrides_new_; |
| 1576 unsigned diag_class_declares_pure_virtual_trace_; | 1720 unsigned diag_class_declares_pure_virtual_trace_; |
| 1721 unsigned diag_left_most_base_must_be_polymorphic_; | |
| 1722 unsigned diag_base_class_must_declare_virtual_trace_; | |
| 1577 | 1723 |
| 1578 unsigned diag_base_requires_tracing_note_; | 1724 unsigned diag_base_requires_tracing_note_; |
| 1579 unsigned diag_field_requires_tracing_note_; | 1725 unsigned diag_field_requires_tracing_note_; |
| 1580 unsigned diag_raw_ptr_to_gc_managed_class_note_; | 1726 unsigned diag_raw_ptr_to_gc_managed_class_note_; |
| 1581 unsigned diag_ref_ptr_to_gc_managed_class_note_; | 1727 unsigned diag_ref_ptr_to_gc_managed_class_note_; |
| 1582 unsigned diag_own_ptr_to_gc_managed_class_note_; | 1728 unsigned diag_own_ptr_to_gc_managed_class_note_; |
| 1583 unsigned diag_stack_allocated_field_note_; | 1729 unsigned diag_stack_allocated_field_note_; |
| 1584 unsigned diag_member_in_unmanaged_class_note_; | 1730 unsigned diag_member_in_unmanaged_class_note_; |
| 1585 unsigned diag_part_object_to_gc_derived_class_note_; | 1731 unsigned diag_part_object_to_gc_derived_class_note_; |
| 1586 unsigned diag_part_object_contains_gc_root_note_; | 1732 unsigned diag_part_object_contains_gc_root_note_; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1631 | 1777 |
| 1632 private: | 1778 private: |
| 1633 BlinkGCPluginOptions options_; | 1779 BlinkGCPluginOptions options_; |
| 1634 }; | 1780 }; |
| 1635 | 1781 |
| 1636 } // namespace | 1782 } // namespace |
| 1637 | 1783 |
| 1638 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( | 1784 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( |
| 1639 "blink-gc-plugin", | 1785 "blink-gc-plugin", |
| 1640 "Check Blink GC invariants"); | 1786 "Check Blink GC invariants"); |
| OLD | NEW |