// Copyright 2015 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 "BlinkGCPluginConsumer.h"

#include <algorithm>
#include <set>

#include "CheckDispatchVisitor.h"
#include "CheckTraceVisitor.h"
#include "CollectVisitor.h"
#include "JsonWriter.h"
#include "RecordInfo.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Sema/Sema.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.";

const char kClassMustDeclareGCMixinTraceMethod[] =
    "[blink-gc] Class %0 which inherits from GarbageCollectedMixin must"
    " locally declare and override trace(Visitor*)";

// Use a local RAV implementation to simply collect all FunctionDecls marked for
// late template parsing. This happens with the flag -fdelayed-template-parsing,
// which is on by default in MSVC-compatible mode.
std::set<FunctionDecl*> GetLateParsedFunctionDecls(TranslationUnitDecl* decl) {
  struct Visitor : public RecursiveASTVisitor<Visitor> {
    bool VisitFunctionDecl(FunctionDecl* function_decl) {
      if (function_decl->isLateTemplateParsed())
        late_parsed_decls.insert(function_decl);
      return true;
    }

    std::set<FunctionDecl*> late_parsed_decls;
  } v;
  v.TraverseDecl(decl);
  return v.late_parsed_decls;
}

class EmptyStmtVisitor : public RecursiveASTVisitor<EmptyStmtVisitor> {
 public:
  static bool isEmpty(Stmt* stmt) {
    EmptyStmtVisitor visitor;
    visitor.TraverseStmt(stmt);
    return visitor.empty_;
  }

  bool WalkUpFromCompoundStmt(CompoundStmt* stmt) {
    empty_ = stmt->body_empty();
    return false;
  }
  bool VisitStmt(Stmt*) {
    empty_ = false;
    return false;
  }
 private:
  EmptyStmtVisitor() : empty_(true) {}
  bool empty_;
};

}  // namespace

BlinkGCPluginConsumer::BlinkGCPluginConsumer(
    clang::CompilerInstance& instance,
    const BlinkGCPluginOptions& options)
    : instance_(instance),
      diagnostic_(instance.getDiagnostics()),
      options_(options),
      json_(0) {
  // Only check structures in the blink and WebKit namespaces.
  options_.checked_namespaces.insert("blink");

  // Ignore GC implementation files.
  options_.ignored_directories.push_back("/heap/");

  // 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_invalid_fields_warning_ = diagnostic_.getCustomDiagID(
      DiagnosticsEngine::Warning, 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);
  diag_class_must_declare_gc_mixin_trace_method_ =
      diagnostic_.getCustomDiagID(getErrorLevel(),
                                  kClassMustDeclareGCMixinTraceMethod);

  // 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);
}

void BlinkGCPluginConsumer::HandleTranslationUnit(ASTContext& context) {
  // Don't run the plugin if the compilation unit is already invalid.
  if (diagnostic_.hasErrorOccurred())
    return;

  ParseFunctionTemplates(context.getTranslationUnitDecl());

  CollectVisitor visitor;
  visitor.TraverseDecl(context.getTranslationUnitDecl());

  if (options_.dump_graph) {
    std::error_code err;
    // TODO: Make createDefaultOutputFile or a shorter createOutputFile work.
    json_ = JsonWriter::from(instance_.createOutputFile(
        "",                                      // OutputPath
        err,                                     // Errors
        true,                                    // Binary
        true,                                    // RemoveFileOnSignal
        instance_.getFrontendOpts().OutputFile,  // BaseInput
        "graph.json",                            // Extension
        false,                                   // UseTemporary
        false,                                   // CreateMissingDirectories
        0,                                       // ResultPathName
        0));                                     // TempPathName
    if (!err && json_) {
      json_->OpenList();
    } else {
      json_ = 0;
      llvm::errs()
          << "[blink-gc] "
          << "Failed to create an output file for the object graph.\n";
    }
  }

  for (CollectVisitor::RecordVector::iterator it =
           visitor.record_decls().begin();
       it != visitor.record_decls().end();
       ++it) {
    CheckRecord(cache_.Lookup(*it));
  }

  for (CollectVisitor::MethodVector::iterator it =
           visitor.trace_decls().begin();
       it != visitor.trace_decls().end();
       ++it) {
    CheckTracingMethod(*it);
  }

  if (json_) {
    json_->CloseList();
    delete json_;
    json_ = 0;
  }
}

void BlinkGCPluginConsumer::ParseFunctionTemplates(TranslationUnitDecl* decl) {
  if (!instance_.getLangOpts().DelayedTemplateParsing)
    return;  // Nothing to do.

  std::set<FunctionDecl*> late_parsed_decls = GetLateParsedFunctionDecls(decl);
  clang::Sema& sema = instance_.getSema();

  for (const FunctionDecl* fd : late_parsed_decls) {
    assert(fd->isLateTemplateParsed());

    if (!Config::IsTraceMethod(fd))
      continue;

    if (instance_.getSourceManager().isInSystemHeader(
            instance_.getSourceManager().getSpellingLoc(fd->getLocation())))
      continue;

    // Force parsing and AST building of the yet-uninstantiated function
    // template trace method bodies.
    clang::LateParsedTemplate* lpt = sema.LateParsedTemplateMap[fd];
    sema.LateTemplateParser(sema.OpaqueParser, *lpt);
  }
}

