OLD | NEW |
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 23 matching lines...) Expand all Loading... |
34 | 34 |
35 const char kFieldRequiresTracingNote[] = | 35 const char kFieldRequiresTracingNote[] = |
36 "[blink-gc] Untraced field %0 declared here:"; | 36 "[blink-gc] Untraced field %0 declared here:"; |
37 | 37 |
38 const char kClassContainsInvalidFields[] = | 38 const char kClassContainsInvalidFields[] = |
39 "[blink-gc] Class %0 contains invalid fields."; | 39 "[blink-gc] Class %0 contains invalid fields."; |
40 | 40 |
41 const char kClassContainsGCRoot[] = | 41 const char kClassContainsGCRoot[] = |
42 "[blink-gc] Class %0 contains GC root in field %1."; | 42 "[blink-gc] Class %0 contains GC root in field %1."; |
43 | 43 |
44 const char kFinalizerInNonFinalizedClass[] = | 44 const char kClassRequiresFinalization[] = |
45 "[blink-gc] Non-finalized class %0 has a user-declared finalizer %1."; | 45 "[blink-gc] Class %0 requires finalization."; |
46 | 46 |
47 const char kFinalizerAccessesFinalizedField[] = | 47 const char kFinalizerAccessesFinalizedField[] = |
48 "[blink-gc] Finalizer %0 accesses potentially finalized field %1."; | 48 "[blink-gc] Finalizer %0 accesses potentially finalized field %1."; |
49 | 49 |
50 const char kRawPtrToGCManagedClassNote[] = | 50 const char kRawPtrToGCManagedClassNote[] = |
51 "[blink-gc] Raw pointer field %0 to a GC managed class declared here:"; | 51 "[blink-gc] Raw pointer field %0 to a GC managed class declared here:"; |
52 | 52 |
53 const char kRefPtrToGCManagedClassNote[] = | 53 const char kRefPtrToGCManagedClassNote[] = |
54 "[blink-gc] RefPtr field %0 to a GC managed class declared here:"; | 54 "[blink-gc] RefPtr field %0 to a GC managed class declared here:"; |
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 kFinalizedFieldNote[] = | 65 const char kFinalizedFieldNote[] = |
66 "[blink-gc] Potentially finalized field %0 declared here:"; | 66 "[blink-gc] Potentially finalized field %0 declared here:"; |
67 | 67 |
| 68 const char kUserDeclaredDestructorNote[] = |
| 69 "[blink-gc] User-declared destructor declared here:"; |
| 70 |
| 71 const char kBaseRequiresFinalizationNote[] = |
| 72 "[blink-gc] Base class %0 requiring finalization declared here:"; |
| 73 |
| 74 const char kFieldRequiresFinalizationNote[] = |
| 75 "[blink-gc] Field %0 requiring finalization declared here:"; |
| 76 |
68 struct BlinkGCPluginOptions { | 77 struct BlinkGCPluginOptions { |
69 BlinkGCPluginOptions() : enable_oilpan(false) {} | 78 BlinkGCPluginOptions() : enable_oilpan(false) {} |
70 bool enable_oilpan; | 79 bool enable_oilpan; |
71 std::set<std::string> ignored_classes; | 80 std::set<std::string> ignored_classes; |
72 std::set<std::string> checked_namespaces; | 81 std::set<std::string> checked_namespaces; |
73 std::vector<std::string> ignored_directories; | 82 std::vector<std::string> ignored_directories; |
74 }; | 83 }; |
75 | 84 |
76 typedef std::vector<CXXRecordDecl*> RecordVector; | 85 typedef std::vector<CXXRecordDecl*> RecordVector; |
77 typedef std::vector<CXXMethodDecl*> MethodVector; | 86 typedef std::vector<CXXMethodDecl*> MethodVector; |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 diagnostic_.getCustomDiagID(getErrorLevel(), kClassRequiresTraceMethod); | 411 diagnostic_.getCustomDiagID(getErrorLevel(), kClassRequiresTraceMethod); |
403 diag_base_requires_tracing_ = | 412 diag_base_requires_tracing_ = |
404 diagnostic_.getCustomDiagID(getErrorLevel(), kBaseRequiresTracing); | 413 diagnostic_.getCustomDiagID(getErrorLevel(), kBaseRequiresTracing); |
405 diag_fields_require_tracing_ = | 414 diag_fields_require_tracing_ = |
406 diagnostic_.getCustomDiagID(getErrorLevel(), kFieldsRequireTracing); | 415 diagnostic_.getCustomDiagID(getErrorLevel(), kFieldsRequireTracing); |
407 diag_class_contains_invalid_fields_ = | 416 diag_class_contains_invalid_fields_ = |
408 diagnostic_.getCustomDiagID(getErrorLevel(), | 417 diagnostic_.getCustomDiagID(getErrorLevel(), |
409 kClassContainsInvalidFields); | 418 kClassContainsInvalidFields); |
410 diag_class_contains_gc_root_ = | 419 diag_class_contains_gc_root_ = |
411 diagnostic_.getCustomDiagID(getErrorLevel(), kClassContainsGCRoot); | 420 diagnostic_.getCustomDiagID(getErrorLevel(), kClassContainsGCRoot); |
412 diag_finalizer_in_nonfinalized_class_ = diagnostic_.getCustomDiagID( | 421 diag_class_requires_finalization_ = diagnostic_.getCustomDiagID( |
413 getErrorLevel(), kFinalizerInNonFinalizedClass); | 422 getErrorLevel(), kClassRequiresFinalization); |
414 diag_finalizer_accesses_finalized_field_ = diagnostic_.getCustomDiagID( | 423 diag_finalizer_accesses_finalized_field_ = diagnostic_.getCustomDiagID( |
415 getErrorLevel(), kFinalizerAccessesFinalizedField); | 424 getErrorLevel(), kFinalizerAccessesFinalizedField); |
416 | 425 |
417 // Register note messages. | 426 // Register note messages. |
418 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID( | 427 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID( |
419 DiagnosticsEngine::Note, kFieldRequiresTracingNote); | 428 DiagnosticsEngine::Note, kFieldRequiresTracingNote); |
420 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 429 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
421 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); | 430 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); |
422 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 431 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
423 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); | 432 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); |
424 diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 433 diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
425 DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote); | 434 DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote); |
426 diag_part_object_contains_gc_root_note_ = diagnostic_.getCustomDiagID( | 435 diag_part_object_contains_gc_root_note_ = diagnostic_.getCustomDiagID( |
427 DiagnosticsEngine::Note, kPartObjectContainsGCRoot); | 436 DiagnosticsEngine::Note, kPartObjectContainsGCRoot); |
428 diag_field_contains_gc_root_note_ = diagnostic_.getCustomDiagID( | 437 diag_field_contains_gc_root_note_ = diagnostic_.getCustomDiagID( |
429 DiagnosticsEngine::Note, kFieldContainsGCRoot); | 438 DiagnosticsEngine::Note, kFieldContainsGCRoot); |
430 diag_finalized_field_note_ = diagnostic_.getCustomDiagID( | 439 diag_finalized_field_note_ = diagnostic_.getCustomDiagID( |
431 DiagnosticsEngine::Note, kFinalizedFieldNote); | 440 DiagnosticsEngine::Note, kFinalizedFieldNote); |
| 441 diag_user_declared_destructor_note_ = diagnostic_.getCustomDiagID( |
| 442 DiagnosticsEngine::Note, kUserDeclaredDestructorNote); |
| 443 diag_base_requires_finalization_note_ = diagnostic_.getCustomDiagID( |
| 444 DiagnosticsEngine::Note, kBaseRequiresFinalizationNote); |
| 445 diag_field_requires_finalization_note_ = diagnostic_.getCustomDiagID( |
| 446 DiagnosticsEngine::Note, kFieldRequiresFinalizationNote); |
432 } | 447 } |
433 | 448 |
434 virtual void HandleTranslationUnit(ASTContext& context) { | 449 virtual void HandleTranslationUnit(ASTContext& context) { |
435 CollectVisitor visitor; | 450 CollectVisitor visitor; |
436 visitor.TraverseDecl(context.getTranslationUnitDecl()); | 451 visitor.TraverseDecl(context.getTranslationUnitDecl()); |
437 | 452 |
438 for (RecordVector::iterator it = visitor.record_decls().begin(); | 453 for (RecordVector::iterator it = visitor.record_decls().begin(); |
439 it != visitor.record_decls().end(); | 454 it != visitor.record_decls().end(); |
440 ++it) { | 455 ++it) { |
441 CheckRecord(cache_.Lookup(*it)); | 456 CheckRecord(cache_.Lookup(*it)); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
483 if (info->RequiresTraceMethod() && !info->GetTraceMethod()) | 498 if (info->RequiresTraceMethod() && !info->GetTraceMethod()) |
484 ReportClassRequiresTraceMethod(info); | 499 ReportClassRequiresTraceMethod(info); |
485 | 500 |
486 { | 501 { |
487 CheckFieldsVisitor visitor(options_); | 502 CheckFieldsVisitor visitor(options_); |
488 if (visitor.ContainsInvalidFields(info)) | 503 if (visitor.ContainsInvalidFields(info)) |
489 ReportClassContainsInvalidFields(info, &visitor.invalid_fields()); | 504 ReportClassContainsInvalidFields(info, &visitor.invalid_fields()); |
490 } | 505 } |
491 | 506 |
492 if (info->IsGCDerived()) { | 507 if (info->IsGCDerived()) { |
493 { | 508 CheckGCRootsVisitor visitor; |
494 CheckGCRootsVisitor visitor; | 509 if (visitor.ContainsGCRoots(info)) |
495 if (visitor.ContainsGCRoots(info)) | 510 ReportClassContainsGCRoots(info, &visitor.gc_roots()); |
496 ReportClassContainsGCRoots(info, &visitor.gc_roots()); | |
497 } | |
498 | 511 |
499 // TODO: check for non-user defined and non-trivial destructors too. | 512 if (info->NeedsFinalization()) |
500 // TODO: support overridden finalize(). | 513 CheckFinalization(info); |
501 if (CXXDestructorDecl* dtor = info->record()->getDestructor()) { | |
502 if (dtor->isUserProvided() && !info->IsGCFinalized()) { | |
503 // Don't report if using transition types and the body is empty. | |
504 if (!options_.enable_oilpan) { | |
505 ReportFinalizerInNonFinalizedClass(info, dtor); | |
506 } else { | |
507 if (dtor->hasBody()) { | |
508 CompoundStmt* stmt = cast<CompoundStmt>(dtor->getBody()); | |
509 if (stmt && !stmt->body_empty()) | |
510 ReportFinalizerInNonFinalizedClass(info, dtor); | |
511 } | |
512 } | |
513 } | |
514 | |
515 if (dtor->hasBody()) { | |
516 CheckFinalizerVisitor visitor(&cache_); | |
517 visitor.TraverseCXXMethodDecl(dtor); | |
518 if (!visitor.finalized_fields().empty()) { | |
519 ReportFinalizerAccessesFinalizedFields(dtor, | |
520 &visitor.finalized_fields()); | |
521 } | |
522 } | |
523 } | |
524 } | 514 } |
525 } | 515 } |
526 | 516 |
| 517 void CheckFinalization(RecordInfo* info) { |
| 518 // TODO: Should we collect destructors similar to trace methods? |
| 519 // TODO: Check overridden finalize(). |
| 520 CXXDestructorDecl* dtor = info->record()->getDestructor(); |
| 521 |
| 522 // For finalized classes, check the finalization method if possible. |
| 523 if (info->IsGCFinalized()) { |
| 524 if (dtor && dtor->hasBody()) { |
| 525 CheckFinalizerVisitor visitor(&cache_); |
| 526 visitor.TraverseCXXMethodDecl(dtor); |
| 527 if (!visitor.finalized_fields().empty()) { |
| 528 ReportFinalizerAccessesFinalizedFields( |
| 529 dtor, &visitor.finalized_fields()); |
| 530 } |
| 531 } |
| 532 return; |
| 533 } |
| 534 |
| 535 // Don't require finalization of a mixin that has not yet been "mixed in". |
| 536 if (info->IsUnmixedGCMixin()) |
| 537 return; |
| 538 |
| 539 // Report the finalization error, and proceed to print possible causes for |
| 540 // the finalization requirement. |
| 541 ReportClassRequiresFinalization(info); |
| 542 |
| 543 if (dtor && dtor->isUserProvided()) |
| 544 NoteUserDeclaredDestructor(dtor); |
| 545 |
| 546 for (RecordInfo::Bases::iterator it = info->GetBases().begin(); |
| 547 it != info->GetBases().end(); |
| 548 ++it) { |
| 549 if (it->second.info()->NeedsFinalization()) |
| 550 NoteBaseRequiresFinalization(&it->second); |
| 551 } |
| 552 |
| 553 for (RecordInfo::Fields::iterator it = info->GetFields().begin(); |
| 554 it != info->GetFields().end(); |
| 555 ++it) { |
| 556 if (it->second.edge()->NeedsFinalization()) |
| 557 NoteField(&it->second, diag_field_requires_finalization_note_); |
| 558 } |
| 559 } |
| 560 |
527 // This is the main entry for tracing method definitions. | 561 // This is the main entry for tracing method definitions. |
528 void CheckTracingMethod(CXXMethodDecl* method) { | 562 void CheckTracingMethod(CXXMethodDecl* method) { |
529 RecordInfo* parent = cache_.Lookup(method->getParent()); | 563 RecordInfo* parent = cache_.Lookup(method->getParent()); |
530 if (IsIgnored(parent)) | 564 if (IsIgnored(parent)) |
531 return; | 565 return; |
532 | 566 |
533 // Check templated tracing methods by checking the template instantiations. | 567 // Check templated tracing methods by checking the template instantiations. |
534 // Specialized templates are handled as ordinary classes. | 568 // Specialized templates are handled as ordinary classes. |
535 if (ClassTemplateDecl* tmpl = | 569 if (ClassTemplateDecl* tmpl = |
536 parent->record()->getDescribedClassTemplate()) { | 570 parent->record()->getDescribedClassTemplate()) { |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
718 diagnostic_.Report(full_loc, diag_class_contains_gc_root_) | 752 diagnostic_.Report(full_loc, diag_class_contains_gc_root_) |
719 << info->record() << point->field(); | 753 << info->record() << point->field(); |
720 while (++path != it->end()) { | 754 while (++path != it->end()) { |
721 NotePartObjectContainsGCRoot(point); | 755 NotePartObjectContainsGCRoot(point); |
722 point = *path; | 756 point = *path; |
723 } | 757 } |
724 NoteFieldContainsGCRoot(point); | 758 NoteFieldContainsGCRoot(point); |
725 } | 759 } |
726 } | 760 } |
727 | 761 |
728 void ReportFinalizerInNonFinalizedClass(RecordInfo* info, | |
729 CXXMethodDecl* dtor) { | |
730 SourceLocation loc = dtor->getLocStart(); | |
731 SourceManager& manager = instance_.getSourceManager(); | |
732 FullSourceLoc full_loc(loc, manager); | |
733 diagnostic_.Report(full_loc, diag_finalizer_in_nonfinalized_class_) | |
734 << info->record() << dtor; | |
735 } | |
736 | |
737 void ReportFinalizerAccessesFinalizedFields( | 762 void ReportFinalizerAccessesFinalizedFields( |
738 CXXMethodDecl* dtor, | 763 CXXMethodDecl* dtor, |
739 CheckFinalizerVisitor::Errors* fields) { | 764 CheckFinalizerVisitor::Errors* fields) { |
740 for (CheckFinalizerVisitor::Errors::iterator it = fields->begin(); | 765 for (CheckFinalizerVisitor::Errors::iterator it = fields->begin(); |
741 it != fields->end(); | 766 it != fields->end(); |
742 ++it) { | 767 ++it) { |
743 SourceLocation loc = it->first->getLocStart(); | 768 SourceLocation loc = it->first->getLocStart(); |
744 SourceManager& manager = instance_.getSourceManager(); | 769 SourceManager& manager = instance_.getSourceManager(); |
745 FullSourceLoc full_loc(loc, manager); | 770 FullSourceLoc full_loc(loc, manager); |
746 diagnostic_.Report(full_loc, diag_finalizer_accesses_finalized_field_) | 771 diagnostic_.Report(full_loc, diag_finalizer_accesses_finalized_field_) |
747 << dtor << it->second->field(); | 772 << dtor << it->second->field(); |
748 NoteField(it->second, diag_finalized_field_note_); | 773 NoteField(it->second, diag_finalized_field_note_); |
749 } | 774 } |
750 } | 775 } |
751 | 776 |
| 777 void ReportClassRequiresFinalization(RecordInfo* info) { |
| 778 SourceLocation loc = info->record()->getInnerLocStart(); |
| 779 SourceManager& manager = instance_.getSourceManager(); |
| 780 FullSourceLoc full_loc(loc, manager); |
| 781 diagnostic_.Report(full_loc, diag_class_requires_finalization_) |
| 782 << info->record(); |
| 783 } |
| 784 |
752 void NoteFieldRequiresTracing(RecordInfo* holder, FieldDecl* field) { | 785 void NoteFieldRequiresTracing(RecordInfo* holder, FieldDecl* field) { |
753 NoteField(field, diag_field_requires_tracing_note_); | 786 NoteField(field, diag_field_requires_tracing_note_); |
754 } | 787 } |
755 | 788 |
756 void NotePartObjectContainsGCRoot(FieldPoint* point) { | 789 void NotePartObjectContainsGCRoot(FieldPoint* point) { |
757 FieldDecl* field = point->field(); | 790 FieldDecl* field = point->field(); |
758 SourceLocation loc = field->getLocStart(); | 791 SourceLocation loc = field->getLocStart(); |
759 SourceManager& manager = instance_.getSourceManager(); | 792 SourceManager& manager = instance_.getSourceManager(); |
760 FullSourceLoc full_loc(loc, manager); | 793 FullSourceLoc full_loc(loc, manager); |
761 diagnostic_.Report(full_loc, diag_part_object_contains_gc_root_note_) | 794 diagnostic_.Report(full_loc, diag_part_object_contains_gc_root_note_) |
762 << field << field->getParent(); | 795 << field << field->getParent(); |
763 } | 796 } |
764 | 797 |
765 void NoteFieldContainsGCRoot(FieldPoint* point) { | 798 void NoteFieldContainsGCRoot(FieldPoint* point) { |
766 NoteField(point, diag_field_contains_gc_root_note_); | 799 NoteField(point, diag_field_contains_gc_root_note_); |
767 } | 800 } |
768 | 801 |
| 802 void NoteUserDeclaredDestructor(CXXMethodDecl* dtor) { |
| 803 SourceLocation loc = dtor->getLocStart(); |
| 804 SourceManager& manager = instance_.getSourceManager(); |
| 805 FullSourceLoc full_loc(loc, manager); |
| 806 diagnostic_.Report(full_loc, diag_user_declared_destructor_note_); |
| 807 } |
| 808 |
| 809 void NoteBaseRequiresFinalization(BasePoint* base) { |
| 810 SourceLocation loc = base->spec().getLocStart(); |
| 811 SourceManager& manager = instance_.getSourceManager(); |
| 812 FullSourceLoc full_loc(loc, manager); |
| 813 diagnostic_.Report(full_loc, diag_base_requires_finalization_note_) |
| 814 << base->info()->record(); |
| 815 } |
| 816 |
769 void NoteField(FieldPoint* point, unsigned note) { | 817 void NoteField(FieldPoint* point, unsigned note) { |
770 NoteField(point->field(), note); | 818 NoteField(point->field(), note); |
771 } | 819 } |
772 | 820 |
773 void NoteField(FieldDecl* field, unsigned note) { | 821 void NoteField(FieldDecl* field, unsigned note) { |
774 SourceLocation loc = field->getLocStart(); | 822 SourceLocation loc = field->getLocStart(); |
775 SourceManager& manager = instance_.getSourceManager(); | 823 SourceManager& manager = instance_.getSourceManager(); |
776 FullSourceLoc full_loc(loc, manager); | 824 FullSourceLoc full_loc(loc, manager); |
777 diagnostic_.Report(full_loc, note) << field; | 825 diagnostic_.Report(full_loc, note) << field; |
778 } | 826 } |
779 | 827 |
780 unsigned diag_class_requires_trace_method_; | 828 unsigned diag_class_requires_trace_method_; |
781 unsigned diag_base_requires_tracing_; | 829 unsigned diag_base_requires_tracing_; |
782 unsigned diag_fields_require_tracing_; | 830 unsigned diag_fields_require_tracing_; |
783 unsigned diag_class_contains_invalid_fields_; | 831 unsigned diag_class_contains_invalid_fields_; |
784 unsigned diag_class_contains_gc_root_; | 832 unsigned diag_class_contains_gc_root_; |
785 unsigned diag_finalizer_in_nonfinalized_class_; | 833 unsigned diag_class_requires_finalization_; |
786 unsigned diag_finalizer_accesses_finalized_field_; | 834 unsigned diag_finalizer_accesses_finalized_field_; |
787 | 835 |
788 unsigned diag_field_requires_tracing_note_; | 836 unsigned diag_field_requires_tracing_note_; |
789 unsigned diag_raw_ptr_to_gc_managed_class_note_; | 837 unsigned diag_raw_ptr_to_gc_managed_class_note_; |
790 unsigned diag_ref_ptr_to_gc_managed_class_note_; | 838 unsigned diag_ref_ptr_to_gc_managed_class_note_; |
791 unsigned diag_own_ptr_to_gc_managed_class_note_; | 839 unsigned diag_own_ptr_to_gc_managed_class_note_; |
792 unsigned diag_part_object_contains_gc_root_note_; | 840 unsigned diag_part_object_contains_gc_root_note_; |
793 unsigned diag_field_contains_gc_root_note_; | 841 unsigned diag_field_contains_gc_root_note_; |
794 unsigned diag_finalized_field_note_; | 842 unsigned diag_finalized_field_note_; |
| 843 unsigned diag_user_declared_destructor_note_; |
| 844 unsigned diag_base_requires_finalization_note_; |
| 845 unsigned diag_field_requires_finalization_note_; |
795 | 846 |
796 CompilerInstance& instance_; | 847 CompilerInstance& instance_; |
797 DiagnosticsEngine& diagnostic_; | 848 DiagnosticsEngine& diagnostic_; |
798 BlinkGCPluginOptions options_; | 849 BlinkGCPluginOptions options_; |
799 RecordCache cache_; | 850 RecordCache cache_; |
800 }; | 851 }; |
801 | 852 |
802 class BlinkGCPluginAction : public PluginASTAction { | 853 class BlinkGCPluginAction : public PluginASTAction { |
803 public: | 854 public: |
804 BlinkGCPluginAction() {} | 855 BlinkGCPluginAction() {} |
(...skipping 23 matching lines...) Expand all Loading... |
828 | 879 |
829 private: | 880 private: |
830 BlinkGCPluginOptions options_; | 881 BlinkGCPluginOptions options_; |
831 }; | 882 }; |
832 | 883 |
833 } // namespace | 884 } // namespace |
834 | 885 |
835 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( | 886 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( |
836 "blink-gc-plugin", | 887 "blink-gc-plugin", |
837 "Check Blink GC invariants"); | 888 "Check Blink GC invariants"); |
OLD | NEW |