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