| Index: tools/clang/blink_gc_plugin/DiagnosticsReporter.cpp
|
| diff --git a/tools/clang/blink_gc_plugin/DiagnosticsReporter.cpp b/tools/clang/blink_gc_plugin/DiagnosticsReporter.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..0057d80da58cbb89efa25c85720c82f5ebce6ec3
|
| --- /dev/null
|
| +++ b/tools/clang/blink_gc_plugin/DiagnosticsReporter.cpp
|
| @@ -0,0 +1,527 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "DiagnosticsReporter.h"
|
| +
|
| +using namespace clang;
|
| +
|
| +namespace {
|
| +
|
| +const char kClassMustLeftMostlyDeriveGC[] =
|
| + "[blink-gc] Class %0 must derive its GC base in the left-most position.";
|
| +
|
| +const char kClassRequiresTraceMethod[] =
|
| + "[blink-gc] Class %0 requires a trace method.";
|
| +
|
| +const char kBaseRequiresTracing[] =
|
| + "[blink-gc] Base class %0 of derived class %1 requires tracing.";
|
| +
|
| +const char kBaseRequiresTracingNote[] =
|
| + "[blink-gc] Untraced base class %0 declared here:";
|
| +
|
| +const char kFieldsRequireTracing[] =
|
| + "[blink-gc] Class %0 has untraced fields that require tracing.";
|
| +
|
| +const char kFieldRequiresTracingNote[] =
|
| + "[blink-gc] Untraced field %0 declared here:";
|
| +
|
| +const char kClassContainsInvalidFields[] =
|
| + "[blink-gc] Class %0 contains invalid fields.";
|
| +
|
| +const char kClassContainsGCRoot[] =
|
| + "[blink-gc] Class %0 contains GC root in field %1.";
|
| +
|
| +const char kClassRequiresFinalization[] =
|
| + "[blink-gc] Class %0 requires finalization.";
|
| +
|
| +const char kClassDoesNotRequireFinalization[] =
|
| + "[blink-gc] Class %0 may not require finalization.";
|
| +
|
| +const char kFinalizerAccessesFinalizedField[] =
|
| + "[blink-gc] Finalizer %0 accesses potentially finalized field %1.";
|
| +
|
| +const char kFinalizerAccessesEagerlyFinalizedField[] =
|
| + "[blink-gc] Finalizer %0 accesses eagerly finalized field %1.";
|
| +
|
| +const char kRawPtrToGCManagedClassNote[] =
|
| + "[blink-gc] Raw pointer field %0 to a GC managed class declared here:";
|
| +
|
| +const char kRefPtrToGCManagedClassNote[] =
|
| + "[blink-gc] RefPtr field %0 to a GC managed class declared here:";
|
| +
|
| +const char kReferencePtrToGCManagedClassNote[] =
|
| + "[blink-gc] Reference pointer field %0 to a GC managed class"
|
| + " declared here:";
|
| +
|
| +const char kOwnPtrToGCManagedClassNote[] =
|
| + "[blink-gc] OwnPtr field %0 to a GC managed class declared here:";
|
| +
|
| +const char kMemberToGCUnmanagedClassNote[] =
|
| + "[blink-gc] Member field %0 to non-GC managed class declared here:";
|
| +
|
| +const char kStackAllocatedFieldNote[] =
|
| + "[blink-gc] Stack-allocated field %0 declared here:";
|
| +
|
| +const char kMemberInUnmanagedClassNote[] =
|
| + "[blink-gc] Member field %0 in unmanaged class declared here:";
|
| +
|
| +const char kPartObjectToGCDerivedClassNote[] =
|
| + "[blink-gc] Part-object field %0 to a GC derived class declared here:";
|
| +
|
| +const char kPartObjectContainsGCRootNote[] =
|
| + "[blink-gc] Field %0 with embedded GC root in %1 declared here:";
|
| +
|
| +const char kFieldContainsGCRootNote[] =
|
| + "[blink-gc] Field %0 defining a GC root declared here:";
|
| +
|
| +const char kOverriddenNonVirtualTrace[] =
|
| + "[blink-gc] Class %0 overrides non-virtual trace of base class %1.";
|
| +
|
| +const char kOverriddenNonVirtualTraceNote[] =
|
| + "[blink-gc] Non-virtual trace method declared here:";
|
| +
|
| +const char kMissingTraceDispatchMethod[] =
|
| + "[blink-gc] Class %0 is missing manual trace dispatch.";
|
| +
|
| +const char kMissingFinalizeDispatchMethod[] =
|
| + "[blink-gc] Class %0 is missing manual finalize dispatch.";
|
| +
|
| +const char kVirtualAndManualDispatch[] =
|
| + "[blink-gc] Class %0 contains or inherits virtual methods"
|
| + " but implements manual dispatching.";
|
| +
|
| +const char kMissingTraceDispatch[] =
|
| + "[blink-gc] Missing dispatch to class %0 in manual trace dispatch.";
|
| +
|
| +const char kMissingFinalizeDispatch[] =
|
| + "[blink-gc] Missing dispatch to class %0 in manual finalize dispatch.";
|
| +
|
| +const char kFinalizedFieldNote[] =
|
| + "[blink-gc] Potentially finalized field %0 declared here:";
|
| +
|
| +const char kEagerlyFinalizedFieldNote[] =
|
| + "[blink-gc] Field %0 having eagerly finalized value, declared here:";
|
| +
|
| +const char kUserDeclaredDestructorNote[] =
|
| + "[blink-gc] User-declared destructor declared here:";
|
| +
|
| +const char kUserDeclaredFinalizerNote[] =
|
| + "[blink-gc] User-declared finalizer declared here:";
|
| +
|
| +const char kBaseRequiresFinalizationNote[] =
|
| + "[blink-gc] Base class %0 requiring finalization declared here:";
|
| +
|
| +const char kFieldRequiresFinalizationNote[] =
|
| + "[blink-gc] Field %0 requiring finalization declared here:";
|
| +
|
| +const char kManualDispatchMethodNote[] =
|
| + "[blink-gc] Manual dispatch %0 declared here:";
|
| +
|
| +const char kDerivesNonStackAllocated[] =
|
| + "[blink-gc] Stack-allocated class %0 derives class %1"
|
| + " which is not stack allocated.";
|
| +
|
| +const char kClassOverridesNew[] =
|
| + "[blink-gc] Garbage collected class %0"
|
| + " is not permitted to override its new operator.";
|
| +
|
| +const char kClassDeclaresPureVirtualTrace[] =
|
| + "[blink-gc] Garbage collected class %0"
|
| + " is not permitted to declare a pure-virtual trace method.";
|
| +
|
| +const char kLeftMostBaseMustBePolymorphic[] =
|
| + "[blink-gc] Left-most base class %0 of derived class %1"
|
| + " must be polymorphic.";
|
| +
|
| +const char kBaseClassMustDeclareVirtualTrace[] =
|
| + "[blink-gc] Left-most base class %0 of derived class %1"
|
| + " must define a virtual trace method.";
|
| +
|
| +} // namespace
|
| +
|
| +DiagnosticBuilder DiagnosticsReporter::ReportDiagnostic(
|
| + SourceLocation location,
|
| + unsigned diag_id) {
|
| + SourceManager& manager = instance_.getSourceManager();
|
| + FullSourceLoc full_loc(location, manager);
|
| + return diagnostic_.Report(full_loc, diag_id);
|
| +}
|
| +
|
| +DiagnosticsReporter::DiagnosticsReporter(
|
| + clang::CompilerInstance& instance)
|
| + : instance_(instance),
|
| + diagnostic_(instance.getDiagnostics())
|
| +{
|
| + // Register warning/error messages.
|
| + diag_class_must_left_mostly_derive_gc_ = diagnostic_.getCustomDiagID(
|
| + getErrorLevel(), kClassMustLeftMostlyDeriveGC);
|
| + diag_class_requires_trace_method_ =
|
| + diagnostic_.getCustomDiagID(getErrorLevel(), kClassRequiresTraceMethod);
|
| + diag_base_requires_tracing_ =
|
| + diagnostic_.getCustomDiagID(getErrorLevel(), kBaseRequiresTracing);
|
| + diag_fields_require_tracing_ =
|
| + diagnostic_.getCustomDiagID(getErrorLevel(), kFieldsRequireTracing);
|
| + diag_class_contains_invalid_fields_ = diagnostic_.getCustomDiagID(
|
| + getErrorLevel(), kClassContainsInvalidFields);
|
| + diag_class_contains_gc_root_ =
|
| + diagnostic_.getCustomDiagID(getErrorLevel(), kClassContainsGCRoot);
|
| + diag_class_requires_finalization_ = diagnostic_.getCustomDiagID(
|
| + getErrorLevel(), kClassRequiresFinalization);
|
| + diag_class_does_not_require_finalization_ = diagnostic_.getCustomDiagID(
|
| + DiagnosticsEngine::Warning, kClassDoesNotRequireFinalization);
|
| + diag_finalizer_accesses_finalized_field_ = diagnostic_.getCustomDiagID(
|
| + getErrorLevel(), kFinalizerAccessesFinalizedField);
|
| + diag_finalizer_eagerly_finalized_field_ = diagnostic_.getCustomDiagID(
|
| + getErrorLevel(), kFinalizerAccessesEagerlyFinalizedField);
|
| + diag_overridden_non_virtual_trace_ = diagnostic_.getCustomDiagID(
|
| + getErrorLevel(), kOverriddenNonVirtualTrace);
|
| + diag_missing_trace_dispatch_method_ = diagnostic_.getCustomDiagID(
|
| + getErrorLevel(), kMissingTraceDispatchMethod);
|
| + diag_missing_finalize_dispatch_method_ = diagnostic_.getCustomDiagID(
|
| + getErrorLevel(), kMissingFinalizeDispatchMethod);
|
| + diag_virtual_and_manual_dispatch_ =
|
| + diagnostic_.getCustomDiagID(getErrorLevel(), kVirtualAndManualDispatch);
|
| + diag_missing_trace_dispatch_ =
|
| + diagnostic_.getCustomDiagID(getErrorLevel(), kMissingTraceDispatch);
|
| + diag_missing_finalize_dispatch_ =
|
| + diagnostic_.getCustomDiagID(getErrorLevel(), kMissingFinalizeDispatch);
|
| + diag_derives_non_stack_allocated_ =
|
| + diagnostic_.getCustomDiagID(getErrorLevel(), kDerivesNonStackAllocated);
|
| + diag_class_overrides_new_ =
|
| + diagnostic_.getCustomDiagID(getErrorLevel(), kClassOverridesNew);
|
| + diag_class_declares_pure_virtual_trace_ = diagnostic_.getCustomDiagID(
|
| + getErrorLevel(), kClassDeclaresPureVirtualTrace);
|
| + diag_left_most_base_must_be_polymorphic_ = diagnostic_.getCustomDiagID(
|
| + getErrorLevel(), kLeftMostBaseMustBePolymorphic);
|
| + diag_base_class_must_declare_virtual_trace_ = diagnostic_.getCustomDiagID(
|
| + getErrorLevel(), kBaseClassMustDeclareVirtualTrace);
|
| +
|
| + // Register note messages.
|
| + diag_base_requires_tracing_note_ = diagnostic_.getCustomDiagID(
|
| + DiagnosticsEngine::Note, kBaseRequiresTracingNote);
|
| + diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID(
|
| + DiagnosticsEngine::Note, kFieldRequiresTracingNote);
|
| + diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
|
| + DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote);
|
| + diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
|
| + DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote);
|
| + diag_reference_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
|
| + DiagnosticsEngine::Note, kReferencePtrToGCManagedClassNote);
|
| + diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
|
| + DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote);
|
| + diag_member_to_gc_unmanaged_class_note_ = diagnostic_.getCustomDiagID(
|
| + DiagnosticsEngine::Note, kMemberToGCUnmanagedClassNote);
|
| + diag_stack_allocated_field_note_ = diagnostic_.getCustomDiagID(
|
| + DiagnosticsEngine::Note, kStackAllocatedFieldNote);
|
| + diag_member_in_unmanaged_class_note_ = diagnostic_.getCustomDiagID(
|
| + DiagnosticsEngine::Note, kMemberInUnmanagedClassNote);
|
| + diag_part_object_to_gc_derived_class_note_ = diagnostic_.getCustomDiagID(
|
| + DiagnosticsEngine::Note, kPartObjectToGCDerivedClassNote);
|
| + diag_part_object_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
|
| + DiagnosticsEngine::Note, kPartObjectContainsGCRootNote);
|
| + diag_field_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
|
| + DiagnosticsEngine::Note, kFieldContainsGCRootNote);
|
| + diag_finalized_field_note_ = diagnostic_.getCustomDiagID(
|
| + DiagnosticsEngine::Note, kFinalizedFieldNote);
|
| + diag_eagerly_finalized_field_note_ = diagnostic_.getCustomDiagID(
|
| + DiagnosticsEngine::Note, kEagerlyFinalizedFieldNote);
|
| + diag_user_declared_destructor_note_ = diagnostic_.getCustomDiagID(
|
| + DiagnosticsEngine::Note, kUserDeclaredDestructorNote);
|
| + diag_user_declared_finalizer_note_ = diagnostic_.getCustomDiagID(
|
| + DiagnosticsEngine::Note, kUserDeclaredFinalizerNote);
|
| + diag_base_requires_finalization_note_ = diagnostic_.getCustomDiagID(
|
| + DiagnosticsEngine::Note, kBaseRequiresFinalizationNote);
|
| + diag_field_requires_finalization_note_ = diagnostic_.getCustomDiagID(
|
| + DiagnosticsEngine::Note, kFieldRequiresFinalizationNote);
|
| + diag_overridden_non_virtual_trace_note_ = diagnostic_.getCustomDiagID(
|
| + DiagnosticsEngine::Note, kOverriddenNonVirtualTraceNote);
|
| + diag_manual_dispatch_method_note_ = diagnostic_.getCustomDiagID(
|
| + DiagnosticsEngine::Note, kManualDispatchMethodNote);
|
| +}
|
| +
|
| +bool DiagnosticsReporter::hasErrorOccurred() const
|
| +{
|
| + return diagnostic_.hasErrorOccurred();
|
| +}
|
| +
|
| +DiagnosticsEngine::Level DiagnosticsReporter::getErrorLevel() const {
|
| + return diagnostic_.getWarningsAsErrors() ? DiagnosticsEngine::Error
|
| + : DiagnosticsEngine::Warning;
|
| +}
|
| +
|
| +void DiagnosticsReporter::ClassMustLeftMostlyDeriveGC(
|
| + RecordInfo* info) {
|
| + ReportDiagnostic(info->record()->getInnerLocStart(),
|
| + diag_class_must_left_mostly_derive_gc_)
|
| + << info->record();
|
| +}
|
| +
|
| +void DiagnosticsReporter::ClassRequiresTraceMethod(RecordInfo* info) {
|
| + ReportDiagnostic(info->record()->getInnerLocStart(),
|
| + diag_class_requires_trace_method_)
|
| + << info->record();
|
| +
|
| + for (auto& base : info->GetBases())
|
| + if (base.second.NeedsTracing().IsNeeded())
|
| + NoteBaseRequiresTracing(&base.second);
|
| +
|
| + for (auto& field : info->GetFields())
|
| + if (!field.second.IsProperlyTraced())
|
| + NoteFieldRequiresTracing(info, field.first);
|
| +}
|
| +
|
| +void DiagnosticsReporter::BaseRequiresTracing(
|
| + RecordInfo* derived,
|
| + CXXMethodDecl* trace,
|
| + CXXRecordDecl* base) {
|
| + ReportDiagnostic(trace->getLocStart(), diag_base_requires_tracing_)
|
| + << base << derived->record();
|
| +}
|
| +
|
| +void DiagnosticsReporter::FieldsRequireTracing(
|
| + RecordInfo* info,
|
| + CXXMethodDecl* trace) {
|
| + ReportDiagnostic(trace->getLocStart(), diag_fields_require_tracing_)
|
| + << info->record();
|
| + for (auto& field : info->GetFields())
|
| + if (!field.second.IsProperlyTraced())
|
| + NoteFieldRequiresTracing(info, field.first);
|
| +}
|
| +
|
| +void DiagnosticsReporter::ClassContainsInvalidFields(
|
| + RecordInfo* info,
|
| + const CheckFieldsVisitor::Errors& errors) {
|
| +
|
| + ReportDiagnostic(info->record()->getLocStart(),
|
| + diag_class_contains_invalid_fields_)
|
| + << info->record();
|
| +
|
| + for (auto& error : errors) {
|
| + unsigned note;
|
| + if (error.second == CheckFieldsVisitor::kRawPtrToGCManaged) {
|
| + note = diag_raw_ptr_to_gc_managed_class_note_;
|
| + } else if (error.second == CheckFieldsVisitor::kRefPtrToGCManaged) {
|
| + note = diag_ref_ptr_to_gc_managed_class_note_;
|
| + } else if (error.second == CheckFieldsVisitor::kReferencePtrToGCManaged) {
|
| + note = diag_reference_ptr_to_gc_managed_class_note_;
|
| + } else if (error.second == CheckFieldsVisitor::kOwnPtrToGCManaged) {
|
| + note = diag_own_ptr_to_gc_managed_class_note_;
|
| + } else if (error.second == CheckFieldsVisitor::kMemberToGCUnmanaged) {
|
| + note = diag_member_to_gc_unmanaged_class_note_;
|
| + } else if (error.second == CheckFieldsVisitor::kMemberInUnmanaged) {
|
| + note = diag_member_in_unmanaged_class_note_;
|
| + } else if (error.second == CheckFieldsVisitor::kPtrFromHeapToStack) {
|
| + note = diag_stack_allocated_field_note_;
|
| + } else if (error.second == CheckFieldsVisitor::kGCDerivedPartObject) {
|
| + note = diag_part_object_to_gc_derived_class_note_;
|
| + } else {
|
| + assert(false && "Unknown field error");
|
| + }
|
| + NoteField(error.first, note);
|
| + }
|
| +}
|
| +
|
| +void DiagnosticsReporter::ClassContainsGCRoots(
|
| + RecordInfo* info,
|
| + const CheckGCRootsVisitor::Errors& errors) {
|
| + for (auto& error : errors) {
|
| + FieldPoint* point = nullptr;
|
| + for (FieldPoint* path : error) {
|
| + if (!point) {
|
| + point = path;
|
| + ReportDiagnostic(info->record()->getLocStart(),
|
| + diag_class_contains_gc_root_)
|
| + << info->record() << point->field();
|
| + continue;
|
| + }
|
| + NotePartObjectContainsGCRoot(point);
|
| + point = path;
|
| + }
|
| + NoteFieldContainsGCRoot(point);
|
| + }
|
| +}
|
| +
|
| +void DiagnosticsReporter::FinalizerAccessesFinalizedFields(
|
| + CXXMethodDecl* dtor,
|
| + const CheckFinalizerVisitor::Errors& errors) {
|
| + for (auto& error : errors) {
|
| + bool as_eagerly_finalized = error.as_eagerly_finalized;
|
| + unsigned diag_error = as_eagerly_finalized ?
|
| + diag_finalizer_eagerly_finalized_field_ :
|
| + diag_finalizer_accesses_finalized_field_;
|
| + unsigned diag_note = as_eagerly_finalized ?
|
| + diag_eagerly_finalized_field_note_ :
|
| + diag_finalized_field_note_;
|
| + ReportDiagnostic(error.member->getLocStart(), diag_error)
|
| + << dtor << error.field->field();
|
| + NoteField(error.field, diag_note);
|
| + }
|
| +}
|
| +
|
| +void DiagnosticsReporter::ClassRequiresFinalization(RecordInfo* info) {
|
| + ReportDiagnostic(info->record()->getInnerLocStart(),
|
| + diag_class_requires_finalization_)
|
| + << info->record();
|
| +}
|
| +
|
| +void DiagnosticsReporter::ClassDoesNotRequireFinalization(
|
| + RecordInfo* info) {
|
| + ReportDiagnostic(info->record()->getInnerLocStart(),
|
| + diag_class_does_not_require_finalization_)
|
| + << info->record();
|
| +}
|
| +
|
| +void DiagnosticsReporter::OverriddenNonVirtualTrace(
|
| + RecordInfo* info,
|
| + CXXMethodDecl* trace,
|
| + CXXMethodDecl* overridden) {
|
| + ReportDiagnostic(trace->getLocStart(), diag_overridden_non_virtual_trace_)
|
| + << info->record() << overridden->getParent();
|
| + NoteOverriddenNonVirtualTrace(overridden);
|
| +}
|
| +
|
| +void DiagnosticsReporter::MissingTraceDispatchMethod(RecordInfo* info) {
|
| + ReportMissingDispatchMethod(info, diag_missing_trace_dispatch_method_);
|
| +}
|
| +
|
| +void DiagnosticsReporter::MissingFinalizeDispatchMethod(
|
| + RecordInfo* info) {
|
| + ReportMissingDispatchMethod(info, diag_missing_finalize_dispatch_method_);
|
| +}
|
| +
|
| +void DiagnosticsReporter::ReportMissingDispatchMethod(
|
| + RecordInfo* info,
|
| + unsigned error) {
|
| + ReportDiagnostic(info->record()->getInnerLocStart(), error)
|
| + << info->record();
|
| +}
|
| +
|
| +void DiagnosticsReporter::VirtualAndManualDispatch(
|
| + RecordInfo* info,
|
| + CXXMethodDecl* dispatch) {
|
| + ReportDiagnostic(info->record()->getInnerLocStart(),
|
| + diag_virtual_and_manual_dispatch_)
|
| + << info->record();
|
| + NoteManualDispatchMethod(dispatch);
|
| +}
|
| +
|
| +void DiagnosticsReporter::MissingTraceDispatch(
|
| + const FunctionDecl* dispatch,
|
| + RecordInfo* receiver) {
|
| + ReportMissingDispatch(dispatch, receiver, diag_missing_trace_dispatch_);
|
| +}
|
| +
|
| +void DiagnosticsReporter::MissingFinalizeDispatch(
|
| + const FunctionDecl* dispatch,
|
| + RecordInfo* receiver) {
|
| + ReportMissingDispatch(dispatch, receiver, diag_missing_finalize_dispatch_);
|
| +}
|
| +
|
| +void DiagnosticsReporter::ReportMissingDispatch(
|
| + const FunctionDecl* dispatch,
|
| + RecordInfo* receiver,
|
| + unsigned error) {
|
| + ReportDiagnostic(dispatch->getLocStart(), error) << receiver->record();
|
| +}
|
| +
|
| +void DiagnosticsReporter::DerivesNonStackAllocated(
|
| + RecordInfo* info,
|
| + BasePoint* base) {
|
| + ReportDiagnostic(base->spec().getLocStart(),
|
| + diag_derives_non_stack_allocated_)
|
| + << info->record() << base->info()->record();
|
| +}
|
| +
|
| +void DiagnosticsReporter::ClassOverridesNew(
|
| + RecordInfo* info,
|
| + CXXMethodDecl* newop) {
|
| + ReportDiagnostic(newop->getLocStart(), diag_class_overrides_new_)
|
| + << info->record();
|
| +}
|
| +
|
| +void DiagnosticsReporter::ClassDeclaresPureVirtualTrace(
|
| + RecordInfo* info,
|
| + CXXMethodDecl* trace) {
|
| + ReportDiagnostic(trace->getLocStart(),
|
| + diag_class_declares_pure_virtual_trace_)
|
| + << info->record();
|
| +}
|
| +
|
| +void DiagnosticsReporter::LeftMostBaseMustBePolymorphic(
|
| + RecordInfo* derived,
|
| + CXXRecordDecl* base) {
|
| + ReportDiagnostic(base->getLocStart(),
|
| + diag_left_most_base_must_be_polymorphic_)
|
| + << base << derived->record();
|
| +}
|
| +
|
| +void DiagnosticsReporter::BaseClassMustDeclareVirtualTrace(
|
| + RecordInfo* derived,
|
| + CXXRecordDecl* base) {
|
| + ReportDiagnostic(base->getLocStart(),
|
| + diag_base_class_must_declare_virtual_trace_)
|
| + << base << derived->record();
|
| +}
|
| +
|
| +void DiagnosticsReporter::NoteManualDispatchMethod(CXXMethodDecl* dispatch) {
|
| + ReportDiagnostic(dispatch->getLocStart(),
|
| + diag_manual_dispatch_method_note_)
|
| + << dispatch;
|
| +}
|
| +
|
| +void DiagnosticsReporter::NoteBaseRequiresTracing(BasePoint* base) {
|
| + ReportDiagnostic(base->spec().getLocStart(),
|
| + diag_base_requires_tracing_note_)
|
| + << base->info()->record();
|
| +}
|
| +
|
| +void DiagnosticsReporter::NoteFieldRequiresTracing(
|
| + RecordInfo* holder,
|
| + FieldDecl* field) {
|
| + NoteField(field, diag_field_requires_tracing_note_);
|
| +}
|
| +
|
| +void DiagnosticsReporter::NotePartObjectContainsGCRoot(FieldPoint* point) {
|
| + FieldDecl* field = point->field();
|
| + ReportDiagnostic(field->getLocStart(),
|
| + diag_part_object_contains_gc_root_note_)
|
| + << field << field->getParent();
|
| +}
|
| +
|
| +void DiagnosticsReporter::NoteFieldContainsGCRoot(FieldPoint* point) {
|
| + NoteField(point, diag_field_contains_gc_root_note_);
|
| +}
|
| +
|
| +void DiagnosticsReporter::NoteUserDeclaredDestructor(CXXMethodDecl* dtor) {
|
| + ReportDiagnostic(dtor->getLocStart(), diag_user_declared_destructor_note_);
|
| +}
|
| +
|
| +void DiagnosticsReporter::NoteUserDeclaredFinalizer(CXXMethodDecl* dtor) {
|
| + ReportDiagnostic(dtor->getLocStart(), diag_user_declared_finalizer_note_);
|
| +}
|
| +
|
| +void DiagnosticsReporter::NoteBaseRequiresFinalization(BasePoint* base) {
|
| + ReportDiagnostic(base->spec().getLocStart(),
|
| + diag_base_requires_finalization_note_)
|
| + << base->info()->record();
|
| +}
|
| +
|
| +void DiagnosticsReporter::NoteFieldRequiresFinalization(FieldPoint* point) {
|
| + NoteField(point, diag_field_requires_finalization_note_);
|
| +}
|
| +
|
| +void DiagnosticsReporter::NoteField(FieldPoint* point, unsigned note) {
|
| + NoteField(point->field(), note);
|
| +}
|
| +
|
| +void DiagnosticsReporter::NoteField(FieldDecl* field, unsigned note) {
|
| + ReportDiagnostic(field->getLocStart(), note) << field;
|
| +}
|
| +
|
| +void DiagnosticsReporter::NoteOverriddenNonVirtualTrace(
|
| + CXXMethodDecl* overridden) {
|
| + ReportDiagnostic(overridden->getLocStart(),
|
| + diag_overridden_non_virtual_trace_note_)
|
| + << overridden;
|
| +}
|
|
|