void BlinkGCPluginConsumer::CheckRecord(RecordInfo* info) {
  if (IsIgnored(info))
    return;

  CXXRecordDecl* record = info->record();

  // TODO: what should we do to check unions?
  if (record->isUnion())
    return;

  // If this is the primary template declaration, check its specializations.
  if (record->isThisDeclarationADefinition() &&
      record->getDescribedClassTemplate()) {
    ClassTemplateDecl* tmpl = record->getDescribedClassTemplate();
    for (ClassTemplateDecl::spec_iterator it = tmpl->spec_begin();
         it != tmpl->spec_end();
         ++it) {
      CheckClass(cache_.Lookup(*it));
    }
    return;
  }

  CheckClass(info);
}

void BlinkGCPluginConsumer::CheckClass(RecordInfo* info) {
  if (!info)
    return;

  // Check consistency of stack-allocated hierarchies.
  if (info->IsStackAllocated()) {
    for (RecordInfo::Bases::iterator it = info->GetBases().begin();
         it != info->GetBases().end();
         ++it) {
      if (!it->second.info()->IsStackAllocated())
        ReportDerivesNonStackAllocated(info, &it->second);
    }
  }

  if (CXXMethodDecl* trace = info->GetTraceMethod()) {
    if (trace->isPure())
      ReportClassDeclaresPureVirtualTrace(info, trace);
  } else if (info->RequiresTraceMethod()) {
    ReportClassRequiresTraceMethod(info);
  }

  // Check polymorphic classes that are GC-derived or have a trace method.
  if (info->record()->hasDefinition() && info->record()->isPolymorphic()) {
    // TODO: Check classes that inherit a trace method.
    CXXMethodDecl* trace = info->GetTraceMethod();
    if (trace || info->IsGCDerived())
      CheckPolymorphicClass(info, trace);
  }

  {
    CheckFieldsVisitor visitor(options_);
    if (visitor.ContainsInvalidFields(info))
      ReportClassContainsInvalidFields(info, &visitor.invalid_fields());
  }

  if (info->IsGCDerived()) {
    if (!info->IsGCMixin()) {
      CheckLeftMostDerived(info);
      CheckDispatch(info);
      if (CXXMethodDecl* newop = info->DeclaresNewOperator())
        if (!Config::IsIgnoreAnnotated(newop))
          ReportClassOverridesNew(info, newop);
      if (info->IsGCMixinInstance()) {
        // Require that declared GCMixin implementations
        // also provide a trace() override.
        if (info->DeclaresGCMixinMethods()
            && !info->DeclaresLocalTraceMethod())
          ReportClassMustDeclareGCMixinTraceMethod(info);
      }
    }

    {
      CheckGCRootsVisitor visitor;
      if (visitor.ContainsGCRoots(info))
        ReportClassContainsGCRoots(info, &visitor.gc_roots());
    }

    if (info->NeedsFinalization())
      CheckFinalization(info);

    if (options_.warn_unneeded_finalizer && info->IsGCFinalized())
      CheckUnneededFinalization(info);
  }

  DumpClass(info);
}

CXXRecordDecl* BlinkGCPluginConsumer::GetDependentTemplatedDecl(
    const Type& type) {
  const TemplateSpecializationType* tmpl_type =
      type.getAs<TemplateSpecializationType>();
  if (!tmpl_type)
    return 0;

  TemplateDecl* tmpl_decl = tmpl_type->getTemplateName().getAsTemplateDecl();
  if (!tmpl_decl)
    return 0;

  return dyn_cast<CXXRecordDecl>(tmpl_decl->getTemplatedDecl());
}

