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