Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Unified Diff: tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.cpp

Issue 1709343002: Remove tools/clang (this will break things temporarily). Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.cpp
diff --git a/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.cpp b/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.cpp
deleted file mode 100644
index 441138a724b25ef6ba0070d8a4d84efc58aaa288..0000000000000000000000000000000000000000
--- a/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.cpp
+++ /dev/null
@@ -1,1275 +0,0 @@
-// 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;
-}
« no previous file with comments | « tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.h ('k') | tools/clang/blink_gc_plugin/BlinkGCPluginOptions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698