// The GC infrastructure assumes that if the vtable of a polymorphic
// base-class is not initialized for a given object (ie, it is partially
// initialized) then the object does not need to be traced. Thus, we must
// ensure that any polymorphic class with a trace method does not have any
// tractable fields that are initialized before we are sure that the vtable
// and the trace method are both defined.  There are two cases that need to
// hold to satisfy that assumption:
//
// 1. If trace is virtual, then it must be defined in the left-most base.
// This ensures that if the vtable is initialized then it contains a pointer
// to the trace method.
//
// 2. If trace is non-virtual, then the trace method is defined and we must
// ensure that the left-most base defines a vtable. This ensures that the
// first thing to be initialized when constructing the object is the vtable
// itself.
void BlinkGCPluginConsumer::CheckPolymorphicClass(
    RecordInfo* info,
    CXXMethodDecl* trace) {
  CXXRecordDecl* left_most = info->record();
  CXXRecordDecl::base_class_iterator it = left_most->bases_begin();
  CXXRecordDecl* left_most_base = 0;
  while (it != left_most->bases_end()) {
    left_most_base = it->getType()->getAsCXXRecordDecl();
    if (!left_most_base && it->getType()->isDependentType())
      left_most_base = RecordInfo::GetDependentTemplatedDecl(*it->getType());

    // TODO: Find a way to correctly check actual instantiations
    // for dependent types. The escape below will be hit, eg, when
    // we have a primary template with no definition and
    // specializations for each case (such as SupplementBase) in
    // which case we don't succeed in checking the required
    // properties.
    if (!left_most_base || !left_most_base->hasDefinition())
      return;

    StringRef name = left_most_base->getName();
    // We know GCMixin base defines virtual trace.
    if (Config::IsGCMixinBase(name))
      return;

    // Stop with the left-most prior to a safe polymorphic base (a safe base
    // is non-polymorphic and contains no fields).
    if (Config::IsSafePolymorphicBase(name))
      break;

    left_most = left_most_base;
    it = left_most->bases_begin();
  }

  if (RecordInfo* left_most_info = cache_.Lookup(left_most)) {
    // Check condition (1):
    if (trace && trace->isVirtual()) {
      if (CXXMethodDecl* trace = left_most_info->GetTraceMethod()) {
        if (trace->isVirtual())
          return;
      }
      ReportBaseClassMustDeclareVirtualTrace(info, left_most);
      return;
    }

    // Check condition (2):
    if (DeclaresVirtualMethods(left_most))
      return;
    if (left_most_base) {
      // Get the base next to the "safe polymorphic base"
      if (it != left_most->bases_end())
        ++it;
      if (it != left_most->bases_end()) {
        if (CXXRecordDecl* next_base = it->getType()->getAsCXXRecordDecl()) {
          if (CXXRecordDecl* next_left_most = GetLeftMostBase(next_base)) {
            if (DeclaresVirtualMethods(next_left_most))
              return;
            ReportLeftMostBaseMustBePolymorphic(info, next_left_most);
            return;
          }
        }
      }
    }
    ReportLeftMostBaseMustBePolymorphic(info, left_most);
  }
}

CXXRecordDecl* BlinkGCPluginConsumer::GetLeftMostBase(
    CXXRecordDecl* left_most) {
  CXXRecordDecl::base_class_iterator it = left_most->bases_begin();
  while (it != left_most->bases_end()) {
    if (it->getType()->isDependentType())
      left_most = RecordInfo::GetDependentTemplatedDecl(*it->getType());
    else
      left_most = it->getType()->getAsCXXRecordDecl();
    if (!left_most || !left_most->hasDefinition())
      return 0;
    it = left_most->bases_begin();
  }
  return left_most;
}

bool BlinkGCPluginConsumer::DeclaresVirtualMethods(CXXRecordDecl* decl) {
  CXXRecordDecl::method_iterator it = decl->method_begin();
  for (; it != decl->method_end(); ++it)
    if (it->isVirtual() && !it->isPure())
      return true;
  return false;
}

void BlinkGCPluginConsumer::CheckLeftMostDerived(RecordInfo* info) {
  CXXRecordDecl* left_most = GetLeftMostBase(info->record());
  if (!left_most)
    return;
  if (!Config::IsGCBase(left_most->getName()))
    ReportClassMustLeftMostlyDeriveGC(info);
}

void BlinkGCPluginConsumer::CheckDispatch(RecordInfo* info) {
  bool finalized = info->IsGCFinalized();
  CXXMethodDecl* trace_dispatch = info->GetTraceDispatchMethod();
  CXXMethodDecl* finalize_dispatch = info->GetFinalizeDispatchMethod();
  if (!trace_dispatch && !finalize_dispatch)
    return;

  CXXRecordDecl* base = trace_dispatch ? trace_dispatch->getParent()
                                       : finalize_dispatch->getParent();

  // Check that dispatch methods are defined at the base.
  if (base == info->record()) {
    if (!trace_dispatch)
      ReportMissingTraceDispatchMethod(info);
    if (finalized && !finalize_dispatch)
      ReportMissingFinalizeDispatchMethod(info);
    if (!finalized && finalize_dispatch) {
      ReportClassRequiresFinalization(info);
      NoteUserDeclaredFinalizer(finalize_dispatch);
    }
  }

  // Check that classes implementing manual dispatch do not have vtables.
  if (info->record()->isPolymorphic()) {
    ReportVirtualAndManualDispatch(
        info, trace_dispatch ? trace_dispatch : finalize_dispatch);
  }

  // If this is a non-abstract class check that it is dispatched to.
  // TODO: Create a global variant of this local check. We can only check if
  // the dispatch body is known in this compilation unit.
  if (info->IsConsideredAbstract())
    return;

  const FunctionDecl* defn;

  if (trace_dispatch && trace_dispatch->isDefined(defn)) {
    CheckDispatchVisitor visitor(info);
    visitor.TraverseStmt(defn->getBody());
    if (!visitor.dispatched_to_receiver())
      ReportMissingTraceDispatch(defn, info);
  }

  if (finalized && finalize_dispatch && finalize_dispatch->isDefined(defn)) {
    CheckDispatchVisitor visitor(info);
    visitor.TraverseStmt(defn->getBody());
    if (!visitor.dispatched_to_receiver())
      ReportMissingFinalizeDispatch(defn, info);
  }
}

