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

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

Issue 1926863002: GC plugin: split out reporting of errors/warnings. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: whitespace Created 4 years, 7 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 #include "BlinkGCPluginConsumer.h" 5 #include "BlinkGCPluginConsumer.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <set> 8 #include <set>
9 9
10 #include "CheckDispatchVisitor.h" 10 #include "CheckDispatchVisitor.h"
11 #include "CheckFieldsVisitor.h"
12 #include "CheckFinalizerVisitor.h"
13 #include "CheckGCRootsVisitor.h"
11 #include "CheckTraceVisitor.h" 14 #include "CheckTraceVisitor.h"
12 #include "CollectVisitor.h" 15 #include "CollectVisitor.h"
13 #include "JsonWriter.h" 16 #include "JsonWriter.h"
14 #include "RecordInfo.h" 17 #include "RecordInfo.h"
15 #include "clang/AST/RecursiveASTVisitor.h" 18 #include "clang/AST/RecursiveASTVisitor.h"
16 #include "clang/Sema/Sema.h" 19 #include "clang/Sema/Sema.h"
17 20
18 using namespace clang; 21 using namespace clang;
19 22
20 namespace { 23 namespace {
21 24
22 const char kClassMustLeftMostlyDeriveGC[] =
23 "[blink-gc] Class %0 must derive its GC base in the left-most position.";
24
25 const char kClassRequiresTraceMethod[] =
26 "[blink-gc] Class %0 requires a trace method.";
27
28 const char kBaseRequiresTracing[] =
29 "[blink-gc] Base class %0 of derived class %1 requires tracing.";
30
31 const char kBaseRequiresTracingNote[] =
32 "[blink-gc] Untraced base class %0 declared here:";
33
34 const char kFieldsRequireTracing[] =
35 "[blink-gc] Class %0 has untraced fields that require tracing.";
36
37 const char kFieldRequiresTracingNote[] =
38 "[blink-gc] Untraced field %0 declared here:";
39
40 const char kClassContainsInvalidFields[] =
41 "[blink-gc] Class %0 contains invalid fields.";
42
43 const char kClassContainsGCRoot[] =
44 "[blink-gc] Class %0 contains GC root in field %1.";
45
46 const char kClassRequiresFinalization[] =
47 "[blink-gc] Class %0 requires finalization.";
48
49 const char kClassDoesNotRequireFinalization[] =
50 "[blink-gc] Class %0 may not require finalization.";
51
52 const char kFinalizerAccessesFinalizedField[] =
53 "[blink-gc] Finalizer %0 accesses potentially finalized field %1.";
54
55 const char kFinalizerAccessesEagerlyFinalizedField[] =
56 "[blink-gc] Finalizer %0 accesses eagerly finalized field %1.";
57
58 const char kRawPtrToGCManagedClassNote[] =
59 "[blink-gc] Raw pointer field %0 to a GC managed class declared here:";
60
61 const char kRefPtrToGCManagedClassNote[] =
62 "[blink-gc] RefPtr field %0 to a GC managed class declared here:";
63
64 const char kReferencePtrToGCManagedClassNote[] =
65 "[blink-gc] Reference pointer field %0 to a GC managed class"
66 " declared here:";
67
68 const char kOwnPtrToGCManagedClassNote[] =
69 "[blink-gc] OwnPtr field %0 to a GC managed class declared here:";
70
71 const char kMemberToGCUnmanagedClassNote[] =
72 "[blink-gc] Member field %0 to non-GC managed class declared here:";
73
74 const char kStackAllocatedFieldNote[] =
75 "[blink-gc] Stack-allocated field %0 declared here:";
76
77 const char kMemberInUnmanagedClassNote[] =
78 "[blink-gc] Member field %0 in unmanaged class declared here:";
79
80 const char kPartObjectToGCDerivedClassNote[] =
81 "[blink-gc] Part-object field %0 to a GC derived class declared here:";
82
83 const char kPartObjectContainsGCRootNote[] =
84 "[blink-gc] Field %0 with embedded GC root in %1 declared here:";
85
86 const char kFieldContainsGCRootNote[] =
87 "[blink-gc] Field %0 defining a GC root declared here:";
88
89 const char kOverriddenNonVirtualTrace[] =
90 "[blink-gc] Class %0 overrides non-virtual trace of base class %1.";
91
92 const char kOverriddenNonVirtualTraceNote[] =
93 "[blink-gc] Non-virtual trace method declared here:";
94
95 const char kMissingTraceDispatchMethod[] =
96 "[blink-gc] Class %0 is missing manual trace dispatch.";
97
98 const char kMissingFinalizeDispatchMethod[] =
99 "[blink-gc] Class %0 is missing manual finalize dispatch.";
100
101 const char kVirtualAndManualDispatch[] =
102 "[blink-gc] Class %0 contains or inherits virtual methods"
103 " but implements manual dispatching.";
104
105 const char kMissingTraceDispatch[] =
106 "[blink-gc] Missing dispatch to class %0 in manual trace dispatch.";
107
108 const char kMissingFinalizeDispatch[] =
109 "[blink-gc] Missing dispatch to class %0 in manual finalize dispatch.";
110
111 const char kFinalizedFieldNote[] =
112 "[blink-gc] Potentially finalized field %0 declared here:";
113
114 const char kEagerlyFinalizedFieldNote[] =
115 "[blink-gc] Field %0 having eagerly finalized value, declared here:";
116
117 const char kUserDeclaredDestructorNote[] =
118 "[blink-gc] User-declared destructor declared here:";
119
120 const char kUserDeclaredFinalizerNote[] =
121 "[blink-gc] User-declared finalizer declared here:";
122
123 const char kBaseRequiresFinalizationNote[] =
124 "[blink-gc] Base class %0 requiring finalization declared here:";
125
126 const char kFieldRequiresFinalizationNote[] =
127 "[blink-gc] Field %0 requiring finalization declared here:";
128
129 const char kManualDispatchMethodNote[] =
130 "[blink-gc] Manual dispatch %0 declared here:";
131
132 const char kDerivesNonStackAllocated[] =
133 "[blink-gc] Stack-allocated class %0 derives class %1"
134 " which is not stack allocated.";
135
136 const char kClassOverridesNew[] =
137 "[blink-gc] Garbage collected class %0"
138 " is not permitted to override its new operator.";
139
140 const char kClassDeclaresPureVirtualTrace[] =
141 "[blink-gc] Garbage collected class %0"
142 " is not permitted to declare a pure-virtual trace method.";
143
144 const char kLeftMostBaseMustBePolymorphic[] =
145 "[blink-gc] Left-most base class %0 of derived class %1"
146 " must be polymorphic.";
147
148 const char kBaseClassMustDeclareVirtualTrace[] =
149 "[blink-gc] Left-most base class %0 of derived class %1"
150 " must define a virtual trace method.";
151
152 // Use a local RAV implementation to simply collect all FunctionDecls marked for 25 // Use a local RAV implementation to simply collect all FunctionDecls marked for
153 // late template parsing. This happens with the flag -fdelayed-template-parsing, 26 // late template parsing. This happens with the flag -fdelayed-template-parsing,
154 // which is on by default in MSVC-compatible mode. 27 // which is on by default in MSVC-compatible mode.
155 std::set<FunctionDecl*> GetLateParsedFunctionDecls(TranslationUnitDecl* decl) { 28 std::set<FunctionDecl*> GetLateParsedFunctionDecls(TranslationUnitDecl* decl) {
156 struct Visitor : public RecursiveASTVisitor<Visitor> { 29 struct Visitor : public RecursiveASTVisitor<Visitor> {
157 bool VisitFunctionDecl(FunctionDecl* function_decl) { 30 bool VisitFunctionDecl(FunctionDecl* function_decl) {
158 if (function_decl->isLateTemplateParsed()) 31 if (function_decl->isLateTemplateParsed())
159 late_parsed_decls.insert(function_decl); 32 late_parsed_decls.insert(function_decl);
160 return true; 33 return true;
161 } 34 }
(...skipping 24 matching lines...) Expand all
186 EmptyStmtVisitor() : empty_(true) {} 59 EmptyStmtVisitor() : empty_(true) {}
187 bool empty_; 60 bool empty_;
188 }; 61 };
189 62
190 } // namespace 63 } // namespace
191 64
192 BlinkGCPluginConsumer::BlinkGCPluginConsumer( 65 BlinkGCPluginConsumer::BlinkGCPluginConsumer(
193 clang::CompilerInstance& instance, 66 clang::CompilerInstance& instance,
194 const BlinkGCPluginOptions& options) 67 const BlinkGCPluginOptions& options)
195 : instance_(instance), 68 : instance_(instance),
196 diagnostic_(instance.getDiagnostics()), 69 reporter_(instance),
197 options_(options), 70 options_(options),
198 json_(0) { 71 json_(0) {
199 // Only check structures in the blink and WebKit namespaces. 72 // Only check structures in the blink and WebKit namespaces.
200 options_.checked_namespaces.insert("blink"); 73 options_.checked_namespaces.insert("blink");
201 74
202 // Ignore GC implementation files. 75 // Ignore GC implementation files.
203 options_.ignored_directories.push_back("/heap/"); 76 options_.ignored_directories.push_back("/heap/");
204
205 // Register warning/error messages.
206 diag_class_must_left_mostly_derive_gc_ = diagnostic_.getCustomDiagID(
207 getErrorLevel(), kClassMustLeftMostlyDeriveGC);
208 diag_class_requires_trace_method_ =
209 diagnostic_.getCustomDiagID(getErrorLevel(), kClassRequiresTraceMethod);
210 diag_base_requires_tracing_ =
211 diagnostic_.getCustomDiagID(getErrorLevel(), kBaseRequiresTracing);
212 diag_fields_require_tracing_ =
213 diagnostic_.getCustomDiagID(getErrorLevel(), kFieldsRequireTracing);
214 diag_class_contains_invalid_fields_ = diagnostic_.getCustomDiagID(
215 getErrorLevel(), kClassContainsInvalidFields);
216 diag_class_contains_gc_root_ =
217 diagnostic_.getCustomDiagID(getErrorLevel(), kClassContainsGCRoot);
218 diag_class_requires_finalization_ = diagnostic_.getCustomDiagID(
219 getErrorLevel(), kClassRequiresFinalization);
220 diag_class_does_not_require_finalization_ = diagnostic_.getCustomDiagID(
221 DiagnosticsEngine::Warning, kClassDoesNotRequireFinalization);
222 diag_finalizer_accesses_finalized_field_ = diagnostic_.getCustomDiagID(
223 getErrorLevel(), kFinalizerAccessesFinalizedField);
224 diag_finalizer_eagerly_finalized_field_ = diagnostic_.getCustomDiagID(
225 getErrorLevel(), kFinalizerAccessesEagerlyFinalizedField);
226 diag_overridden_non_virtual_trace_ = diagnostic_.getCustomDiagID(
227 getErrorLevel(), kOverriddenNonVirtualTrace);
228 diag_missing_trace_dispatch_method_ = diagnostic_.getCustomDiagID(
229 getErrorLevel(), kMissingTraceDispatchMethod);
230 diag_missing_finalize_dispatch_method_ = diagnostic_.getCustomDiagID(
231 getErrorLevel(), kMissingFinalizeDispatchMethod);
232 diag_virtual_and_manual_dispatch_ =
233 diagnostic_.getCustomDiagID(getErrorLevel(), kVirtualAndManualDispatch);
234 diag_missing_trace_dispatch_ =
235 diagnostic_.getCustomDiagID(getErrorLevel(), kMissingTraceDispatch);
236 diag_missing_finalize_dispatch_ =
237 diagnostic_.getCustomDiagID(getErrorLevel(), kMissingFinalizeDispatch);
238 diag_derives_non_stack_allocated_ =
239 diagnostic_.getCustomDiagID(getErrorLevel(), kDerivesNonStackAllocated);
240 diag_class_overrides_new_ =
241 diagnostic_.getCustomDiagID(getErrorLevel(), kClassOverridesNew);
242 diag_class_declares_pure_virtual_trace_ = diagnostic_.getCustomDiagID(
243 getErrorLevel(), kClassDeclaresPureVirtualTrace);
244 diag_left_most_base_must_be_polymorphic_ = diagnostic_.getCustomDiagID(
245 getErrorLevel(), kLeftMostBaseMustBePolymorphic);
246 diag_base_class_must_declare_virtual_trace_ = diagnostic_.getCustomDiagID(
247 getErrorLevel(), kBaseClassMustDeclareVirtualTrace);
248
249 // Register note messages.
250 diag_base_requires_tracing_note_ = diagnostic_.getCustomDiagID(
251 DiagnosticsEngine::Note, kBaseRequiresTracingNote);
252 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID(
253 DiagnosticsEngine::Note, kFieldRequiresTracingNote);
254 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
255 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote);
256 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
257 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote);
258 diag_reference_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
259 DiagnosticsEngine::Note, kReferencePtrToGCManagedClassNote);
260 diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
261 DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote);
262 diag_member_to_gc_unmanaged_class_note_ = diagnostic_.getCustomDiagID(
263 DiagnosticsEngine::Note, kMemberToGCUnmanagedClassNote);
264 diag_stack_allocated_field_note_ = diagnostic_.getCustomDiagID(
265 DiagnosticsEngine::Note, kStackAllocatedFieldNote);
266 diag_member_in_unmanaged_class_note_ = diagnostic_.getCustomDiagID(
267 DiagnosticsEngine::Note, kMemberInUnmanagedClassNote);
268 diag_part_object_to_gc_derived_class_note_ = diagnostic_.getCustomDiagID(
269 DiagnosticsEngine::Note, kPartObjectToGCDerivedClassNote);
270 diag_part_object_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
271 DiagnosticsEngine::Note, kPartObjectContainsGCRootNote);
272 diag_field_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
273 DiagnosticsEngine::Note, kFieldContainsGCRootNote);
274 diag_finalized_field_note_ = diagnostic_.getCustomDiagID(
275 DiagnosticsEngine::Note, kFinalizedFieldNote);
276 diag_eagerly_finalized_field_note_ = diagnostic_.getCustomDiagID(
277 DiagnosticsEngine::Note, kEagerlyFinalizedFieldNote);
278 diag_user_declared_destructor_note_ = diagnostic_.getCustomDiagID(
279 DiagnosticsEngine::Note, kUserDeclaredDestructorNote);
280 diag_user_declared_finalizer_note_ = diagnostic_.getCustomDiagID(
281 DiagnosticsEngine::Note, kUserDeclaredFinalizerNote);
282 diag_base_requires_finalization_note_ = diagnostic_.getCustomDiagID(
283 DiagnosticsEngine::Note, kBaseRequiresFinalizationNote);
284 diag_field_requires_finalization_note_ = diagnostic_.getCustomDiagID(
285 DiagnosticsEngine::Note, kFieldRequiresFinalizationNote);
286 diag_overridden_non_virtual_trace_note_ = diagnostic_.getCustomDiagID(
287 DiagnosticsEngine::Note, kOverriddenNonVirtualTraceNote);
288 diag_manual_dispatch_method_note_ = diagnostic_.getCustomDiagID(
289 DiagnosticsEngine::Note, kManualDispatchMethodNote);
290 } 77 }
291 78
292 void BlinkGCPluginConsumer::HandleTranslationUnit(ASTContext& context) { 79 void BlinkGCPluginConsumer::HandleTranslationUnit(ASTContext& context) {
293 // Don't run the plugin if the compilation unit is already invalid. 80 // Don't run the plugin if the compilation unit is already invalid.
294 if (diagnostic_.hasErrorOccurred()) 81 if (reporter_.hasErrorOccurred())
295 return; 82 return;
296 83
297 ParseFunctionTemplates(context.getTranslationUnitDecl()); 84 ParseFunctionTemplates(context.getTranslationUnitDecl());
298 85
299 CollectVisitor visitor; 86 CollectVisitor visitor;
300 visitor.TraverseDecl(context.getTranslationUnitDecl()); 87 visitor.TraverseDecl(context.getTranslationUnitDecl());
301 88
302 if (options_.dump_graph) { 89 if (options_.dump_graph) {
303 std::error_code err; 90 std::error_code err;
304 // TODO: Make createDefaultOutputFile or a shorter createOutputFile work. 91 // TODO: Make createDefaultOutputFile or a shorter createOutputFile work.
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 } 173 }
387 174
388 void BlinkGCPluginConsumer::CheckClass(RecordInfo* info) { 175 void BlinkGCPluginConsumer::CheckClass(RecordInfo* info) {
389 if (!info) 176 if (!info)
390 return; 177 return;
391 178
392 // Check consistency of stack-allocated hierarchies. 179 // Check consistency of stack-allocated hierarchies.
393 if (info->IsStackAllocated()) { 180 if (info->IsStackAllocated()) {
394 for (auto& base : info->GetBases()) 181 for (auto& base : info->GetBases())
395 if (!base.second.info()->IsStackAllocated()) 182 if (!base.second.info()->IsStackAllocated())
396 ReportDerivesNonStackAllocated(info, &base.second); 183 reporter_.DerivesNonStackAllocated(info, &base.second);
397 } 184 }
398 185
399 if (CXXMethodDecl* trace = info->GetTraceMethod()) { 186 if (CXXMethodDecl* trace = info->GetTraceMethod()) {
400 if (trace->isPure()) 187 if (trace->isPure())
401 ReportClassDeclaresPureVirtualTrace(info, trace); 188 reporter_.ClassDeclaresPureVirtualTrace(info, trace);
402 } else if (info->RequiresTraceMethod()) { 189 } else if (info->RequiresTraceMethod()) {
403 ReportClassRequiresTraceMethod(info); 190 reporter_.ClassRequiresTraceMethod(info);
404 } 191 }
405 192
406 // Check polymorphic classes that are GC-derived or have a trace method. 193 // Check polymorphic classes that are GC-derived or have a trace method.
407 if (info->record()->hasDefinition() && info->record()->isPolymorphic()) { 194 if (info->record()->hasDefinition() && info->record()->isPolymorphic()) {
408 // TODO: Check classes that inherit a trace method. 195 // TODO: Check classes that inherit a trace method.
409 CXXMethodDecl* trace = info->GetTraceMethod(); 196 CXXMethodDecl* trace = info->GetTraceMethod();
410 if (trace || info->IsGCDerived()) 197 if (trace || info->IsGCDerived())
411 CheckPolymorphicClass(info, trace); 198 CheckPolymorphicClass(info, trace);
412 } 199 }
413 200
414 { 201 {
415 CheckFieldsVisitor visitor(options_); 202 CheckFieldsVisitor visitor;
416 if (visitor.ContainsInvalidFields(info)) 203 if (visitor.ContainsInvalidFields(info))
417 ReportClassContainsInvalidFields(info, visitor.invalid_fields()); 204 reporter_.ClassContainsInvalidFields(info, visitor.invalid_fields());
418 } 205 }
419 206
420 if (info->IsGCDerived()) { 207 if (info->IsGCDerived()) {
421 if (!info->IsGCMixin()) { 208 if (!info->IsGCMixin()) {
422 CheckLeftMostDerived(info); 209 CheckLeftMostDerived(info);
423 CheckDispatch(info); 210 CheckDispatch(info);
424 if (CXXMethodDecl* newop = info->DeclaresNewOperator()) 211 if (CXXMethodDecl* newop = info->DeclaresNewOperator())
425 if (!Config::IsIgnoreAnnotated(newop)) 212 if (!Config::IsIgnoreAnnotated(newop))
426 ReportClassOverridesNew(info, newop); 213 reporter_.ClassOverridesNew(info, newop);
427 } 214 }
428 215
429 { 216 {
430 CheckGCRootsVisitor visitor; 217 CheckGCRootsVisitor visitor;
431 if (visitor.ContainsGCRoots(info)) 218 if (visitor.ContainsGCRoots(info))
432 ReportClassContainsGCRoots(info, visitor.gc_roots()); 219 reporter_.ClassContainsGCRoots(info, visitor.gc_roots());
433 } 220 }
434 221
435 if (info->NeedsFinalization()) 222 if (info->NeedsFinalization())
436 CheckFinalization(info); 223 CheckFinalization(info);
437 224
438 if (options_.warn_unneeded_finalizer && info->IsGCFinalized()) 225 if (options_.warn_unneeded_finalizer && info->IsGCFinalized())
439 CheckUnneededFinalization(info); 226 CheckUnneededFinalization(info);
440 } 227 }
441 228
442 DumpClass(info); 229 DumpClass(info);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 it = left_most->bases_begin(); 293 it = left_most->bases_begin();
507 } 294 }
508 295
509 if (RecordInfo* left_most_info = cache_.Lookup(left_most)) { 296 if (RecordInfo* left_most_info = cache_.Lookup(left_most)) {
510 // Check condition (1): 297 // Check condition (1):
511 if (trace && trace->isVirtual()) { 298 if (trace && trace->isVirtual()) {
512 if (CXXMethodDecl* trace = left_most_info->GetTraceMethod()) { 299 if (CXXMethodDecl* trace = left_most_info->GetTraceMethod()) {
513 if (trace->isVirtual()) 300 if (trace->isVirtual())
514 return; 301 return;
515 } 302 }
516 ReportBaseClassMustDeclareVirtualTrace(info, left_most); 303 reporter_.BaseClassMustDeclareVirtualTrace(info, left_most);
517 return; 304 return;
518 } 305 }
519 306
520 // Check condition (2): 307 // Check condition (2):
521 if (DeclaresVirtualMethods(left_most)) 308 if (DeclaresVirtualMethods(left_most))
522 return; 309 return;
523 if (left_most_base) { 310 if (left_most_base) {
524 // Get the base next to the "safe polymorphic base" 311 // Get the base next to the "safe polymorphic base"
525 if (it != left_most->bases_end()) 312 if (it != left_most->bases_end())
526 ++it; 313 ++it;
527 if (it != left_most->bases_end()) { 314 if (it != left_most->bases_end()) {
528 if (CXXRecordDecl* next_base = it->getType()->getAsCXXRecordDecl()) { 315 if (CXXRecordDecl* next_base = it->getType()->getAsCXXRecordDecl()) {
529 if (CXXRecordDecl* next_left_most = GetLeftMostBase(next_base)) { 316 if (CXXRecordDecl* next_left_most = GetLeftMostBase(next_base)) {
530 if (DeclaresVirtualMethods(next_left_most)) 317 if (DeclaresVirtualMethods(next_left_most))
531 return; 318 return;
532 ReportLeftMostBaseMustBePolymorphic(info, next_left_most); 319 reporter_.LeftMostBaseMustBePolymorphic(info, next_left_most);
533 return; 320 return;
534 } 321 }
535 } 322 }
536 } 323 }
537 } 324 }
538 ReportLeftMostBaseMustBePolymorphic(info, left_most); 325 reporter_.LeftMostBaseMustBePolymorphic(info, left_most);
539 } 326 }
540 } 327 }
541 328
542 CXXRecordDecl* BlinkGCPluginConsumer::GetLeftMostBase( 329 CXXRecordDecl* BlinkGCPluginConsumer::GetLeftMostBase(
543 CXXRecordDecl* left_most) { 330 CXXRecordDecl* left_most) {
544 CXXRecordDecl::base_class_iterator it = left_most->bases_begin(); 331 CXXRecordDecl::base_class_iterator it = left_most->bases_begin();
545 while (it != left_most->bases_end()) { 332 while (it != left_most->bases_end()) {
546 if (it->getType()->isDependentType()) 333 if (it->getType()->isDependentType())
547 left_most = RecordInfo::GetDependentTemplatedDecl(*it->getType()); 334 left_most = RecordInfo::GetDependentTemplatedDecl(*it->getType());
548 else 335 else
(...skipping 11 matching lines...) Expand all
560 if (it->isVirtual() && !it->isPure()) 347 if (it->isVirtual() && !it->isPure())
561 return true; 348 return true;
562 return false; 349 return false;
563 } 350 }
564 351
565 void BlinkGCPluginConsumer::CheckLeftMostDerived(RecordInfo* info) { 352 void BlinkGCPluginConsumer::CheckLeftMostDerived(RecordInfo* info) {
566 CXXRecordDecl* left_most = GetLeftMostBase(info->record()); 353 CXXRecordDecl* left_most = GetLeftMostBase(info->record());
567 if (!left_most) 354 if (!left_most)
568 return; 355 return;
569 if (!Config::IsGCBase(left_most->getName())) 356 if (!Config::IsGCBase(left_most->getName()))
570 ReportClassMustLeftMostlyDeriveGC(info); 357 reporter_.ClassMustLeftMostlyDeriveGC(info);
571 } 358 }
572 359
573 void BlinkGCPluginConsumer::CheckDispatch(RecordInfo* info) { 360 void BlinkGCPluginConsumer::CheckDispatch(RecordInfo* info) {
574 bool finalized = info->IsGCFinalized(); 361 bool finalized = info->IsGCFinalized();
575 CXXMethodDecl* trace_dispatch = info->GetTraceDispatchMethod(); 362 CXXMethodDecl* trace_dispatch = info->GetTraceDispatchMethod();
576 CXXMethodDecl* finalize_dispatch = info->GetFinalizeDispatchMethod(); 363 CXXMethodDecl* finalize_dispatch = info->GetFinalizeDispatchMethod();
577 if (!trace_dispatch && !finalize_dispatch) 364 if (!trace_dispatch && !finalize_dispatch)
578 return; 365 return;
579 366
580 CXXRecordDecl* base = trace_dispatch ? trace_dispatch->getParent() 367 CXXRecordDecl* base = trace_dispatch ? trace_dispatch->getParent()
581 : finalize_dispatch->getParent(); 368 : finalize_dispatch->getParent();
582 369
583 // Check that dispatch methods are defined at the base. 370 // Check that dispatch methods are defined at the base.
584 if (base == info->record()) { 371 if (base == info->record()) {
585 if (!trace_dispatch) 372 if (!trace_dispatch)
586 ReportMissingTraceDispatchMethod(info); 373 reporter_.MissingTraceDispatchMethod(info);
587 if (finalized && !finalize_dispatch) 374 if (finalized && !finalize_dispatch)
588 ReportMissingFinalizeDispatchMethod(info); 375 reporter_.MissingFinalizeDispatchMethod(info);
589 if (!finalized && finalize_dispatch) { 376 if (!finalized && finalize_dispatch) {
590 ReportClassRequiresFinalization(info); 377 reporter_.ClassRequiresFinalization(info);
591 NoteUserDeclaredFinalizer(finalize_dispatch); 378 reporter_.NoteUserDeclaredFinalizer(finalize_dispatch);
592 } 379 }
593 } 380 }
594 381
595 // Check that classes implementing manual dispatch do not have vtables. 382 // Check that classes implementing manual dispatch do not have vtables.
596 if (info->record()->isPolymorphic()) { 383 if (info->record()->isPolymorphic()) {
597 ReportVirtualAndManualDispatch( 384 reporter_.VirtualAndManualDispatch(
598 info, trace_dispatch ? trace_dispatch : finalize_dispatch); 385 info, trace_dispatch ? trace_dispatch : finalize_dispatch);
599 } 386 }
600 387
601 // If this is a non-abstract class check that it is dispatched to. 388 // If this is a non-abstract class check that it is dispatched to.
602 // TODO: Create a global variant of this local check. We can only check if 389 // TODO: Create a global variant of this local check. We can only check if
603 // the dispatch body is known in this compilation unit. 390 // the dispatch body is known in this compilation unit.
604 if (info->IsConsideredAbstract()) 391 if (info->IsConsideredAbstract())
605 return; 392 return;
606 393
607 const FunctionDecl* defn; 394 const FunctionDecl* defn;
608 395
609 if (trace_dispatch && trace_dispatch->isDefined(defn)) { 396 if (trace_dispatch && trace_dispatch->isDefined(defn)) {
610 CheckDispatchVisitor visitor(info); 397 CheckDispatchVisitor visitor(info);
611 visitor.TraverseStmt(defn->getBody()); 398 visitor.TraverseStmt(defn->getBody());
612 if (!visitor.dispatched_to_receiver()) 399 if (!visitor.dispatched_to_receiver())
613 ReportMissingTraceDispatch(defn, info); 400 reporter_.MissingTraceDispatch(defn, info);
614 } 401 }
615 402
616 if (finalized && finalize_dispatch && finalize_dispatch->isDefined(defn)) { 403 if (finalized && finalize_dispatch && finalize_dispatch->isDefined(defn)) {
617 CheckDispatchVisitor visitor(info); 404 CheckDispatchVisitor visitor(info);
618 visitor.TraverseStmt(defn->getBody()); 405 visitor.TraverseStmt(defn->getBody());
619 if (!visitor.dispatched_to_receiver()) 406 if (!visitor.dispatched_to_receiver())
620 ReportMissingFinalizeDispatch(defn, info); 407 reporter_.MissingFinalizeDispatch(defn, info);
621 } 408 }
622 } 409 }
623 410
624 // TODO: Should we collect destructors similar to trace methods? 411 // TODO: Should we collect destructors similar to trace methods?
625 void BlinkGCPluginConsumer::CheckFinalization(RecordInfo* info) { 412 void BlinkGCPluginConsumer::CheckFinalization(RecordInfo* info) {
626 CXXDestructorDecl* dtor = info->record()->getDestructor(); 413 CXXDestructorDecl* dtor = info->record()->getDestructor();
627 414
628 // For finalized classes, check the finalization method if possible. 415 // For finalized classes, check the finalization method if possible.
629 if (info->IsGCFinalized()) { 416 if (info->IsGCFinalized()) {
630 if (dtor && dtor->hasBody()) { 417 if (dtor && dtor->hasBody()) {
631 CheckFinalizerVisitor visitor(&cache_, info->IsEagerlyFinalized()); 418 CheckFinalizerVisitor visitor(&cache_, info->IsEagerlyFinalized());
632 visitor.TraverseCXXMethodDecl(dtor); 419 visitor.TraverseCXXMethodDecl(dtor);
633 if (!visitor.finalized_fields().empty()) { 420 if (!visitor.finalized_fields().empty()) {
634 ReportFinalizerAccessesFinalizedFields( 421 reporter_.FinalizerAccessesFinalizedFields(
635 dtor, visitor.finalized_fields()); 422 dtor, visitor.finalized_fields());
636 } 423 }
637 } 424 }
638 return; 425 return;
639 } 426 }
640 427
641 // Don't require finalization of a mixin that has not yet been "mixed in". 428 // Don't require finalization of a mixin that has not yet been "mixed in".
642 if (info->IsGCMixin()) 429 if (info->IsGCMixin())
643 return; 430 return;
644 431
645 // Report the finalization error, and proceed to print possible causes for 432 // Report the finalization error, and proceed to print possible causes for
646 // the finalization requirement. 433 // the finalization requirement.
647 ReportClassRequiresFinalization(info); 434 reporter_.ClassRequiresFinalization(info);
648 435
649 if (dtor && dtor->isUserProvided()) 436 if (dtor && dtor->isUserProvided())
650 NoteUserDeclaredDestructor(dtor); 437 reporter_.NoteUserDeclaredDestructor(dtor);
651 438
652 for (auto& base : info->GetBases()) 439 for (auto& base : info->GetBases())
653 if (base.second.info()->NeedsFinalization()) 440 if (base.second.info()->NeedsFinalization())
654 NoteBaseRequiresFinalization(&base.second); 441 reporter_.NoteBaseRequiresFinalization(&base.second);
655 442
656 for (auto& field : info->GetFields()) 443 for (auto& field : info->GetFields())
657 if (field.second.edge()->NeedsFinalization()) 444 if (field.second.edge()->NeedsFinalization())
658 NoteField(&field.second, diag_field_requires_finalization_note_); 445 reporter_.NoteFieldRequiresFinalization(&field.second);
659 } 446 }
660 447
661 void BlinkGCPluginConsumer::CheckUnneededFinalization(RecordInfo* info) { 448 void BlinkGCPluginConsumer::CheckUnneededFinalization(RecordInfo* info) {
662 if (!HasNonEmptyFinalizer(info)) 449 if (!HasNonEmptyFinalizer(info))
663 ReportClassDoesNotRequireFinalization(info); 450 reporter_.ClassDoesNotRequireFinalization(info);
664 } 451 }
665 452
666 bool BlinkGCPluginConsumer::HasNonEmptyFinalizer(RecordInfo* info) { 453 bool BlinkGCPluginConsumer::HasNonEmptyFinalizer(RecordInfo* info) {
667 CXXDestructorDecl* dtor = info->record()->getDestructor(); 454 CXXDestructorDecl* dtor = info->record()->getDestructor();
668 455
669 // If the destructor is virtual (or one of the bases are by way of the 456 // If the destructor is virtual (or one of the bases are by way of the
670 // recursive call below), consider this class as having a non-empty 457 // recursive call below), consider this class as having a non-empty
671 // finalizer. Not doing so runs counter to standard C++ reflexes like 458 // finalizer. Not doing so runs counter to standard C++ reflexes like
672 // 459 //
673 // class A : public GarbageCollectedMixin { 460 // class A : public GarbageCollectedMixin {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 } 528 }
742 529
743 void BlinkGCPluginConsumer::CheckTraceMethod( 530 void BlinkGCPluginConsumer::CheckTraceMethod(
744 RecordInfo* parent, 531 RecordInfo* parent,
745 CXXMethodDecl* trace, 532 CXXMethodDecl* trace,
746 Config::TraceMethodType trace_type) { 533 Config::TraceMethodType trace_type) {
747 // A trace method must not override any non-virtual trace methods. 534 // A trace method must not override any non-virtual trace methods.
748 if (trace_type == Config::TRACE_METHOD) { 535 if (trace_type == Config::TRACE_METHOD) {
749 for (auto& base : parent->GetBases()) 536 for (auto& base : parent->GetBases())
750 if (CXXMethodDecl* other = base.second.info()->InheritsNonVirtualTrace()) 537 if (CXXMethodDecl* other = base.second.info()->InheritsNonVirtualTrace())
751 ReportOverriddenNonVirtualTrace(parent, trace, other); 538 reporter_.OverriddenNonVirtualTrace(parent, trace, other);
752 } 539 }
753 540
754 CheckTraceVisitor visitor(trace, parent, &cache_); 541 CheckTraceVisitor visitor(trace, parent, &cache_);
755 visitor.TraverseCXXMethodDecl(trace); 542 visitor.TraverseCXXMethodDecl(trace);
756 543
757 // Skip reporting if this trace method is a just delegate to 544 // Skip reporting if this trace method is a just delegate to
758 // traceImpl (or traceAfterDispatchImpl) method. We will report on 545 // traceImpl (or traceAfterDispatchImpl) method. We will report on
759 // CheckTraceMethod on traceImpl method. 546 // CheckTraceMethod on traceImpl method.
760 if (visitor.delegates_to_traceimpl()) 547 if (visitor.delegates_to_traceimpl())
761 return; 548 return;
762 549
763 for (auto& base : parent->GetBases()) 550 for (auto& base : parent->GetBases())
764 if (!base.second.IsProperlyTraced()) 551 if (!base.second.IsProperlyTraced())
765 ReportBaseRequiresTracing(parent, trace, base.first); 552 reporter_.BaseRequiresTracing(parent, trace, base.first);
766 553
767 for (auto& field : parent->GetFields()) { 554 for (auto& field : parent->GetFields()) {
768 if (!field.second.IsProperlyTraced()) { 555 if (!field.second.IsProperlyTraced()) {
769 // Discontinue once an untraced-field error is found. 556 // Discontinue once an untraced-field error is found.
770 ReportFieldsRequireTracing(parent, trace); 557 reporter_.FieldsRequireTracing(parent, trace);
771 break; 558 break;
772 } 559 }
773 } 560 }
774 } 561 }
775 562
776 void BlinkGCPluginConsumer::DumpClass(RecordInfo* info) { 563 void BlinkGCPluginConsumer::DumpClass(RecordInfo* info) {
777 if (!json_) 564 if (!json_)
778 return; 565 return;
779 566
780 json_->OpenObject(); 567 json_->OpenObject();
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 "<super>", 638 "<super>",
852 Edge::kStrong, 639 Edge::kStrong,
853 GetLocString(base.second.spec().getLocStart())); 640 GetLocString(base.second.spec().getLocStart()));
854 641
855 for (auto& field : info->GetFields()) 642 for (auto& field : info->GetFields())
856 visitor.DumpField(info, 643 visitor.DumpField(info,
857 &field.second, 644 &field.second,
858 GetLocString(field.second.field()->getLocStart())); 645 GetLocString(field.second.field()->getLocStart()));
859 } 646 }
860 647
861 DiagnosticsEngine::Level BlinkGCPluginConsumer::getErrorLevel() {
862 return diagnostic_.getWarningsAsErrors() ? DiagnosticsEngine::Error
863 : DiagnosticsEngine::Warning;
864 }
865
866 std::string BlinkGCPluginConsumer::GetLocString(SourceLocation loc) { 648 std::string BlinkGCPluginConsumer::GetLocString(SourceLocation loc) {
867 const SourceManager& source_manager = instance_.getSourceManager(); 649 const SourceManager& source_manager = instance_.getSourceManager();
868 PresumedLoc ploc = source_manager.getPresumedLoc(loc); 650 PresumedLoc ploc = source_manager.getPresumedLoc(loc);
869 if (ploc.isInvalid()) 651 if (ploc.isInvalid())
870 return ""; 652 return "";
871 std::string loc_str; 653 std::string loc_str;
872 llvm::raw_string_ostream os(loc_str); 654 llvm::raw_string_ostream os(loc_str);
873 os << ploc.getFilename() 655 os << ploc.getFilename()
874 << ":" << ploc.getLine() 656 << ":" << ploc.getLine()
875 << ":" << ploc.getColumn(); 657 << ":" << ploc.getColumn();
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
930 SourceLocation spelling_location = source_manager.getSpellingLoc(loc); 712 SourceLocation spelling_location = source_manager.getSpellingLoc(loc);
931 PresumedLoc ploc = source_manager.getPresumedLoc(spelling_location); 713 PresumedLoc ploc = source_manager.getPresumedLoc(spelling_location);
932 if (ploc.isInvalid()) { 714 if (ploc.isInvalid()) {
933 // If we're in an invalid location, we're looking at things that aren't 715 // If we're in an invalid location, we're looking at things that aren't
934 // actually stated in the source. 716 // actually stated in the source.
935 return false; 717 return false;
936 } 718 }
937 *filename = ploc.getFilename(); 719 *filename = ploc.getFilename();
938 return true; 720 return true;
939 } 721 }
940
941 DiagnosticBuilder BlinkGCPluginConsumer::ReportDiagnostic(
942 SourceLocation location,
943 unsigned diag_id) {
944 SourceManager& manager = instance_.getSourceManager();
945 FullSourceLoc full_loc(location, manager);
946 return diagnostic_.Report(full_loc, diag_id);
947 }
948
949 void BlinkGCPluginConsumer::ReportClassMustLeftMostlyDeriveGC(
950 RecordInfo* info) {
951 ReportDiagnostic(info->record()->getInnerLocStart(),
952 diag_class_must_left_mostly_derive_gc_)
953 << info->record();
954 }
955
956 void BlinkGCPluginConsumer::ReportClassRequiresTraceMethod(RecordInfo* info) {
957 ReportDiagnostic(info->record()->getInnerLocStart(),
958 diag_class_requires_trace_method_)
959 << info->record();
960
961 for (auto& base : info->GetBases())
962 if (base.second.NeedsTracing().IsNeeded())
963 NoteBaseRequiresTracing(&base.second);
964
965 for (auto& field : info->GetFields())
966 if (!field.second.IsProperlyTraced())
967 NoteFieldRequiresTracing(info, field.first);
968 }
969
970 void BlinkGCPluginConsumer::ReportBaseRequiresTracing(
971 RecordInfo* derived,
972 CXXMethodDecl* trace,
973 CXXRecordDecl* base) {
974 ReportDiagnostic(trace->getLocStart(), diag_base_requires_tracing_)
975 << base << derived->record();
976 }
977
978 void BlinkGCPluginConsumer::ReportFieldsRequireTracing(
979 RecordInfo* info,
980 CXXMethodDecl* trace) {
981 ReportDiagnostic(trace->getLocStart(), diag_fields_require_tracing_)
982 << info->record();
983 for (auto& field : info->GetFields())
984 if (!field.second.IsProperlyTraced())
985 NoteFieldRequiresTracing(info, field.first);
986 }
987
988 void BlinkGCPluginConsumer::ReportClassContainsInvalidFields(
989 RecordInfo* info,
990 const CheckFieldsVisitor::Errors& errors) {
991
992 ReportDiagnostic(info->record()->getLocStart(),
993 diag_class_contains_invalid_fields_)
994 << info->record();
995
996 for (auto& error : errors) {
997 unsigned note;
998 if (error.second == CheckFieldsVisitor::kRawPtrToGCManaged) {
999 note = diag_raw_ptr_to_gc_managed_class_note_;
1000 } else if (error.second == CheckFieldsVisitor::kRefPtrToGCManaged) {
1001 note = diag_ref_ptr_to_gc_managed_class_note_;
1002 } else if (error.second == CheckFieldsVisitor::kReferencePtrToGCManaged) {
1003 note = diag_reference_ptr_to_gc_managed_class_note_;
1004 } else if (error.second == CheckFieldsVisitor::kOwnPtrToGCManaged) {
1005 note = diag_own_ptr_to_gc_managed_class_note_;
1006 } else if (error.second == CheckFieldsVisitor::kMemberToGCUnmanaged) {
1007 note = diag_member_to_gc_unmanaged_class_note_;
1008 } else if (error.second == CheckFieldsVisitor::kMemberInUnmanaged) {
1009 note = diag_member_in_unmanaged_class_note_;
1010 } else if (error.second == CheckFieldsVisitor::kPtrFromHeapToStack) {
1011 note = diag_stack_allocated_field_note_;
1012 } else if (error.second == CheckFieldsVisitor::kGCDerivedPartObject) {
1013 note = diag_part_object_to_gc_derived_class_note_;
1014 } else {
1015 assert(false && "Unknown field error");
1016 }
1017 NoteField(error.first, note);
1018 }
1019 }
1020
1021 void BlinkGCPluginConsumer::ReportClassContainsGCRoots(
1022 RecordInfo* info,
1023 const CheckGCRootsVisitor::Errors& errors) {
1024 for (auto& error : errors) {
1025 FieldPoint* point = nullptr;
1026 for (FieldPoint* path : error) {
1027 if (!point) {
1028 point = path;
1029 ReportDiagnostic(info->record()->getLocStart(),
1030 diag_class_contains_gc_root_)
1031 << info->record() << point->field();
1032 continue;
1033 }
1034 NotePartObjectContainsGCRoot(point);
1035 point = path;
1036 }
1037 NoteFieldContainsGCRoot(point);
1038 }
1039 }
1040
1041 void BlinkGCPluginConsumer::ReportFinalizerAccessesFinalizedFields(
1042 CXXMethodDecl* dtor,
1043 const CheckFinalizerVisitor::Errors& errors) {
1044 for (auto& error : errors) {
1045 bool as_eagerly_finalized = error.as_eagerly_finalized;
1046 unsigned diag_error = as_eagerly_finalized ?
1047 diag_finalizer_eagerly_finalized_field_ :
1048 diag_finalizer_accesses_finalized_field_;
1049 unsigned diag_note = as_eagerly_finalized ?
1050 diag_eagerly_finalized_field_note_ :
1051 diag_finalized_field_note_;
1052 ReportDiagnostic(error.member->getLocStart(), diag_error)
1053 << dtor << error.field->field();
1054 NoteField(error.field, diag_note);
1055 }
1056 }
1057
1058 void BlinkGCPluginConsumer::ReportClassRequiresFinalization(RecordInfo* info) {
1059 ReportDiagnostic(info->record()->getInnerLocStart(),
1060 diag_class_requires_finalization_)
1061 << info->record();
1062 }
1063
1064 void BlinkGCPluginConsumer::ReportClassDoesNotRequireFinalization(
1065 RecordInfo* info) {
1066 ReportDiagnostic(info->record()->getInnerLocStart(),
1067 diag_class_does_not_require_finalization_)
1068 << info->record();
1069 }
1070
1071 void BlinkGCPluginConsumer::ReportOverriddenNonVirtualTrace(
1072 RecordInfo* info,
1073 CXXMethodDecl* trace,
1074 CXXMethodDecl* overridden) {
1075 ReportDiagnostic(trace->getLocStart(), diag_overridden_non_virtual_trace_)
1076 << info->record() << overridden->getParent();
1077 NoteOverriddenNonVirtualTrace(overridden);
1078 }
1079
1080 void BlinkGCPluginConsumer::ReportMissingTraceDispatchMethod(RecordInfo* info) {
1081 ReportMissingDispatchMethod(info, diag_missing_trace_dispatch_method_);
1082 }
1083
1084 void BlinkGCPluginConsumer::ReportMissingFinalizeDispatchMethod(
1085 RecordInfo* info) {
1086 ReportMissingDispatchMethod(info, diag_missing_finalize_dispatch_method_);
1087 }
1088
1089 void BlinkGCPluginConsumer::ReportMissingDispatchMethod(
1090 RecordInfo* info,
1091 unsigned error) {
1092 ReportDiagnostic(info->record()->getInnerLocStart(), error)
1093 << info->record();
1094 }
1095
1096 void BlinkGCPluginConsumer::ReportVirtualAndManualDispatch(
1097 RecordInfo* info,
1098 CXXMethodDecl* dispatch) {
1099 ReportDiagnostic(info->record()->getInnerLocStart(),
1100 diag_virtual_and_manual_dispatch_)
1101 << info->record();
1102 NoteManualDispatchMethod(dispatch);
1103 }
1104
1105 void BlinkGCPluginConsumer::ReportMissingTraceDispatch(
1106 const FunctionDecl* dispatch,
1107 RecordInfo* receiver) {
1108 ReportMissingDispatch(dispatch, receiver, diag_missing_trace_dispatch_);
1109 }
1110
1111 void BlinkGCPluginConsumer::ReportMissingFinalizeDispatch(
1112 const FunctionDecl* dispatch,
1113 RecordInfo* receiver) {
1114 ReportMissingDispatch(dispatch, receiver, diag_missing_finalize_dispatch_);
1115 }
1116
1117 void BlinkGCPluginConsumer::ReportMissingDispatch(
1118 const FunctionDecl* dispatch,
1119 RecordInfo* receiver,
1120 unsigned error) {
1121 ReportDiagnostic(dispatch->getLocStart(), error) << receiver->record();
1122 }
1123
1124 void BlinkGCPluginConsumer::ReportDerivesNonStackAllocated(
1125 RecordInfo* info,
1126 BasePoint* base) {
1127 ReportDiagnostic(base->spec().getLocStart(),
1128 diag_derives_non_stack_allocated_)
1129 << info->record() << base->info()->record();
1130 }
1131
1132 void BlinkGCPluginConsumer::ReportClassOverridesNew(
1133 RecordInfo* info,
1134 CXXMethodDecl* newop) {
1135 ReportDiagnostic(newop->getLocStart(), diag_class_overrides_new_)
1136 << info->record();
1137 }
1138
1139 void BlinkGCPluginConsumer::ReportClassDeclaresPureVirtualTrace(
1140 RecordInfo* info,
1141 CXXMethodDecl* trace) {
1142 ReportDiagnostic(trace->getLocStart(),
1143 diag_class_declares_pure_virtual_trace_)
1144 << info->record();
1145 }
1146
1147 void BlinkGCPluginConsumer::ReportLeftMostBaseMustBePolymorphic(
1148 RecordInfo* derived,
1149 CXXRecordDecl* base) {
1150 ReportDiagnostic(base->getLocStart(),
1151 diag_left_most_base_must_be_polymorphic_)
1152 << base << derived->record();
1153 }
1154
1155 void BlinkGCPluginConsumer::ReportBaseClassMustDeclareVirtualTrace(
1156 RecordInfo* derived,
1157 CXXRecordDecl* base) {
1158 ReportDiagnostic(base->getLocStart(),
1159 diag_base_class_must_declare_virtual_trace_)
1160 << base << derived->record();
1161 }
1162
1163 void BlinkGCPluginConsumer::NoteManualDispatchMethod(CXXMethodDecl* dispatch) {
1164 ReportDiagnostic(dispatch->getLocStart(),
1165 diag_manual_dispatch_method_note_)
1166 << dispatch;
1167 }
1168
1169 void BlinkGCPluginConsumer::NoteBaseRequiresTracing(BasePoint* base) {
1170 ReportDiagnostic(base->spec().getLocStart(),
1171 diag_base_requires_tracing_note_)
1172 << base->info()->record();
1173 }
1174
1175 void BlinkGCPluginConsumer::NoteFieldRequiresTracing(
1176 RecordInfo* holder,
1177 FieldDecl* field) {
1178 NoteField(field, diag_field_requires_tracing_note_);
1179 }
1180
1181 void BlinkGCPluginConsumer::NotePartObjectContainsGCRoot(FieldPoint* point) {
1182 FieldDecl* field = point->field();
1183 ReportDiagnostic(field->getLocStart(),
1184 diag_part_object_contains_gc_root_note_)
1185 << field << field->getParent();
1186 }
1187
1188 void BlinkGCPluginConsumer::NoteFieldContainsGCRoot(FieldPoint* point) {
1189 NoteField(point, diag_field_contains_gc_root_note_);
1190 }
1191
1192 void BlinkGCPluginConsumer::NoteUserDeclaredDestructor(CXXMethodDecl* dtor) {
1193 ReportDiagnostic(dtor->getLocStart(), diag_user_declared_destructor_note_);
1194 }
1195
1196 void BlinkGCPluginConsumer::NoteUserDeclaredFinalizer(CXXMethodDecl* dtor) {
1197 ReportDiagnostic(dtor->getLocStart(), diag_user_declared_finalizer_note_);
1198 }
1199
1200 void BlinkGCPluginConsumer::NoteBaseRequiresFinalization(BasePoint* base) {
1201 ReportDiagnostic(base->spec().getLocStart(),
1202 diag_base_requires_finalization_note_)
1203 << base->info()->record();
1204 }
1205
1206 void BlinkGCPluginConsumer::NoteField(FieldPoint* point, unsigned note) {
1207 NoteField(point->field(), note);
1208 }
1209
1210 void BlinkGCPluginConsumer::NoteField(FieldDecl* field, unsigned note) {
1211 ReportDiagnostic(field->getLocStart(), note) << field;
1212 }
1213
1214 void BlinkGCPluginConsumer::NoteOverriddenNonVirtualTrace(
1215 CXXMethodDecl* overridden) {
1216 ReportDiagnostic(overridden->getLocStart(),
1217 diag_overridden_non_virtual_trace_note_)
1218 << overridden;
1219 }
OLDNEW
« no previous file with comments | « tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.h ('k') | tools/clang/blink_gc_plugin/CMakeLists.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698