Home | History | Annotate | Download | only in blink_gc_plugin
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // This clang plugin checks various invariants of the Blink garbage
      6 // collection infrastructure.
      7 //
      8 // Errors are described at:
      9 // http://www.chromium.org/developers/blink-gc-plugin-errors
     10 
     11 #include "Config.h"
     12 #include "JsonWriter.h"
     13 #include "RecordInfo.h"
     14 
     15 #include "clang/AST/AST.h"
     16 #include "clang/AST/ASTConsumer.h"
     17 #include "clang/AST/RecursiveASTVisitor.h"
     18 #include "clang/Frontend/CompilerInstance.h"
     19 #include "clang/Frontend/FrontendPluginRegistry.h"
     20 
     21 using namespace clang;
     22 using std::string;
     23 
     24 namespace {
     25 
     26 const char kClassMustLeftMostlyDeriveGC[] =
     27     "[blink-gc] Class %0 must derive its GC base in the left-most position.";
     28 
     29 const char kClassRequiresTraceMethod[] =
     30     "[blink-gc] Class %0 requires a trace method.";
     31 
     32 const char kBaseRequiresTracing[] =
     33     "[blink-gc] Base class %0 of derived class %1 requires tracing.";
     34 
     35 const char kBaseRequiresTracingNote[] =
     36     "[blink-gc] Untraced base class %0 declared here:";
     37 
     38 const char kFieldsRequireTracing[] =
     39     "[blink-gc] Class %0 has untraced fields that require tracing.";
     40 
     41 const char kFieldRequiresTracingNote[] =
     42     "[blink-gc] Untraced field %0 declared here:";
     43 
     44 const char kClassContainsInvalidFields[] =
     45     "[blink-gc] Class %0 contains invalid fields.";
     46 
     47 const char kClassContainsGCRoot[] =
     48     "[blink-gc] Class %0 contains GC root in field %1.";
     49 
     50 const char kClassRequiresFinalization[] =
     51     "[blink-gc] Class %0 requires finalization.";
     52 
     53 const char kClassDoesNotRequireFinalization[] =
     54     "[blink-gc] Class %0 may not require finalization.";
     55 
     56 const char kFinalizerAccessesFinalizedField[] =
     57     "[blink-gc] Finalizer %0 accesses potentially finalized field %1.";
     58 
     59 const char kRawPtrToGCManagedClassNote[] =
     60     "[blink-gc] Raw pointer field %0 to a GC managed class declared here:";
     61 
     62 const char kRefPtrToGCManagedClassNote[] =
     63     "[blink-gc] RefPtr field %0 to a GC managed class declared here:";
     64 
     65 const char kOwnPtrToGCManagedClassNote[] =
     66     "[blink-gc] OwnPtr field %0 to a GC managed class declared here:";
     67 
     68 const char kStackAllocatedFieldNote[] =
     69     "[blink-gc] Stack-allocated field %0 declared here:";
     70 
     71 const char kMemberInUnmanagedClassNote[] =
     72     "[blink-gc] Member field %0 in unmanaged class declared here:";
     73 
     74 const char kPartObjectToGCDerivedClassNote[] =
     75     "[blink-gc] Part-object field %0 to a GC derived class declared here:";
     76 
     77 const char kPartObjectContainsGCRootNote[] =
     78     "[blink-gc] Field %0 with embedded GC root in %1 declared here:";
     79 
     80 const char kFieldContainsGCRootNote[] =
     81     "[blink-gc] Field %0 defining a GC root declared here:";
     82 
     83 const char kOverriddenNonVirtualTrace[] =
     84     "[blink-gc] Class %0 overrides non-virtual trace of base class %1.";
     85 
     86 const char kOverriddenNonVirtualTraceNote[] =
     87     "[blink-gc] Non-virtual trace method declared here:";
     88 
     89 const char kMissingTraceDispatchMethod[] =
     90     "[blink-gc] Class %0 is missing manual trace dispatch.";
     91 
     92 const char kMissingFinalizeDispatchMethod[] =
     93     "[blink-gc] Class %0 is missing manual finalize dispatch.";
     94 
     95 const char kVirtualAndManualDispatch[] =
     96     "[blink-gc] Class %0 contains or inherits virtual methods"
     97     " but implements manual dispatching.";
     98 
     99 const char kMissingTraceDispatch[] =
    100     "[blink-gc] Missing dispatch to class %0 in manual trace dispatch.";
    101 
    102 const char kMissingFinalizeDispatch[] =
    103     "[blink-gc] Missing dispatch to class %0 in manual finalize dispatch.";
    104 
    105 const char kFinalizedFieldNote[] =
    106     "[blink-gc] Potentially finalized field %0 declared here:";
    107 
    108 const char kUserDeclaredDestructorNote[] =
    109     "[blink-gc] User-declared destructor declared here:";
    110 
    111 const char kUserDeclaredFinalizerNote[] =
    112     "[blink-gc] User-declared finalizer declared here:";
    113 
    114 const char kBaseRequiresFinalizationNote[] =
    115     "[blink-gc] Base class %0 requiring finalization declared here:";
    116 
    117 const char kFieldRequiresFinalizationNote[] =
    118     "[blink-gc] Field %0 requiring finalization declared here:";
    119 
    120 const char kManualDispatchMethodNote[] =
    121     "[blink-gc] Manual dispatch %0 declared here:";
    122 
    123 const char kDerivesNonStackAllocated[] =
    124     "[blink-gc] Stack-allocated class %0 derives class %1"
    125     " which is not stack allocated.";
    126 
    127 const char kClassOverridesNew[] =
    128     "[blink-gc] Garbage collected class %0"
    129     " is not permitted to override its new operator.";
    130 
    131 const char kClassDeclaresPureVirtualTrace[] =
    132     "[blink-gc] Garbage collected class %0"
    133     " is not permitted to declare a pure-virtual trace method.";
    134 
    135 const char kLeftMostBaseMustBePolymorphic[] =
    136     "[blink-gc] Left-most base class %0 of derived class %1"
    137     " must be polymorphic.";
    138 
    139 const char kBaseClassMustDeclareVirtualTrace[] =
    140     "[blink-gc] Left-most base class %0 of derived class %1"
    141     " must define a virtual trace method.";
    142 
    143 struct BlinkGCPluginOptions {
    144   BlinkGCPluginOptions()
    145     : enable_oilpan(false)
    146     , dump_graph(false)
    147     , warn_raw_ptr(false)
    148     , warn_unneeded_finalizer(false) {}
    149   bool enable_oilpan;
    150   bool dump_graph;
    151   bool warn_raw_ptr;
    152   bool warn_unneeded_finalizer;
    153   std::set<std::string> ignored_classes;
    154   std::set<std::string> checked_namespaces;
    155   std::vector<std::string> ignored_directories;
    156 };
    157 
    158 typedef std::vector<CXXRecordDecl*> RecordVector;
    159 typedef std::vector<CXXMethodDecl*> MethodVector;
    160 
    161 // Test if a template specialization is an instantiation.
    162 static bool IsTemplateInstantiation(CXXRecordDecl* record) {
    163   ClassTemplateSpecializationDecl* spec =
    164       dyn_cast<ClassTemplateSpecializationDecl>(record);
    165   if (!spec)
    166     return false;
    167   switch (spec->getTemplateSpecializationKind()) {
    168     case TSK_ImplicitInstantiation:
    169     case TSK_ExplicitInstantiationDefinition:
    170       return true;
    171     case TSK_Undeclared:
    172     case TSK_ExplicitSpecialization:
    173       return false;
    174     // TODO: unsupported cases.
    175     case TSK_ExplicitInstantiationDeclaration:
    176       return false;
    177   }
    178   assert(false && "Unknown template specialization kind");
    179 }
    180 
    181 // This visitor collects the entry points for the checker.
    182 class CollectVisitor : public RecursiveASTVisitor<CollectVisitor> {
    183  public:
    184   CollectVisitor() {}
    185 
    186   RecordVector& record_decls() { return record_decls_; }
    187   MethodVector& trace_decls() { return trace_decls_; }
    188 
    189   bool shouldVisitTemplateInstantiations() { return false; }
    190 
    191   // Collect record declarations, including nested declarations.
    192   bool VisitCXXRecordDecl(CXXRecordDecl* record) {
    193     if (record->hasDefinition() && record->isCompleteDefinition())
    194       record_decls_.push_back(record);
    195     return true;
    196   }
    197 
    198   // Collect tracing method definitions, but don't traverse method bodies.
    199   bool TraverseCXXMethodDecl(CXXMethodDecl* method) {
    200     if (method->isThisDeclarationADefinition() && Config::IsTraceMethod(method))
    201       trace_decls_.push_back(method);
    202     return true;
    203   }
    204 
    205  private:
    206   RecordVector record_decls_;
    207   MethodVector trace_decls_;
    208 };
    209 
    210 // This visitor checks that a finalizer method does not have invalid access to
    211 // fields that are potentially finalized. A potentially finalized field is
    212 // either a Member, a heap-allocated collection or an off-heap collection that
    213 // contains Members.  Invalid uses are currently identified as passing the field
    214 // as the argument of a procedure call or using the -> or [] operators on it.
    215 class CheckFinalizerVisitor
    216     : public RecursiveASTVisitor<CheckFinalizerVisitor> {
    217  private:
    218   // Simple visitor to determine if the content of a field might be collected
    219   // during finalization.
    220   class MightBeCollectedVisitor : public EdgeVisitor {
    221    public:
    222     MightBeCollectedVisitor() : might_be_collected_(false) {}
    223     bool might_be_collected() { return might_be_collected_; }
    224     void VisitMember(Member* edge) override { might_be_collected_ = true; }
    225     void VisitCollection(Collection* edge) override {
    226       if (edge->on_heap()) {
    227         might_be_collected_ = !edge->is_root();
    228       } else {
    229         edge->AcceptMembers(this);
    230       }
    231     }
    232 
    233    private:
    234     bool might_be_collected_;
    235   };
    236 
    237  public:
    238   typedef std::vector<std::pair<MemberExpr*, FieldPoint*> > Errors;
    239 
    240   CheckFinalizerVisitor(RecordCache* cache)
    241       : blacklist_context_(false), cache_(cache) {}
    242 
    243   Errors& finalized_fields() { return finalized_fields_; }
    244 
    245   bool WalkUpFromCXXOperatorCallExpr(CXXOperatorCallExpr* expr) {
    246     // Only continue the walk-up if the operator is a blacklisted one.
    247     switch (expr->getOperator()) {
    248       case OO_Arrow:
    249       case OO_Subscript:
    250         this->WalkUpFromCallExpr(expr);
    251       default:
    252         return true;
    253     }
    254   }
    255 
    256   // We consider all non-operator calls to be blacklisted contexts.
    257   bool WalkUpFromCallExpr(CallExpr* expr) {
    258     bool prev_blacklist_context = blacklist_context_;
    259     blacklist_context_ = true;
    260     for (size_t i = 0; i < expr->getNumArgs(); ++i)
    261       this->TraverseStmt(expr->getArg(i));
    262     blacklist_context_ = prev_blacklist_context;
    263     return true;
    264   }
    265 
    266   bool VisitMemberExpr(MemberExpr* member) {
    267     FieldDecl* field = dyn_cast<FieldDecl>(member->getMemberDecl());
    268     if (!field)
    269       return true;
    270 
    271     RecordInfo* info = cache_->Lookup(field->getParent());
    272     if (!info)
    273       return true;
    274 
    275     RecordInfo::Fields::iterator it = info->GetFields().find(field);
    276     if (it == info->GetFields().end())
    277       return true;
    278 
    279     if (blacklist_context_ && MightBeCollected(&it->second))
    280       finalized_fields_.push_back(std::make_pair(member, &it->second));
    281     return true;
    282   }
    283 
    284   bool MightBeCollected(FieldPoint* point) {
    285     MightBeCollectedVisitor visitor;
    286     point->edge()->Accept(&visitor);
    287     return visitor.might_be_collected();
    288   }
    289 
    290  private:
    291   bool blacklist_context_;
    292   Errors finalized_fields_;
    293   RecordCache* cache_;
    294 };
    295 
    296 // This visitor checks that a method contains within its body, a call to a
    297 // method on the provided receiver class. This is used to check manual
    298 // dispatching for trace and finalize methods.
    299 class CheckDispatchVisitor : public RecursiveASTVisitor<CheckDispatchVisitor> {
    300  public:
    301   CheckDispatchVisitor(RecordInfo* receiver)
    302       : receiver_(receiver), dispatched_to_receiver_(false) {}
    303 
    304   bool dispatched_to_receiver() { return dispatched_to_receiver_; }
    305 
    306   bool VisitMemberExpr(MemberExpr* member) {
    307     if (CXXMethodDecl* fn = dyn_cast<CXXMethodDecl>(member->getMemberDecl())) {
    308       if (fn->getParent() == receiver_->record())
    309         dispatched_to_receiver_ = true;
    310     }
    311     return true;
    312   }
    313 
    314  private:
    315   RecordInfo* receiver_;
    316   bool dispatched_to_receiver_;
    317 };
    318 
    319 // This visitor checks a tracing method by traversing its body.
    320 // - A member field is considered traced if it is referenced in the body.
    321 // - A base is traced if a base-qualified call to a trace method is found.
    322 class CheckTraceVisitor : public RecursiveASTVisitor<CheckTraceVisitor> {
    323  public:
    324   CheckTraceVisitor(CXXMethodDecl* trace, RecordInfo* info)
    325       : trace_(trace), info_(info) {}
    326 
    327   bool VisitMemberExpr(MemberExpr* member) {
    328     // In weak callbacks, consider any occurrence as a correct usage.
    329     // TODO: We really want to require that isAlive is checked on manually
    330     // processed weak fields.
    331     if (IsWeakCallback()) {
    332       if (FieldDecl* field = dyn_cast<FieldDecl>(member->getMemberDecl()))
    333         FoundField(field);
    334     }
    335     return true;
    336   }
    337 
    338   bool VisitCallExpr(CallExpr* call) {
    339     // In weak callbacks we don't check calls (see VisitMemberExpr).
    340     if (IsWeakCallback())
    341       return true;
    342 
    343     Expr* callee = call->getCallee();
    344 
    345     // Trace calls from a templated derived class result in a
    346     // DependentScopeMemberExpr because the concrete trace call depends on the
    347     // instantiation of any shared template parameters. In this case the call is
    348     // "unresolved" and we resort to comparing the syntactic type names.
    349     if (CXXDependentScopeMemberExpr* expr =
    350         dyn_cast<CXXDependentScopeMemberExpr>(callee)) {
    351       CheckCXXDependentScopeMemberExpr(call, expr);
    352       return true;
    353     }
    354 
    355     // A tracing call will have either a |visitor| or a |m_field| argument.
    356     // A registerWeakMembers call will have a |this| argument.
    357     if (call->getNumArgs() != 1)
    358       return true;
    359     Expr* arg = call->getArg(0);
    360 
    361     if (UnresolvedMemberExpr* expr = dyn_cast<UnresolvedMemberExpr>(callee)) {
    362       // If we find a call to registerWeakMembers which is unresolved we
    363       // unsoundly consider all weak members as traced.
    364       // TODO: Find out how to validate weak member tracing for unresolved call.
    365       if (expr->getMemberName().getAsString() == kRegisterWeakMembersName) {
    366         for (RecordInfo::Fields::iterator it = info_->GetFields().begin();
    367              it != info_->GetFields().end();
    368              ++it) {
    369           if (it->second.edge()->IsWeakMember())
    370             it->second.MarkTraced();
    371         }
    372       }
    373 
    374       QualType base = expr->getBaseType();
    375       if (!base->isPointerType())
    376         return true;
    377       CXXRecordDecl* decl = base->getPointeeType()->getAsCXXRecordDecl();
    378       if (decl)
    379         CheckTraceFieldCall(expr->getMemberName().getAsString(), decl, arg);
    380       return true;
    381     }
    382 
    383     if (CXXMemberCallExpr* expr = dyn_cast<CXXMemberCallExpr>(call)) {
    384       if (CheckTraceFieldCall(expr) || CheckRegisterWeakMembers(expr))
    385         return true;
    386     }
    387 
    388     CheckTraceBaseCall(call);
    389     return true;
    390   }
    391 
    392  private:
    393 
    394   CXXRecordDecl* GetDependentTemplatedDecl(CXXDependentScopeMemberExpr* expr) {
    395     NestedNameSpecifier* qual = expr->getQualifier();
    396     if (!qual)
    397       return 0;
    398 
    399     const Type* type = qual->getAsType();
    400     if (!type)
    401       return 0;
    402 
    403     const TemplateSpecializationType* tmpl_type =
    404         type->getAs<TemplateSpecializationType>();
    405     if (!tmpl_type)
    406       return 0;
    407 
    408     TemplateDecl* tmpl_decl = tmpl_type->getTemplateName().getAsTemplateDecl();
    409     if (!tmpl_decl)
    410       return 0;
    411 
    412     return dyn_cast<CXXRecordDecl>(tmpl_decl->getTemplatedDecl());
    413   }
    414 
    415   void CheckCXXDependentScopeMemberExpr(CallExpr* call,
    416                                         CXXDependentScopeMemberExpr* expr) {
    417     string fn_name = expr->getMember().getAsString();
    418     CXXRecordDecl* tmpl = GetDependentTemplatedDecl(expr);
    419     if (!tmpl)
    420       return;
    421 
    422     // Check for Super<T>::trace(visitor)
    423     if (call->getNumArgs() == 1 && fn_name == trace_->getName()) {
    424       RecordInfo::Bases::iterator it = info_->GetBases().begin();
    425       for (; it != info_->GetBases().end(); ++it) {
    426         if (it->first->getName() == tmpl->getName())
    427           it->second.MarkTraced();
    428       }
    429       return;
    430     }
    431 
    432     // Check for TraceIfNeeded<T>::trace(visitor, &field)
    433     if (call->getNumArgs() == 2 && fn_name == kTraceName &&
    434         tmpl->getName() == kTraceIfNeededName) {
    435       FindFieldVisitor finder;
    436       finder.TraverseStmt(call->getArg(1));
    437       if (finder.field())
    438         FoundField(finder.field());
    439     }
    440   }
    441 
    442   bool CheckTraceBaseCall(CallExpr* call) {
    443     MemberExpr* callee = dyn_cast<MemberExpr>(call->getCallee());
    444     if (!callee)
    445       return false;
    446 
    447     FunctionDecl* fn = dyn_cast<FunctionDecl>(callee->getMemberDecl());
    448     if (!fn || !Config::IsTraceMethod(fn))
    449       return false;
    450 
    451     // Currently, a manually dispatched class cannot have mixin bases (having
    452     // one would add a vtable which we explicitly check against). This means
    453     // that we can only make calls to a trace method of the same name. Revisit
    454     // this if our mixin/vtable assumption changes.
    455     if (fn->getName() != trace_->getName())
    456       return false;
    457 
    458     CXXRecordDecl* decl = 0;
    459     if (callee && callee->hasQualifier()) {
    460       if (const Type* type = callee->getQualifier()->getAsType())
    461         decl = type->getAsCXXRecordDecl();
    462     }
    463     if (!decl)
    464       return false;
    465 
    466     RecordInfo::Bases::iterator it = info_->GetBases().find(decl);
    467     if (it != info_->GetBases().end()) {
    468       it->second.MarkTraced();
    469     }
    470 
    471     return true;
    472   }
    473 
    474   bool CheckTraceFieldCall(CXXMemberCallExpr* call) {
    475     return CheckTraceFieldCall(call->getMethodDecl()->getNameAsString(),
    476                                call->getRecordDecl(),
    477                                call->getArg(0));
    478   }
    479 
    480   bool CheckTraceFieldCall(string name, CXXRecordDecl* callee, Expr* arg) {
    481     if (name != kTraceName || !Config::IsVisitor(callee->getName()))
    482       return false;
    483 
    484     FindFieldVisitor finder;
    485     finder.TraverseStmt(arg);
    486     if (finder.field())
    487       FoundField(finder.field());
    488 
    489     return true;
    490   }
    491 
    492   bool CheckRegisterWeakMembers(CXXMemberCallExpr* call) {
    493     CXXMethodDecl* fn = call->getMethodDecl();
    494     if (fn->getName() != kRegisterWeakMembersName)
    495       return false;
    496 
    497     if (fn->isTemplateInstantiation()) {
    498       const TemplateArgumentList& args =
    499           *fn->getTemplateSpecializationInfo()->TemplateArguments;
    500       // The second template argument is the callback method.
    501       if (args.size() > 1 &&
    502           args[1].getKind() == TemplateArgument::Declaration) {
    503         if (FunctionDecl* callback =
    504             dyn_cast<FunctionDecl>(args[1].getAsDecl())) {
    505           if (callback->hasBody()) {
    506             CheckTraceVisitor nested_visitor(info_);
    507             nested_visitor.TraverseStmt(callback->getBody());
    508           }
    509         }
    510       }
    511     }
    512     return true;
    513   }
    514 
    515   class FindFieldVisitor : public RecursiveASTVisitor<FindFieldVisitor> {
    516    public:
    517     FindFieldVisitor() : member_(0), field_(0) {}
    518     MemberExpr* member() const { return member_; }
    519     FieldDecl* field() const { return field_; }
    520     bool TraverseMemberExpr(MemberExpr* member) {
    521       if (FieldDecl* field = dyn_cast<FieldDecl>(member->getMemberDecl())) {
    522         member_ = member;
    523         field_ = field;
    524         return false;
    525       }
    526       return true;
    527     }
    528    private:
    529     MemberExpr* member_;
    530     FieldDecl* field_;
    531   };
    532 
    533   // Nested checking for weak callbacks.
    534   CheckTraceVisitor(RecordInfo* info) : trace_(0), info_(info) {}
    535 
    536   bool IsWeakCallback() { return !trace_; }
    537 
    538   void MarkTraced(RecordInfo::Fields::iterator it) {
    539     // In a weak callback we can't mark strong fields as traced.
    540     if (IsWeakCallback() && !it->second.edge()->IsWeakMember())
    541       return;
    542     it->second.MarkTraced();
    543   }
    544 
    545   void FoundField(FieldDecl* field) {
    546     if (IsTemplateInstantiation(info_->record())) {
    547       // Pointer equality on fields does not work for template instantiations.
    548       // The trace method refers to fields of the template definition which
    549       // are different from the instantiated fields that need to be traced.
    550       const string& name = field->getNameAsString();
    551       for (RecordInfo::Fields::iterator it = info_->GetFields().begin();
    552            it != info_->GetFields().end();
    553            ++it) {
    554         if (it->first->getNameAsString() == name) {
    555           MarkTraced(it);
    556           break;
    557         }
    558       }
    559     } else {
    560       RecordInfo::Fields::iterator it = info_->GetFields().find(field);
    561       if (it != info_->GetFields().end())
    562         MarkTraced(it);
    563     }
    564   }
    565 
    566   CXXMethodDecl* trace_;
    567   RecordInfo* info_;
    568 };
    569 
    570 // This visitor checks that the fields of a class and the fields of
    571 // its part objects don't define GC roots.
    572 class CheckGCRootsVisitor : public RecursiveEdgeVisitor {
    573  public:
    574   typedef std::vector<FieldPoint*> RootPath;
    575   typedef std::vector<RootPath> Errors;
    576 
    577   CheckGCRootsVisitor() {}
    578 
    579   Errors& gc_roots() { return gc_roots_; }
    580 
    581   bool ContainsGCRoots(RecordInfo* info) {
    582     for (RecordInfo::Fields::iterator it = info->GetFields().begin();
    583          it != info->GetFields().end();
    584          ++it) {
    585       current_.push_back(&it->second);
    586       it->second.edge()->Accept(this);
    587       current_.pop_back();
    588     }
    589     return !gc_roots_.empty();
    590   }
    591 
    592   void VisitValue(Value* edge) override {
    593     // TODO: what should we do to check unions?
    594     if (edge->value()->record()->isUnion())
    595       return;
    596 
    597     // If the value is a part object, then continue checking for roots.
    598     for (Context::iterator it = context().begin();
    599          it != context().end();
    600          ++it) {
    601       if (!(*it)->IsCollection())
    602         return;
    603     }
    604     ContainsGCRoots(edge->value());
    605   }
    606 
    607   void VisitPersistent(Persistent* edge) override {
    608     gc_roots_.push_back(current_);
    609   }
    610 
    611   void AtCollection(Collection* edge) override {
    612     if (edge->is_root())
    613       gc_roots_.push_back(current_);
    614   }
    615 
    616  protected:
    617   RootPath current_;
    618   Errors gc_roots_;
    619 };
    620 
    621 // This visitor checks that the fields of a class are "well formed".
    622 // - OwnPtr, RefPtr and RawPtr must not point to a GC derived types.
    623 // - Part objects must not be GC derived types.
    624 // - An on-heap class must never contain GC roots.
    625 // - Only stack-allocated types may point to stack-allocated types.
    626 class CheckFieldsVisitor : public RecursiveEdgeVisitor {
    627  public:
    628 
    629   enum Error {
    630     kRawPtrToGCManaged,
    631     kRawPtrToGCManagedWarning,
    632     kRefPtrToGCManaged,
    633     kOwnPtrToGCManaged,
    634     kMemberInUnmanaged,
    635     kPtrFromHeapToStack,
    636     kGCDerivedPartObject
    637   };
    638 
    639   typedef std::vector<std::pair<FieldPoint*, Error> > Errors;
    640 
    641   CheckFieldsVisitor(const BlinkGCPluginOptions& options)
    642       : options_(options), current_(0), stack_allocated_host_(false) {}
    643 
    644   Errors& invalid_fields() { return invalid_fields_; }
    645 
    646   bool ContainsInvalidFields(RecordInfo* info) {
    647     stack_allocated_host_ = info->IsStackAllocated();
    648     managed_host_ = stack_allocated_host_ ||
    649                     info->IsGCAllocated() ||
    650                     info->IsNonNewable() ||
    651                     info->IsOnlyPlacementNewable();
    652     for (RecordInfo::Fields::iterator it = info->GetFields().begin();
    653          it != info->GetFields().end();
    654          ++it) {
    655       context().clear();
    656       current_ = &it->second;
    657       current_->edge()->Accept(this);
    658     }
    659     return !invalid_fields_.empty();
    660   }
    661 
    662   void AtMember(Member* edge) override {
    663     if (managed_host_)
    664       return;
    665     // A member is allowed to appear in the context of a root.
    666     for (Context::iterator it = context().begin();
    667          it != context().end();
    668          ++it) {
    669       if ((*it)->Kind() == Edge::kRoot)
    670         return;
    671     }
    672     invalid_fields_.push_back(std::make_pair(current_, kMemberInUnmanaged));
    673   }
    674 
    675   void AtValue(Value* edge) override {
    676     // TODO: what should we do to check unions?
    677     if (edge->value()->record()->isUnion())
    678       return;
    679 
    680     if (!stack_allocated_host_ && edge->value()->IsStackAllocated()) {
    681       invalid_fields_.push_back(std::make_pair(current_, kPtrFromHeapToStack));
    682       return;
    683     }
    684 
    685     if (!Parent() &&
    686         edge->value()->IsGCDerived() &&
    687         !edge->value()->IsGCMixin()) {
    688       invalid_fields_.push_back(std::make_pair(current_, kGCDerivedPartObject));
    689       return;
    690     }
    691 
    692     if (!Parent() || !edge->value()->IsGCAllocated())
    693       return;
    694 
    695     // In transition mode, disallow  OwnPtr<T>, RawPtr<T> to GC allocated T's,
    696     // also disallow T* in stack-allocated types.
    697     if (options_.enable_oilpan) {
    698       if (Parent()->IsOwnPtr() ||
    699           Parent()->IsRawPtrClass() ||
    700           (stack_allocated_host_ && Parent()->IsRawPtr())) {
    701         invalid_fields_.push_back(std::make_pair(
    702             current_, InvalidSmartPtr(Parent())));
    703         return;
    704       }
    705       if (options_.warn_raw_ptr && Parent()->IsRawPtr()) {
    706         invalid_fields_.push_back(std::make_pair(
    707             current_, kRawPtrToGCManagedWarning));
    708       }
    709       return;
    710     }
    711 
    712     if (Parent()->IsRawPtr() || Parent()->IsRefPtr() || Parent()->IsOwnPtr()) {
    713       invalid_fields_.push_back(std::make_pair(
    714           current_, InvalidSmartPtr(Parent())));
    715       return;
    716     }
    717   }
    718 
    719   void AtCollection(Collection* edge) override {
    720     if (edge->on_heap() && Parent() && Parent()->IsOwnPtr())
    721       invalid_fields_.push_back(std::make_pair(current_, kOwnPtrToGCManaged));
    722   }
    723 
    724  private:
    725   Error InvalidSmartPtr(Edge* ptr) {
    726     if (ptr->IsRawPtr())
    727       return kRawPtrToGCManaged;
    728     if (ptr->IsRefPtr())
    729       return kRefPtrToGCManaged;
    730     if (ptr->IsOwnPtr())
    731       return kOwnPtrToGCManaged;
    732     assert(false && "Unknown smart pointer kind");
    733   }
    734 
    735   const BlinkGCPluginOptions& options_;
    736   FieldPoint* current_;
    737   bool stack_allocated_host_;
    738   bool managed_host_;
    739   Errors invalid_fields_;
    740 };
    741 
    742 class EmptyStmtVisitor
    743     : public RecursiveASTVisitor<EmptyStmtVisitor> {
    744 public:
    745   static bool isEmpty(Stmt* stmt) {
    746     EmptyStmtVisitor visitor;
    747     visitor.TraverseStmt(stmt);
    748     return visitor.empty_;
    749   }
    750 
    751   bool WalkUpFromCompoundStmt(CompoundStmt* stmt) {
    752     empty_ = stmt->body_empty();
    753     return false;
    754   }
    755   bool VisitStmt(Stmt*) {
    756     empty_ = false;
    757     return false;
    758   }
    759 private:
    760   EmptyStmtVisitor() : empty_(true) {}
    761   bool empty_;
    762 };
    763 
    764 // Main class containing checks for various invariants of the Blink
    765 // garbage collection infrastructure.
    766 class BlinkGCPluginConsumer : public ASTConsumer {
    767  public:
    768   BlinkGCPluginConsumer(CompilerInstance& instance,
    769                         const BlinkGCPluginOptions& options)
    770       : instance_(instance),
    771         diagnostic_(instance.getDiagnostics()),
    772         options_(options),
    773         json_(0) {
    774 
    775     // Only check structures in the blink and WebKit namespaces.
    776     options_.checked_namespaces.insert("blink");
    777     options_.checked_namespaces.insert("WebKit");
    778 
    779     // Ignore GC implementation files.
    780     options_.ignored_directories.push_back("/heap/");
    781 
    782     // Register warning/error messages.
    783     diag_class_must_left_mostly_derive_gc_ = diagnostic_.getCustomDiagID(
    784         getErrorLevel(), kClassMustLeftMostlyDeriveGC);
    785     diag_class_requires_trace_method_ =
    786         diagnostic_.getCustomDiagID(getErrorLevel(), kClassRequiresTraceMethod);
    787     diag_base_requires_tracing_ =
    788         diagnostic_.getCustomDiagID(getErrorLevel(), kBaseRequiresTracing);
    789     diag_fields_require_tracing_ =
    790         diagnostic_.getCustomDiagID(getErrorLevel(), kFieldsRequireTracing);
    791     diag_class_contains_invalid_fields_ = diagnostic_.getCustomDiagID(
    792         getErrorLevel(), kClassContainsInvalidFields);
    793     diag_class_contains_invalid_fields_warning_ = diagnostic_.getCustomDiagID(
    794         DiagnosticsEngine::Warning, kClassContainsInvalidFields);
    795     diag_class_contains_gc_root_ =
    796         diagnostic_.getCustomDiagID(getErrorLevel(), kClassContainsGCRoot);
    797     diag_class_requires_finalization_ = diagnostic_.getCustomDiagID(
    798         getErrorLevel(), kClassRequiresFinalization);
    799     diag_class_does_not_require_finalization_ = diagnostic_.getCustomDiagID(
    800         DiagnosticsEngine::Warning, kClassDoesNotRequireFinalization);
    801     diag_finalizer_accesses_finalized_field_ = diagnostic_.getCustomDiagID(
    802         getErrorLevel(), kFinalizerAccessesFinalizedField);
    803     diag_overridden_non_virtual_trace_ = diagnostic_.getCustomDiagID(
    804         getErrorLevel(), kOverriddenNonVirtualTrace);
    805     diag_missing_trace_dispatch_method_ = diagnostic_.getCustomDiagID(
    806         getErrorLevel(), kMissingTraceDispatchMethod);
    807     diag_missing_finalize_dispatch_method_ = diagnostic_.getCustomDiagID(
    808         getErrorLevel(), kMissingFinalizeDispatchMethod);
    809     diag_virtual_and_manual_dispatch_ =
    810         diagnostic_.getCustomDiagID(getErrorLevel(), kVirtualAndManualDispatch);
    811     diag_missing_trace_dispatch_ =
    812         diagnostic_.getCustomDiagID(getErrorLevel(), kMissingTraceDispatch);
    813     diag_missing_finalize_dispatch_ =
    814         diagnostic_.getCustomDiagID(getErrorLevel(), kMissingFinalizeDispatch);
    815     diag_derives_non_stack_allocated_ =
    816         diagnostic_.getCustomDiagID(getErrorLevel(), kDerivesNonStackAllocated);
    817     diag_class_overrides_new_ =
    818         diagnostic_.getCustomDiagID(getErrorLevel(), kClassOverridesNew);
    819     diag_class_declares_pure_virtual_trace_ = diagnostic_.getCustomDiagID(
    820         getErrorLevel(), kClassDeclaresPureVirtualTrace);
    821     diag_left_most_base_must_be_polymorphic_ = diagnostic_.getCustomDiagID(
    822         getErrorLevel(), kLeftMostBaseMustBePolymorphic);
    823     diag_base_class_must_declare_virtual_trace_ = diagnostic_.getCustomDiagID(
    824         getErrorLevel(), kBaseClassMustDeclareVirtualTrace);
    825 
    826     // Register note messages.
    827     diag_base_requires_tracing_note_ = diagnostic_.getCustomDiagID(
    828         DiagnosticsEngine::Note, kBaseRequiresTracingNote);
    829     diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID(
    830         DiagnosticsEngine::Note, kFieldRequiresTracingNote);
    831     diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
    832         DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote);
    833     diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
    834         DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote);
    835     diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
    836         DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote);
    837     diag_stack_allocated_field_note_ = diagnostic_.getCustomDiagID(
    838         DiagnosticsEngine::Note, kStackAllocatedFieldNote);
    839     diag_member_in_unmanaged_class_note_ = diagnostic_.getCustomDiagID(
    840         DiagnosticsEngine::Note, kMemberInUnmanagedClassNote);
    841     diag_part_object_to_gc_derived_class_note_ = diagnostic_.getCustomDiagID(
    842         DiagnosticsEngine::Note, kPartObjectToGCDerivedClassNote);
    843     diag_part_object_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
    844         DiagnosticsEngine::Note, kPartObjectContainsGCRootNote);
    845     diag_field_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
    846         DiagnosticsEngine::Note, kFieldContainsGCRootNote);
    847     diag_finalized_field_note_ = diagnostic_.getCustomDiagID(
    848         DiagnosticsEngine::Note, kFinalizedFieldNote);
    849     diag_user_declared_destructor_note_ = diagnostic_.getCustomDiagID(
    850         DiagnosticsEngine::Note, kUserDeclaredDestructorNote);
    851     diag_user_declared_finalizer_note_ = diagnostic_.getCustomDiagID(
    852         DiagnosticsEngine::Note, kUserDeclaredFinalizerNote);
    853     diag_base_requires_finalization_note_ = diagnostic_.getCustomDiagID(
    854         DiagnosticsEngine::Note, kBaseRequiresFinalizationNote);
    855     diag_field_requires_finalization_note_ = diagnostic_.getCustomDiagID(
    856         DiagnosticsEngine::Note, kFieldRequiresFinalizationNote);
    857     diag_overridden_non_virtual_trace_note_ = diagnostic_.getCustomDiagID(
    858         DiagnosticsEngine::Note, kOverriddenNonVirtualTraceNote);
    859     diag_manual_dispatch_method_note_ = diagnostic_.getCustomDiagID(
    860         DiagnosticsEngine::Note, kManualDispatchMethodNote);
    861   }
    862 
    863   void HandleTranslationUnit(ASTContext& context) override {
    864     CollectVisitor visitor;
    865     visitor.TraverseDecl(context.getTranslationUnitDecl());
    866 
    867     if (options_.dump_graph) {
    868       std::error_code err;
    869       // TODO: Make createDefaultOutputFile or a shorter createOutputFile work.
    870       json_ = JsonWriter::from(instance_.createOutputFile(
    871           "",                                      // OutputPath
    872           err,                                     // Errors
    873           true,                                    // Binary
    874           true,                                    // RemoveFileOnSignal
    875           instance_.getFrontendOpts().OutputFile,  // BaseInput
    876           "graph.json",                            // Extension
    877           false,                                   // UseTemporary
    878           false,                                   // CreateMissingDirectories
    879           0,                                       // ResultPathName
    880           0));                                     // TempPathName
    881       if (!err && json_) {
    882         json_->OpenList();
    883       } else {
    884         json_ = 0;
    885         llvm::errs()
    886             << "[blink-gc] "
    887             << "Failed to create an output file for the object graph.\n";
    888       }
    889     }
    890 
    891     for (RecordVector::iterator it = visitor.record_decls().begin();
    892          it != visitor.record_decls().end();
    893          ++it) {
    894       CheckRecord(cache_.Lookup(*it));
    895     }
    896 
    897     for (MethodVector::iterator it = visitor.trace_decls().begin();
    898          it != visitor.trace_decls().end();
    899          ++it) {
    900       CheckTracingMethod(*it);
    901     }
    902 
    903     if (json_) {
    904       json_->CloseList();
    905       delete json_;
    906       json_ = 0;
    907     }
    908   }
    909 
    910   // Main entry for checking a record declaration.
    911   void CheckRecord(RecordInfo* info) {
    912     if (IsIgnored(info))
    913       return;
    914 
    915     CXXRecordDecl* record = info->record();
    916 
    917     // TODO: what should we do to check unions?
    918     if (record->isUnion())
    919       return;
    920 
    921     // If this is the primary template declaration, check its specializations.
    922     if (record->isThisDeclarationADefinition() &&
    923         record->getDescribedClassTemplate()) {
    924       ClassTemplateDecl* tmpl = record->getDescribedClassTemplate();
    925       for (ClassTemplateDecl::spec_iterator it = tmpl->spec_begin();
    926            it != tmpl->spec_end();
    927            ++it) {
    928         CheckClass(cache_.Lookup(*it));
    929       }
    930       return;
    931     }
    932 
    933     CheckClass(info);
    934   }
    935 
    936   // Check a class-like object (eg, class, specialization, instantiation).
    937   void CheckClass(RecordInfo* info) {
    938     if (!info)
    939       return;
    940 
    941     // Check consistency of stack-allocated hierarchies.
    942     if (info->IsStackAllocated()) {
    943       for (RecordInfo::Bases::iterator it = info->GetBases().begin();
    944            it != info->GetBases().end();
    945            ++it) {
    946         if (!it->second.info()->IsStackAllocated())
    947           ReportDerivesNonStackAllocated(info, &it->second);
    948       }
    949     }
    950 
    951     if (CXXMethodDecl* trace = info->GetTraceMethod()) {
    952       if (trace->isPure())
    953         ReportClassDeclaresPureVirtualTrace(info, trace);
    954     } else if (info->RequiresTraceMethod()) {
    955       ReportClassRequiresTraceMethod(info);
    956     }
    957 
    958     // Check polymorphic classes that are GC-derived or have a trace method.
    959     if (info->record()->hasDefinition() && info->record()->isPolymorphic()) {
    960       CXXMethodDecl* trace = info->GetTraceMethod();
    961       if (trace || info->IsGCDerived())
    962         CheckPolymorphicClass(info, trace);
    963     }
    964 
    965     {
    966       CheckFieldsVisitor visitor(options_);
    967       if (visitor.ContainsInvalidFields(info))
    968         ReportClassContainsInvalidFields(info, &visitor.invalid_fields());
    969     }
    970 
    971     if (info->IsGCDerived()) {
    972 
    973       if (!info->IsGCMixin()) {
    974         CheckLeftMostDerived(info);
    975         CheckDispatch(info);
    976         if (CXXMethodDecl* newop = info->DeclaresNewOperator())
    977           ReportClassOverridesNew(info, newop);
    978       }
    979 
    980       {
    981         CheckGCRootsVisitor visitor;
    982         if (visitor.ContainsGCRoots(info))
    983           ReportClassContainsGCRoots(info, &visitor.gc_roots());
    984       }
    985 
    986       if (info->NeedsFinalization())
    987         CheckFinalization(info);
    988 
    989       if (options_.warn_unneeded_finalizer && info->IsGCFinalized())
    990         CheckUnneededFinalization(info);
    991     }
    992 
    993     DumpClass(info);
    994   }
    995 
    996   CXXRecordDecl* GetDependentTemplatedDecl(const Type& type) {
    997     const TemplateSpecializationType* tmpl_type =
    998         type.getAs<TemplateSpecializationType>();
    999     if (!tmpl_type)
   1000       return 0;
   1001 
   1002     TemplateDecl* tmpl_decl = tmpl_type->getTemplateName().getAsTemplateDecl();
   1003     if (!tmpl_decl)
   1004       return 0;
   1005 
   1006     return dyn_cast<CXXRecordDecl>(tmpl_decl->getTemplatedDecl());
   1007   }
   1008 
   1009   // The GC infrastructure assumes that if the vtable of a polymorphic
   1010   // base-class is not initialized for a given object (ie, it is partially
   1011   // initialized) then the object does not need to be traced. Thus, we must
   1012   // ensure that any polymorphic class with a trace method does not have any
   1013   // tractable fields that are initialized before we are sure that the vtable
   1014   // and the trace method are both defined.  There are two cases that need to
   1015   // hold to satisfy that assumption:
   1016   //
   1017   // 1. If trace is virtual, then it must be defined in the left-most base.
   1018   // This ensures that if the vtable is initialized then it contains a pointer
   1019   // to the trace method.
   1020   //
   1021   // 2. If trace is non-virtual, then the trace method is defined and we must
   1022   // ensure that the left-most base defines a vtable. This ensures that the
   1023   // first thing to be initialized when constructing the object is the vtable
   1024   // itself.
   1025   void CheckPolymorphicClass(RecordInfo* info, CXXMethodDecl* trace) {
   1026     CXXRecordDecl* left_most = info->record();
   1027     CXXRecordDecl::base_class_iterator it = left_most->bases_begin();
   1028     CXXRecordDecl* left_most_base = 0;
   1029     while (it != left_most->bases_end()) {
   1030       left_most_base = it->getType()->getAsCXXRecordDecl();
   1031       if (!left_most_base && it->getType()->isDependentType())
   1032         left_most_base = GetDependentTemplatedDecl(*it->getType());
   1033 
   1034       // TODO: Find a way to correctly check actual instantiations
   1035       // for dependent types. The escape below will be hit, eg, when
   1036       // we have a primary template with no definition and
   1037       // specializations for each case (such as SupplementBase) in
   1038       // which case we don't succeed in checking the required
   1039       // properties.
   1040       if (!left_most_base || !left_most_base->hasDefinition())
   1041         return;
   1042 
   1043       StringRef name = left_most_base->getName();
   1044       // We know GCMixin base defines virtual trace.
   1045       if (Config::IsGCMixinBase(name))
   1046         return;
   1047 
   1048       // Stop with the left-most prior to a safe polymorphic base (a safe base
   1049       // is non-polymorphic and contains no fields).
   1050       if (Config::IsSafePolymorphicBase(name))
   1051         break;
   1052 
   1053       left_most = left_most_base;
   1054       it = left_most->bases_begin();
   1055     }
   1056 
   1057     if (RecordInfo* left_most_info = cache_.Lookup(left_most)) {
   1058 
   1059       // Check condition (1):
   1060       if (trace && trace->isVirtual()) {
   1061         if (CXXMethodDecl* trace = left_most_info->GetTraceMethod()) {
   1062           if (trace->isVirtual())
   1063             return;
   1064         }
   1065         ReportBaseClassMustDeclareVirtualTrace(info, left_most);
   1066         return;
   1067       }
   1068 
   1069       // Check condition (2):
   1070       if (DeclaresVirtualMethods(left_most))
   1071         return;
   1072       if (left_most_base) {
   1073         ++it; // Get the base next to the "safe polymorphic base"
   1074         if (it != left_most->bases_end()) {
   1075           if (CXXRecordDecl* next_base = it->getType()->getAsCXXRecordDecl()) {
   1076             if (CXXRecordDecl* next_left_most = GetLeftMostBase(next_base)) {
   1077               if (DeclaresVirtualMethods(next_left_most))
   1078                 return;
   1079               ReportLeftMostBaseMustBePolymorphic(info, next_left_most);
   1080               return;
   1081             }
   1082           }
   1083         }
   1084       }
   1085       ReportLeftMostBaseMustBePolymorphic(info, left_most);
   1086     }
   1087   }
   1088 
   1089   CXXRecordDecl* GetLeftMostBase(CXXRecordDecl* left_most) {
   1090     CXXRecordDecl::base_class_iterator it = left_most->bases_begin();
   1091     while (it != left_most->bases_end()) {
   1092       if (it->getType()->isDependentType())
   1093         left_most = GetDependentTemplatedDecl(*it->getType());
   1094       else
   1095         left_most = it->getType()->getAsCXXRecordDecl();
   1096       if (!left_most || !left_most->hasDefinition())
   1097         return 0;
   1098       it = left_most->bases_begin();
   1099     }
   1100     return left_most;
   1101   }
   1102 
   1103   bool DeclaresVirtualMethods(CXXRecordDecl* decl) {
   1104     CXXRecordDecl::method_iterator it = decl->method_begin();
   1105     for (; it != decl->method_end(); ++it)
   1106       if (it->isVirtual() && !it->isPure())
   1107         return true;
   1108     return false;
   1109   }
   1110 
   1111   void CheckLeftMostDerived(RecordInfo* info) {
   1112     CXXRecordDecl* left_most = info->record();
   1113     CXXRecordDecl::base_class_iterator it = left_most->bases_begin();
   1114     while (it != left_most->bases_end()) {
   1115       left_most = it->getType()->getAsCXXRecordDecl();
   1116       it = left_most->bases_begin();
   1117     }
   1118     if (!Config::IsGCBase(left_most->getName()))
   1119       ReportClassMustLeftMostlyDeriveGC(info);
   1120   }
   1121 
   1122   void CheckDispatch(RecordInfo* info) {
   1123     bool finalized = info->IsGCFinalized();
   1124     CXXMethodDecl* trace_dispatch = info->GetTraceDispatchMethod();
   1125     CXXMethodDecl* finalize_dispatch = info->GetFinalizeDispatchMethod();
   1126     if (!trace_dispatch && !finalize_dispatch)
   1127       return;
   1128 
   1129     CXXRecordDecl* base = trace_dispatch ? trace_dispatch->getParent()
   1130                                          : finalize_dispatch->getParent();
   1131 
   1132     // Check that dispatch methods are defined at the base.
   1133     if (base == info->record()) {
   1134       if (!trace_dispatch)
   1135         ReportMissingTraceDispatchMethod(info);
   1136       if (finalized && !finalize_dispatch)
   1137         ReportMissingFinalizeDispatchMethod(info);
   1138       if (!finalized && finalize_dispatch) {
   1139         ReportClassRequiresFinalization(info);
   1140         NoteUserDeclaredFinalizer(finalize_dispatch);
   1141       }
   1142     }
   1143 
   1144     // Check that classes implementing manual dispatch do not have vtables.
   1145     if (info->record()->isPolymorphic())
   1146       ReportVirtualAndManualDispatch(
   1147           info, trace_dispatch ? trace_dispatch : finalize_dispatch);
   1148 
   1149     // If this is a non-abstract class check that it is dispatched to.
   1150     // TODO: Create a global variant of this local check. We can only check if
   1151     // the dispatch body is known in this compilation unit.
   1152     if (info->IsConsideredAbstract())
   1153       return;
   1154 
   1155     const FunctionDecl* defn;
   1156 
   1157     if (trace_dispatch && trace_dispatch->isDefined(defn)) {
   1158       CheckDispatchVisitor visitor(info);
   1159       visitor.TraverseStmt(defn->getBody());
   1160       if (!visitor.dispatched_to_receiver())
   1161         ReportMissingTraceDispatch(defn, info);
   1162     }
   1163 
   1164     if (finalized && finalize_dispatch && finalize_dispatch->isDefined(defn)) {
   1165       CheckDispatchVisitor visitor(info);
   1166       visitor.TraverseStmt(defn->getBody());
   1167       if (!visitor.dispatched_to_receiver())
   1168         ReportMissingFinalizeDispatch(defn, info);
   1169     }
   1170   }
   1171 
   1172   // TODO: Should we collect destructors similar to trace methods?
   1173   void CheckFinalization(RecordInfo* info) {
   1174     CXXDestructorDecl* dtor = info->record()->getDestructor();
   1175 
   1176     // For finalized classes, check the finalization method if possible.
   1177     if (info->IsGCFinalized()) {
   1178       if (dtor && dtor->hasBody()) {
   1179         CheckFinalizerVisitor visitor(&cache_);
   1180         visitor.TraverseCXXMethodDecl(dtor);
   1181         if (!visitor.finalized_fields().empty()) {
   1182           ReportFinalizerAccessesFinalizedFields(
   1183               dtor, &visitor.finalized_fields());
   1184         }
   1185       }
   1186       return;
   1187     }
   1188 
   1189     // Don't require finalization of a mixin that has not yet been "mixed in".
   1190     if (info->IsGCMixin())
   1191       return;
   1192 
   1193     // Report the finalization error, and proceed to print possible causes for
   1194     // the finalization requirement.
   1195     ReportClassRequiresFinalization(info);
   1196 
   1197     if (dtor && dtor->isUserProvided())
   1198       NoteUserDeclaredDestructor(dtor);
   1199 
   1200     for (RecordInfo::Bases::iterator it = info->GetBases().begin();
   1201          it != info->GetBases().end();
   1202          ++it) {
   1203       if (it->second.info()->NeedsFinalization())
   1204         NoteBaseRequiresFinalization(&it->second);
   1205     }
   1206 
   1207     for (RecordInfo::Fields::iterator it = info->GetFields().begin();
   1208          it != info->GetFields().end();
   1209          ++it) {
   1210       if (it->second.edge()->NeedsFinalization())
   1211         NoteField(&it->second, diag_field_requires_finalization_note_);
   1212     }
   1213   }
   1214 
   1215   void CheckUnneededFinalization(RecordInfo* info) {
   1216     if (!HasNonEmptyFinalizer(info))
   1217       ReportClassDoesNotRequireFinalization(info);
   1218   }
   1219 
   1220   bool HasNonEmptyFinalizer(RecordInfo* info) {
   1221     CXXDestructorDecl* dtor = info->record()->getDestructor();
   1222     if (dtor && dtor->isUserProvided()) {
   1223       if (!dtor->hasBody() || !EmptyStmtVisitor::isEmpty(dtor->getBody()))
   1224         return true;
   1225     }
   1226     for (RecordInfo::Bases::iterator it = info->GetBases().begin();
   1227          it != info->GetBases().end();
   1228          ++it) {
   1229       if (HasNonEmptyFinalizer(it->second.info()))
   1230         return true;
   1231     }
   1232     for (RecordInfo::Fields::iterator it = info->GetFields().begin();
   1233          it != info->GetFields().end();
   1234          ++it) {
   1235       if (it->second.edge()->NeedsFinalization())
   1236         return true;
   1237     }
   1238     return false;
   1239   }
   1240 
   1241   // This is the main entry for tracing method definitions.
   1242   void CheckTracingMethod(CXXMethodDecl* method) {
   1243     RecordInfo* parent = cache_.Lookup(method->getParent());
   1244     if (IsIgnored(parent))
   1245       return;
   1246 
   1247     // Check templated tracing methods by checking the template instantiations.
   1248     // Specialized templates are handled as ordinary classes.
   1249     if (ClassTemplateDecl* tmpl =
   1250             parent->record()->getDescribedClassTemplate()) {
   1251       for (ClassTemplateDecl::spec_iterator it = tmpl->spec_begin();
   1252            it != tmpl->spec_end();
   1253            ++it) {
   1254         // Check trace using each template instantiation as the holder.
   1255         if (IsTemplateInstantiation(*it))
   1256           CheckTraceOrDispatchMethod(cache_.Lookup(*it), method);
   1257       }
   1258       return;
   1259     }
   1260 
   1261     CheckTraceOrDispatchMethod(parent, method);
   1262   }
   1263 
   1264   // Determine what type of tracing method this is (dispatch or trace).
   1265   void CheckTraceOrDispatchMethod(RecordInfo* parent, CXXMethodDecl* method) {
   1266     bool isTraceAfterDispatch;
   1267     if (Config::IsTraceMethod(method, &isTraceAfterDispatch)) {
   1268       if (isTraceAfterDispatch || !parent->GetTraceDispatchMethod()) {
   1269         CheckTraceMethod(parent, method, isTraceAfterDispatch);
   1270       }
   1271       // Dispatch methods are checked when we identify subclasses.
   1272     }
   1273   }
   1274 
   1275   // Check an actual trace method.
   1276   void CheckTraceMethod(RecordInfo* parent,
   1277                         CXXMethodDecl* trace,
   1278                         bool isTraceAfterDispatch) {
   1279     // A trace method must not override any non-virtual trace methods.
   1280     if (!isTraceAfterDispatch) {
   1281       for (RecordInfo::Bases::iterator it = parent->GetBases().begin();
   1282            it != parent->GetBases().end();
   1283            ++it) {
   1284         RecordInfo* base = it->second.info();
   1285         if (CXXMethodDecl* other = base->InheritsNonVirtualTrace())
   1286           ReportOverriddenNonVirtualTrace(parent, trace, other);
   1287       }
   1288     }
   1289 
   1290     CheckTraceVisitor visitor(trace, parent);
   1291     visitor.TraverseCXXMethodDecl(trace);
   1292 
   1293     for (RecordInfo::Bases::iterator it = parent->GetBases().begin();
   1294          it != parent->GetBases().end();
   1295          ++it) {
   1296       if (!it->second.IsProperlyTraced())
   1297         ReportBaseRequiresTracing(parent, trace, it->first);
   1298     }
   1299 
   1300     for (RecordInfo::Fields::iterator it = parent->GetFields().begin();
   1301          it != parent->GetFields().end();
   1302          ++it) {
   1303       if (!it->second.IsProperlyTraced()) {
   1304         // Discontinue once an untraced-field error is found.
   1305         ReportFieldsRequireTracing(parent, trace);
   1306         break;
   1307       }
   1308     }
   1309   }
   1310 
   1311   void DumpClass(RecordInfo* info) {
   1312     if (!json_)
   1313       return;
   1314 
   1315     json_->OpenObject();
   1316     json_->Write("name", info->record()->getQualifiedNameAsString());
   1317     json_->Write("loc", GetLocString(info->record()->getLocStart()));
   1318     json_->CloseObject();
   1319 
   1320     class DumpEdgeVisitor : public RecursiveEdgeVisitor {
   1321      public:
   1322       DumpEdgeVisitor(JsonWriter* json) : json_(json) {}
   1323       void DumpEdge(RecordInfo* src,
   1324                     RecordInfo* dst,
   1325                     const string& lbl,
   1326                     const Edge::LivenessKind& kind,
   1327                     const string& loc) {
   1328         json_->OpenObject();
   1329         json_->Write("src", src->record()->getQualifiedNameAsString());
   1330         json_->Write("dst", dst->record()->getQualifiedNameAsString());
   1331         json_->Write("lbl", lbl);
   1332         json_->Write("kind", kind);
   1333         json_->Write("loc", loc);
   1334         json_->Write("ptr",
   1335                      !Parent() ? "val" :
   1336                      Parent()->IsRawPtr() ? "raw" :
   1337                      Parent()->IsRefPtr() ? "ref" :
   1338                      Parent()->IsOwnPtr() ? "own" :
   1339                      (Parent()->IsMember() ||
   1340                       Parent()->IsWeakMember()) ? "mem" :
   1341                      "val");
   1342         json_->CloseObject();
   1343       }
   1344 
   1345       void DumpField(RecordInfo* src, FieldPoint* point, const string& loc) {
   1346         src_ = src;
   1347         point_ = point;
   1348         loc_ = loc;
   1349         point_->edge()->Accept(this);
   1350       }
   1351 
   1352       void AtValue(Value* e) override {
   1353         // The liveness kind of a path from the point to this value
   1354         // is given by the innermost place that is non-strong.
   1355         Edge::LivenessKind kind = Edge::kStrong;
   1356         if (Config::IsIgnoreCycleAnnotated(point_->field())) {
   1357           kind = Edge::kWeak;
   1358         } else {
   1359           for (Context::iterator it = context().begin();
   1360                it != context().end();
   1361                ++it) {
   1362             Edge::LivenessKind pointer_kind = (*it)->Kind();
   1363             if (pointer_kind != Edge::kStrong) {
   1364               kind = pointer_kind;
   1365               break;
   1366             }
   1367           }
   1368         }
   1369         DumpEdge(
   1370             src_, e->value(), point_->field()->getNameAsString(), kind, loc_);
   1371       }
   1372 
   1373      private:
   1374       JsonWriter* json_;
   1375       RecordInfo* src_;
   1376       FieldPoint* point_;
   1377       string loc_;
   1378     };
   1379 
   1380     DumpEdgeVisitor visitor(json_);
   1381 
   1382     RecordInfo::Bases& bases = info->GetBases();
   1383     for (RecordInfo::Bases::iterator it = bases.begin();
   1384          it != bases.end();
   1385          ++it) {
   1386       visitor.DumpEdge(info,
   1387                        it->second.info(),
   1388                        "<super>",
   1389                        Edge::kStrong,
   1390                        GetLocString(it->second.spec().getLocStart()));
   1391     }
   1392 
   1393     RecordInfo::Fields& fields = info->GetFields();
   1394     for (RecordInfo::Fields::iterator it = fields.begin();
   1395          it != fields.end();
   1396          ++it) {
   1397       visitor.DumpField(info,
   1398                         &it->second,
   1399                         GetLocString(it->second.field()->getLocStart()));
   1400     }
   1401   }
   1402 
   1403   // Adds either a warning or error, based on the current handling of -Werror.
   1404   DiagnosticsEngine::Level getErrorLevel() {
   1405     return diagnostic_.getWarningsAsErrors() ? DiagnosticsEngine::Error
   1406                                              : DiagnosticsEngine::Warning;
   1407   }
   1408 
   1409   const string GetLocString(SourceLocation loc) {
   1410     const SourceManager& source_manager = instance_.getSourceManager();
   1411     PresumedLoc ploc = source_manager.getPresumedLoc(loc);
   1412     if (ploc.isInvalid())
   1413       return "";
   1414     string loc_str;
   1415     llvm::raw_string_ostream OS(loc_str);
   1416     OS << ploc.getFilename()
   1417        << ":" << ploc.getLine()
   1418        << ":" << ploc.getColumn();
   1419     return OS.str();
   1420   }
   1421 
   1422   bool IsIgnored(RecordInfo* record) {
   1423     return !record ||
   1424            !InCheckedNamespace(record) ||
   1425            IsIgnoredClass(record) ||
   1426            InIgnoredDirectory(record);
   1427   }
   1428 
   1429   bool IsIgnoredClass(RecordInfo* info) {
   1430     // Ignore any class prefixed by SameSizeAs. These are used in
   1431     // Blink to verify class sizes and don't need checking.
   1432     const string SameSizeAs = "SameSizeAs";
   1433     if (info->name().compare(0, SameSizeAs.size(), SameSizeAs) == 0)
   1434       return true;
   1435     return options_.ignored_classes.find(info->name()) !=
   1436            options_.ignored_classes.end();
   1437   }
   1438 
   1439   bool InIgnoredDirectory(RecordInfo* info) {
   1440     string filename;
   1441     if (!GetFilename(info->record()->getLocStart(), &filename))
   1442       return false;  // TODO: should we ignore non-existing file locations?
   1443     std::vector<string>::iterator it = options_.ignored_directories.begin();
   1444     for (; it != options_.ignored_directories.end(); ++it)
   1445       if (filename.find(*it) != string::npos)
   1446         return true;
   1447     return false;
   1448   }
   1449 
   1450   bool InCheckedNamespace(RecordInfo* info) {
   1451     if (!info)
   1452       return false;
   1453     for (DeclContext* context = info->record()->getDeclContext();
   1454          !context->isTranslationUnit();
   1455          context = context->getParent()) {
   1456       if (NamespaceDecl* decl = dyn_cast<NamespaceDecl>(context)) {
   1457         if (options_.checked_namespaces.find(decl->getNameAsString()) !=
   1458             options_.checked_namespaces.end()) {
   1459           return true;
   1460         }
   1461       }
   1462     }
   1463     return false;
   1464   }
   1465 
   1466   bool GetFilename(SourceLocation loc, string* filename) {
   1467     const SourceManager& source_manager = instance_.getSourceManager();
   1468     SourceLocation spelling_location = source_manager.getSpellingLoc(loc);
   1469     PresumedLoc ploc = source_manager.getPresumedLoc(spelling_location);
   1470     if (ploc.isInvalid()) {
   1471       // If we're in an invalid location, we're looking at things that aren't
   1472       // actually stated in the source.
   1473       return false;
   1474     }
   1475     *filename = ploc.getFilename();
   1476     return true;
   1477   }
   1478 
   1479   void ReportClassMustLeftMostlyDeriveGC(RecordInfo* info) {
   1480     SourceLocation loc = info->record()->getInnerLocStart();
   1481     SourceManager& manager = instance_.getSourceManager();
   1482     FullSourceLoc full_loc(loc, manager);
   1483     diagnostic_.Report(full_loc, diag_class_must_left_mostly_derive_gc_)
   1484         << info->record();
   1485   }
   1486 
   1487   void ReportClassRequiresTraceMethod(RecordInfo* info) {
   1488     SourceLocation loc = info->record()->getInnerLocStart();
   1489     SourceManager& manager = instance_.getSourceManager();
   1490     FullSourceLoc full_loc(loc, manager);
   1491     diagnostic_.Report(full_loc, diag_class_requires_trace_method_)
   1492         << info->record();
   1493 
   1494     for (RecordInfo::Bases::iterator it = info->GetBases().begin();
   1495          it != info->GetBases().end();
   1496          ++it) {
   1497       if (it->second.NeedsTracing().IsNeeded())
   1498         NoteBaseRequiresTracing(&it->second);
   1499     }
   1500 
   1501     for (RecordInfo::Fields::iterator it = info->GetFields().begin();
   1502          it != info->GetFields().end();
   1503          ++it) {
   1504       if (!it->second.IsProperlyTraced())
   1505         NoteFieldRequiresTracing(info, it->first);
   1506     }
   1507   }
   1508 
   1509   void ReportBaseRequiresTracing(RecordInfo* derived,
   1510                                  CXXMethodDecl* trace,
   1511                                  CXXRecordDecl* base) {
   1512     SourceLocation loc = trace->getLocStart();
   1513     SourceManager& manager = instance_.getSourceManager();
   1514     FullSourceLoc full_loc(loc, manager);
   1515     diagnostic_.Report(full_loc, diag_base_requires_tracing_)
   1516         << base << derived->record();
   1517   }
   1518 
   1519   void ReportFieldsRequireTracing(RecordInfo* info, CXXMethodDecl* trace) {
   1520     SourceLocation loc = trace->getLocStart();
   1521     SourceManager& manager = instance_.getSourceManager();
   1522     FullSourceLoc full_loc(loc, manager);
   1523     diagnostic_.Report(full_loc, diag_fields_require_tracing_)
   1524         << info->record();
   1525     for (RecordInfo::Fields::iterator it = info->GetFields().begin();
   1526          it != info->GetFields().end();
   1527          ++it) {
   1528       if (!it->second.IsProperlyTraced())
   1529         NoteFieldRequiresTracing(info, it->first);
   1530     }
   1531   }
   1532 
   1533   void ReportClassContainsInvalidFields(RecordInfo* info,
   1534                                         CheckFieldsVisitor::Errors* errors) {
   1535     SourceLocation loc = info->record()->getLocStart();
   1536     SourceManager& manager = instance_.getSourceManager();
   1537     FullSourceLoc full_loc(loc, manager);
   1538     bool only_warnings = options_.warn_raw_ptr;
   1539     for (CheckFieldsVisitor::Errors::iterator it = errors->begin();
   1540          only_warnings && it != errors->end();
   1541          ++it) {
   1542       if (it->second != CheckFieldsVisitor::kRawPtrToGCManagedWarning)
   1543         only_warnings = false;
   1544     }
   1545     diagnostic_.Report(full_loc, only_warnings ?
   1546                        diag_class_contains_invalid_fields_warning_ :
   1547                        diag_class_contains_invalid_fields_)
   1548         << info->record();
   1549     for (CheckFieldsVisitor::Errors::iterator it = errors->begin();
   1550          it != errors->end();
   1551          ++it) {
   1552       unsigned error;
   1553       if (it->second == CheckFieldsVisitor::kRawPtrToGCManaged ||
   1554           it->second == CheckFieldsVisitor::kRawPtrToGCManagedWarning) {
   1555         error = diag_raw_ptr_to_gc_managed_class_note_;
   1556       } else if (it->second == CheckFieldsVisitor::kRefPtrToGCManaged) {
   1557         error = diag_ref_ptr_to_gc_managed_class_note_;
   1558       } else if (it->second == CheckFieldsVisitor::kOwnPtrToGCManaged) {
   1559         error = diag_own_ptr_to_gc_managed_class_note_;
   1560       } else if (it->second == CheckFieldsVisitor::kMemberInUnmanaged) {
   1561         error = diag_member_in_unmanaged_class_note_;
   1562       } else if (it->second == CheckFieldsVisitor::kPtrFromHeapToStack) {
   1563         error = diag_stack_allocated_field_note_;
   1564       } else if (it->second == CheckFieldsVisitor::kGCDerivedPartObject) {
   1565         error = diag_part_object_to_gc_derived_class_note_;
   1566       } else {
   1567         assert(false && "Unknown field error");
   1568       }
   1569       NoteField(it->first, error);
   1570     }
   1571   }
   1572 
   1573   void ReportClassContainsGCRoots(RecordInfo* info,
   1574                                   CheckGCRootsVisitor::Errors* errors) {
   1575     SourceLocation loc = info->record()->getLocStart();
   1576     SourceManager& manager = instance_.getSourceManager();
   1577     FullSourceLoc full_loc(loc, manager);
   1578     for (CheckGCRootsVisitor::Errors::iterator it = errors->begin();
   1579          it != errors->end();
   1580          ++it) {
   1581       CheckGCRootsVisitor::RootPath::iterator path = it->begin();
   1582       FieldPoint* point = *path;
   1583       diagnostic_.Report(full_loc, diag_class_contains_gc_root_)
   1584           << info->record() << point->field();
   1585       while (++path != it->end()) {
   1586         NotePartObjectContainsGCRoot(point);
   1587         point = *path;
   1588       }
   1589       NoteFieldContainsGCRoot(point);
   1590     }
   1591   }
   1592 
   1593   void ReportFinalizerAccessesFinalizedFields(
   1594       CXXMethodDecl* dtor,
   1595       CheckFinalizerVisitor::Errors* fields) {
   1596     for (CheckFinalizerVisitor::Errors::iterator it = fields->begin();
   1597          it != fields->end();
   1598          ++it) {
   1599       SourceLocation loc = it->first->getLocStart();
   1600       SourceManager& manager = instance_.getSourceManager();
   1601       FullSourceLoc full_loc(loc, manager);
   1602       diagnostic_.Report(full_loc, diag_finalizer_accesses_finalized_field_)
   1603           << dtor << it->second->field();
   1604       NoteField(it->second, diag_finalized_field_note_);
   1605     }
   1606   }
   1607 
   1608   void ReportClassRequiresFinalization(RecordInfo* info) {
   1609     SourceLocation loc = info->record()->getInnerLocStart();
   1610     SourceManager& manager = instance_.getSourceManager();
   1611     FullSourceLoc full_loc(loc, manager);
   1612     diagnostic_.Report(full_loc, diag_class_requires_finalization_)
   1613         << info->record();
   1614   }
   1615 
   1616   void ReportClassDoesNotRequireFinalization(RecordInfo* info) {
   1617     SourceLocation loc = info->record()->getInnerLocStart();
   1618     SourceManager& manager = instance_.getSourceManager();
   1619     FullSourceLoc full_loc(loc, manager);
   1620     diagnostic_.Report(full_loc, diag_class_does_not_require_finalization_)
   1621         << info->record();
   1622   }
   1623 
   1624   void ReportOverriddenNonVirtualTrace(RecordInfo* info,
   1625                                        CXXMethodDecl* trace,
   1626                                        CXXMethodDecl* overridden) {
   1627     SourceLocation loc = trace->getLocStart();
   1628     SourceManager& manager = instance_.getSourceManager();
   1629     FullSourceLoc full_loc(loc, manager);
   1630     diagnostic_.Report(full_loc, diag_overridden_non_virtual_trace_)
   1631         << info->record() << overridden->getParent();
   1632     NoteOverriddenNonVirtualTrace(overridden);
   1633   }
   1634 
   1635   void ReportMissingTraceDispatchMethod(RecordInfo* info) {
   1636     ReportMissingDispatchMethod(info, diag_missing_trace_dispatch_method_);
   1637   }
   1638 
   1639   void ReportMissingFinalizeDispatchMethod(RecordInfo* info) {
   1640     ReportMissingDispatchMethod(info, diag_missing_finalize_dispatch_method_);
   1641   }
   1642 
   1643   void ReportMissingDispatchMethod(RecordInfo* info, unsigned error) {
   1644     SourceLocation loc = info->record()->getInnerLocStart();
   1645     SourceManager& manager = instance_.getSourceManager();
   1646     FullSourceLoc full_loc(loc, manager);
   1647     diagnostic_.Report(full_loc, error) << info->record();
   1648   }
   1649 
   1650   void ReportVirtualAndManualDispatch(RecordInfo* info,
   1651                                       CXXMethodDecl* dispatch) {
   1652     SourceLocation loc = info->record()->getInnerLocStart();
   1653     SourceManager& manager = instance_.getSourceManager();
   1654     FullSourceLoc full_loc(loc, manager);
   1655     diagnostic_.Report(full_loc, diag_virtual_and_manual_dispatch_)
   1656         << info->record();
   1657     NoteManualDispatchMethod(dispatch);
   1658   }
   1659 
   1660   void ReportMissingTraceDispatch(const FunctionDecl* dispatch,
   1661                                   RecordInfo* receiver) {
   1662     ReportMissingDispatch(dispatch, receiver, diag_missing_trace_dispatch_);
   1663   }
   1664 
   1665   void ReportMissingFinalizeDispatch(const FunctionDecl* dispatch,
   1666                                      RecordInfo* receiver) {
   1667     ReportMissingDispatch(dispatch, receiver, diag_missing_finalize_dispatch_);
   1668   }
   1669 
   1670   void ReportMissingDispatch(const FunctionDecl* dispatch,
   1671                              RecordInfo* receiver,
   1672                              unsigned error) {
   1673     SourceLocation loc = dispatch->getLocStart();
   1674     SourceManager& manager = instance_.getSourceManager();
   1675     FullSourceLoc full_loc(loc, manager);
   1676     diagnostic_.Report(full_loc, error) << receiver->record();
   1677   }
   1678 
   1679   void ReportDerivesNonStackAllocated(RecordInfo* info, BasePoint* base) {
   1680     SourceLocation loc = base->spec().getLocStart();
   1681     SourceManager& manager = instance_.getSourceManager();
   1682     FullSourceLoc full_loc(loc, manager);
   1683     diagnostic_.Report(full_loc, diag_derives_non_stack_allocated_)
   1684         << info->record() << base->info()->record();
   1685   }
   1686 
   1687   void ReportClassOverridesNew(RecordInfo* info, CXXMethodDecl* newop) {
   1688     SourceLocation loc = newop->getLocStart();
   1689     SourceManager& manager = instance_.getSourceManager();
   1690     FullSourceLoc full_loc(loc, manager);
   1691     diagnostic_.Report(full_loc, diag_class_overrides_new_) << info->record();
   1692   }
   1693 
   1694   void ReportClassDeclaresPureVirtualTrace(RecordInfo* info,
   1695                                            CXXMethodDecl* trace) {
   1696     SourceLocation loc = trace->getLocStart();
   1697     SourceManager& manager = instance_.getSourceManager();
   1698     FullSourceLoc full_loc(loc, manager);
   1699     diagnostic_.Report(full_loc, diag_class_declares_pure_virtual_trace_)
   1700         << info->record();
   1701   }
   1702 
   1703   void ReportLeftMostBaseMustBePolymorphic(RecordInfo* derived,
   1704                                            CXXRecordDecl* base) {
   1705     SourceLocation loc = base->getLocStart();
   1706     SourceManager& manager = instance_.getSourceManager();
   1707     FullSourceLoc full_loc(loc, manager);
   1708     diagnostic_.Report(full_loc, diag_left_most_base_must_be_polymorphic_)
   1709         << base << derived->record();
   1710   }
   1711 
   1712   void ReportBaseClassMustDeclareVirtualTrace(RecordInfo* derived,
   1713                                               CXXRecordDecl* base) {
   1714     SourceLocation loc = base->getLocStart();
   1715     SourceManager& manager = instance_.getSourceManager();
   1716     FullSourceLoc full_loc(loc, manager);
   1717     diagnostic_.Report(full_loc, diag_base_class_must_declare_virtual_trace_)
   1718         << base << derived->record();
   1719   }
   1720 
   1721   void NoteManualDispatchMethod(CXXMethodDecl* dispatch) {
   1722     SourceLocation loc = dispatch->getLocStart();
   1723     SourceManager& manager = instance_.getSourceManager();
   1724     FullSourceLoc full_loc(loc, manager);
   1725     diagnostic_.Report(full_loc, diag_manual_dispatch_method_note_) << dispatch;
   1726   }
   1727 
   1728   void NoteBaseRequiresTracing(BasePoint* base) {
   1729     SourceLocation loc = base->spec().getLocStart();
   1730     SourceManager& manager = instance_.getSourceManager();
   1731     FullSourceLoc full_loc(loc, manager);
   1732     diagnostic_.Report(full_loc, diag_base_requires_tracing_note_)
   1733         << base->info()->record();
   1734   }
   1735 
   1736   void NoteFieldRequiresTracing(RecordInfo* holder, FieldDecl* field) {
   1737     NoteField(field, diag_field_requires_tracing_note_);
   1738   }
   1739 
   1740   void NotePartObjectContainsGCRoot(FieldPoint* point) {
   1741     FieldDecl* field = point->field();
   1742     SourceLocation loc = field->getLocStart();
   1743     SourceManager& manager = instance_.getSourceManager();
   1744     FullSourceLoc full_loc(loc, manager);
   1745     diagnostic_.Report(full_loc, diag_part_object_contains_gc_root_note_)
   1746         << field << field->getParent();
   1747   }
   1748 
   1749   void NoteFieldContainsGCRoot(FieldPoint* point) {
   1750     NoteField(point, diag_field_contains_gc_root_note_);
   1751   }
   1752 
   1753   void NoteUserDeclaredDestructor(CXXMethodDecl* dtor) {
   1754     SourceLocation loc = dtor->getLocStart();
   1755     SourceManager& manager = instance_.getSourceManager();
   1756     FullSourceLoc full_loc(loc, manager);
   1757     diagnostic_.Report(full_loc, diag_user_declared_destructor_note_);
   1758   }
   1759 
   1760   void NoteUserDeclaredFinalizer(CXXMethodDecl* dtor) {
   1761     SourceLocation loc = dtor->getLocStart();
   1762     SourceManager& manager = instance_.getSourceManager();
   1763     FullSourceLoc full_loc(loc, manager);
   1764     diagnostic_.Report(full_loc, diag_user_declared_finalizer_note_);
   1765   }
   1766 
   1767   void NoteBaseRequiresFinalization(BasePoint* base) {
   1768     SourceLocation loc = base->spec().getLocStart();
   1769     SourceManager& manager = instance_.getSourceManager();
   1770     FullSourceLoc full_loc(loc, manager);
   1771     diagnostic_.Report(full_loc, diag_base_requires_finalization_note_)
   1772         << base->info()->record();
   1773   }
   1774 
   1775   void NoteField(FieldPoint* point, unsigned note) {
   1776     NoteField(point->field(), note);
   1777   }
   1778 
   1779   void NoteField(FieldDecl* field, unsigned note) {
   1780     SourceLocation loc = field->getLocStart();
   1781     SourceManager& manager = instance_.getSourceManager();
   1782     FullSourceLoc full_loc(loc, manager);
   1783     diagnostic_.Report(full_loc, note) << field;
   1784   }
   1785 
   1786   void NoteOverriddenNonVirtualTrace(CXXMethodDecl* overridden) {
   1787     SourceLocation loc = overridden->getLocStart();
   1788     SourceManager& manager = instance_.getSourceManager();
   1789     FullSourceLoc full_loc(loc, manager);
   1790     diagnostic_.Report(full_loc, diag_overridden_non_virtual_trace_note_)
   1791         << overridden;
   1792   }
   1793 
   1794   unsigned diag_class_must_left_mostly_derive_gc_;
   1795   unsigned diag_class_requires_trace_method_;
   1796   unsigned diag_base_requires_tracing_;
   1797   unsigned diag_fields_require_tracing_;
   1798   unsigned diag_class_contains_invalid_fields_;
   1799   unsigned diag_class_contains_invalid_fields_warning_;
   1800   unsigned diag_class_contains_gc_root_;
   1801   unsigned diag_class_requires_finalization_;
   1802   unsigned diag_class_does_not_require_finalization_;
   1803   unsigned diag_finalizer_accesses_finalized_field_;
   1804   unsigned diag_overridden_non_virtual_trace_;
   1805   unsigned diag_missing_trace_dispatch_method_;
   1806   unsigned diag_missing_finalize_dispatch_method_;
   1807   unsigned diag_virtual_and_manual_dispatch_;
   1808   unsigned diag_missing_trace_dispatch_;
   1809   unsigned diag_missing_finalize_dispatch_;
   1810   unsigned diag_derives_non_stack_allocated_;
   1811   unsigned diag_class_overrides_new_;
   1812   unsigned diag_class_declares_pure_virtual_trace_;
   1813   unsigned diag_left_most_base_must_be_polymorphic_;
   1814   unsigned diag_base_class_must_declare_virtual_trace_;
   1815 
   1816   unsigned diag_base_requires_tracing_note_;
   1817   unsigned diag_field_requires_tracing_note_;
   1818   unsigned diag_raw_ptr_to_gc_managed_class_note_;
   1819   unsigned diag_ref_ptr_to_gc_managed_class_note_;
   1820   unsigned diag_own_ptr_to_gc_managed_class_note_;
   1821   unsigned diag_stack_allocated_field_note_;
   1822   unsigned diag_member_in_unmanaged_class_note_;
   1823   unsigned diag_part_object_to_gc_derived_class_note_;
   1824   unsigned diag_part_object_contains_gc_root_note_;
   1825   unsigned diag_field_contains_gc_root_note_;
   1826   unsigned diag_finalized_field_note_;
   1827   unsigned diag_user_declared_destructor_note_;
   1828   unsigned diag_user_declared_finalizer_note_;
   1829   unsigned diag_base_requires_finalization_note_;
   1830   unsigned diag_field_requires_finalization_note_;
   1831   unsigned diag_overridden_non_virtual_trace_note_;
   1832   unsigned diag_manual_dispatch_method_note_;
   1833 
   1834   CompilerInstance& instance_;
   1835   DiagnosticsEngine& diagnostic_;
   1836   BlinkGCPluginOptions options_;
   1837   RecordCache cache_;
   1838   JsonWriter* json_;
   1839 };
   1840 
   1841 class BlinkGCPluginAction : public PluginASTAction {
   1842  public:
   1843   BlinkGCPluginAction() {}
   1844 
   1845  protected:
   1846   // Overridden from PluginASTAction:
   1847   virtual std::unique_ptr<ASTConsumer> CreateASTConsumer(
   1848       CompilerInstance& instance,
   1849       llvm::StringRef ref) {
   1850     return llvm::make_unique<BlinkGCPluginConsumer>(instance, options_);
   1851   }
   1852 
   1853   virtual bool ParseArgs(const CompilerInstance& instance,
   1854                          const std::vector<string>& args) {
   1855     bool parsed = true;
   1856 
   1857     for (size_t i = 0; i < args.size() && parsed; ++i) {
   1858       if (args[i] == "enable-oilpan") {
   1859         options_.enable_oilpan = true;
   1860       } else if (args[i] == "dump-graph") {
   1861         options_.dump_graph = true;
   1862       } else if (args[i] == "warn-raw-ptr") {
   1863         options_.warn_raw_ptr = true;
   1864       } else if (args[i] == "warn-unneeded-finalizer") {
   1865         options_.warn_unneeded_finalizer = true;
   1866       } else {
   1867         parsed = false;
   1868         llvm::errs() << "Unknown blink-gc-plugin argument: " << args[i] << "\n";
   1869       }
   1870     }
   1871 
   1872     return parsed;
   1873   }
   1874 
   1875  private:
   1876   BlinkGCPluginOptions options_;
   1877 };
   1878 
   1879 }  // namespace
   1880 
   1881 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X(
   1882     "blink-gc-plugin",
   1883     "Check Blink GC invariants");
   1884