// TODO: Should we collect destructors similar to trace methods?
void BlinkGCPluginConsumer::CheckFinalization(RecordInfo* info) {
  CXXDestructorDecl* dtor = info->record()->getDestructor();

  // For finalized classes, check the finalization method if possible.
  if (info->IsGCFinalized()) {
    if (dtor && dtor->hasBody()) {
      CheckFinalizerVisitor visitor(&cache_, info->IsEagerlyFinalized());
      visitor.TraverseCXXMethodDecl(dtor);
      if (!visitor.finalized_fields().empty()) {
        ReportFinalizerAccessesFinalizedFields(
            dtor, &visitor.finalized_fields());
      }
    }
    return;
  }

  // Don't require finalization of a mixin that has not yet been "mixed in".
  if (info->IsGCMixin())
    return;

  // Report the finalization error, and proceed to print possible causes for
  // the finalization requirement.
  ReportClassRequiresFinalization(info);

  if (dtor && dtor->isUserProvided())
    NoteUserDeclaredDestructor(dtor);

  for (RecordInfo::Bases::iterator it = info->GetBases().begin();
       it != info->GetBases().end();
       ++it) {
    if (it->second.info()->NeedsFinalization())
      NoteBaseRequiresFinalization(&it->second);
  }

  for (RecordInfo::Fields::iterator it = info->GetFields().begin();
       it != info->GetFields().end();
       ++it) {
    if (it->second.edge()->NeedsFinalization())
      NoteField(&it->second, diag_field_requires_finalization_note_);
  }
}

void BlinkGCPluginConsumer::CheckUnneededFinalization(RecordInfo* info) {
  if (!HasNonEmptyFinalizer(info))
    ReportClassDoesNotRequireFinalization(info);
}

bool BlinkGCPluginConsumer::HasNonEmptyFinalizer(RecordInfo* info) {
  CXXDestructorDecl* dtor = info->record()->getDestructor();
  if (dtor && dtor->isUserProvided()) {
    if (!dtor->hasBody() || !EmptyStmtVisitor::isEmpty(dtor->getBody()))
      return true;
  }
  for (RecordInfo::Bases::iterator it = info->GetBases().begin();
       it != info->GetBases().end();
       ++it) {
    if (HasNonEmptyFinalizer(it->second.info()))
      return true;
  }
  for (RecordInfo::Fields::iterator it = info->GetFields().begin();
       it != info->GetFields().end();
       ++it) {
    if (it->second.edge()->NeedsFinalization())
      return true;
  }
  return false;
}

void BlinkGCPluginConsumer::CheckTracingMethod(CXXMethodDecl* method) {
  RecordInfo* parent = cache_.Lookup(method->getParent());
  if (IsIgnored(parent))
    return;

  // Check templated tracing methods by checking the template instantiations.
  // Specialized templates are handled as ordinary classes.
  if (ClassTemplateDecl* tmpl =
      parent->record()->getDescribedClassTemplate()) {
    for (ClassTemplateDecl::spec_iterator it = tmpl->spec_begin();
         it != tmpl->spec_end();
         ++it) {
      // Check trace using each template instantiation as the holder.
      if (Config::IsTemplateInstantiation(*it))
        CheckTraceOrDispatchMethod(cache_.Lookup(*it), method);
    }
    return;
  }

  CheckTraceOrDispatchMethod(parent, method);
}

void BlinkGCPluginConsumer::CheckTraceOrDispatchMethod(
    RecordInfo* parent,
    CXXMethodDecl* method) {
  Config::TraceMethodType trace_type = Config::GetTraceMethodType(method);
  if (trace_type == Config::TRACE_AFTER_DISPATCH_METHOD ||
      trace_type == Config::TRACE_AFTER_DISPATCH_IMPL_METHOD ||
      !parent->GetTraceDispatchMethod()) {
    CheckTraceMethod(parent, method, trace_type);
  }
  // Dispatch methods are checked when we identify subclasses.
}

