• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "DiagnosticsReporter.h"
6 
7 using namespace clang;
8 
9 namespace {
10 
11 const char kClassMustLeftMostlyDeriveGC[] =
12     "[blink-gc] Class %0 must derive its GC base in the left-most position.";
13 
14 const char kClassRequiresTraceMethod[] =
15     "[blink-gc] Class %0 requires a trace method.";
16 
17 const char kBaseRequiresTracing[] =
18     "[blink-gc] Base class %0 of derived class %1 requires tracing.";
19 
20 const char kBaseRequiresTracingNote[] =
21     "[blink-gc] Untraced base class %0 declared here:";
22 
23 const char kFieldsRequireTracing[] =
24     "[blink-gc] Class %0 has untraced fields that require tracing.";
25 
26 const char kFieldsImproperlyTraced[] =
27     "[blink-gc] Class %0 has untraced or not traceable fields.";
28 
29 const char kFieldRequiresTracingNote[] =
30     "[blink-gc] Untraced field %0 declared here:";
31 
32 const char kFieldShouldNotBeTracedNote[] =
33     "[blink-gc] Untraceable field %0 declared here:";
34 
35 const char kClassContainsInvalidFields[] =
36     "[blink-gc] Class %0 contains invalid fields.";
37 
38 const char kClassContainsGCRoot[] =
39     "[blink-gc] Class %0 contains GC root in field %1.";
40 
41 const char kClassRequiresFinalization[] =
42     "[blink-gc] Class %0 requires finalization.";
43 
44 const char kClassDoesNotRequireFinalization[] =
45     "[blink-gc] Class %0 may not require finalization.";
46 
47 const char kFinalizerAccessesFinalizedField[] =
48     "[blink-gc] Finalizer %0 accesses potentially finalized field %1.";
49 
50 const char kFinalizerAccessesEagerlyFinalizedField[] =
51     "[blink-gc] Finalizer %0 accesses eagerly finalized field %1.";
52 
53 const char kRawPtrToGCManagedClassNote[] =
54     "[blink-gc] Raw pointer field %0 to a GC managed class declared here:";
55 
56 const char kRefPtrToGCManagedClassNote[] =
57     "[blink-gc] RefPtr field %0 to a GC managed class declared here:";
58 
59 const char kReferencePtrToGCManagedClassNote[] =
60     "[blink-gc] Reference pointer field %0 to a GC managed class"
61     " declared here:";
62 
63 const char kOwnPtrToGCManagedClassNote[] =
64     "[blink-gc] OwnPtr field %0 to a GC managed class declared here:";
65 
66 const char kUniquePtrToGCManagedClassNote[] =
67     "[blink-gc] std::unique_ptr field %0 to a GC managed class declared here:";
68 
69 const char kMemberToGCUnmanagedClassNote[] =
70     "[blink-gc] Member field %0 to non-GC managed class declared here:";
71 
72 const char kStackAllocatedFieldNote[] =
73     "[blink-gc] Stack-allocated field %0 declared here:";
74 
75 const char kMemberInUnmanagedClassNote[] =
76     "[blink-gc] Member field %0 in unmanaged class declared here:";
77 
78 const char kPartObjectToGCDerivedClassNote[] =
79     "[blink-gc] Part-object field %0 to a GC derived class declared here:";
80 
81 const char kPartObjectContainsGCRootNote[] =
82     "[blink-gc] Field %0 with embedded GC root in %1 declared here:";
83 
84 const char kFieldContainsGCRootNote[] =
85     "[blink-gc] Field %0 defining a GC root declared here:";
86 
87 const char kOverriddenNonVirtualTrace[] =
88     "[blink-gc] Class %0 overrides non-virtual trace of base class %1.";
89 
90 const char kOverriddenNonVirtualTraceNote[] =
91     "[blink-gc] Non-virtual trace method declared here:";
92 
93 const char kMissingTraceDispatchMethod[] =
94     "[blink-gc] Class %0 is missing manual trace dispatch.";
95 
96 const char kMissingFinalizeDispatchMethod[] =
97     "[blink-gc] Class %0 is missing manual finalize dispatch.";
98 
99 const char kVirtualAndManualDispatch[] =
100     "[blink-gc] Class %0 contains or inherits virtual methods"
101     " but implements manual dispatching.";
102 
103 const char kMissingTraceDispatch[] =
104     "[blink-gc] Missing dispatch to class %0 in manual trace dispatch.";
105 
106 const char kMissingFinalizeDispatch[] =
107     "[blink-gc] Missing dispatch to class %0 in manual finalize dispatch.";
108 
109 const char kFinalizedFieldNote[] =
110     "[blink-gc] Potentially finalized field %0 declared here:";
111 
112 const char kEagerlyFinalizedFieldNote[] =
113     "[blink-gc] Field %0 having eagerly finalized value, declared here:";
114 
115 const char kUserDeclaredDestructorNote[] =
116     "[blink-gc] User-declared destructor declared here:";
117 
118 const char kUserDeclaredFinalizerNote[] =
119     "[blink-gc] User-declared finalizer declared here:";
120 
121 const char kBaseRequiresFinalizationNote[] =
122     "[blink-gc] Base class %0 requiring finalization declared here:";
123 
124 const char kFieldRequiresFinalizationNote[] =
125     "[blink-gc] Field %0 requiring finalization declared here:";
126 
127 const char kManualDispatchMethodNote[] =
128     "[blink-gc] Manual dispatch %0 declared here:";
129 
130 const char kStackAllocatedDerivesGarbageCollected[] =
131     "[blink-gc] Stack-allocated class %0 derives class %1"
132     " which is garbage collected.";
133 
134 const char kClassOverridesNew[] =
135     "[blink-gc] Garbage collected class %0"
136     " is not permitted to override its new operator.";
137 
138 const char kClassDeclaresPureVirtualTrace[] =
139     "[blink-gc] Garbage collected class %0"
140     " is not permitted to declare a pure-virtual trace method.";
141 
142 const char kLeftMostBaseMustBePolymorphic[] =
143     "[blink-gc] Left-most base class %0 of derived class %1"
144     " must be polymorphic.";
145 
146 const char kBaseClassMustDeclareVirtualTrace[] =
147     "[blink-gc] Left-most base class %0 of derived class %1"
148     " must define a virtual trace method.";
149 
150 } // namespace
151 
ReportDiagnostic(SourceLocation location,unsigned diag_id)152 DiagnosticBuilder DiagnosticsReporter::ReportDiagnostic(
153     SourceLocation location,
154     unsigned diag_id) {
155   SourceManager& manager = instance_.getSourceManager();
156   FullSourceLoc full_loc(location, manager);
157   return diagnostic_.Report(full_loc, diag_id);
158 }
159 
DiagnosticsReporter(clang::CompilerInstance & instance)160 DiagnosticsReporter::DiagnosticsReporter(
161     clang::CompilerInstance& instance)
162     : instance_(instance),
163       diagnostic_(instance.getDiagnostics())
164 {
165   // Register warning/error messages.
166   diag_class_must_left_mostly_derive_gc_ = diagnostic_.getCustomDiagID(
167       getErrorLevel(), kClassMustLeftMostlyDeriveGC);
168   diag_class_requires_trace_method_ =
169       diagnostic_.getCustomDiagID(getErrorLevel(), kClassRequiresTraceMethod);
170   diag_base_requires_tracing_ =
171       diagnostic_.getCustomDiagID(getErrorLevel(), kBaseRequiresTracing);
172   diag_fields_require_tracing_ =
173       diagnostic_.getCustomDiagID(getErrorLevel(), kFieldsRequireTracing);
174   diag_fields_improperly_traced_ =
175       diagnostic_.getCustomDiagID(getErrorLevel(), kFieldsImproperlyTraced);
176   diag_class_contains_invalid_fields_ = diagnostic_.getCustomDiagID(
177       getErrorLevel(), kClassContainsInvalidFields);
178   diag_class_contains_gc_root_ =
179       diagnostic_.getCustomDiagID(getErrorLevel(), kClassContainsGCRoot);
180   diag_class_requires_finalization_ = diagnostic_.getCustomDiagID(
181       getErrorLevel(), kClassRequiresFinalization);
182   diag_class_does_not_require_finalization_ = diagnostic_.getCustomDiagID(
183       DiagnosticsEngine::Warning, kClassDoesNotRequireFinalization);
184   diag_finalizer_accesses_finalized_field_ = diagnostic_.getCustomDiagID(
185       getErrorLevel(), kFinalizerAccessesFinalizedField);
186   diag_finalizer_eagerly_finalized_field_ = diagnostic_.getCustomDiagID(
187       getErrorLevel(), kFinalizerAccessesEagerlyFinalizedField);
188   diag_overridden_non_virtual_trace_ = diagnostic_.getCustomDiagID(
189       getErrorLevel(), kOverriddenNonVirtualTrace);
190   diag_missing_trace_dispatch_method_ = diagnostic_.getCustomDiagID(
191       getErrorLevel(), kMissingTraceDispatchMethod);
192   diag_missing_finalize_dispatch_method_ = diagnostic_.getCustomDiagID(
193       getErrorLevel(), kMissingFinalizeDispatchMethod);
194   diag_virtual_and_manual_dispatch_ =
195       diagnostic_.getCustomDiagID(getErrorLevel(), kVirtualAndManualDispatch);
196   diag_missing_trace_dispatch_ =
197       diagnostic_.getCustomDiagID(getErrorLevel(), kMissingTraceDispatch);
198   diag_missing_finalize_dispatch_ =
199       diagnostic_.getCustomDiagID(getErrorLevel(), kMissingFinalizeDispatch);
200   diag_stack_allocated_derives_gc_ = diagnostic_.getCustomDiagID(
201       getErrorLevel(), kStackAllocatedDerivesGarbageCollected);
202   diag_class_overrides_new_ =
203       diagnostic_.getCustomDiagID(getErrorLevel(), kClassOverridesNew);
204   diag_class_declares_pure_virtual_trace_ = diagnostic_.getCustomDiagID(
205       getErrorLevel(), kClassDeclaresPureVirtualTrace);
206   diag_left_most_base_must_be_polymorphic_ = diagnostic_.getCustomDiagID(
207       getErrorLevel(), kLeftMostBaseMustBePolymorphic);
208   diag_base_class_must_declare_virtual_trace_ = diagnostic_.getCustomDiagID(
209       getErrorLevel(), kBaseClassMustDeclareVirtualTrace);
210 
211   // Register note messages.
212   diag_base_requires_tracing_note_ = diagnostic_.getCustomDiagID(
213       DiagnosticsEngine::Note, kBaseRequiresTracingNote);
214   diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID(
215       DiagnosticsEngine::Note, kFieldRequiresTracingNote);
216   diag_field_should_not_be_traced_note_ = diagnostic_.getCustomDiagID(
217       DiagnosticsEngine::Note, kFieldShouldNotBeTracedNote);
218   diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
219       DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote);
220   diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
221       DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote);
222   diag_reference_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
223       DiagnosticsEngine::Note, kReferencePtrToGCManagedClassNote);
224   diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
225       DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote);
226   diag_unique_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
227       DiagnosticsEngine::Note, kUniquePtrToGCManagedClassNote);
228   diag_member_to_gc_unmanaged_class_note_ = diagnostic_.getCustomDiagID(
229       DiagnosticsEngine::Note, kMemberToGCUnmanagedClassNote);
230   diag_stack_allocated_field_note_ = diagnostic_.getCustomDiagID(
231       DiagnosticsEngine::Note, kStackAllocatedFieldNote);
232   diag_member_in_unmanaged_class_note_ = diagnostic_.getCustomDiagID(
233       DiagnosticsEngine::Note, kMemberInUnmanagedClassNote);
234   diag_part_object_to_gc_derived_class_note_ = diagnostic_.getCustomDiagID(
235       DiagnosticsEngine::Note, kPartObjectToGCDerivedClassNote);
236   diag_part_object_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
237       DiagnosticsEngine::Note, kPartObjectContainsGCRootNote);
238   diag_field_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
239       DiagnosticsEngine::Note, kFieldContainsGCRootNote);
240   diag_finalized_field_note_ = diagnostic_.getCustomDiagID(
241       DiagnosticsEngine::Note, kFinalizedFieldNote);
242   diag_eagerly_finalized_field_note_ = diagnostic_.getCustomDiagID(
243       DiagnosticsEngine::Note, kEagerlyFinalizedFieldNote);
244   diag_user_declared_destructor_note_ = diagnostic_.getCustomDiagID(
245       DiagnosticsEngine::Note, kUserDeclaredDestructorNote);
246   diag_user_declared_finalizer_note_ = diagnostic_.getCustomDiagID(
247       DiagnosticsEngine::Note, kUserDeclaredFinalizerNote);
248   diag_base_requires_finalization_note_ = diagnostic_.getCustomDiagID(
249       DiagnosticsEngine::Note, kBaseRequiresFinalizationNote);
250   diag_field_requires_finalization_note_ = diagnostic_.getCustomDiagID(
251       DiagnosticsEngine::Note, kFieldRequiresFinalizationNote);
252   diag_overridden_non_virtual_trace_note_ = diagnostic_.getCustomDiagID(
253       DiagnosticsEngine::Note, kOverriddenNonVirtualTraceNote);
254   diag_manual_dispatch_method_note_ = diagnostic_.getCustomDiagID(
255       DiagnosticsEngine::Note, kManualDispatchMethodNote);
256 }
257 
hasErrorOccurred() const258 bool DiagnosticsReporter::hasErrorOccurred() const
259 {
260   return diagnostic_.hasErrorOccurred();
261 }
262 
getErrorLevel() const263 DiagnosticsEngine::Level DiagnosticsReporter::getErrorLevel() const {
264   return diagnostic_.getWarningsAsErrors() ? DiagnosticsEngine::Error
265                                            : DiagnosticsEngine::Warning;
266 }
267 
ClassMustLeftMostlyDeriveGC(RecordInfo * info)268 void DiagnosticsReporter::ClassMustLeftMostlyDeriveGC(
269     RecordInfo* info) {
270   ReportDiagnostic(info->record()->getInnerLocStart(),
271                    diag_class_must_left_mostly_derive_gc_)
272       << info->record();
273 }
274 
ClassRequiresTraceMethod(RecordInfo * info)275 void DiagnosticsReporter::ClassRequiresTraceMethod(RecordInfo* info) {
276   ReportDiagnostic(info->record()->getInnerLocStart(),
277                    diag_class_requires_trace_method_)
278       << info->record();
279 
280   for (auto& base : info->GetBases())
281     if (base.second.NeedsTracing().IsNeeded())
282       NoteBaseRequiresTracing(&base.second);
283 
284   for (auto& field : info->GetFields())
285     if (!field.second.IsProperlyTraced())
286       NoteFieldRequiresTracing(info, field.first);
287 }
288 
BaseRequiresTracing(RecordInfo * derived,CXXMethodDecl * trace,CXXRecordDecl * base)289 void DiagnosticsReporter::BaseRequiresTracing(
290     RecordInfo* derived,
291     CXXMethodDecl* trace,
292     CXXRecordDecl* base) {
293   ReportDiagnostic(trace->getLocStart(), diag_base_requires_tracing_)
294       << base << derived->record();
295 }
296 
FieldsImproperlyTraced(RecordInfo * info,CXXMethodDecl * trace)297 void DiagnosticsReporter::FieldsImproperlyTraced(
298     RecordInfo* info,
299     CXXMethodDecl* trace) {
300   // Only mention untraceable in header diagnostic if they appear.
301   unsigned diag = diag_fields_require_tracing_;
302   for (auto& field : info->GetFields()) {
303     if (field.second.IsInproperlyTraced()) {
304       diag = diag_fields_improperly_traced_;
305       break;
306     }
307   }
308   ReportDiagnostic(trace->getLocStart(), diag)
309       << info->record();
310   for (auto& field : info->GetFields()) {
311     if (!field.second.IsProperlyTraced())
312       NoteFieldRequiresTracing(info, field.first);
313     if (field.second.IsInproperlyTraced())
314       NoteFieldShouldNotBeTraced(info, field.first);
315   }
316 }
317 
ClassContainsInvalidFields(RecordInfo * info,const CheckFieldsVisitor::Errors & errors)318 void DiagnosticsReporter::ClassContainsInvalidFields(
319     RecordInfo* info,
320     const CheckFieldsVisitor::Errors& errors) {
321 
322   ReportDiagnostic(info->record()->getLocStart(),
323                    diag_class_contains_invalid_fields_)
324       << info->record();
325 
326   for (auto& error : errors) {
327     unsigned note;
328     if (error.second == CheckFieldsVisitor::kRawPtrToGCManaged) {
329       note = diag_raw_ptr_to_gc_managed_class_note_;
330     } else if (error.second == CheckFieldsVisitor::kRefPtrToGCManaged) {
331       note = diag_ref_ptr_to_gc_managed_class_note_;
332     } else if (error.second == CheckFieldsVisitor::kReferencePtrToGCManaged) {
333       note = diag_reference_ptr_to_gc_managed_class_note_;
334     } else if (error.second == CheckFieldsVisitor::kOwnPtrToGCManaged) {
335       note = diag_own_ptr_to_gc_managed_class_note_;
336     } else if (error.second == CheckFieldsVisitor::kUniquePtrToGCManaged) {
337       note = diag_unique_ptr_to_gc_managed_class_note_;
338     } else if (error.second == CheckFieldsVisitor::kMemberToGCUnmanaged) {
339       note = diag_member_to_gc_unmanaged_class_note_;
340     } else if (error.second == CheckFieldsVisitor::kMemberInUnmanaged) {
341       note = diag_member_in_unmanaged_class_note_;
342     } else if (error.second == CheckFieldsVisitor::kPtrFromHeapToStack) {
343       note = diag_stack_allocated_field_note_;
344     } else if (error.second == CheckFieldsVisitor::kGCDerivedPartObject) {
345       note = diag_part_object_to_gc_derived_class_note_;
346     } else {
347       assert(false && "Unknown field error");
348     }
349     NoteField(error.first, note);
350   }
351 }
352 
ClassContainsGCRoots(RecordInfo * info,const CheckGCRootsVisitor::Errors & errors)353 void DiagnosticsReporter::ClassContainsGCRoots(
354     RecordInfo* info,
355     const CheckGCRootsVisitor::Errors& errors) {
356   for (auto& error : errors) {
357     FieldPoint* point = nullptr;
358     for (FieldPoint* path : error) {
359       if (!point) {
360         point = path;
361         ReportDiagnostic(info->record()->getLocStart(),
362                          diag_class_contains_gc_root_)
363             << info->record() << point->field();
364         continue;
365       }
366       NotePartObjectContainsGCRoot(point);
367       point = path;
368     }
369     NoteFieldContainsGCRoot(point);
370   }
371 }
372 
FinalizerAccessesFinalizedFields(CXXMethodDecl * dtor,const CheckFinalizerVisitor::Errors & errors)373 void DiagnosticsReporter::FinalizerAccessesFinalizedFields(
374     CXXMethodDecl* dtor,
375     const CheckFinalizerVisitor::Errors& errors) {
376   for (auto& error : errors) {
377     bool as_eagerly_finalized = error.as_eagerly_finalized;
378     unsigned diag_error = as_eagerly_finalized ?
379                           diag_finalizer_eagerly_finalized_field_ :
380                           diag_finalizer_accesses_finalized_field_;
381     unsigned diag_note = as_eagerly_finalized ?
382                          diag_eagerly_finalized_field_note_ :
383                          diag_finalized_field_note_;
384     ReportDiagnostic(error.member->getLocStart(), diag_error)
385         << dtor << error.field->field();
386     NoteField(error.field, diag_note);
387   }
388 }
389 
ClassRequiresFinalization(RecordInfo * info)390 void DiagnosticsReporter::ClassRequiresFinalization(RecordInfo* info) {
391   ReportDiagnostic(info->record()->getInnerLocStart(),
392                    diag_class_requires_finalization_)
393       << info->record();
394 }
395 
ClassDoesNotRequireFinalization(RecordInfo * info)396 void DiagnosticsReporter::ClassDoesNotRequireFinalization(
397     RecordInfo* info) {
398   ReportDiagnostic(info->record()->getInnerLocStart(),
399                    diag_class_does_not_require_finalization_)
400       << info->record();
401 }
402 
OverriddenNonVirtualTrace(RecordInfo * info,CXXMethodDecl * trace,CXXMethodDecl * overridden)403 void DiagnosticsReporter::OverriddenNonVirtualTrace(
404     RecordInfo* info,
405     CXXMethodDecl* trace,
406     CXXMethodDecl* overridden) {
407   ReportDiagnostic(trace->getLocStart(), diag_overridden_non_virtual_trace_)
408       << info->record() << overridden->getParent();
409   NoteOverriddenNonVirtualTrace(overridden);
410 }
411 
MissingTraceDispatchMethod(RecordInfo * info)412 void DiagnosticsReporter::MissingTraceDispatchMethod(RecordInfo* info) {
413   ReportMissingDispatchMethod(info, diag_missing_trace_dispatch_method_);
414 }
415 
MissingFinalizeDispatchMethod(RecordInfo * info)416 void DiagnosticsReporter::MissingFinalizeDispatchMethod(
417     RecordInfo* info) {
418   ReportMissingDispatchMethod(info, diag_missing_finalize_dispatch_method_);
419 }
420 
ReportMissingDispatchMethod(RecordInfo * info,unsigned error)421 void DiagnosticsReporter::ReportMissingDispatchMethod(
422     RecordInfo* info,
423     unsigned error) {
424   ReportDiagnostic(info->record()->getInnerLocStart(), error)
425       << info->record();
426 }
427 
VirtualAndManualDispatch(RecordInfo * info,CXXMethodDecl * dispatch)428 void DiagnosticsReporter::VirtualAndManualDispatch(
429     RecordInfo* info,
430     CXXMethodDecl* dispatch) {
431   ReportDiagnostic(info->record()->getInnerLocStart(),
432                    diag_virtual_and_manual_dispatch_)
433       << info->record();
434   NoteManualDispatchMethod(dispatch);
435 }
436 
MissingTraceDispatch(const FunctionDecl * dispatch,RecordInfo * receiver)437 void DiagnosticsReporter::MissingTraceDispatch(
438     const FunctionDecl* dispatch,
439     RecordInfo* receiver) {
440   ReportMissingDispatch(dispatch, receiver, diag_missing_trace_dispatch_);
441 }
442 
MissingFinalizeDispatch(const FunctionDecl * dispatch,RecordInfo * receiver)443 void DiagnosticsReporter::MissingFinalizeDispatch(
444     const FunctionDecl* dispatch,
445     RecordInfo* receiver) {
446   ReportMissingDispatch(dispatch, receiver, diag_missing_finalize_dispatch_);
447 }
448 
ReportMissingDispatch(const FunctionDecl * dispatch,RecordInfo * receiver,unsigned error)449 void DiagnosticsReporter::ReportMissingDispatch(
450     const FunctionDecl* dispatch,
451     RecordInfo* receiver,
452     unsigned error) {
453   ReportDiagnostic(dispatch->getLocStart(), error) << receiver->record();
454 }
455 
StackAllocatedDerivesGarbageCollected(RecordInfo * info,BasePoint * base)456 void DiagnosticsReporter::StackAllocatedDerivesGarbageCollected(
457     RecordInfo* info,
458     BasePoint* base) {
459   ReportDiagnostic(base->spec().getLocStart(),
460                    diag_stack_allocated_derives_gc_)
461       << info->record() << base->info()->record();
462 }
463 
ClassOverridesNew(RecordInfo * info,CXXMethodDecl * newop)464 void DiagnosticsReporter::ClassOverridesNew(
465     RecordInfo* info,
466     CXXMethodDecl* newop) {
467   ReportDiagnostic(newop->getLocStart(), diag_class_overrides_new_)
468       << info->record();
469 }
470 
ClassDeclaresPureVirtualTrace(RecordInfo * info,CXXMethodDecl * trace)471 void DiagnosticsReporter::ClassDeclaresPureVirtualTrace(
472     RecordInfo* info,
473     CXXMethodDecl* trace) {
474   ReportDiagnostic(trace->getLocStart(),
475                    diag_class_declares_pure_virtual_trace_)
476       << info->record();
477 }
478 
LeftMostBaseMustBePolymorphic(RecordInfo * derived,CXXRecordDecl * base)479 void DiagnosticsReporter::LeftMostBaseMustBePolymorphic(
480     RecordInfo* derived,
481     CXXRecordDecl* base) {
482   ReportDiagnostic(base->getLocStart(),
483                    diag_left_most_base_must_be_polymorphic_)
484       << base << derived->record();
485 }
486 
BaseClassMustDeclareVirtualTrace(RecordInfo * derived,CXXRecordDecl * base)487 void DiagnosticsReporter::BaseClassMustDeclareVirtualTrace(
488     RecordInfo* derived,
489     CXXRecordDecl* base) {
490   ReportDiagnostic(base->getLocStart(),
491                    diag_base_class_must_declare_virtual_trace_)
492       << base << derived->record();
493 }
494 
NoteManualDispatchMethod(CXXMethodDecl * dispatch)495 void DiagnosticsReporter::NoteManualDispatchMethod(CXXMethodDecl* dispatch) {
496   ReportDiagnostic(dispatch->getLocStart(),
497                    diag_manual_dispatch_method_note_)
498       << dispatch;
499 }
500 
NoteBaseRequiresTracing(BasePoint * base)501 void DiagnosticsReporter::NoteBaseRequiresTracing(BasePoint* base) {
502   ReportDiagnostic(base->spec().getLocStart(),
503                    diag_base_requires_tracing_note_)
504       << base->info()->record();
505 }
506 
NoteFieldRequiresTracing(RecordInfo * holder,FieldDecl * field)507 void DiagnosticsReporter::NoteFieldRequiresTracing(
508     RecordInfo* holder,
509     FieldDecl* field) {
510   NoteField(field, diag_field_requires_tracing_note_);
511 }
512 
NoteFieldShouldNotBeTraced(RecordInfo * holder,FieldDecl * field)513 void DiagnosticsReporter::NoteFieldShouldNotBeTraced(
514     RecordInfo* holder,
515     FieldDecl* field) {
516   NoteField(field, diag_field_should_not_be_traced_note_);
517 }
518 
NotePartObjectContainsGCRoot(FieldPoint * point)519 void DiagnosticsReporter::NotePartObjectContainsGCRoot(FieldPoint* point) {
520   FieldDecl* field = point->field();
521   ReportDiagnostic(field->getLocStart(),
522                    diag_part_object_contains_gc_root_note_)
523       << field << field->getParent();
524 }
525 
NoteFieldContainsGCRoot(FieldPoint * point)526 void DiagnosticsReporter::NoteFieldContainsGCRoot(FieldPoint* point) {
527   NoteField(point, diag_field_contains_gc_root_note_);
528 }
529 
NoteUserDeclaredDestructor(CXXMethodDecl * dtor)530 void DiagnosticsReporter::NoteUserDeclaredDestructor(CXXMethodDecl* dtor) {
531   ReportDiagnostic(dtor->getLocStart(), diag_user_declared_destructor_note_);
532 }
533 
NoteUserDeclaredFinalizer(CXXMethodDecl * dtor)534 void DiagnosticsReporter::NoteUserDeclaredFinalizer(CXXMethodDecl* dtor) {
535   ReportDiagnostic(dtor->getLocStart(), diag_user_declared_finalizer_note_);
536 }
537 
NoteBaseRequiresFinalization(BasePoint * base)538 void DiagnosticsReporter::NoteBaseRequiresFinalization(BasePoint* base) {
539   ReportDiagnostic(base->spec().getLocStart(),
540                    diag_base_requires_finalization_note_)
541       << base->info()->record();
542 }
543 
NoteFieldRequiresFinalization(FieldPoint * point)544 void DiagnosticsReporter::NoteFieldRequiresFinalization(FieldPoint* point) {
545   NoteField(point, diag_field_requires_finalization_note_);
546 }
547 
NoteField(FieldPoint * point,unsigned note)548 void DiagnosticsReporter::NoteField(FieldPoint* point, unsigned note) {
549   NoteField(point->field(), note);
550 }
551 
NoteField(FieldDecl * field,unsigned note)552 void DiagnosticsReporter::NoteField(FieldDecl* field, unsigned note) {
553   ReportDiagnostic(field->getLocStart(), note) << field;
554 }
555 
NoteOverriddenNonVirtualTrace(CXXMethodDecl * overridden)556 void DiagnosticsReporter::NoteOverriddenNonVirtualTrace(
557     CXXMethodDecl* overridden) {
558   ReportDiagnostic(overridden->getLocStart(),
559                    diag_overridden_non_virtual_trace_note_)
560       << overridden;
561 }
562