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