void BlinkGCPluginConsumer::CheckTraceMethod(
    RecordInfo* parent,
    CXXMethodDecl* trace,
    Config::TraceMethodType trace_type) {
  // A trace method must not override any non-virtual trace methods.
  if (trace_type == Config::TRACE_METHOD) {
    for (RecordInfo::Bases::iterator it = parent->GetBases().begin();
         it != parent->GetBases().end();
         ++it) {
      RecordInfo* base = it->second.info();
      if (CXXMethodDecl* other = base->InheritsNonVirtualTrace())
        ReportOverriddenNonVirtualTrace(parent, trace, other);
    }
  }

  CheckTraceVisitor visitor(trace, parent, &cache_);
  visitor.TraverseCXXMethodDecl(trace);

  // Skip reporting if this trace method is a just delegate to
  // traceImpl (or traceAfterDispatchImpl) method. We will report on
  // CheckTraceMethod on traceImpl method.
  if (visitor.delegates_to_traceimpl())
    return;

  for (RecordInfo::Bases::iterator it = parent->GetBases().begin();
       it != parent->GetBases().end();
       ++it) {
    if (!it->second.IsProperlyTraced())
      ReportBaseRequiresTracing(parent, trace, it->first);
  }

  for (RecordInfo::Fields::iterator it = parent->GetFields().begin();
       it != parent->GetFields().end();
       ++it) {
    if (!it->second.IsProperlyTraced()) {
      // Discontinue once an untraced-field error is found.
      ReportFieldsRequireTracing(parent, trace);
      break;
    }
  }
}

void BlinkGCPluginConsumer::DumpClass(RecordInfo* info) {
  if (!json_)
    return;

  json_->OpenObject();
  json_->Write("name", info->record()->getQualifiedNameAsString());
  json_->Write("loc", GetLocString(info->record()->getLocStart()));
  json_->CloseObject();

  class DumpEdgeVisitor : public RecursiveEdgeVisitor {
   public:
    DumpEdgeVisitor(JsonWriter* json) : json_(json) {}
    void DumpEdge(RecordInfo* src,
                  RecordInfo* dst,
                  const std::string& lbl,
                  const Edge::LivenessKind& kind,
                  const std::string& loc) {
      json_->OpenObject();
      json_->Write("src", src->record()->getQualifiedNameAsString());
      json_->Write("dst", dst->record()->getQualifiedNameAsString());
      json_->Write("lbl", lbl);
      json_->Write("kind", kind);
      json_->Write("loc", loc);
      json_->Write("ptr",
                   !Parent() ? "val" :
                   Parent()->IsRawPtr() ?
                       (static_cast<RawPtr*>(Parent())->HasReferenceType() ?
                        "reference" : "raw") :
                   Parent()->IsRefPtr() ? "ref" :
                   Parent()->IsOwnPtr() ? "own" :
                   (Parent()->IsMember() || Parent()->IsWeakMember()) ? "mem" :
                   "val");
      json_->CloseObject();
    }

    void DumpField(RecordInfo* src, FieldPoint* point, const std::string& loc) {
      src_ = src;
      point_ = point;
      loc_ = loc;
      point_->edge()->Accept(this);
    }

    void AtValue(Value* e) override {
      // The liveness kind of a path from the point to this value
      // is given by the innermost place that is non-strong.
      Edge::LivenessKind kind = Edge::kStrong;
      if (Config::IsIgnoreCycleAnnotated(point_->field())) {
        kind = Edge::kWeak;
      } else {
        for (Context::iterator it = context().begin();
             it != context().end();
             ++it) {
          Edge::LivenessKind pointer_kind = (*it)->Kind();
          if (pointer_kind != Edge::kStrong) {
            kind = pointer_kind;
            break;
          }
        }
      }
      DumpEdge(
          src_, e->value(), point_->field()->getNameAsString(), kind, loc_);
    }

   private:
    JsonWriter* json_;
    RecordInfo* src_;
    FieldPoint* point_;
    std::string loc_;
  };

  DumpEdgeVisitor visitor(json_);

  RecordInfo::Bases& bases = info->GetBases();
  for (RecordInfo::Bases::iterator it = bases.begin();
       it != bases.end();
       ++it) {
    visitor.DumpEdge(info,
                     it->second.info(),
                     "<super>",
                     Edge::kStrong,
                     GetLocString(it->second.spec().getLocStart()));
  }

  RecordInfo::Fields& fields = info->GetFields();
  for (RecordInfo::Fields::iterator it = fields.begin();
       it != fields.end();
       ++it) {
    visitor.DumpField(info,
                      &it->second,
                      GetLocString(it->second.field()->getLocStart()));
  }
}

DiagnosticsEngine::Level BlinkGCPluginConsumer::getErrorLevel() {
  return diagnostic_.getWarningsAsErrors() ? DiagnosticsEngine::Error
                                           : DiagnosticsEngine::Warning;
}

std::string BlinkGCPluginConsumer::GetLocString(SourceLocation loc) {
  const SourceManager& source_manager = instance_.getSourceManager();
  PresumedLoc ploc = source_manager.getPresumedLoc(loc);
  if (ploc.isInvalid())
    return "";
  std::string loc_str;
  llvm::raw_string_ostream os(loc_str);
  os << ploc.getFilename()
     << ":" << ploc.getLine()
     << ":" << ploc.getColumn();
  return os.str();
}

