• 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 const char kIteratorToGCManagedCollectionNote[] =
151     "[blink-gc] Iterator field %0 to a GC managed collection declared here:";
152 
153 } // namespace
154 
ReportDiagnostic(SourceLocation location,unsigned diag_id)155 DiagnosticBuilder DiagnosticsReporter::ReportDiagnostic(
156     SourceLocation location,
157     unsigned diag_id) {
158   SourceManager& manager = instance_.getSourceManager();
159   FullSourceLoc full_loc(location, manager);
160   return diagnostic_.Report(full_loc, diag_id);
161 }
162 
DiagnosticsReporter(clang::CompilerInstance & instance)163 DiagnosticsReporter::DiagnosticsReporter(
164     clang::CompilerInstance& instance)
165     : instance_(instance),
166       diagnostic_(instance.getDiagnostics())
167 {
168   // Register warning/error messages.
169   diag_class_must_left_mostly_derive_gc_ = diagnostic_.getCustomDiagID(
170       getErrorLevel(), kClassMustLeftMostlyDeriveGC);
171   diag_class_requires_trace_method_ =
172       diagnostic_.getCustomDiagID(getErrorLevel(), kClassRequiresTraceMethod);
173   diag_base_requires_tracing_ =
174       diagnostic_.getCustomDiagID(getErrorLevel(), kBaseRequiresTracing);
175   diag_fields_require_tracing_ =
176       diagnostic_.getCustomDiagID(getErrorLevel(), kFieldsRequireTracing);
177   diag_fields_improperly_traced_ =
178       diagnostic_.getCustomDiagID(getErrorLevel(), kFieldsImproperlyTraced);
179   diag_class_contains_invalid_fields_ = diagnostic_.getCustomDiagID(
180       getErrorLevel(), kClassContainsInvalidFields);
181   diag_class_contains_gc_root_ =
182       diagnostic_.getCustomDiagID(getErrorLevel(), kClassContainsGCRoot);
183   diag_class_requires_finalization_ = diagnostic_.getCustomDiagID(
184       getErrorLevel(), kClassRequiresFinalization);
185   diag_class_does_not_require_finalization_ = diagnostic_.getCustomDiagID(
186       DiagnosticsEngine::Warning, kClassDoesNotRequireFinalization);
187   diag_finalizer_accesses_finalized_field_ = diagnostic_.getCustomDiagID(
188       getErrorLevel(), kFinalizerAccessesFinalizedField);
189   diag_finalizer_eagerly_finalized_field_ = diagnostic_.getCustomDiagID(
190       getErrorLevel(), kFinalizerAccessesEagerlyFinalizedField);
191   diag_overridden_non_virtual_trace_ = diagnostic_.getCustomDiagID(
192       getErrorLevel(), kOverriddenNonVirtualTrace);
193   diag_missing_trace_dispatch_method_ = diagnostic_.getCustomDiagID(
194       getErrorLevel(), kMissingTraceDispatchMethod);
195   diag_missing_finalize_dispatch_method_ = diagnostic_.getCustomDiagID(
196       getErrorLevel(), kMissingFinalizeDispatchMethod);
197   diag_virtual_and_manual_dispatch_ =
198       diagnostic_.getCustomDiagID(getErrorLevel(), kVirtualAndManualDispatch);
199   diag_missing_trace_dispatch_ =
200       diagnostic_.getCustomDiagID(getErrorLevel(), kMissingTraceDispatch);
201   diag_missing_finalize_dispatch_ =
202       diagnostic_.getCustomDiagID(getErrorLevel(), kMissingFinalizeDispatch);
203   diag_stack_allocated_derives_gc_ = diagnostic_.getCustomDiagID(
204       getErrorLevel(), kStackAllocatedDerivesGarbageCollected);
205   diag_class_overrides_new_ =
206       diagnostic_.getCustomDiagID(getErrorLevel(), kClassOverridesNew);
207   diag_class_declares_pure_virtual_trace_ = diagnostic_.getCustomDiagID(
208       getErrorLevel(), kClassDeclaresPureVirtualTrace);
209   diag_left_most_base_must_be_polymorphic_ = diagnostic_.getCustomDiagID(
210       getErrorLevel(), kLeftMostBaseMustBePolymorphic);
211   diag_base_class_must_declare_virtual_trace_ = diagnostic_.getCustomDiagID(
212       getErrorLevel(), kBaseClassMustDeclareVirtualTrace);
213 
214   // Register note messages.
215   diag_base_requires_tracing_note_ = diagnostic_.getCustomDiagID(
216       DiagnosticsEngine::Note, kBaseRequiresTracingNote);
217   diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID(
218       DiagnosticsEngine::Note, kFieldRequiresTracingNote);
219   diag_field_should_not_be_traced_note_ = diagnostic_.getCustomDiagID(
220       DiagnosticsEngine::Note, kFieldShouldNotBeTracedNote);
221   diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
222       DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote);
223   diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
224       DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote);
225   diag_reference_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
226       DiagnosticsEngine::Note, kReferencePtrToGCManagedClassNote);
227   diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
228       DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote);
229   diag_unique_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
230       DiagnosticsEngine::Note, kUniquePtrToGCManagedClassNote);
231   diag_member_to_gc_unmanaged_class_note_ = diagnostic_.getCustomDiagID(
232       DiagnosticsEngine::Note, kMemberToGCUnmanagedClassNote);
233   diag_stack_allocated_field_note_ = diagnostic_.getCustomDiagID(
234       DiagnosticsEngine::Note, kStackAllocatedFieldNote);
235   diag_member_in_unmanaged_class_note_ = diagnostic_.getCustomDiagID(
236       DiagnosticsEngine::Note, kMemberInUnmanagedClassNote);
237   diag_part_object_to_gc_derived_class_note_ = diagnostic_.getCustomDiagID(
238       DiagnosticsEngine::Note, kPartObjectToGCDerivedClassNote);
239   diag_part_object_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
240       DiagnosticsEngine::Note, kPartObjectContainsGCRootNote);
241   diag_field_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
242       DiagnosticsEngine::Note, kFieldContainsGCRootNote);
243   diag_finalized_field_note_ = diagnostic_.getCustomDiagID(
244       DiagnosticsEngine::Note, kFinalizedFieldNote);
245   diag_eagerly_finalized_field_note_ = diagnostic_.getCustomDiagID(
246       DiagnosticsEngine::Note, kEagerlyFinalizedFieldNote);
247   diag_user_declared_destructor_note_ = diagnostic_.getCustomDiagID(
248       DiagnosticsEngine::Note, kUserDeclaredDestructorNote);
249   diag_user_declared_finalizer_note_ = diagnostic_.getCustomDiagID(
250       DiagnosticsEngine::Note, kUserDeclaredFinalizerNote);
251   diag_base_requires_finalization_note_ = diagnostic_.getCustomDiagID(
252       DiagnosticsEngine::Note, kBaseRequiresFinalizationNote);
253   diag_field_requires_finalization_note_ = diagnostic_.getCustomDiagID(
254       DiagnosticsEngine::Note, kFieldRequiresFinalizationNote);
255   diag_overridden_non_virtual_trace_note_ = diagnostic_.getCustomDiagID(
256       DiagnosticsEngine::Note, kOverriddenNonVirtualTraceNote);
257   diag_manual_dispatch_method_note_ = diagnostic_.getCustomDiagID(
258       DiagnosticsEngine::Note, kManualDispatchMethodNote);
259   diag_iterator_to_gc_managed_collection_note_ = diagnostic_.getCustomDiagID(
260       DiagnosticsEngine::Note, kIteratorToGCManagedCollectionNote);
261 }
262 
hasErrorOccurred() const263 bool DiagnosticsReporter::hasErrorOccurred() const
264 {
265   return diagnostic_.hasErrorOccurred();
266 }
267 
getErrorLevel() const268 DiagnosticsEngine::Level DiagnosticsReporter::getErrorLevel() const {
269   return diagnostic_.getWarningsAsErrors() ? DiagnosticsEngine::Error
270                                            : DiagnosticsEngine::Warning;
271 }
272 
ClassMustLeftMostlyDeriveGC(RecordInfo * info)273 void DiagnosticsReporter::ClassMustLeftMostlyDeriveGC(
274     RecordInfo* info) {
275   ReportDiagnostic(info->record()->getInnerLocStart(),
276                    diag_class_must_left_mostly_derive_gc_)
277       << info->record();
278 }
279 
ClassRequiresTraceMethod(RecordInfo * info)280 void DiagnosticsReporter::ClassRequiresTraceMethod(RecordInfo* info) {
281   ReportDiagnostic(info->record()->getInnerLocStart(),
282                    diag_class_requires_trace_method_)
283       << info->record();
284 
285   for (auto& base : info->GetBases())
286     if (base.second.NeedsTracing().IsNeeded())
287       NoteBaseRequiresTracing(&base.second);
288 
289   for (auto& field : info->GetFields())
290     if (!field.second.IsProperlyTraced())
291       NoteFieldRequiresTracing(info, field.first);
292 }
293 
BaseRequiresTracing(RecordInfo * derived,CXXMethodDecl * trace,CXXRecordDecl * base)294 void DiagnosticsReporter::BaseRequiresTracing(
295     RecordInfo* derived,
296     CXXMethodDecl* trace,
297     CXXRecordDecl* base) {
298   ReportDiagnostic(trace->getLocStart(), diag_base_requires_tracing_)
299       << base << derived->record();
300 }
301 
FieldsImproperlyTraced(RecordInfo * info,CXXMethodDecl * trace)302 void DiagnosticsReporter::FieldsImproperlyTraced(
303     RecordInfo* info,
304     CXXMethodDecl* trace) {
305   // Only mention untraceable in header diagnostic if they appear.
306   unsigned diag = diag_fields_require_tracing_;
307   for (auto& field : info->GetFields()) {
308     if (field.second.IsInproperlyTraced()) {
309       diag = diag_fields_improperly_traced_;
310       break;
311     }
312   }
313   ReportDiagnostic(trace->getLocStart(), diag)
314       << info->record();
315   for (auto& field : info->GetFields()) {
316     if (!field.second.IsProperlyTraced())
317       NoteFieldRequiresTracing(info, field.first);
318     if (field.second.IsInproperlyTraced())
319       NoteFieldShouldNotBeTraced(info, field.first);
320   }
321 }
322 
ClassContainsInvalidFields(RecordInfo * info,const CheckFieldsVisitor::Errors & errors)323 void DiagnosticsReporter::ClassContainsInvalidFields(
324     RecordInfo* info,
325     const CheckFieldsVisitor::Errors& errors) {
326 
327   ReportDiagnostic(info->record()->getLocStart(),
328                    diag_class_contains_invalid_fields_)
329       << info->record();
330 
331   for (auto& error : errors) {
332     unsigned note;
333     if (error.second == CheckFieldsVisitor::kRawPtrToGCManaged) {
334       note = diag_raw_ptr_to_gc_managed_class_note_;
335     } else if (error.second == CheckFieldsVisitor::kRefPtrToGCManaged) {
336       note = diag_ref_ptr_to_gc_managed_class_note_;
337     } else if (error.second == CheckFieldsVisitor::kReferencePtrToGCManaged) {
338       note = diag_reference_ptr_to_gc_managed_class_note_;
339     } else if (error.second == CheckFieldsVisitor::kOwnPtrToGCManaged) {
340       note = diag_own_ptr_to_gc_managed_class_note_;
341     } else if (error.second == CheckFieldsVisitor::kUniquePtrToGCManaged) {
342       note = diag_unique_ptr_to_gc_managed_class_note_;
343     } else if (error.second == CheckFieldsVisitor::kMemberToGCUnmanaged) {
344       note = diag_member_to_gc_unmanaged_class_note_;
345     } else if (error.second == CheckFieldsVisitor::kMemberInUnmanaged) {
346       note = diag_member_in_unmanaged_class_note_;
347     } else if (error.second == CheckFieldsVisitor::kPtrFromHeapToStack) {
348       note = diag_stack_allocated_field_note_;
349     } else if (error.second == CheckFieldsVisitor::kGCDerivedPartObject) {
350       note = diag_part_object_to_gc_derived_class_note_;
351     } else if (error.second == CheckFieldsVisitor::kIteratorToGCManaged) {
352       note = diag_iterator_to_gc_managed_collection_note_;
353     } else {
354       assert(false && "Unknown field error");
355     }
356     NoteField(error.first, note);
357   }
358 }
359 
ClassContainsGCRoots(RecordInfo * info,const CheckGCRootsVisitor::Errors & errors)360 void DiagnosticsReporter::ClassContainsGCRoots(
361     RecordInfo* info,
362     const CheckGCRootsVisitor::Errors& errors) {
363   for (auto& error : errors) {
364     FieldPoint* point = nullptr;
365     for (FieldPoint* path : error) {
366       if (!point) {
367         point = path;
368         ReportDiagnostic(info->record()->getLocStart(),
369                          diag_class_contains_gc_root_)
370             << info->record() << point->field();
371         continue;
372       }
373       NotePartObjectContainsGCRoot(point);
374       point = path;
375     }
376     NoteFieldContainsGCRoot(point);
377   }
378 }
379 
FinalizerAccessesFinalizedFields(CXXMethodDecl * dtor,const CheckFinalizerVisitor::Errors & errors)380 void DiagnosticsReporter::FinalizerAccessesFinalizedFields(
381     CXXMethodDecl* dtor,
382     const CheckFinalizerVisitor::Errors& errors) {
383   for (auto& error : errors) {
384     bool as_eagerly_finalized = error.as_eagerly_finalized;
385     unsigned diag_error = as_eagerly_finalized ?
386                           diag_finalizer_eagerly_finalized_field_ :
387                           diag_finalizer_accesses_finalized_field_;
388     unsigned diag_note = as_eagerly_finalized ?
389                          diag_eagerly_finalized_field_note_ :
390                          diag_finalized_field_note_;
391     ReportDiagnostic(error.member->getLocStart(), diag_error)
392         << dtor << error.field->field();
393     NoteField(error.field, diag_note);
394   }
395 }
396 
ClassRequiresFinalization(RecordInfo * info)397 void DiagnosticsReporter::ClassRequiresFinalization(RecordInfo* info) {
398   ReportDiagnostic(info->record()->getInnerLocStart(),
399                    diag_class_requires_finalization_)
400       << info->record();
401 }
402 
ClassDoesNotRequireFinalization(RecordInfo * info)403 void DiagnosticsReporter::ClassDoesNotRequireFinalization(
404     RecordInfo* info) {
405   ReportDiagnostic(info->record()->getInnerLocStart(),
406                    diag_class_does_not_require_finalization_)
407       << info->record();
408 }
409 
OverriddenNonVirtualTrace(RecordInfo * info,CXXMethodDecl * trace,CXXMethodDecl * overridden)410 void DiagnosticsReporter::OverriddenNonVirtualTrace(
411     RecordInfo* info,
412     CXXMethodDecl* trace,
413     CXXMethodDecl* overridden) {
414   ReportDiagnostic(trace->getLocStart(), diag_overridden_non_virtual_trace_)
415       << info->record() << overridden->getParent();
416   NoteOverriddenNonVirtualTrace(overridden);
417 }
418 
MissingTraceDispatchMethod(RecordInfo * info)419 void DiagnosticsReporter::MissingTraceDispatchMethod(RecordInfo* info) {
420   ReportMissingDispatchMethod(info, diag_missing_trace_dispatch_method_);
421 }
422 
MissingFinalizeDispatchMethod(RecordInfo * info)423 void DiagnosticsReporter::MissingFinalizeDispatchMethod(
424     RecordInfo* info) {
425   ReportMissingDispatchMethod(info, diag_missing_finalize_dispatch_method_);
426 }
427 
ReportMissingDispatchMethod(RecordInfo * info,unsigned error)428 void DiagnosticsReporter::ReportMissingDispatchMethod(
429     RecordInfo* info,
430     unsigned error) {
431   ReportDiagnostic(info->record()->getInnerLocStart(), error)
432       << info->record();
433 }
434 
VirtualAndManualDispatch(RecordInfo * info,CXXMethodDecl * dispatch)435 void DiagnosticsReporter::VirtualAndManualDispatch(
436     RecordInfo* info,
437     CXXMethodDecl* dispatch) {
438   ReportDiagnostic(info->record()->getInnerLocStart(),
439                    diag_virtual_and_manual_dispatch_)
440       << info->record();
441   NoteManualDispatchMethod(dispatch);
442 }
443 
MissingTraceDispatch(const FunctionDecl * dispatch,RecordInfo * receiver)444 void DiagnosticsReporter::MissingTraceDispatch(
445     const FunctionDecl* dispatch,
446     RecordInfo* receiver) {
447   ReportMissingDispatch(dispatch, receiver, diag_missing_trace_dispatch_);
448 }
449 
MissingFinalizeDispatch(const FunctionDecl * dispatch,RecordInfo * receiver)450 void DiagnosticsReporter::MissingFinalizeDispatch(
451     const FunctionDecl* dispatch,
452     RecordInfo* receiver) {
453   ReportMissingDispatch(dispatch, receiver, diag_missing_finalize_dispatch_);
454 }
455 
ReportMissingDispatch(const FunctionDecl * dispatch,RecordInfo * receiver,unsigned error)456 void DiagnosticsReporter::ReportMissingDispatch(
457     const FunctionDecl* dispatch,
458     RecordInfo* receiver,
459     unsigned error) {
460   ReportDiagnostic(dispatch->getLocStart(), error) << receiver->record();
461 }
462 
StackAllocatedDerivesGarbageCollected(RecordInfo * info,BasePoint * base)463 void DiagnosticsReporter::StackAllocatedDerivesGarbageCollected(
464     RecordInfo* info,
465     BasePoint* base) {
466   ReportDiagnostic(base->spec().getLocStart(),
467                    diag_stack_allocated_derives_gc_)
468       << info->record() << base->info()->record();
469 }
470 
ClassOverridesNew(RecordInfo * info,CXXMethodDecl * newop)471 void DiagnosticsReporter::ClassOverridesNew(
472     RecordInfo* info,
473     CXXMethodDecl* newop) {
474   ReportDiagnostic(newop->getLocStart(), diag_class_overrides_new_)
475       << info->record();
476 }
477 
ClassDeclaresPureVirtualTrace(RecordInfo * info,CXXMethodDecl * trace)478 void DiagnosticsReporter::ClassDeclaresPureVirtualTrace(
479     RecordInfo* info,
480     CXXMethodDecl* trace) {
481   ReportDiagnostic(trace->getLocStart(),
482                    diag_class_declares_pure_virtual_trace_)
483       << info->record();
484 }
485 
LeftMostBaseMustBePolymorphic(RecordInfo * derived,CXXRecordDecl * base)486 void DiagnosticsReporter::LeftMostBaseMustBePolymorphic(
487     RecordInfo* derived,
488     CXXRecordDecl* base) {
489   ReportDiagnostic(base->getLocStart(),
490                    diag_left_most_base_must_be_polymorphic_)
491       << base << derived->record();
492 }
493 
BaseClassMustDeclareVirtualTrace(RecordInfo * derived,CXXRecordDecl * base)494 void DiagnosticsReporter::BaseClassMustDeclareVirtualTrace(
495     RecordInfo* derived,
496     CXXRecordDecl* base) {
497   ReportDiagnostic(base->getLocStart(),
498                    diag_base_class_must_declare_virtual_trace_)
499       << base << derived->record();
500 }
501 
NoteManualDispatchMethod(CXXMethodDecl * dispatch)502 void DiagnosticsReporter::NoteManualDispatchMethod(CXXMethodDecl* dispatch) {
503   ReportDiagnostic(dispatch->getLocStart(),
504                    diag_manual_dispatch_method_note_)
505       << dispatch;
506 }
507 
NoteBaseRequiresTracing(BasePoint * base)508 void DiagnosticsReporter::NoteBaseRequiresTracing(BasePoint* base) {
509   ReportDiagnostic(base->spec().getLocStart(),
510                    diag_base_requires_tracing_note_)
511       << base->info()->record();
512 }
513 
NoteFieldRequiresTracing(RecordInfo * holder,FieldDecl * field)514 void DiagnosticsReporter::NoteFieldRequiresTracing(
515     RecordInfo* holder,
516     FieldDecl* field) {
517   NoteField(field, diag_field_requires_tracing_note_);
518 }
519 
NoteFieldShouldNotBeTraced(RecordInfo * holder,FieldDecl * field)520 void DiagnosticsReporter::NoteFieldShouldNotBeTraced(
521     RecordInfo* holder,
522     FieldDecl* field) {
523   NoteField(field, diag_field_should_not_be_traced_note_);
524 }
525 
NotePartObjectContainsGCRoot(FieldPoint * point)526 void DiagnosticsReporter::NotePartObjectContainsGCRoot(FieldPoint* point) {
527   FieldDecl* field = point->field();
528   ReportDiagnostic(field->getLocStart(),
529                    diag_part_object_contains_gc_root_note_)
530       << field << field->getParent();
531 }
532 
NoteFieldContainsGCRoot(FieldPoint * point)533 void DiagnosticsReporter::NoteFieldContainsGCRoot(FieldPoint* point) {
534   NoteField(point, diag_field_contains_gc_root_note_);
535 }
536 
NoteUserDeclaredDestructor(CXXMethodDecl * dtor)537 void DiagnosticsReporter::NoteUserDeclaredDestructor(CXXMethodDecl* dtor) {
538   ReportDiagnostic(dtor->getLocStart(), diag_user_declared_destructor_note_);
539 }
540 
NoteUserDeclaredFinalizer(CXXMethodDecl * dtor)541 void DiagnosticsReporter::NoteUserDeclaredFinalizer(CXXMethodDecl* dtor) {
542   ReportDiagnostic(dtor->getLocStart(), diag_user_declared_finalizer_note_);
543 }
544 
NoteBaseRequiresFinalization(BasePoint * base)545 void DiagnosticsReporter::NoteBaseRequiresFinalization(BasePoint* base) {
546   ReportDiagnostic(base->spec().getLocStart(),
547                    diag_base_requires_finalization_note_)
548       << base->info()->record();
549 }
550 
NoteFieldRequiresFinalization(FieldPoint * point)551 void DiagnosticsReporter::NoteFieldRequiresFinalization(FieldPoint* point) {
552   NoteField(point, diag_field_requires_finalization_note_);
553 }
554 
NoteField(FieldPoint * point,unsigned note)555 void DiagnosticsReporter::NoteField(FieldPoint* point, unsigned note) {
556   NoteField(point->field(), note);
557 }
558 
NoteField(FieldDecl * field,unsigned note)559 void DiagnosticsReporter::NoteField(FieldDecl* field, unsigned note) {
560   ReportDiagnostic(field->getLocStart(), note) << field;
561 }
562 
NoteOverriddenNonVirtualTrace(CXXMethodDecl * overridden)563 void DiagnosticsReporter::NoteOverriddenNonVirtualTrace(
564     CXXMethodDecl* overridden) {
565   ReportDiagnostic(overridden->getLocStart(),
566                    diag_overridden_non_virtual_trace_note_)
567       << overridden;
568 }
569