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
21using namespace clang;
22using std::string;
23
24namespace {
25
26const char kClassMustLeftMostlyDeriveGC[] =
27    "[blink-gc] Class %0 must derive its GC base in the left-most position.";
28
29const char kClassRequiresTraceMethod[] =
30    "[blink-gc] Class %0 requires a trace method.";
31
32const char kBaseRequiresTracing[] =
33    "[blink-gc] Base class %0 of derived class %1 requires tracing.";
34
35const char kBaseRequiresTracingNote[] =
36    "[blink-gc] Untraced base class %0 declared here:";
37
38const char kFieldsRequireTracing[] =
39    "[blink-gc] Class %0 has untraced fields that require tracing.";
40
41const char kFieldRequiresTracingNote[] =
42    "[blink-gc] Untraced field %0 declared here:";
43
44const char kClassContainsInvalidFields[] =
45    "[blink-gc] Class %0 contains invalid fields.";
46
47const char kClassContainsGCRoot[] =
48    "[blink-gc] Class %0 contains GC root in field %1.";
49
50const char kClassRequiresFinalization[] =
51    "[blink-gc] Class %0 requires finalization.";
52
53const char kClassDoesNotRequireFinalization[] =
54    "[blink-gc] Class %0 may not require finalization.";
55
56const char kFinalizerAccessesFinalizedField[] =
57    "[blink-gc] Finalizer %0 accesses potentially finalized field %1.";
58
59const char kRawPtrToGCManagedClassNote[] =
60    "[blink-gc] Raw pointer field %0 to a GC managed class declared here:";
61
62const char kRefPtrToGCManagedClassNote[] =
63    "[blink-gc] RefPtr field %0 to a GC managed class declared here:";
64
65const char kOwnPtrToGCManagedClassNote[] =
66    "[blink-gc] OwnPtr field %0 to a GC managed class declared here:";
67
68const char kStackAllocatedFieldNote[] =
69    "[blink-gc] Stack-allocated field %0 declared here:";
70
71const char kMemberInUnmanagedClassNote[] =
72    "[blink-gc] Member field %0 in unmanaged class declared here:";
73
74const char kPartObjectToGCDerivedClassNote[] =
75    "[blink-gc] Part-object field %0 to a GC derived class declared here:";
76
77const char kPartObjectContainsGCRootNote[] =
78    "[blink-gc] Field %0 with embedded GC root in %1 declared here:";
79
80const char kFieldContainsGCRootNote[] =
81    "[blink-gc] Field %0 defining a GC root declared here:";
82
83const char kOverriddenNonVirtualTrace[] =
84    "[blink-gc] Class %0 overrides non-virtual trace of base class %1.";
85
86const char kOverriddenNonVirtualTraceNote[] =
87    "[blink-gc] Non-virtual trace method declared here:";
88
89const char kMissingTraceDispatchMethod[] =
90    "[blink-gc] Class %0 is missing manual trace dispatch.";
91
92const char kMissingFinalizeDispatchMethod[] =
93    "[blink-gc] Class %0 is missing manual finalize dispatch.";
94
95const char kVirtualAndManualDispatch[] =
96    "[blink-gc] Class %0 contains or inherits virtual methods"
97    " but implements manual dispatching.";
98
99const char kMissingTraceDispatch[] =
100    "[blink-gc] Missing dispatch to class %0 in manual trace dispatch.";
101
102const char kMissingFinalizeDispatch[] =
103    "[blink-gc] Missing dispatch to class %0 in manual finalize dispatch.";
104
105const char kFinalizedFieldNote[] =
106    "[blink-gc] Potentially finalized field %0 declared here:";
107
108const char kUserDeclaredDestructorNote[] =
109    "[blink-gc] User-declared destructor declared here:";
110
111const char kUserDeclaredFinalizerNote[] =
112    "[blink-gc] User-declared finalizer declared here:";
113
114const char kBaseRequiresFinalizationNote[] =
115    "[blink-gc] Base class %0 requiring finalization declared here:";
116
117const char kFieldRequiresFinalizationNote[] =
118    "[blink-gc] Field %0 requiring finalization declared here:";
119
120const char kManualDispatchMethodNote[] =
121    "[blink-gc] Manual dispatch %0 declared here:";
122
123const char kDerivesNonStackAllocated[] =
124    "[blink-gc] Stack-allocated class %0 derives class %1"
125    " which is not stack allocated.";
126
127const char kClassOverridesNew[] =
128    "[blink-gc] Garbage collected class %0"
129    " is not permitted to override its new operator.";
130
131const char kClassDeclaresPureVirtualTrace[] =
132    "[blink-gc] Garbage collected class %0"
133    " is not permitted to declare a pure-virtual trace method.";
134
135const char kLeftMostBaseMustBePolymorphic[] =
136    "[blink-gc] Left-most base class %0 of derived class %1"
137    " must be polymorphic.";
138
139const char kBaseClassMustDeclareVirtualTrace[] =
140    "[blink-gc] Left-most base class %0 of derived class %1"
141    " must define a virtual trace method.";
142
143struct 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
158typedef std::vector<CXXRecordDecl*> RecordVector;
159typedef std::vector<CXXMethodDecl*> MethodVector;
160
161// Test if a template specialization is an instantiation.
162static 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.
182class 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.
215class 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.
299class 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.
322class 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.
572class 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.
626class 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
742class EmptyStmtVisitor
743    : public RecursiveASTVisitor<EmptyStmtVisitor> {
744public:
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  }
759private:
760  EmptyStmtVisitor() : empty_(true) {}
761  bool empty_;
762};
763
764// Main class containing checks for various invariants of the Blink
765// garbage collection infrastructure.
766class 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
1841class 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
1881static FrontendPluginRegistry::Add<BlinkGCPluginAction> X(
1882    "blink-gc-plugin",
1883    "Check Blink GC invariants");
1884