bool BlinkGCPluginConsumer::IsIgnored(RecordInfo* record) {
  return (!record ||
          !InCheckedNamespace(record) ||
          IsIgnoredClass(record) ||
          InIgnoredDirectory(record));
}

bool BlinkGCPluginConsumer::IsIgnoredClass(RecordInfo* info) {
  // Ignore any class prefixed by SameSizeAs. These are used in
  // Blink to verify class sizes and don't need checking.
  const std::string SameSizeAs = "SameSizeAs";
  if (info->name().compare(0, SameSizeAs.size(), SameSizeAs) == 0)
    return true;
  return (options_.ignored_classes.find(info->name()) !=
          options_.ignored_classes.end());
}

bool BlinkGCPluginConsumer::InIgnoredDirectory(RecordInfo* info) {
  std::string filename;
  if (!GetFilename(info->record()->getLocStart(), &filename))
    return false;  // TODO: should we ignore non-existing file locations?
#if defined(LLVM_ON_WIN32)
  std::replace(filename.begin(), filename.end(), '\\', '/');
#endif
  std::vector<std::string>::iterator it = options_.ignored_directories.begin();
  for (; it != options_.ignored_directories.end(); ++it)
    if (filename.find(*it) != std::string::npos)
      return true;
  return false;
}

bool BlinkGCPluginConsumer::InCheckedNamespace(RecordInfo* info) {
  if (!info)
    return false;
  for (DeclContext* context = info->record()->getDeclContext();
       !context->isTranslationUnit();
       context = context->getParent()) {
    if (NamespaceDecl* decl = dyn_cast<NamespaceDecl>(context)) {
      if (decl->isAnonymousNamespace())
        return true;
      if (options_.checked_namespaces.find(decl->getNameAsString()) !=
          options_.checked_namespaces.end()) {
        return true;
      }
    }
  }
  return false;
}

bool BlinkGCPluginConsumer::GetFilename(SourceLocation loc,
                                        std::string* filename) {
  const SourceManager& source_manager = instance_.getSourceManager();
  SourceLocation spelling_location = source_manager.getSpellingLoc(loc);
  PresumedLoc ploc = source_manager.getPresumedLoc(spelling_location);
  if (ploc.isInvalid()) {
    // If we're in an invalid location, we're looking at things that aren't
    // actually stated in the source.
    return false;
  }
  *filename = ploc.getFilename();
  return true;
}

DiagnosticBuilder BlinkGCPluginConsumer::ReportDiagnostic(
    SourceLocation location,
    unsigned diag_id) {
  SourceManager& manager = instance_.getSourceManager();
  FullSourceLoc full_loc(location, manager);
  return diagnostic_.Report(full_loc, diag_id);
}

void BlinkGCPluginConsumer::ReportClassMustLeftMostlyDeriveGC(
    RecordInfo* info) {
  ReportDiagnostic(info->record()->getInnerLocStart(),
                   diag_class_must_left_mostly_derive_gc_)
      << info->record();
}

void BlinkGCPluginConsumer::ReportClassRequiresTraceMethod(RecordInfo* info) {
  ReportDiagnostic(info->record()->getInnerLocStart(),
                   diag_class_requires_trace_method_)
      << info->record();

  for (RecordInfo::Bases::iterator it = info->GetBases().begin();
       it != info->GetBases().end();
       ++it) {
    if (it->second.NeedsTracing().IsNeeded())
      NoteBaseRequiresTracing(&it->second);
  }

  for (RecordInfo::Fields::iterator it = info->GetFields().begin();
       it != info->GetFields().end();
       ++it) {
    if (!it->second.IsProperlyTraced())
      NoteFieldRequiresTracing(info, it->first);
  }
}

void BlinkGCPluginConsumer::ReportBaseRequiresTracing(
    RecordInfo* derived,
    CXXMethodDecl* trace,
    CXXRecordDecl* base) {
  ReportDiagnostic(trace->getLocStart(), diag_base_requires_tracing_)
      << base << derived->record();
}

void BlinkGCPluginConsumer::ReportFieldsRequireTracing(
    RecordInfo* info,
    CXXMethodDecl* trace) {
  ReportDiagnostic(trace->getLocStart(), diag_fields_require_tracing_)
      << info->record();
  for (RecordInfo::Fields::iterator it = info->GetFields().begin();
       it != info->GetFields().end();
       ++it) {
    if (!it->second.IsProperlyTraced())
      NoteFieldRequiresTracing(info, it->first);
  }
}

