Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp

Issue 1180693002: Update from https://crrev.com/333737 (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: rebased Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/android/mempressure.py ('k') | tools/clang/blink_gc_plugin/Config.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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");
OLDNEW
« no previous file with comments | « tools/android/mempressure.py ('k') | tools/clang/blink_gc_plugin/Config.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698