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

Side by Side Diff: tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp

Issue 197863003: Check consistency of manual trace and finalization dispatching. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: finalization and considered-abstract Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // This clang plugin checks various invariants of the Blink garbage 5 // This clang plugin checks various invariants of the Blink garbage
6 // collection infrastructure. 6 // collection infrastructure.
7 // 7 //
8 // Errors are described at: 8 // Errors are described at:
9 // http://www.chromium.org/developers/blink-gc-plugin-errors 9 // http://www.chromium.org/developers/blink-gc-plugin-errors
10 10
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 55
56 const char kOwnPtrToGCManagedClassNote[] = 56 const char kOwnPtrToGCManagedClassNote[] =
57 "[blink-gc] OwnPtr field %0 to a GC managed class declared here:"; 57 "[blink-gc] OwnPtr field %0 to a GC managed class declared here:";
58 58
59 const char kPartObjectContainsGCRoot[] = 59 const char kPartObjectContainsGCRoot[] =
60 "[blink-gc] Field %0 with embedded GC root in %1 declared here:"; 60 "[blink-gc] Field %0 with embedded GC root in %1 declared here:";
61 61
62 const char kFieldContainsGCRoot[] = 62 const char kFieldContainsGCRoot[] =
63 "[blink-gc] Field %0 defining a GC root declared here:"; 63 "[blink-gc] Field %0 defining a GC root declared here:";
64 64
65 const char kOverriddenNonVirtualTrace[] =
66 "[blink-gc] Class %0 overrides non-virtual trace of base class %1.";
67
68 const char kOverriddenNonVirtualTraceNote[] =
69 "[blink-gc] Non-virtual trace method declared here:";
70
71 const char kVirtualTraceAndManualDispatch[] =
72 "[blink-gc] Class %0 declares a virtual trace"
73 " but implements manual dispatching.";
74
75 const char kVirtualAndManualDispatch[] =
76 "[blink-gc] Class %0 contains or inherits virtual methods"
77 " but implements manual dispatching.";
78
79 const char kMissingTraceDispatch[] =
80 "[blink-gc] Missing dispatch to class %0 in manual trace dispatch.";
81
82 const char kMissingFinalize[] =
83 "[blink-gc] Class %0 is missing manual finalize dispatch.";
84
85 const char kMissingFinalizeDispatch[] =
86 "[blink-gc] Missing dispatch to class %0 in manual finalize dispatch.";
87
65 const char kFinalizedFieldNote[] = 88 const char kFinalizedFieldNote[] =
66 "[blink-gc] Potentially finalized field %0 declared here:"; 89 "[blink-gc] Potentially finalized field %0 declared here:";
67 90
68 const char kUserDeclaredDestructorNote[] = 91 const char kUserDeclaredDestructorNote[] =
69 "[blink-gc] User-declared destructor declared here:"; 92 "[blink-gc] User-declared destructor declared here:";
70 93
71 const char kBaseRequiresFinalizationNote[] = 94 const char kBaseRequiresFinalizationNote[] =
72 "[blink-gc] Base class %0 requiring finalization declared here:"; 95 "[blink-gc] Base class %0 requiring finalization declared here:";
73 96
74 const char kFieldRequiresFinalizationNote[] = 97 const char kFieldRequiresFinalizationNote[] =
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 : blacklist_context_(false), cache_(cache) {} 192 : blacklist_context_(false), cache_(cache) {}
170 193
171 Errors& finalized_fields() { return finalized_fields_; } 194 Errors& finalized_fields() { return finalized_fields_; }
172 195
173 bool WalkUpFromCXXOperatorCallExpr(CXXOperatorCallExpr* expr) { 196 bool WalkUpFromCXXOperatorCallExpr(CXXOperatorCallExpr* expr) {
174 // Only continue the walk-up if the operator is a blacklisted one. 197 // Only continue the walk-up if the operator is a blacklisted one.
175 switch (expr->getOperator()) { 198 switch (expr->getOperator()) {
176 case OO_Arrow: 199 case OO_Arrow:
177 case OO_Subscript: 200 case OO_Subscript:
178 this->WalkUpFromCallExpr(expr); 201 this->WalkUpFromCallExpr(expr);
202 default:
203 return true;
179 } 204 }
180 return true;
181 } 205 }
182 206
183 // We consider all non-operator calls to be blacklisted contexts. 207 // We consider all non-operator calls to be blacklisted contexts.
184 bool WalkUpFromCallExpr(CallExpr* expr) { 208 bool WalkUpFromCallExpr(CallExpr* expr) {
185 bool prev_blacklist_context = blacklist_context_; 209 bool prev_blacklist_context = blacklist_context_;
186 blacklist_context_ = true; 210 blacklist_context_ = true;
187 for (size_t i = 0; i < expr->getNumArgs(); ++i) 211 for (size_t i = 0; i < expr->getNumArgs(); ++i)
188 this->TraverseStmt(expr->getArg(i)); 212 this->TraverseStmt(expr->getArg(i));
189 blacklist_context_ = prev_blacklist_context; 213 blacklist_context_ = prev_blacklist_context;
190 return true; 214 return true;
(...skipping 22 matching lines...) Expand all
213 point->edge()->Accept(&visitor); 237 point->edge()->Accept(&visitor);
214 return visitor.might_be_collected(); 238 return visitor.might_be_collected();
215 } 239 }
216 240
217 private: 241 private:
218 bool blacklist_context_; 242 bool blacklist_context_;
219 Errors finalized_fields_; 243 Errors finalized_fields_;
220 RecordCache* cache_; 244 RecordCache* cache_;
221 }; 245 };
222 246
247 // This visitor checks that a method contains within its body, a call to a
248 // method on the provided receiver class. This is used to check manual
249 // dispatching for trace and finalize methods.
250 class CheckDispatchVisitor : public RecursiveASTVisitor<CheckDispatchVisitor> {
251 public:
252 CheckDispatchVisitor(RecordInfo* receiver)
253 : receiver_(receiver), dispatched_to_receiver_(false) { }
254
255 bool dispatched_to_receiver() { return dispatched_to_receiver_; }
256
257 bool VisitMemberExpr(MemberExpr* member) {
258 if (CXXMethodDecl* fn = dyn_cast<CXXMethodDecl>(member->getMemberDecl())) {
259 if (fn->getParent() == receiver_->record())
260 dispatched_to_receiver_ = true;
261 }
262 return true;
263 }
264
265 private:
266 RecordInfo* receiver_;
267 bool dispatched_to_receiver_;
268 };
269
223 // This visitor checks a tracing method by traversing its body. 270 // This visitor checks a tracing method by traversing its body.
224 // - A member field is considered traced if it is referenced in the body. 271 // - A member field is considered traced if it is referenced in the body.
225 // - A base is traced if a base-qualified call to a trace method is found. 272 // - A base is traced if a base-qualified call to a trace method is found.
226 class CheckTraceVisitor : public RecursiveASTVisitor<CheckTraceVisitor> { 273 class CheckTraceVisitor : public RecursiveASTVisitor<CheckTraceVisitor> {
227 public: 274 public:
228 CheckTraceVisitor(CXXMethodDecl* trace, RecordInfo* info) 275 CheckTraceVisitor(CXXMethodDecl* trace, RecordInfo* info)
229 : trace_(trace), info_(info) {} 276 : trace_(trace), info_(info) {}
230 277
231 // Allow recursive traversal by using VisitMemberExpr. 278 // Allow recursive traversal by using VisitMemberExpr.
232 bool VisitMemberExpr(MemberExpr* member) { 279 bool VisitMemberExpr(MemberExpr* member) {
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 diagnostic_.getCustomDiagID(getErrorLevel(), kFieldsRequireTracing); 486 diagnostic_.getCustomDiagID(getErrorLevel(), kFieldsRequireTracing);
440 diag_class_contains_invalid_fields_ = 487 diag_class_contains_invalid_fields_ =
441 diagnostic_.getCustomDiagID(getErrorLevel(), 488 diagnostic_.getCustomDiagID(getErrorLevel(),
442 kClassContainsInvalidFields); 489 kClassContainsInvalidFields);
443 diag_class_contains_gc_root_ = 490 diag_class_contains_gc_root_ =
444 diagnostic_.getCustomDiagID(getErrorLevel(), kClassContainsGCRoot); 491 diagnostic_.getCustomDiagID(getErrorLevel(), kClassContainsGCRoot);
445 diag_class_requires_finalization_ = diagnostic_.getCustomDiagID( 492 diag_class_requires_finalization_ = diagnostic_.getCustomDiagID(
446 getErrorLevel(), kClassRequiresFinalization); 493 getErrorLevel(), kClassRequiresFinalization);
447 diag_finalizer_accesses_finalized_field_ = diagnostic_.getCustomDiagID( 494 diag_finalizer_accesses_finalized_field_ = diagnostic_.getCustomDiagID(
448 getErrorLevel(), kFinalizerAccessesFinalizedField); 495 getErrorLevel(), kFinalizerAccessesFinalizedField);
496 diag_overridden_non_virtual_trace_ = diagnostic_.getCustomDiagID(
497 getErrorLevel(), kOverriddenNonVirtualTrace);
498 diag_virtual_and_manual_dispatch_ = diagnostic_.getCustomDiagID(
499 getErrorLevel(), kVirtualAndManualDispatch);
500 diag_missing_trace_dispatch_ = diagnostic_.getCustomDiagID(
501 getErrorLevel(), kMissingTraceDispatch);
502 diag_missing_finalize_ = diagnostic_.getCustomDiagID(
503 getErrorLevel(), kMissingFinalize);
504 diag_missing_finalize_dispatch_ = diagnostic_.getCustomDiagID(
505 getErrorLevel(), kMissingFinalizeDispatch);
449 506
450 // Register note messages. 507 // Register note messages.
451 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID( 508 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID(
452 DiagnosticsEngine::Note, kFieldRequiresTracingNote); 509 DiagnosticsEngine::Note, kFieldRequiresTracingNote);
453 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( 510 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
454 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); 511 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote);
455 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( 512 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
456 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); 513 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote);
457 diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( 514 diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
458 DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote); 515 DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote);
459 diag_part_object_contains_gc_root_note_ = diagnostic_.getCustomDiagID( 516 diag_part_object_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
460 DiagnosticsEngine::Note, kPartObjectContainsGCRoot); 517 DiagnosticsEngine::Note, kPartObjectContainsGCRoot);
461 diag_field_contains_gc_root_note_ = diagnostic_.getCustomDiagID( 518 diag_field_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
462 DiagnosticsEngine::Note, kFieldContainsGCRoot); 519 DiagnosticsEngine::Note, kFieldContainsGCRoot);
463 diag_finalized_field_note_ = diagnostic_.getCustomDiagID( 520 diag_finalized_field_note_ = diagnostic_.getCustomDiagID(
464 DiagnosticsEngine::Note, kFinalizedFieldNote); 521 DiagnosticsEngine::Note, kFinalizedFieldNote);
465 diag_user_declared_destructor_note_ = diagnostic_.getCustomDiagID( 522 diag_user_declared_destructor_note_ = diagnostic_.getCustomDiagID(
466 DiagnosticsEngine::Note, kUserDeclaredDestructorNote); 523 DiagnosticsEngine::Note, kUserDeclaredDestructorNote);
467 diag_base_requires_finalization_note_ = diagnostic_.getCustomDiagID( 524 diag_base_requires_finalization_note_ = diagnostic_.getCustomDiagID(
468 DiagnosticsEngine::Note, kBaseRequiresFinalizationNote); 525 DiagnosticsEngine::Note, kBaseRequiresFinalizationNote);
469 diag_field_requires_finalization_note_ = diagnostic_.getCustomDiagID( 526 diag_field_requires_finalization_note_ = diagnostic_.getCustomDiagID(
470 DiagnosticsEngine::Note, kFieldRequiresFinalizationNote); 527 DiagnosticsEngine::Note, kFieldRequiresFinalizationNote);
528 diag_overridden_non_virtual_trace_note_ = diagnostic_.getCustomDiagID(
529 DiagnosticsEngine::Note, kOverriddenNonVirtualTraceNote);
471 } 530 }
472 531
473 virtual void HandleTranslationUnit(ASTContext& context) { 532 virtual void HandleTranslationUnit(ASTContext& context) {
474 CollectVisitor visitor; 533 CollectVisitor visitor;
475 visitor.TraverseDecl(context.getTranslationUnitDecl()); 534 visitor.TraverseDecl(context.getTranslationUnitDecl());
476 535
477 for (RecordVector::iterator it = visitor.record_decls().begin(); 536 for (RecordVector::iterator it = visitor.record_decls().begin();
478 it != visitor.record_decls().end(); 537 it != visitor.record_decls().end();
479 ++it) { 538 ++it) {
480 CheckRecord(cache_.Lookup(*it)); 539 CheckRecord(cache_.Lookup(*it));
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 574
516 // Check a class-like object (eg, class, specialization, instantiation). 575 // Check a class-like object (eg, class, specialization, instantiation).
517 void CheckClass(RecordInfo* info) { 576 void CheckClass(RecordInfo* info) {
518 // Don't enforce tracing of stack allocated objects. 577 // Don't enforce tracing of stack allocated objects.
519 if (!info || info->IsStackAllocated()) 578 if (!info || info->IsStackAllocated())
520 return; 579 return;
521 580
522 if (info->RequiresTraceMethod() && !info->GetTraceMethod()) 581 if (info->RequiresTraceMethod() && !info->GetTraceMethod())
523 ReportClassRequiresTraceMethod(info); 582 ReportClassRequiresTraceMethod(info);
524 583
584 if (CXXMethodDecl* dispatch = info->GetTraceDispatchMethod())
585 CheckDispatch(info, dispatch);
586
525 { 587 {
526 CheckFieldsVisitor visitor(options_); 588 CheckFieldsVisitor visitor(options_);
527 if (visitor.ContainsInvalidFields(info)) 589 if (visitor.ContainsInvalidFields(info))
528 ReportClassContainsInvalidFields(info, &visitor.invalid_fields()); 590 ReportClassContainsInvalidFields(info, &visitor.invalid_fields());
529 } 591 }
530 592
531 if (info->IsGCDerived()) { 593 if (info->IsGCDerived()) {
532 CheckGCRootsVisitor visitor; 594 CheckGCRootsVisitor visitor;
533 if (visitor.ContainsGCRoots(info)) 595 if (visitor.ContainsGCRoots(info))
534 ReportClassContainsGCRoots(info, &visitor.gc_roots()); 596 ReportClassContainsGCRoots(info, &visitor.gc_roots());
535 597
536 if (info->NeedsFinalization()) 598 if (info->NeedsFinalization())
537 CheckFinalization(info); 599 CheckFinalization(info);
538 } 600 }
539 } 601 }
540 602
603 void CheckDispatch(RecordInfo* info, CXXMethodDecl* dispatch) {
604 if (info->record()->isPolymorphic())
605 ReportVirtualAndManualDispatch(info);
606
607 CXXRecordDecl* base = dispatch->getParent();
608 // If this class is finalized get its finalize dispatch method.
609 bool is_finalized = info->IsGCFinalized();
610 CXXMethodDecl* finalize = 0;
611 if (is_finalized) {
612 for (CXXRecordDecl::method_iterator it = base->method_begin();
613 it != base->method_end();
614 ++it) {
615 if (it->getNameAsString() == kFinalizeName) {
616 finalize = *it;
617 break;
618 }
619 }
620 }
621
622 // Check that the dispatching class implements finalize if needed.
623 if (is_finalized && !finalize && base == info->record())
624 ReportMissingFinalize(info);
625
626 // If this is a non-abstract class check that it is dispatched to.
627 // TODO: Create a global variant of this local check. We can only check if
628 // the dispatch body is known in this compilation unit.
629 if (info->IsConsideredAbstract())
630 return;
631
632 const FunctionDecl* defn;
633
634 if (dispatch->isDefined(defn)) {
635 CheckDispatchVisitor visitor(info);
636 visitor.TraverseStmt(defn->getBody());
637 if (!visitor.dispatched_to_receiver())
638 ReportMissingTraceDispatch(defn, info);
639 }
640
641 if (is_finalized && finalize && finalize->isDefined(defn)) {
642 CheckDispatchVisitor visitor(info);
643 visitor.TraverseStmt(defn->getBody());
644 if (!visitor.dispatched_to_receiver())
645 ReportMissingFinalizeDispatch(defn, info);
646 }
647 }
648
541 void CheckFinalization(RecordInfo* info) { 649 void CheckFinalization(RecordInfo* info) {
542 // TODO: Should we collect destructors similar to trace methods? 650 // TODO: Should we collect destructors similar to trace methods?
543 // TODO: Check overridden finalize(). 651 // TODO: Check overridden finalize().
544 CXXDestructorDecl* dtor = info->record()->getDestructor(); 652 CXXDestructorDecl* dtor = info->record()->getDestructor();
545 653
546 // For finalized classes, check the finalization method if possible. 654 // For finalized classes, check the finalization method if possible.
547 if (info->IsGCFinalized()) { 655 if (info->IsGCFinalized()) {
548 if (dtor && dtor->hasBody()) { 656 if (dtor && dtor->hasBody()) {
549 CheckFinalizerVisitor visitor(&cache_); 657 CheckFinalizerVisitor visitor(&cache_);
550 visitor.TraverseCXXMethodDecl(dtor); 658 visitor.TraverseCXXMethodDecl(dtor);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
602 return; 710 return;
603 } 711 }
604 712
605 CheckTraceOrDispatchMethod(parent, method); 713 CheckTraceOrDispatchMethod(parent, method);
606 } 714 }
607 715
608 // Determine what type of tracing method this is (dispatch or trace). 716 // Determine what type of tracing method this is (dispatch or trace).
609 void CheckTraceOrDispatchMethod(RecordInfo* parent, CXXMethodDecl* method) { 717 void CheckTraceOrDispatchMethod(RecordInfo* parent, CXXMethodDecl* method) {
610 bool isTraceAfterDispatch; 718 bool isTraceAfterDispatch;
611 if (Config::IsTraceMethod(method, &isTraceAfterDispatch)) { 719 if (Config::IsTraceMethod(method, &isTraceAfterDispatch)) {
612 if (!isTraceAfterDispatch && parent->GetTraceDispatchMethod()) 720 if (isTraceAfterDispatch || !parent->GetTraceDispatchMethod()) {
613 CheckTraceDispatchMethod(parent, method); 721 CheckTraceMethod(parent, method, isTraceAfterDispatch);
614 else 722 }
615 CheckTraceMethod(parent, method); 723 // Dispatch methods are checked when we identify subclasses.
616 } 724 }
617 } 725 }
618 726
619 // Check a tracing dispatch (ie, it dispatches to traceAfterDispatch) 727 // Check an actual trace method.
620 void CheckTraceDispatchMethod(RecordInfo* parent, CXXMethodDecl* trace) { 728 void CheckTraceMethod(RecordInfo* parent,
621 // TODO: check correct dispatch. 729 CXXMethodDecl* trace,
622 } 730 bool isTraceAfterDispatch) {
731 // A non-virtual trace method must not override another trace.
732 if (!isTraceAfterDispatch && !trace->isVirtual()) {
733 for (RecordInfo::Bases::iterator it = parent->GetBases().begin();
734 it != parent->GetBases().end();
735 ++it) {
736 RecordInfo* base = it->second.info();
737 // We allow mixin bases to contain a non-virtual trace since it is will
738 // never be used for dispatching.
739 if (base->IsUnmixedGCMixin())
Mads Ager (chromium) 2014/03/18 09:19:32 Can we find a better name for IsUnmixedGCMixin? I
zerny-chromium 2014/03/18 10:03:41 Changed to just IsGCMixin().
740 continue;
741 if (CXXMethodDecl* other = base->InheritsNonVirtualTrace())
742 ReportOverriddenNonVirtualTrace(parent, trace, other);
743 }
744 }
623 745
624 // Check an actual trace method.
625 void CheckTraceMethod(RecordInfo* parent, CXXMethodDecl* trace) {
626 CheckTraceVisitor visitor(trace, parent); 746 CheckTraceVisitor visitor(trace, parent);
627 visitor.TraverseCXXMethodDecl(trace); 747 visitor.TraverseCXXMethodDecl(trace);
628 748
629 for (RecordInfo::Bases::iterator it = parent->GetBases().begin(); 749 for (RecordInfo::Bases::iterator it = parent->GetBases().begin();
630 it != parent->GetBases().end(); 750 it != parent->GetBases().end();
631 ++it) { 751 ++it) {
632 if (!it->second.IsProperlyTraced()) 752 if (!it->second.IsProperlyTraced())
633 ReportBaseRequiresTracing(parent, trace, it->first); 753 ReportBaseRequiresTracing(parent, trace, it->first);
634 } 754 }
635 755
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
800 } 920 }
801 921
802 void ReportClassRequiresFinalization(RecordInfo* info) { 922 void ReportClassRequiresFinalization(RecordInfo* info) {
803 SourceLocation loc = info->record()->getInnerLocStart(); 923 SourceLocation loc = info->record()->getInnerLocStart();
804 SourceManager& manager = instance_.getSourceManager(); 924 SourceManager& manager = instance_.getSourceManager();
805 FullSourceLoc full_loc(loc, manager); 925 FullSourceLoc full_loc(loc, manager);
806 diagnostic_.Report(full_loc, diag_class_requires_finalization_) 926 diagnostic_.Report(full_loc, diag_class_requires_finalization_)
807 << info->record(); 927 << info->record();
808 } 928 }
809 929
930 void ReportOverriddenNonVirtualTrace(RecordInfo* info,
931 CXXMethodDecl* trace,
932 CXXMethodDecl* overridden) {
933 SourceLocation loc = trace->getLocStart();
934 SourceManager& manager = instance_.getSourceManager();
935 FullSourceLoc full_loc(loc, manager);
936 diagnostic_.Report(full_loc, diag_overridden_non_virtual_trace_)
937 << info->record()
938 << overridden->getParent();
939 NoteOverriddenNonVirtualTrace(overridden);
940 }
941
942 void ReportVirtualAndManualDispatch(RecordInfo* info) {
943 SourceLocation loc = info->record()->getInnerLocStart();
944 SourceManager& manager = instance_.getSourceManager();
945 FullSourceLoc full_loc(loc, manager);
946 diagnostic_.Report(full_loc, diag_virtual_and_manual_dispatch_)
947 << info->record();
948 }
949
950 void ReportMissingTraceDispatch(const FunctionDecl* dispatch,
951 RecordInfo* receiver) {
952 ReportMissingDispatch(dispatch, receiver, diag_missing_trace_dispatch_);
953 }
954
955 void ReportMissingFinalize(RecordInfo* info) {
956 SourceLocation loc = info->record()->getInnerLocStart();
957 SourceManager& manager = instance_.getSourceManager();
958 FullSourceLoc full_loc(loc, manager);
959 diagnostic_.Report(full_loc, diag_missing_finalize_) << info->record();
960 }
961
962 void ReportMissingFinalizeDispatch(const FunctionDecl* dispatch,
963 RecordInfo* receiver) {
964 ReportMissingDispatch(dispatch, receiver, diag_missing_finalize_dispatch_);
965 }
966
967 void ReportMissingDispatch(const FunctionDecl* dispatch,
968 RecordInfo* receiver,
969 unsigned error) {
970 SourceLocation loc = dispatch->getLocStart();
971 SourceManager& manager = instance_.getSourceManager();
972 FullSourceLoc full_loc(loc, manager);
973 diagnostic_.Report(full_loc, error) << receiver->record();
974 }
975
810 void NoteFieldRequiresTracing(RecordInfo* holder, FieldDecl* field) { 976 void NoteFieldRequiresTracing(RecordInfo* holder, FieldDecl* field) {
811 NoteField(field, diag_field_requires_tracing_note_); 977 NoteField(field, diag_field_requires_tracing_note_);
812 } 978 }
813 979
814 void NotePartObjectContainsGCRoot(FieldPoint* point) { 980 void NotePartObjectContainsGCRoot(FieldPoint* point) {
815 FieldDecl* field = point->field(); 981 FieldDecl* field = point->field();
816 SourceLocation loc = field->getLocStart(); 982 SourceLocation loc = field->getLocStart();
817 SourceManager& manager = instance_.getSourceManager(); 983 SourceManager& manager = instance_.getSourceManager();
818 FullSourceLoc full_loc(loc, manager); 984 FullSourceLoc full_loc(loc, manager);
819 diagnostic_.Report(full_loc, diag_part_object_contains_gc_root_note_) 985 diagnostic_.Report(full_loc, diag_part_object_contains_gc_root_note_)
(...skipping 23 matching lines...) Expand all
843 NoteField(point->field(), note); 1009 NoteField(point->field(), note);
844 } 1010 }
845 1011
846 void NoteField(FieldDecl* field, unsigned note) { 1012 void NoteField(FieldDecl* field, unsigned note) {
847 SourceLocation loc = field->getLocStart(); 1013 SourceLocation loc = field->getLocStart();
848 SourceManager& manager = instance_.getSourceManager(); 1014 SourceManager& manager = instance_.getSourceManager();
849 FullSourceLoc full_loc(loc, manager); 1015 FullSourceLoc full_loc(loc, manager);
850 diagnostic_.Report(full_loc, note) << field; 1016 diagnostic_.Report(full_loc, note) << field;
851 } 1017 }
852 1018
1019 void NoteOverriddenNonVirtualTrace(CXXMethodDecl* overridden) {
1020 SourceLocation loc = overridden->getLocStart();
1021 SourceManager& manager = instance_.getSourceManager();
1022 FullSourceLoc full_loc(loc, manager);
1023 diagnostic_.Report(full_loc, diag_overridden_non_virtual_trace_note_)
1024 << overridden;
1025 }
1026
853 unsigned diag_class_requires_trace_method_; 1027 unsigned diag_class_requires_trace_method_;
854 unsigned diag_base_requires_tracing_; 1028 unsigned diag_base_requires_tracing_;
855 unsigned diag_fields_require_tracing_; 1029 unsigned diag_fields_require_tracing_;
856 unsigned diag_class_contains_invalid_fields_; 1030 unsigned diag_class_contains_invalid_fields_;
857 unsigned diag_class_contains_gc_root_; 1031 unsigned diag_class_contains_gc_root_;
858 unsigned diag_class_requires_finalization_; 1032 unsigned diag_class_requires_finalization_;
859 unsigned diag_finalizer_accesses_finalized_field_; 1033 unsigned diag_finalizer_accesses_finalized_field_;
1034 unsigned diag_overridden_non_virtual_trace_;
1035 unsigned diag_virtual_and_manual_dispatch_;
1036 unsigned diag_missing_trace_dispatch_;
1037 unsigned diag_missing_finalize_;
1038 unsigned diag_missing_finalize_dispatch_;
860 1039
861 unsigned diag_field_requires_tracing_note_; 1040 unsigned diag_field_requires_tracing_note_;
862 unsigned diag_raw_ptr_to_gc_managed_class_note_; 1041 unsigned diag_raw_ptr_to_gc_managed_class_note_;
863 unsigned diag_ref_ptr_to_gc_managed_class_note_; 1042 unsigned diag_ref_ptr_to_gc_managed_class_note_;
864 unsigned diag_own_ptr_to_gc_managed_class_note_; 1043 unsigned diag_own_ptr_to_gc_managed_class_note_;
865 unsigned diag_part_object_contains_gc_root_note_; 1044 unsigned diag_part_object_contains_gc_root_note_;
866 unsigned diag_field_contains_gc_root_note_; 1045 unsigned diag_field_contains_gc_root_note_;
867 unsigned diag_finalized_field_note_; 1046 unsigned diag_finalized_field_note_;
868 unsigned diag_user_declared_destructor_note_; 1047 unsigned diag_user_declared_destructor_note_;
869 unsigned diag_base_requires_finalization_note_; 1048 unsigned diag_base_requires_finalization_note_;
870 unsigned diag_field_requires_finalization_note_; 1049 unsigned diag_field_requires_finalization_note_;
1050 unsigned diag_overridden_non_virtual_trace_note_;
871 1051
872 CompilerInstance& instance_; 1052 CompilerInstance& instance_;
873 DiagnosticsEngine& diagnostic_; 1053 DiagnosticsEngine& diagnostic_;
874 BlinkGCPluginOptions options_; 1054 BlinkGCPluginOptions options_;
875 RecordCache cache_; 1055 RecordCache cache_;
876 }; 1056 };
877 1057
878 class BlinkGCPluginAction : public PluginASTAction { 1058 class BlinkGCPluginAction : public PluginASTAction {
879 public: 1059 public:
880 BlinkGCPluginAction() {} 1060 BlinkGCPluginAction() {}
(...skipping 23 matching lines...) Expand all
904 1084
905 private: 1085 private:
906 BlinkGCPluginOptions options_; 1086 BlinkGCPluginOptions options_;
907 }; 1087 };
908 1088
909 } // namespace 1089 } // namespace
910 1090
911 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( 1091 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X(
912 "blink-gc-plugin", 1092 "blink-gc-plugin",
913 "Check Blink GC invariants"); 1093 "Check Blink GC invariants");
OLDNEW
« no previous file with comments | « no previous file | tools/clang/blink_gc_plugin/Config.h » ('j') | tools/clang/blink_gc_plugin/RecordInfo.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698