void BlinkGCPluginConsumer::ReportClassContainsInvalidFields(
    RecordInfo* info,
    CheckFieldsVisitor::Errors* errors) {
  bool only_warnings = options_.warn_raw_ptr;
  for (CheckFieldsVisitor::Errors::iterator it = errors->begin();
       only_warnings && it != errors->end();
       ++it) {
    if (!CheckFieldsVisitor::IsWarning(it->second))
      only_warnings = false;
  }
  ReportDiagnostic(info->record()->getLocStart(),
                   only_warnings ?
                   diag_class_contains_invalid_fields_warning_ :
                   diag_class_contains_invalid_fields_)
      << info->record();

  for (CheckFieldsVisitor::Errors::iterator it = errors->begin();
       it != errors->end();
       ++it) {
    unsigned error;
    if (CheckFieldsVisitor::IsRawPtrError(it->second)) {
      error = diag_raw_ptr_to_gc_managed_class_note_;
    } else if (CheckFieldsVisitor::IsReferencePtrError(it->second)) {
      error = diag_reference_ptr_to_gc_managed_class_note_;
    } else if (it->second == CheckFieldsVisitor::kRefPtrToGCManaged) {
      error = diag_ref_ptr_to_gc_managed_class_note_;
    } else if (it->second == CheckFieldsVisitor::kOwnPtrToGCManaged) {
      error = diag_own_ptr_to_gc_managed_class_note_;
    } else if (it->second == CheckFieldsVisitor::kMemberToGCUnmanaged) {
      error = diag_member_to_gc_unmanaged_class_note_;
    } else if (it->second == CheckFieldsVisitor::kMemberInUnmanaged) {
      error = diag_member_in_unmanaged_class_note_;
    } else if (it->second == CheckFieldsVisitor::kPtrFromHeapToStack) {
      error = diag_stack_allocated_field_note_;
    } else if (it->second == CheckFieldsVisitor::kGCDerivedPartObject) {
      error = diag_part_object_to_gc_derived_class_note_;
    } else {
      assert(false && "Unknown field error");
    }
    NoteField(it->first, error);
  }
}

void BlinkGCPluginConsumer::ReportClassContainsGCRoots(
    RecordInfo* info,
    CheckGCRootsVisitor::Errors* errors) {
  for (CheckGCRootsVisitor::Errors::iterator it = errors->begin();
       it != errors->end();
       ++it) {
    CheckGCRootsVisitor::RootPath::iterator path = it->begin();
    FieldPoint* point = *path;
    ReportDiagnostic(info->record()->getLocStart(),
                     diag_class_contains_gc_root_)
        << info->record() << point->field();
    while (++path != it->end()) {
      NotePartObjectContainsGCRoot(point);
      point = *path;
    }
    NoteFieldContainsGCRoot(point);
  }
}

void BlinkGCPluginConsumer::ReportFinalizerAccessesFinalizedFields(
    CXXMethodDecl* dtor,
    CheckFinalizerVisitor::Errors* fields) {
  for (CheckFinalizerVisitor::Errors::iterator it = fields->begin();
       it != fields->end();
       ++it) {
    bool as_eagerly_finalized = it->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(it->member->getLocStart(), diag_error)
        << dtor << it->field->field();
    NoteField(it->field, diag_note);
  }
}

void BlinkGCPluginConsumer::ReportClassRequiresFinalization(RecordInfo* info) {
  ReportDiagnostic(info->record()->getInnerLocStart(),
                   diag_class_requires_finalization_)
      << info->record();
}

void BlinkGCPluginConsumer::ReportClassDoesNotRequireFinalization(
    RecordInfo* info) {
  ReportDiagnostic(info->record()->getInnerLocStart(),
                   diag_class_does_not_require_finalization_)
      << info->record();
}

void BlinkGCPluginConsumer::ReportClassMustDeclareGCMixinTraceMethod(
    RecordInfo* info) {
  ReportDiagnostic(info->record()->getInnerLocStart(),
                   diag_class_must_declare_gc_mixin_trace_method_)
      << info->record();
}

void BlinkGCPluginConsumer::ReportOverriddenNonVirtualTrace(
    RecordInfo* info,
    CXXMethodDecl* trace,
    CXXMethodDecl* overridden) {
  ReportDiagnostic(trace->getLocStart(), diag_overridden_non_virtual_trace_)
      << info->record() << overridden->getParent();
  NoteOverriddenNonVirtualTrace(overridden);
}

void BlinkGCPluginConsumer::ReportMissingTraceDispatchMethod(RecordInfo* info) {
  ReportMissingDispatchMethod(info, diag_missing_trace_dispatch_method_);
}

void BlinkGCPluginConsumer::ReportMissingFinalizeDispatchMethod(
    RecordInfo* info) {
  ReportMissingDispatchMethod(info, diag_missing_finalize_dispatch_method_);
}

void BlinkGCPluginConsumer::ReportMissingDispatchMethod(
    RecordInfo* info,
    unsigned error) {
  ReportDiagnostic(info->record()->getInnerLocStart(), error)
      << info->record();
}

