Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / tools / clang / blink_gc_plugin / BlinkGCPlugin.cpp
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");