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 |
| 11 #include <algorithm> |
| 12 |
11 #include "Config.h" | 13 #include "Config.h" |
12 #include "JsonWriter.h" | 14 #include "JsonWriter.h" |
13 #include "RecordInfo.h" | 15 #include "RecordInfo.h" |
14 | 16 |
15 #include "clang/AST/AST.h" | 17 #include "clang/AST/AST.h" |
16 #include "clang/AST/ASTConsumer.h" | 18 #include "clang/AST/ASTConsumer.h" |
17 #include "clang/AST/RecursiveASTVisitor.h" | 19 #include "clang/AST/RecursiveASTVisitor.h" |
18 #include "clang/Frontend/CompilerInstance.h" | 20 #include "clang/Frontend/CompilerInstance.h" |
19 #include "clang/Frontend/FrontendPluginRegistry.h" | 21 #include "clang/Frontend/FrontendPluginRegistry.h" |
| 22 #include "clang/Sema/Sema.h" |
20 | 23 |
21 using namespace clang; | 24 using namespace clang; |
22 using std::string; | 25 using std::string; |
23 | 26 |
24 namespace { | 27 namespace { |
25 | 28 |
26 const char kClassMustLeftMostlyDeriveGC[] = | 29 const char kClassMustLeftMostlyDeriveGC[] = |
27 "[blink-gc] Class %0 must derive its GC base in the left-most position."; | 30 "[blink-gc] Class %0 must derive its GC base in the left-most position."; |
28 | 31 |
29 const char kClassRequiresTraceMethod[] = | 32 const char kClassRequiresTraceMethod[] = |
(...skipping 19 matching lines...) Expand all Loading... |
49 | 52 |
50 const char kClassRequiresFinalization[] = | 53 const char kClassRequiresFinalization[] = |
51 "[blink-gc] Class %0 requires finalization."; | 54 "[blink-gc] Class %0 requires finalization."; |
52 | 55 |
53 const char kClassDoesNotRequireFinalization[] = | 56 const char kClassDoesNotRequireFinalization[] = |
54 "[blink-gc] Class %0 may not require finalization."; | 57 "[blink-gc] Class %0 may not require finalization."; |
55 | 58 |
56 const char kFinalizerAccessesFinalizedField[] = | 59 const char kFinalizerAccessesFinalizedField[] = |
57 "[blink-gc] Finalizer %0 accesses potentially finalized field %1."; | 60 "[blink-gc] Finalizer %0 accesses potentially finalized field %1."; |
58 | 61 |
| 62 const char kFinalizerAccessesEagerlyFinalizedField[] = |
| 63 "[blink-gc] Finalizer %0 accesses eagerly finalized field %1."; |
| 64 |
59 const char kRawPtrToGCManagedClassNote[] = | 65 const char kRawPtrToGCManagedClassNote[] = |
60 "[blink-gc] Raw pointer field %0 to a GC managed class declared here:"; | 66 "[blink-gc] Raw pointer field %0 to a GC managed class declared here:"; |
61 | 67 |
62 const char kRefPtrToGCManagedClassNote[] = | 68 const char kRefPtrToGCManagedClassNote[] = |
63 "[blink-gc] RefPtr field %0 to a GC managed class declared here:"; | 69 "[blink-gc] RefPtr field %0 to a GC managed class declared here:"; |
64 | 70 |
65 const char kOwnPtrToGCManagedClassNote[] = | 71 const char kOwnPtrToGCManagedClassNote[] = |
66 "[blink-gc] OwnPtr field %0 to a GC managed class declared here:"; | 72 "[blink-gc] OwnPtr field %0 to a GC managed class declared here:"; |
67 | 73 |
| 74 const char kMemberToGCUnmanagedClassNote[] = |
| 75 "[blink-gc] Member field %0 to non-GC managed class declared here:"; |
| 76 |
68 const char kStackAllocatedFieldNote[] = | 77 const char kStackAllocatedFieldNote[] = |
69 "[blink-gc] Stack-allocated field %0 declared here:"; | 78 "[blink-gc] Stack-allocated field %0 declared here:"; |
70 | 79 |
71 const char kMemberInUnmanagedClassNote[] = | 80 const char kMemberInUnmanagedClassNote[] = |
72 "[blink-gc] Member field %0 in unmanaged class declared here:"; | 81 "[blink-gc] Member field %0 in unmanaged class declared here:"; |
73 | 82 |
74 const char kPartObjectToGCDerivedClassNote[] = | 83 const char kPartObjectToGCDerivedClassNote[] = |
75 "[blink-gc] Part-object field %0 to a GC derived class declared here:"; | 84 "[blink-gc] Part-object field %0 to a GC derived class declared here:"; |
76 | 85 |
77 const char kPartObjectContainsGCRootNote[] = | 86 const char kPartObjectContainsGCRootNote[] = |
(...skipping 20 matching lines...) Expand all Loading... |
98 | 107 |
99 const char kMissingTraceDispatch[] = | 108 const char kMissingTraceDispatch[] = |
100 "[blink-gc] Missing dispatch to class %0 in manual trace dispatch."; | 109 "[blink-gc] Missing dispatch to class %0 in manual trace dispatch."; |
101 | 110 |
102 const char kMissingFinalizeDispatch[] = | 111 const char kMissingFinalizeDispatch[] = |
103 "[blink-gc] Missing dispatch to class %0 in manual finalize dispatch."; | 112 "[blink-gc] Missing dispatch to class %0 in manual finalize dispatch."; |
104 | 113 |
105 const char kFinalizedFieldNote[] = | 114 const char kFinalizedFieldNote[] = |
106 "[blink-gc] Potentially finalized field %0 declared here:"; | 115 "[blink-gc] Potentially finalized field %0 declared here:"; |
107 | 116 |
| 117 const char kEagerlyFinalizedFieldNote[] = |
| 118 "[blink-gc] Field %0 having eagerly finalized value, declared here:"; |
| 119 |
108 const char kUserDeclaredDestructorNote[] = | 120 const char kUserDeclaredDestructorNote[] = |
109 "[blink-gc] User-declared destructor declared here:"; | 121 "[blink-gc] User-declared destructor declared here:"; |
110 | 122 |
111 const char kUserDeclaredFinalizerNote[] = | 123 const char kUserDeclaredFinalizerNote[] = |
112 "[blink-gc] User-declared finalizer declared here:"; | 124 "[blink-gc] User-declared finalizer declared here:"; |
113 | 125 |
114 const char kBaseRequiresFinalizationNote[] = | 126 const char kBaseRequiresFinalizationNote[] = |
115 "[blink-gc] Base class %0 requiring finalization declared here:"; | 127 "[blink-gc] Base class %0 requiring finalization declared here:"; |
116 | 128 |
117 const char kFieldRequiresFinalizationNote[] = | 129 const char kFieldRequiresFinalizationNote[] = |
(...skipping 19 matching lines...) Expand all Loading... |
137 " must be polymorphic."; | 149 " must be polymorphic."; |
138 | 150 |
139 const char kBaseClassMustDeclareVirtualTrace[] = | 151 const char kBaseClassMustDeclareVirtualTrace[] = |
140 "[blink-gc] Left-most base class %0 of derived class %1" | 152 "[blink-gc] Left-most base class %0 of derived class %1" |
141 " must define a virtual trace method."; | 153 " must define a virtual trace method."; |
142 | 154 |
143 const char kClassMustDeclareGCMixinTraceMethod[] = | 155 const char kClassMustDeclareGCMixinTraceMethod[] = |
144 "[blink-gc] Class %0 which inherits from GarbageCollectedMixin must" | 156 "[blink-gc] Class %0 which inherits from GarbageCollectedMixin must" |
145 " locally declare and override trace(Visitor*)"; | 157 " locally declare and override trace(Visitor*)"; |
146 | 158 |
| 159 // Use a local RAV implementation to simply collect all FunctionDecls marked for |
| 160 // late template parsing. This happens with the flag -fdelayed-template-parsing, |
| 161 // which is on by default in MSVC-compatible mode. |
| 162 std::set<FunctionDecl*> GetLateParsedFunctionDecls(TranslationUnitDecl* decl) { |
| 163 struct Visitor : public RecursiveASTVisitor<Visitor> { |
| 164 bool VisitFunctionDecl(FunctionDecl* function_decl) { |
| 165 if (function_decl->isLateTemplateParsed()) |
| 166 late_parsed_decls.insert(function_decl); |
| 167 return true; |
| 168 } |
| 169 |
| 170 std::set<FunctionDecl*> late_parsed_decls; |
| 171 } v; |
| 172 v.TraverseDecl(decl); |
| 173 return v.late_parsed_decls; |
| 174 } |
| 175 |
147 struct BlinkGCPluginOptions { | 176 struct BlinkGCPluginOptions { |
148 BlinkGCPluginOptions() | 177 BlinkGCPluginOptions() |
149 : enable_oilpan(false) | 178 : enable_oilpan(false) |
150 , dump_graph(false) | 179 , dump_graph(false) |
151 , warn_raw_ptr(false) | 180 , warn_raw_ptr(false) |
152 , warn_unneeded_finalizer(false) {} | 181 , warn_unneeded_finalizer(false) {} |
153 bool enable_oilpan; | 182 bool enable_oilpan; |
154 bool dump_graph; | 183 bool dump_graph; |
155 bool warn_raw_ptr; | 184 bool warn_raw_ptr; |
156 bool warn_unneeded_finalizer; | 185 bool warn_unneeded_finalizer; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 // either a Member, a heap-allocated collection or an off-heap collection that | 245 // either a Member, a heap-allocated collection or an off-heap collection that |
217 // contains Members. Invalid uses are currently identified as passing the field | 246 // contains Members. Invalid uses are currently identified as passing the field |
218 // as the argument of a procedure call or using the -> or [] operators on it. | 247 // as the argument of a procedure call or using the -> or [] operators on it. |
219 class CheckFinalizerVisitor | 248 class CheckFinalizerVisitor |
220 : public RecursiveASTVisitor<CheckFinalizerVisitor> { | 249 : public RecursiveASTVisitor<CheckFinalizerVisitor> { |
221 private: | 250 private: |
222 // Simple visitor to determine if the content of a field might be collected | 251 // Simple visitor to determine if the content of a field might be collected |
223 // during finalization. | 252 // during finalization. |
224 class MightBeCollectedVisitor : public EdgeVisitor { | 253 class MightBeCollectedVisitor : public EdgeVisitor { |
225 public: | 254 public: |
226 MightBeCollectedVisitor() : might_be_collected_(false) {} | 255 MightBeCollectedVisitor(bool is_eagerly_finalized) |
| 256 : might_be_collected_(false) |
| 257 , is_eagerly_finalized_(is_eagerly_finalized) |
| 258 , as_eagerly_finalized_(false) {} |
227 bool might_be_collected() { return might_be_collected_; } | 259 bool might_be_collected() { return might_be_collected_; } |
228 void VisitMember(Member* edge) override { might_be_collected_ = true; } | 260 bool as_eagerly_finalized() { return as_eagerly_finalized_; } |
| 261 void VisitMember(Member* edge) override { |
| 262 if (is_eagerly_finalized_) { |
| 263 if (edge->ptr()->IsValue()) { |
| 264 Value* member = static_cast<Value*>(edge->ptr()); |
| 265 if (member->value()->IsEagerlyFinalized()) { |
| 266 might_be_collected_ = true; |
| 267 as_eagerly_finalized_ = true; |
| 268 } |
| 269 } |
| 270 return; |
| 271 } |
| 272 might_be_collected_ = true; |
| 273 } |
229 void VisitCollection(Collection* edge) override { | 274 void VisitCollection(Collection* edge) override { |
230 if (edge->on_heap()) { | 275 if (edge->on_heap() && !is_eagerly_finalized_) { |
231 might_be_collected_ = !edge->is_root(); | 276 might_be_collected_ = !edge->is_root(); |
232 } else { | 277 } else { |
233 edge->AcceptMembers(this); | 278 edge->AcceptMembers(this); |
234 } | 279 } |
235 } | 280 } |
236 | 281 |
237 private: | 282 private: |
238 bool might_be_collected_; | 283 bool might_be_collected_; |
| 284 bool is_eagerly_finalized_; |
| 285 bool as_eagerly_finalized_; |
239 }; | 286 }; |
240 | 287 |
241 public: | 288 public: |
242 typedef std::vector<std::pair<MemberExpr*, FieldPoint*> > Errors; | 289 class Error { |
| 290 public: |
| 291 Error(MemberExpr *member, |
| 292 bool as_eagerly_finalized, |
| 293 FieldPoint* field) |
| 294 : member_(member) |
| 295 , as_eagerly_finalized_(as_eagerly_finalized) |
| 296 , field_(field) {} |
243 | 297 |
244 CheckFinalizerVisitor(RecordCache* cache) | 298 MemberExpr* member_; |
245 : blacklist_context_(false), cache_(cache) {} | 299 bool as_eagerly_finalized_; |
| 300 FieldPoint* field_; |
| 301 }; |
| 302 |
| 303 typedef std::vector<Error> Errors; |
| 304 |
| 305 CheckFinalizerVisitor(RecordCache* cache, bool is_eagerly_finalized) |
| 306 : blacklist_context_(false) |
| 307 , cache_(cache) |
| 308 , is_eagerly_finalized_(is_eagerly_finalized) {} |
246 | 309 |
247 Errors& finalized_fields() { return finalized_fields_; } | 310 Errors& finalized_fields() { return finalized_fields_; } |
248 | 311 |
249 bool WalkUpFromCXXOperatorCallExpr(CXXOperatorCallExpr* expr) { | 312 bool WalkUpFromCXXOperatorCallExpr(CXXOperatorCallExpr* expr) { |
250 // Only continue the walk-up if the operator is a blacklisted one. | 313 // Only continue the walk-up if the operator is a blacklisted one. |
251 switch (expr->getOperator()) { | 314 switch (expr->getOperator()) { |
252 case OO_Arrow: | 315 case OO_Arrow: |
253 case OO_Subscript: | 316 case OO_Subscript: |
254 this->WalkUpFromCallExpr(expr); | 317 this->WalkUpFromCallExpr(expr); |
255 default: | 318 default: |
(...skipping 17 matching lines...) Expand all Loading... |
273 return true; | 336 return true; |
274 | 337 |
275 RecordInfo* info = cache_->Lookup(field->getParent()); | 338 RecordInfo* info = cache_->Lookup(field->getParent()); |
276 if (!info) | 339 if (!info) |
277 return true; | 340 return true; |
278 | 341 |
279 RecordInfo::Fields::iterator it = info->GetFields().find(field); | 342 RecordInfo::Fields::iterator it = info->GetFields().find(field); |
280 if (it == info->GetFields().end()) | 343 if (it == info->GetFields().end()) |
281 return true; | 344 return true; |
282 | 345 |
283 if (blacklist_context_ && MightBeCollected(&it->second)) | 346 if (seen_members_.find(member) != seen_members_.end()) |
284 finalized_fields_.push_back(std::make_pair(member, &it->second)); | 347 return true; |
| 348 |
| 349 bool as_eagerly_finalized = false; |
| 350 if (blacklist_context_ && |
| 351 MightBeCollected(&it->second, as_eagerly_finalized)) { |
| 352 finalized_fields_.push_back( |
| 353 Error(member, as_eagerly_finalized, &it->second)); |
| 354 seen_members_.insert(member); |
| 355 } |
285 return true; | 356 return true; |
286 } | 357 } |
287 | 358 |
288 bool MightBeCollected(FieldPoint* point) { | 359 bool MightBeCollected(FieldPoint* point, bool& as_eagerly_finalized) { |
289 MightBeCollectedVisitor visitor; | 360 MightBeCollectedVisitor visitor(is_eagerly_finalized_); |
290 point->edge()->Accept(&visitor); | 361 point->edge()->Accept(&visitor); |
| 362 as_eagerly_finalized = visitor.as_eagerly_finalized(); |
291 return visitor.might_be_collected(); | 363 return visitor.might_be_collected(); |
292 } | 364 } |
293 | 365 |
294 private: | 366 private: |
295 bool blacklist_context_; | 367 bool blacklist_context_; |
296 Errors finalized_fields_; | 368 Errors finalized_fields_; |
| 369 std::set<MemberExpr*> seen_members_; |
297 RecordCache* cache_; | 370 RecordCache* cache_; |
| 371 bool is_eagerly_finalized_; |
298 }; | 372 }; |
299 | 373 |
300 // This visitor checks that a method contains within its body, a call to a | 374 // This visitor checks that a method contains within its body, a call to a |
301 // method on the provided receiver class. This is used to check manual | 375 // method on the provided receiver class. This is used to check manual |
302 // dispatching for trace and finalize methods. | 376 // dispatching for trace and finalize methods. |
303 class CheckDispatchVisitor : public RecursiveASTVisitor<CheckDispatchVisitor> { | 377 class CheckDispatchVisitor : public RecursiveASTVisitor<CheckDispatchVisitor> { |
304 public: | 378 public: |
305 CheckDispatchVisitor(RecordInfo* receiver) | 379 CheckDispatchVisitor(RecordInfo* receiver) |
306 : receiver_(receiver), dispatched_to_receiver_(false) {} | 380 : receiver_(receiver), dispatched_to_receiver_(false) {} |
307 | 381 |
(...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
773 // - An on-heap class must never contain GC roots. | 847 // - An on-heap class must never contain GC roots. |
774 // - Only stack-allocated types may point to stack-allocated types. | 848 // - Only stack-allocated types may point to stack-allocated types. |
775 class CheckFieldsVisitor : public RecursiveEdgeVisitor { | 849 class CheckFieldsVisitor : public RecursiveEdgeVisitor { |
776 public: | 850 public: |
777 | 851 |
778 enum Error { | 852 enum Error { |
779 kRawPtrToGCManaged, | 853 kRawPtrToGCManaged, |
780 kRawPtrToGCManagedWarning, | 854 kRawPtrToGCManagedWarning, |
781 kRefPtrToGCManaged, | 855 kRefPtrToGCManaged, |
782 kOwnPtrToGCManaged, | 856 kOwnPtrToGCManaged, |
| 857 kMemberToGCUnmanaged, |
783 kMemberInUnmanaged, | 858 kMemberInUnmanaged, |
784 kPtrFromHeapToStack, | 859 kPtrFromHeapToStack, |
785 kGCDerivedPartObject | 860 kGCDerivedPartObject |
786 }; | 861 }; |
787 | 862 |
788 typedef std::vector<std::pair<FieldPoint*, Error> > Errors; | 863 typedef std::vector<std::pair<FieldPoint*, Error> > Errors; |
789 | 864 |
790 CheckFieldsVisitor(const BlinkGCPluginOptions& options) | 865 CheckFieldsVisitor(const BlinkGCPluginOptions& options) |
791 : options_(options), current_(0), stack_allocated_host_(false) {} | 866 : options_(options), current_(0), stack_allocated_host_(false) {} |
792 | 867 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
831 return; | 906 return; |
832 } | 907 } |
833 | 908 |
834 if (!Parent() && | 909 if (!Parent() && |
835 edge->value()->IsGCDerived() && | 910 edge->value()->IsGCDerived() && |
836 !edge->value()->IsGCMixin()) { | 911 !edge->value()->IsGCMixin()) { |
837 invalid_fields_.push_back(std::make_pair(current_, kGCDerivedPartObject)); | 912 invalid_fields_.push_back(std::make_pair(current_, kGCDerivedPartObject)); |
838 return; | 913 return; |
839 } | 914 } |
840 | 915 |
| 916 // If in a stack allocated context, be fairly insistent that T in Member<T> |
| 917 // is GC allocated, as stack allocated objects do not have a trace() |
| 918 // that separately verifies the validity of Member<T>. |
| 919 // |
| 920 // Notice that an error is only reported if T's definition is in scope; |
| 921 // we do not require that it must be brought into scope as that would |
| 922 // prevent declarations of mutually dependent class types. |
| 923 // |
| 924 // (Note: Member<>'s constructor will at run-time verify that the |
| 925 // pointer it wraps is indeed heap allocated.) |
| 926 if (stack_allocated_host_ && Parent() && Parent()->IsMember() && |
| 927 edge->value()->HasDefinition() && !edge->value()->IsGCAllocated()) { |
| 928 invalid_fields_.push_back(std::make_pair(current_, |
| 929 kMemberToGCUnmanaged)); |
| 930 return; |
| 931 } |
| 932 |
841 if (!Parent() || !edge->value()->IsGCAllocated()) | 933 if (!Parent() || !edge->value()->IsGCAllocated()) |
842 return; | 934 return; |
843 | 935 |
844 // In transition mode, disallow OwnPtr<T>, RawPtr<T> to GC allocated T's, | 936 // In transition mode, disallow OwnPtr<T>, RawPtr<T> to GC allocated T's, |
845 // also disallow T* in stack-allocated types. | 937 // also disallow T* in stack-allocated types. |
846 if (options_.enable_oilpan) { | 938 if (options_.enable_oilpan) { |
847 if (Parent()->IsOwnPtr() || | 939 if (Parent()->IsOwnPtr() || |
848 Parent()->IsRawPtrClass() || | 940 Parent()->IsRawPtrClass() || |
849 (stack_allocated_host_ && Parent()->IsRawPtr())) { | 941 (stack_allocated_host_ && Parent()->IsRawPtr())) { |
850 invalid_fields_.push_back(std::make_pair( | 942 invalid_fields_.push_back(std::make_pair( |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
942 diag_class_contains_invalid_fields_warning_ = diagnostic_.getCustomDiagID( | 1034 diag_class_contains_invalid_fields_warning_ = diagnostic_.getCustomDiagID( |
943 DiagnosticsEngine::Warning, kClassContainsInvalidFields); | 1035 DiagnosticsEngine::Warning, kClassContainsInvalidFields); |
944 diag_class_contains_gc_root_ = | 1036 diag_class_contains_gc_root_ = |
945 diagnostic_.getCustomDiagID(getErrorLevel(), kClassContainsGCRoot); | 1037 diagnostic_.getCustomDiagID(getErrorLevel(), kClassContainsGCRoot); |
946 diag_class_requires_finalization_ = diagnostic_.getCustomDiagID( | 1038 diag_class_requires_finalization_ = diagnostic_.getCustomDiagID( |
947 getErrorLevel(), kClassRequiresFinalization); | 1039 getErrorLevel(), kClassRequiresFinalization); |
948 diag_class_does_not_require_finalization_ = diagnostic_.getCustomDiagID( | 1040 diag_class_does_not_require_finalization_ = diagnostic_.getCustomDiagID( |
949 DiagnosticsEngine::Warning, kClassDoesNotRequireFinalization); | 1041 DiagnosticsEngine::Warning, kClassDoesNotRequireFinalization); |
950 diag_finalizer_accesses_finalized_field_ = diagnostic_.getCustomDiagID( | 1042 diag_finalizer_accesses_finalized_field_ = diagnostic_.getCustomDiagID( |
951 getErrorLevel(), kFinalizerAccessesFinalizedField); | 1043 getErrorLevel(), kFinalizerAccessesFinalizedField); |
| 1044 diag_finalizer_eagerly_finalized_field_ = diagnostic_.getCustomDiagID( |
| 1045 getErrorLevel(), kFinalizerAccessesEagerlyFinalizedField); |
952 diag_overridden_non_virtual_trace_ = diagnostic_.getCustomDiagID( | 1046 diag_overridden_non_virtual_trace_ = diagnostic_.getCustomDiagID( |
953 getErrorLevel(), kOverriddenNonVirtualTrace); | 1047 getErrorLevel(), kOverriddenNonVirtualTrace); |
954 diag_missing_trace_dispatch_method_ = diagnostic_.getCustomDiagID( | 1048 diag_missing_trace_dispatch_method_ = diagnostic_.getCustomDiagID( |
955 getErrorLevel(), kMissingTraceDispatchMethod); | 1049 getErrorLevel(), kMissingTraceDispatchMethod); |
956 diag_missing_finalize_dispatch_method_ = diagnostic_.getCustomDiagID( | 1050 diag_missing_finalize_dispatch_method_ = diagnostic_.getCustomDiagID( |
957 getErrorLevel(), kMissingFinalizeDispatchMethod); | 1051 getErrorLevel(), kMissingFinalizeDispatchMethod); |
958 diag_virtual_and_manual_dispatch_ = | 1052 diag_virtual_and_manual_dispatch_ = |
959 diagnostic_.getCustomDiagID(getErrorLevel(), kVirtualAndManualDispatch); | 1053 diagnostic_.getCustomDiagID(getErrorLevel(), kVirtualAndManualDispatch); |
960 diag_missing_trace_dispatch_ = | 1054 diag_missing_trace_dispatch_ = |
961 diagnostic_.getCustomDiagID(getErrorLevel(), kMissingTraceDispatch); | 1055 diagnostic_.getCustomDiagID(getErrorLevel(), kMissingTraceDispatch); |
(...skipping 17 matching lines...) Expand all Loading... |
979 diag_base_requires_tracing_note_ = diagnostic_.getCustomDiagID( | 1073 diag_base_requires_tracing_note_ = diagnostic_.getCustomDiagID( |
980 DiagnosticsEngine::Note, kBaseRequiresTracingNote); | 1074 DiagnosticsEngine::Note, kBaseRequiresTracingNote); |
981 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID( | 1075 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID( |
982 DiagnosticsEngine::Note, kFieldRequiresTracingNote); | 1076 DiagnosticsEngine::Note, kFieldRequiresTracingNote); |
983 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 1077 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
984 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); | 1078 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); |
985 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 1079 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
986 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); | 1080 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); |
987 diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 1081 diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
988 DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote); | 1082 DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote); |
| 1083 diag_member_to_gc_unmanaged_class_note_ = diagnostic_.getCustomDiagID( |
| 1084 DiagnosticsEngine::Note, kMemberToGCUnmanagedClassNote); |
989 diag_stack_allocated_field_note_ = diagnostic_.getCustomDiagID( | 1085 diag_stack_allocated_field_note_ = diagnostic_.getCustomDiagID( |
990 DiagnosticsEngine::Note, kStackAllocatedFieldNote); | 1086 DiagnosticsEngine::Note, kStackAllocatedFieldNote); |
991 diag_member_in_unmanaged_class_note_ = diagnostic_.getCustomDiagID( | 1087 diag_member_in_unmanaged_class_note_ = diagnostic_.getCustomDiagID( |
992 DiagnosticsEngine::Note, kMemberInUnmanagedClassNote); | 1088 DiagnosticsEngine::Note, kMemberInUnmanagedClassNote); |
993 diag_part_object_to_gc_derived_class_note_ = diagnostic_.getCustomDiagID( | 1089 diag_part_object_to_gc_derived_class_note_ = diagnostic_.getCustomDiagID( |
994 DiagnosticsEngine::Note, kPartObjectToGCDerivedClassNote); | 1090 DiagnosticsEngine::Note, kPartObjectToGCDerivedClassNote); |
995 diag_part_object_contains_gc_root_note_ = diagnostic_.getCustomDiagID( | 1091 diag_part_object_contains_gc_root_note_ = diagnostic_.getCustomDiagID( |
996 DiagnosticsEngine::Note, kPartObjectContainsGCRootNote); | 1092 DiagnosticsEngine::Note, kPartObjectContainsGCRootNote); |
997 diag_field_contains_gc_root_note_ = diagnostic_.getCustomDiagID( | 1093 diag_field_contains_gc_root_note_ = diagnostic_.getCustomDiagID( |
998 DiagnosticsEngine::Note, kFieldContainsGCRootNote); | 1094 DiagnosticsEngine::Note, kFieldContainsGCRootNote); |
999 diag_finalized_field_note_ = diagnostic_.getCustomDiagID( | 1095 diag_finalized_field_note_ = diagnostic_.getCustomDiagID( |
1000 DiagnosticsEngine::Note, kFinalizedFieldNote); | 1096 DiagnosticsEngine::Note, kFinalizedFieldNote); |
| 1097 diag_eagerly_finalized_field_note_ = diagnostic_.getCustomDiagID( |
| 1098 DiagnosticsEngine::Note, kEagerlyFinalizedFieldNote); |
1001 diag_user_declared_destructor_note_ = diagnostic_.getCustomDiagID( | 1099 diag_user_declared_destructor_note_ = diagnostic_.getCustomDiagID( |
1002 DiagnosticsEngine::Note, kUserDeclaredDestructorNote); | 1100 DiagnosticsEngine::Note, kUserDeclaredDestructorNote); |
1003 diag_user_declared_finalizer_note_ = diagnostic_.getCustomDiagID( | 1101 diag_user_declared_finalizer_note_ = diagnostic_.getCustomDiagID( |
1004 DiagnosticsEngine::Note, kUserDeclaredFinalizerNote); | 1102 DiagnosticsEngine::Note, kUserDeclaredFinalizerNote); |
1005 diag_base_requires_finalization_note_ = diagnostic_.getCustomDiagID( | 1103 diag_base_requires_finalization_note_ = diagnostic_.getCustomDiagID( |
1006 DiagnosticsEngine::Note, kBaseRequiresFinalizationNote); | 1104 DiagnosticsEngine::Note, kBaseRequiresFinalizationNote); |
1007 diag_field_requires_finalization_note_ = diagnostic_.getCustomDiagID( | 1105 diag_field_requires_finalization_note_ = diagnostic_.getCustomDiagID( |
1008 DiagnosticsEngine::Note, kFieldRequiresFinalizationNote); | 1106 DiagnosticsEngine::Note, kFieldRequiresFinalizationNote); |
1009 diag_overridden_non_virtual_trace_note_ = diagnostic_.getCustomDiagID( | 1107 diag_overridden_non_virtual_trace_note_ = diagnostic_.getCustomDiagID( |
1010 DiagnosticsEngine::Note, kOverriddenNonVirtualTraceNote); | 1108 DiagnosticsEngine::Note, kOverriddenNonVirtualTraceNote); |
1011 diag_manual_dispatch_method_note_ = diagnostic_.getCustomDiagID( | 1109 diag_manual_dispatch_method_note_ = diagnostic_.getCustomDiagID( |
1012 DiagnosticsEngine::Note, kManualDispatchMethodNote); | 1110 DiagnosticsEngine::Note, kManualDispatchMethodNote); |
1013 } | 1111 } |
1014 | 1112 |
1015 void HandleTranslationUnit(ASTContext& context) override { | 1113 void HandleTranslationUnit(ASTContext& context) override { |
1016 // Don't run the plugin if the compilation unit is already invalid. | 1114 // Don't run the plugin if the compilation unit is already invalid. |
1017 if (diagnostic_.hasErrorOccurred()) | 1115 if (diagnostic_.hasErrorOccurred()) |
1018 return; | 1116 return; |
1019 | 1117 |
| 1118 ParseFunctionTemplates(context.getTranslationUnitDecl()); |
| 1119 |
1020 CollectVisitor visitor; | 1120 CollectVisitor visitor; |
1021 visitor.TraverseDecl(context.getTranslationUnitDecl()); | 1121 visitor.TraverseDecl(context.getTranslationUnitDecl()); |
1022 | 1122 |
1023 if (options_.dump_graph) { | 1123 if (options_.dump_graph) { |
1024 std::error_code err; | 1124 std::error_code err; |
1025 // TODO: Make createDefaultOutputFile or a shorter createOutputFile work. | 1125 // TODO: Make createDefaultOutputFile or a shorter createOutputFile work. |
1026 json_ = JsonWriter::from(instance_.createOutputFile( | 1126 json_ = JsonWriter::from(instance_.createOutputFile( |
1027 "", // OutputPath | 1127 "", // OutputPath |
1028 err, // Errors | 1128 err, // Errors |
1029 true, // Binary | 1129 true, // Binary |
(...skipping 26 matching lines...) Expand all Loading... |
1056 CheckTracingMethod(*it); | 1156 CheckTracingMethod(*it); |
1057 } | 1157 } |
1058 | 1158 |
1059 if (json_) { | 1159 if (json_) { |
1060 json_->CloseList(); | 1160 json_->CloseList(); |
1061 delete json_; | 1161 delete json_; |
1062 json_ = 0; | 1162 json_ = 0; |
1063 } | 1163 } |
1064 } | 1164 } |
1065 | 1165 |
| 1166 void ParseFunctionTemplates(TranslationUnitDecl* decl) { |
| 1167 if (!instance_.getLangOpts().DelayedTemplateParsing) |
| 1168 return; // Nothing to do. |
| 1169 |
| 1170 std::set<FunctionDecl*> late_parsed_decls = |
| 1171 GetLateParsedFunctionDecls(decl); |
| 1172 clang::Sema& sema = instance_.getSema(); |
| 1173 |
| 1174 for (const FunctionDecl* fd : late_parsed_decls) { |
| 1175 assert(fd->isLateTemplateParsed()); |
| 1176 |
| 1177 if (!Config::IsTraceMethod(fd)) |
| 1178 continue; |
| 1179 |
| 1180 if (instance_.getSourceManager().isInSystemHeader( |
| 1181 instance_.getSourceManager().getSpellingLoc(fd->getLocation()))) |
| 1182 continue; |
| 1183 |
| 1184 // Force parsing and AST building of the yet-uninstantiated function |
| 1185 // template trace method bodies. |
| 1186 clang::LateParsedTemplate* lpt = sema.LateParsedTemplateMap[fd]; |
| 1187 sema.LateTemplateParser(sema.OpaqueParser, *lpt); |
| 1188 } |
| 1189 } |
| 1190 |
1066 // Main entry for checking a record declaration. | 1191 // Main entry for checking a record declaration. |
1067 void CheckRecord(RecordInfo* info) { | 1192 void CheckRecord(RecordInfo* info) { |
1068 if (IsIgnored(info)) | 1193 if (IsIgnored(info)) |
1069 return; | 1194 return; |
1070 | 1195 |
1071 CXXRecordDecl* record = info->record(); | 1196 CXXRecordDecl* record = info->record(); |
1072 | 1197 |
1073 // TODO: what should we do to check unions? | 1198 // TODO: what should we do to check unions? |
1074 if (record->isUnion()) | 1199 if (record->isUnion()) |
1075 return; | 1200 return; |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1333 } | 1458 } |
1334 } | 1459 } |
1335 | 1460 |
1336 // TODO: Should we collect destructors similar to trace methods? | 1461 // TODO: Should we collect destructors similar to trace methods? |
1337 void CheckFinalization(RecordInfo* info) { | 1462 void CheckFinalization(RecordInfo* info) { |
1338 CXXDestructorDecl* dtor = info->record()->getDestructor(); | 1463 CXXDestructorDecl* dtor = info->record()->getDestructor(); |
1339 | 1464 |
1340 // For finalized classes, check the finalization method if possible. | 1465 // For finalized classes, check the finalization method if possible. |
1341 if (info->IsGCFinalized()) { | 1466 if (info->IsGCFinalized()) { |
1342 if (dtor && dtor->hasBody()) { | 1467 if (dtor && dtor->hasBody()) { |
1343 CheckFinalizerVisitor visitor(&cache_); | 1468 CheckFinalizerVisitor visitor(&cache_, info->IsEagerlyFinalized()); |
1344 visitor.TraverseCXXMethodDecl(dtor); | 1469 visitor.TraverseCXXMethodDecl(dtor); |
1345 if (!visitor.finalized_fields().empty()) { | 1470 if (!visitor.finalized_fields().empty()) { |
1346 ReportFinalizerAccessesFinalizedFields( | 1471 ReportFinalizerAccessesFinalizedFields( |
1347 dtor, &visitor.finalized_fields()); | 1472 dtor, &visitor.finalized_fields()); |
1348 } | 1473 } |
1349 } | 1474 } |
1350 return; | 1475 return; |
1351 } | 1476 } |
1352 | 1477 |
1353 // Don't require finalization of a mixin that has not yet been "mixed in". | 1478 // Don't require finalization of a mixin that has not yet been "mixed in". |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1603 if (info->name().compare(0, SameSizeAs.size(), SameSizeAs) == 0) | 1728 if (info->name().compare(0, SameSizeAs.size(), SameSizeAs) == 0) |
1604 return true; | 1729 return true; |
1605 return options_.ignored_classes.find(info->name()) != | 1730 return options_.ignored_classes.find(info->name()) != |
1606 options_.ignored_classes.end(); | 1731 options_.ignored_classes.end(); |
1607 } | 1732 } |
1608 | 1733 |
1609 bool InIgnoredDirectory(RecordInfo* info) { | 1734 bool InIgnoredDirectory(RecordInfo* info) { |
1610 string filename; | 1735 string filename; |
1611 if (!GetFilename(info->record()->getLocStart(), &filename)) | 1736 if (!GetFilename(info->record()->getLocStart(), &filename)) |
1612 return false; // TODO: should we ignore non-existing file locations? | 1737 return false; // TODO: should we ignore non-existing file locations? |
| 1738 #if defined(LLVM_ON_WIN32) |
| 1739 std::replace(filename.begin(), filename.end(), '\\', '/'); |
| 1740 #endif |
1613 std::vector<string>::iterator it = options_.ignored_directories.begin(); | 1741 std::vector<string>::iterator it = options_.ignored_directories.begin(); |
1614 for (; it != options_.ignored_directories.end(); ++it) | 1742 for (; it != options_.ignored_directories.end(); ++it) |
1615 if (filename.find(*it) != string::npos) | 1743 if (filename.find(*it) != string::npos) |
1616 return true; | 1744 return true; |
1617 return false; | 1745 return false; |
1618 } | 1746 } |
1619 | 1747 |
1620 bool InCheckedNamespace(RecordInfo* info) { | 1748 bool InCheckedNamespace(RecordInfo* info) { |
1621 if (!info) | 1749 if (!info) |
1622 return false; | 1750 return false; |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1720 it != errors->end(); | 1848 it != errors->end(); |
1721 ++it) { | 1849 ++it) { |
1722 unsigned error; | 1850 unsigned error; |
1723 if (it->second == CheckFieldsVisitor::kRawPtrToGCManaged || | 1851 if (it->second == CheckFieldsVisitor::kRawPtrToGCManaged || |
1724 it->second == CheckFieldsVisitor::kRawPtrToGCManagedWarning) { | 1852 it->second == CheckFieldsVisitor::kRawPtrToGCManagedWarning) { |
1725 error = diag_raw_ptr_to_gc_managed_class_note_; | 1853 error = diag_raw_ptr_to_gc_managed_class_note_; |
1726 } else if (it->second == CheckFieldsVisitor::kRefPtrToGCManaged) { | 1854 } else if (it->second == CheckFieldsVisitor::kRefPtrToGCManaged) { |
1727 error = diag_ref_ptr_to_gc_managed_class_note_; | 1855 error = diag_ref_ptr_to_gc_managed_class_note_; |
1728 } else if (it->second == CheckFieldsVisitor::kOwnPtrToGCManaged) { | 1856 } else if (it->second == CheckFieldsVisitor::kOwnPtrToGCManaged) { |
1729 error = diag_own_ptr_to_gc_managed_class_note_; | 1857 error = diag_own_ptr_to_gc_managed_class_note_; |
| 1858 } else if (it->second == CheckFieldsVisitor::kMemberToGCUnmanaged) { |
| 1859 error = diag_member_to_gc_unmanaged_class_note_; |
1730 } else if (it->second == CheckFieldsVisitor::kMemberInUnmanaged) { | 1860 } else if (it->second == CheckFieldsVisitor::kMemberInUnmanaged) { |
1731 error = diag_member_in_unmanaged_class_note_; | 1861 error = diag_member_in_unmanaged_class_note_; |
1732 } else if (it->second == CheckFieldsVisitor::kPtrFromHeapToStack) { | 1862 } else if (it->second == CheckFieldsVisitor::kPtrFromHeapToStack) { |
1733 error = diag_stack_allocated_field_note_; | 1863 error = diag_stack_allocated_field_note_; |
1734 } else if (it->second == CheckFieldsVisitor::kGCDerivedPartObject) { | 1864 } else if (it->second == CheckFieldsVisitor::kGCDerivedPartObject) { |
1735 error = diag_part_object_to_gc_derived_class_note_; | 1865 error = diag_part_object_to_gc_derived_class_note_; |
1736 } else { | 1866 } else { |
1737 assert(false && "Unknown field error"); | 1867 assert(false && "Unknown field error"); |
1738 } | 1868 } |
1739 NoteField(it->first, error); | 1869 NoteField(it->first, error); |
(...skipping 19 matching lines...) Expand all Loading... |
1759 NoteFieldContainsGCRoot(point); | 1889 NoteFieldContainsGCRoot(point); |
1760 } | 1890 } |
1761 } | 1891 } |
1762 | 1892 |
1763 void ReportFinalizerAccessesFinalizedFields( | 1893 void ReportFinalizerAccessesFinalizedFields( |
1764 CXXMethodDecl* dtor, | 1894 CXXMethodDecl* dtor, |
1765 CheckFinalizerVisitor::Errors* fields) { | 1895 CheckFinalizerVisitor::Errors* fields) { |
1766 for (CheckFinalizerVisitor::Errors::iterator it = fields->begin(); | 1896 for (CheckFinalizerVisitor::Errors::iterator it = fields->begin(); |
1767 it != fields->end(); | 1897 it != fields->end(); |
1768 ++it) { | 1898 ++it) { |
1769 SourceLocation loc = it->first->getLocStart(); | 1899 SourceLocation loc = it->member_->getLocStart(); |
1770 SourceManager& manager = instance_.getSourceManager(); | 1900 SourceManager& manager = instance_.getSourceManager(); |
| 1901 bool as_eagerly_finalized = it->as_eagerly_finalized_; |
| 1902 unsigned diag_error = as_eagerly_finalized ? |
| 1903 diag_finalizer_eagerly_finalized_field_ : |
| 1904 diag_finalizer_accesses_finalized_field_; |
| 1905 unsigned diag_note = as_eagerly_finalized ? |
| 1906 diag_eagerly_finalized_field_note_ : |
| 1907 diag_finalized_field_note_; |
1771 FullSourceLoc full_loc(loc, manager); | 1908 FullSourceLoc full_loc(loc, manager); |
1772 diagnostic_.Report(full_loc, diag_finalizer_accesses_finalized_field_) | 1909 diagnostic_.Report(full_loc, diag_error) |
1773 << dtor << it->second->field(); | 1910 << dtor << it->field_->field(); |
1774 NoteField(it->second, diag_finalized_field_note_); | 1911 NoteField(it->field_, diag_note); |
1775 } | 1912 } |
1776 } | 1913 } |
1777 | 1914 |
1778 void ReportClassRequiresFinalization(RecordInfo* info) { | 1915 void ReportClassRequiresFinalization(RecordInfo* info) { |
1779 SourceLocation loc = info->record()->getInnerLocStart(); | 1916 SourceLocation loc = info->record()->getInnerLocStart(); |
1780 SourceManager& manager = instance_.getSourceManager(); | 1917 SourceManager& manager = instance_.getSourceManager(); |
1781 FullSourceLoc full_loc(loc, manager); | 1918 FullSourceLoc full_loc(loc, manager); |
1782 diagnostic_.Report(full_loc, diag_class_requires_finalization_) | 1919 diagnostic_.Report(full_loc, diag_class_requires_finalization_) |
1783 << info->record(); | 1920 << info->record(); |
1784 } | 1921 } |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1973 unsigned diag_class_must_left_mostly_derive_gc_; | 2110 unsigned diag_class_must_left_mostly_derive_gc_; |
1974 unsigned diag_class_requires_trace_method_; | 2111 unsigned diag_class_requires_trace_method_; |
1975 unsigned diag_base_requires_tracing_; | 2112 unsigned diag_base_requires_tracing_; |
1976 unsigned diag_fields_require_tracing_; | 2113 unsigned diag_fields_require_tracing_; |
1977 unsigned diag_class_contains_invalid_fields_; | 2114 unsigned diag_class_contains_invalid_fields_; |
1978 unsigned diag_class_contains_invalid_fields_warning_; | 2115 unsigned diag_class_contains_invalid_fields_warning_; |
1979 unsigned diag_class_contains_gc_root_; | 2116 unsigned diag_class_contains_gc_root_; |
1980 unsigned diag_class_requires_finalization_; | 2117 unsigned diag_class_requires_finalization_; |
1981 unsigned diag_class_does_not_require_finalization_; | 2118 unsigned diag_class_does_not_require_finalization_; |
1982 unsigned diag_finalizer_accesses_finalized_field_; | 2119 unsigned diag_finalizer_accesses_finalized_field_; |
| 2120 unsigned diag_finalizer_eagerly_finalized_field_; |
1983 unsigned diag_overridden_non_virtual_trace_; | 2121 unsigned diag_overridden_non_virtual_trace_; |
1984 unsigned diag_missing_trace_dispatch_method_; | 2122 unsigned diag_missing_trace_dispatch_method_; |
1985 unsigned diag_missing_finalize_dispatch_method_; | 2123 unsigned diag_missing_finalize_dispatch_method_; |
1986 unsigned diag_virtual_and_manual_dispatch_; | 2124 unsigned diag_virtual_and_manual_dispatch_; |
1987 unsigned diag_missing_trace_dispatch_; | 2125 unsigned diag_missing_trace_dispatch_; |
1988 unsigned diag_missing_finalize_dispatch_; | 2126 unsigned diag_missing_finalize_dispatch_; |
1989 unsigned diag_derives_non_stack_allocated_; | 2127 unsigned diag_derives_non_stack_allocated_; |
1990 unsigned diag_class_overrides_new_; | 2128 unsigned diag_class_overrides_new_; |
1991 unsigned diag_class_declares_pure_virtual_trace_; | 2129 unsigned diag_class_declares_pure_virtual_trace_; |
1992 unsigned diag_left_most_base_must_be_polymorphic_; | 2130 unsigned diag_left_most_base_must_be_polymorphic_; |
1993 unsigned diag_base_class_must_declare_virtual_trace_; | 2131 unsigned diag_base_class_must_declare_virtual_trace_; |
1994 unsigned diag_class_must_declare_gc_mixin_trace_method_; | 2132 unsigned diag_class_must_declare_gc_mixin_trace_method_; |
1995 | 2133 |
1996 unsigned diag_base_requires_tracing_note_; | 2134 unsigned diag_base_requires_tracing_note_; |
1997 unsigned diag_field_requires_tracing_note_; | 2135 unsigned diag_field_requires_tracing_note_; |
1998 unsigned diag_raw_ptr_to_gc_managed_class_note_; | 2136 unsigned diag_raw_ptr_to_gc_managed_class_note_; |
1999 unsigned diag_ref_ptr_to_gc_managed_class_note_; | 2137 unsigned diag_ref_ptr_to_gc_managed_class_note_; |
2000 unsigned diag_own_ptr_to_gc_managed_class_note_; | 2138 unsigned diag_own_ptr_to_gc_managed_class_note_; |
| 2139 unsigned diag_member_to_gc_unmanaged_class_note_; |
2001 unsigned diag_stack_allocated_field_note_; | 2140 unsigned diag_stack_allocated_field_note_; |
2002 unsigned diag_member_in_unmanaged_class_note_; | 2141 unsigned diag_member_in_unmanaged_class_note_; |
2003 unsigned diag_part_object_to_gc_derived_class_note_; | 2142 unsigned diag_part_object_to_gc_derived_class_note_; |
2004 unsigned diag_part_object_contains_gc_root_note_; | 2143 unsigned diag_part_object_contains_gc_root_note_; |
2005 unsigned diag_field_contains_gc_root_note_; | 2144 unsigned diag_field_contains_gc_root_note_; |
2006 unsigned diag_finalized_field_note_; | 2145 unsigned diag_finalized_field_note_; |
| 2146 unsigned diag_eagerly_finalized_field_note_; |
2007 unsigned diag_user_declared_destructor_note_; | 2147 unsigned diag_user_declared_destructor_note_; |
2008 unsigned diag_user_declared_finalizer_note_; | 2148 unsigned diag_user_declared_finalizer_note_; |
2009 unsigned diag_base_requires_finalization_note_; | 2149 unsigned diag_base_requires_finalization_note_; |
2010 unsigned diag_field_requires_finalization_note_; | 2150 unsigned diag_field_requires_finalization_note_; |
2011 unsigned diag_overridden_non_virtual_trace_note_; | 2151 unsigned diag_overridden_non_virtual_trace_note_; |
2012 unsigned diag_manual_dispatch_method_note_; | 2152 unsigned diag_manual_dispatch_method_note_; |
2013 | 2153 |
2014 CompilerInstance& instance_; | 2154 CompilerInstance& instance_; |
2015 DiagnosticsEngine& diagnostic_; | 2155 DiagnosticsEngine& diagnostic_; |
2016 BlinkGCPluginOptions options_; | 2156 BlinkGCPluginOptions options_; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2054 | 2194 |
2055 private: | 2195 private: |
2056 BlinkGCPluginOptions options_; | 2196 BlinkGCPluginOptions options_; |
2057 }; | 2197 }; |
2058 | 2198 |
2059 } // namespace | 2199 } // namespace |
2060 | 2200 |
2061 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( | 2201 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( |
2062 "blink-gc-plugin", | 2202 "blink-gc-plugin", |
2063 "Check Blink GC invariants"); | 2203 "Check Blink GC invariants"); |
OLD | NEW |