void BlinkGCPluginConsumer::ReportVirtualAndManualDispatch(
    RecordInfo* info,
    CXXMethodDecl* dispatch) {
  ReportDiagnostic(info->record()->getInnerLocStart(),
                   diag_virtual_and_manual_dispatch_)
      << info->record();
  NoteManualDispatchMethod(dispatch);
}

void BlinkGCPluginConsumer::ReportMissingTraceDispatch(
    const FunctionDecl* dispatch,
    RecordInfo* receiver) {
  ReportMissingDispatch(dispatch, receiver, diag_missing_trace_dispatch_);
}

void BlinkGCPluginConsumer::ReportMissingFinalizeDispatch(
    const FunctionDecl* dispatch,
    RecordInfo* receiver) {
  ReportMissingDispatch(dispatch, receiver, diag_missing_finalize_dispatch_);
}

void BlinkGCPluginConsumer::ReportMissingDispatch(
    const FunctionDecl* dispatch,
    RecordInfo* receiver,
    unsigned error) {
  ReportDiagnostic(dispatch->getLocStart(), error) << receiver->record();
}

void BlinkGCPluginConsumer::ReportDerivesNonStackAllocated(
    RecordInfo* info,
    BasePoint* base) {
  ReportDiagnostic(base->spec().getLocStart(),
                   diag_derives_non_stack_allocated_)
      << info->record() << base->info()->record();
}

void BlinkGCPluginConsumer::ReportClassOverridesNew(
    RecordInfo* info,
    CXXMethodDecl* newop) {
  ReportDiagnostic(newop->getLocStart(), diag_class_overrides_new_)
      << info->record();
}

void BlinkGCPluginConsumer::ReportClassDeclaresPureVirtualTrace(
    RecordInfo* info,
    CXXMethodDecl* trace) {
  ReportDiagnostic(trace->getLocStart(),
                   diag_class_declares_pure_virtual_trace_)
      << info->record();
}

void BlinkGCPluginConsumer::ReportLeftMostBaseMustBePolymorphic(
    RecordInfo* derived,
    CXXRecordDecl* base) {
  ReportDiagnostic(base->getLocStart(),
                   diag_left_most_base_must_be_polymorphic_)
      << base << derived->record();
}

void BlinkGCPluginConsumer::ReportBaseClassMustDeclareVirtualTrace(
    RecordInfo* derived,
    CXXRecordDecl* base) {
  ReportDiagnostic(base->getLocStart(),
                   diag_base_class_must_declare_virtual_trace_)
      << base << derived->record();
}

void BlinkGCPluginConsumer::NoteManualDispatchMethod(CXXMethodDecl* dispatch) {
  ReportDiagnostic(dispatch->getLocStart(),
                   diag_manual_dispatch_method_note_)
      << dispatch;
}

void BlinkGCPluginConsumer::NoteBaseRequiresTracing(BasePoint* base) {
  ReportDiagnostic(base->spec().getLocStart(),
                   diag_base_requires_tracing_note_)
      << base->info()->record();
}

void BlinkGCPluginConsumer::NoteFieldRequiresTracing(
    RecordInfo* holder,
    FieldDecl* field) {
  NoteField(field, diag_field_requires_tracing_note_);
}

void BlinkGCPluginConsumer::NotePartObjectContainsGCRoot(FieldPoint* point) {
  FieldDecl* field = point->field();
  ReportDiagnostic(field->getLocStart(),
                   diag_part_object_contains_gc_root_note_)
      << field << field->getParent();
}

void BlinkGCPluginConsumer::NoteFieldContainsGCRoot(FieldPoint* point) {
  NoteField(point, diag_field_contains_gc_root_note_);
}

void BlinkGCPluginConsumer::NoteUserDeclaredDestructor(CXXMethodDecl* dtor) {
  ReportDiagnostic(dtor->getLocStart(), diag_user_declared_destructor_note_);
}

void BlinkGCPluginConsumer::NoteUserDeclaredFinalizer(CXXMethodDecl* dtor) {
  ReportDiagnostic(dtor->getLocStart(), diag_user_declared_finalizer_note_);
}

void BlinkGCPluginConsumer::NoteBaseRequiresFinalization(BasePoint* base) {
  ReportDiagnostic(base->spec().getLocStart(),
                   diag_base_requires_finalization_note_)
      << base->info()->record();
}

void BlinkGCPluginConsumer::NoteField(FieldPoint* point, unsigned note) {
  NoteField(point->field(), note);
}

void BlinkGCPluginConsumer::NoteField(FieldDecl* field, unsigned note) {
  ReportDiagnostic(field->getLocStart(), note) << field;
}

void BlinkGCPluginConsumer::NoteOverriddenNonVirtualTrace(
    CXXMethodDecl* overridden) {
  ReportDiagnostic(overridden->getLocStart(),
                   diag_overridden_non_virtual_trace_note_)
      << overridden;
}
