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