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 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 "[blink-gc] Manual dispatch %0 declared here:"; | 113 "[blink-gc] Manual dispatch %0 declared here:"; |
114 | 114 |
115 const char kDerivesNonStackAllocated[] = | 115 const char kDerivesNonStackAllocated[] = |
116 "[blink-gc] Stack-allocated class %0 derives class %1" | 116 "[blink-gc] Stack-allocated class %0 derives class %1" |
117 " which is not stack allocated."; | 117 " which is not stack allocated."; |
118 | 118 |
119 const char kClassOverridesNew[] = | 119 const char kClassOverridesNew[] = |
120 "[blink-gc] Garbage collected class %0" | 120 "[blink-gc] Garbage collected class %0" |
121 " is not permitted to override its new operator."; | 121 " is not permitted to override its new operator."; |
122 | 122 |
| 123 const char kClassDeclaresPureVirtualTrace[] = |
| 124 "[blink-gc] Garbage collected class %0" |
| 125 " is not permitted to declare a pure-virtual trace method."; |
| 126 |
123 struct BlinkGCPluginOptions { | 127 struct BlinkGCPluginOptions { |
124 BlinkGCPluginOptions() : enable_oilpan(false), dump_graph(false) {} | 128 BlinkGCPluginOptions() : enable_oilpan(false), dump_graph(false) {} |
125 bool enable_oilpan; | 129 bool enable_oilpan; |
126 bool dump_graph; | 130 bool dump_graph; |
127 std::set<std::string> ignored_classes; | 131 std::set<std::string> ignored_classes; |
128 std::set<std::string> checked_namespaces; | 132 std::set<std::string> checked_namespaces; |
129 std::vector<std::string> ignored_directories; | 133 std::vector<std::string> ignored_directories; |
130 }; | 134 }; |
131 | 135 |
132 typedef std::vector<CXXRecordDecl*> RecordVector; | 136 typedef std::vector<CXXRecordDecl*> RecordVector; |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
563 diag_virtual_and_manual_dispatch_ = | 567 diag_virtual_and_manual_dispatch_ = |
564 diagnostic_.getCustomDiagID(getErrorLevel(), kVirtualAndManualDispatch); | 568 diagnostic_.getCustomDiagID(getErrorLevel(), kVirtualAndManualDispatch); |
565 diag_missing_trace_dispatch_ = | 569 diag_missing_trace_dispatch_ = |
566 diagnostic_.getCustomDiagID(getErrorLevel(), kMissingTraceDispatch); | 570 diagnostic_.getCustomDiagID(getErrorLevel(), kMissingTraceDispatch); |
567 diag_missing_finalize_dispatch_ = | 571 diag_missing_finalize_dispatch_ = |
568 diagnostic_.getCustomDiagID(getErrorLevel(), kMissingFinalizeDispatch); | 572 diagnostic_.getCustomDiagID(getErrorLevel(), kMissingFinalizeDispatch); |
569 diag_derives_non_stack_allocated_ = | 573 diag_derives_non_stack_allocated_ = |
570 diagnostic_.getCustomDiagID(getErrorLevel(), kDerivesNonStackAllocated); | 574 diagnostic_.getCustomDiagID(getErrorLevel(), kDerivesNonStackAllocated); |
571 diag_class_overrides_new_ = | 575 diag_class_overrides_new_ = |
572 diagnostic_.getCustomDiagID(getErrorLevel(), kClassOverridesNew); | 576 diagnostic_.getCustomDiagID(getErrorLevel(), kClassOverridesNew); |
| 577 diag_class_declares_pure_virtual_trace_ = diagnostic_.getCustomDiagID( |
| 578 getErrorLevel(), kClassDeclaresPureVirtualTrace); |
573 | 579 |
574 // Register note messages. | 580 // Register note messages. |
575 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID( | 581 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID( |
576 DiagnosticsEngine::Note, kFieldRequiresTracingNote); | 582 DiagnosticsEngine::Note, kFieldRequiresTracingNote); |
577 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 583 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
578 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); | 584 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); |
579 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 585 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
580 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); | 586 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); |
581 diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 587 diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
582 DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote); | 588 DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
685 // Check consistency of stack-allocated hierarchies. | 691 // Check consistency of stack-allocated hierarchies. |
686 if (info->IsStackAllocated()) { | 692 if (info->IsStackAllocated()) { |
687 for (RecordInfo::Bases::iterator it = info->GetBases().begin(); | 693 for (RecordInfo::Bases::iterator it = info->GetBases().begin(); |
688 it != info->GetBases().end(); | 694 it != info->GetBases().end(); |
689 ++it) { | 695 ++it) { |
690 if (!it->second.info()->IsStackAllocated()) | 696 if (!it->second.info()->IsStackAllocated()) |
691 ReportDerivesNonStackAllocated(info, &it->second); | 697 ReportDerivesNonStackAllocated(info, &it->second); |
692 } | 698 } |
693 } | 699 } |
694 | 700 |
695 if (info->RequiresTraceMethod() && !info->GetTraceMethod()) | 701 if (CXXMethodDecl* trace = info->GetTraceMethod()) { |
| 702 if (trace->isPure()) |
| 703 ReportClassDeclaresPureVirtualTrace(info, trace); |
| 704 } else if (info->RequiresTraceMethod()) { |
696 ReportClassRequiresTraceMethod(info); | 705 ReportClassRequiresTraceMethod(info); |
| 706 } |
697 | 707 |
698 { | 708 { |
699 CheckFieldsVisitor visitor(options_); | 709 CheckFieldsVisitor visitor(options_); |
700 if (visitor.ContainsInvalidFields(info)) | 710 if (visitor.ContainsInvalidFields(info)) |
701 ReportClassContainsInvalidFields(info, &visitor.invalid_fields()); | 711 ReportClassContainsInvalidFields(info, &visitor.invalid_fields()); |
702 } | 712 } |
703 | 713 |
704 if (info->IsGCDerived()) { | 714 if (info->IsGCDerived()) { |
705 CheckLeftMostDerived(info); | 715 CheckLeftMostDerived(info); |
706 | 716 |
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1245 << info->record() << base->info()->record(); | 1255 << info->record() << base->info()->record(); |
1246 } | 1256 } |
1247 | 1257 |
1248 void ReportClassOverridesNew(RecordInfo* info, CXXMethodDecl* newop) { | 1258 void ReportClassOverridesNew(RecordInfo* info, CXXMethodDecl* newop) { |
1249 SourceLocation loc = newop->getLocStart(); | 1259 SourceLocation loc = newop->getLocStart(); |
1250 SourceManager& manager = instance_.getSourceManager(); | 1260 SourceManager& manager = instance_.getSourceManager(); |
1251 FullSourceLoc full_loc(loc, manager); | 1261 FullSourceLoc full_loc(loc, manager); |
1252 diagnostic_.Report(full_loc, diag_class_overrides_new_) << info->record(); | 1262 diagnostic_.Report(full_loc, diag_class_overrides_new_) << info->record(); |
1253 } | 1263 } |
1254 | 1264 |
| 1265 void ReportClassDeclaresPureVirtualTrace(RecordInfo* info, |
| 1266 CXXMethodDecl* trace) { |
| 1267 SourceLocation loc = trace->getLocStart(); |
| 1268 SourceManager& manager = instance_.getSourceManager(); |
| 1269 FullSourceLoc full_loc(loc, manager); |
| 1270 diagnostic_.Report(full_loc, diag_class_declares_pure_virtual_trace_) |
| 1271 << info->record(); |
| 1272 } |
| 1273 |
1255 void NoteManualDispatchMethod(CXXMethodDecl* dispatch) { | 1274 void NoteManualDispatchMethod(CXXMethodDecl* dispatch) { |
1256 SourceLocation loc = dispatch->getLocStart(); | 1275 SourceLocation loc = dispatch->getLocStart(); |
1257 SourceManager& manager = instance_.getSourceManager(); | 1276 SourceManager& manager = instance_.getSourceManager(); |
1258 FullSourceLoc full_loc(loc, manager); | 1277 FullSourceLoc full_loc(loc, manager); |
1259 diagnostic_.Report(full_loc, diag_manual_dispatch_method_note_) << dispatch; | 1278 diagnostic_.Report(full_loc, diag_manual_dispatch_method_note_) << dispatch; |
1260 } | 1279 } |
1261 | 1280 |
1262 void NoteFieldRequiresTracing(RecordInfo* holder, FieldDecl* field) { | 1281 void NoteFieldRequiresTracing(RecordInfo* holder, FieldDecl* field) { |
1263 NoteField(field, diag_field_requires_tracing_note_); | 1282 NoteField(field, diag_field_requires_tracing_note_); |
1264 } | 1283 } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1326 unsigned diag_class_requires_finalization_; | 1345 unsigned diag_class_requires_finalization_; |
1327 unsigned diag_finalizer_accesses_finalized_field_; | 1346 unsigned diag_finalizer_accesses_finalized_field_; |
1328 unsigned diag_overridden_non_virtual_trace_; | 1347 unsigned diag_overridden_non_virtual_trace_; |
1329 unsigned diag_missing_trace_dispatch_method_; | 1348 unsigned diag_missing_trace_dispatch_method_; |
1330 unsigned diag_missing_finalize_dispatch_method_; | 1349 unsigned diag_missing_finalize_dispatch_method_; |
1331 unsigned diag_virtual_and_manual_dispatch_; | 1350 unsigned diag_virtual_and_manual_dispatch_; |
1332 unsigned diag_missing_trace_dispatch_; | 1351 unsigned diag_missing_trace_dispatch_; |
1333 unsigned diag_missing_finalize_dispatch_; | 1352 unsigned diag_missing_finalize_dispatch_; |
1334 unsigned diag_derives_non_stack_allocated_; | 1353 unsigned diag_derives_non_stack_allocated_; |
1335 unsigned diag_class_overrides_new_; | 1354 unsigned diag_class_overrides_new_; |
| 1355 unsigned diag_class_declares_pure_virtual_trace_; |
1336 | 1356 |
1337 unsigned diag_field_requires_tracing_note_; | 1357 unsigned diag_field_requires_tracing_note_; |
1338 unsigned diag_raw_ptr_to_gc_managed_class_note_; | 1358 unsigned diag_raw_ptr_to_gc_managed_class_note_; |
1339 unsigned diag_ref_ptr_to_gc_managed_class_note_; | 1359 unsigned diag_ref_ptr_to_gc_managed_class_note_; |
1340 unsigned diag_own_ptr_to_gc_managed_class_note_; | 1360 unsigned diag_own_ptr_to_gc_managed_class_note_; |
1341 unsigned diag_stack_allocated_field_note_; | 1361 unsigned diag_stack_allocated_field_note_; |
1342 unsigned diag_member_in_unmanaged_class_note_; | 1362 unsigned diag_member_in_unmanaged_class_note_; |
1343 unsigned diag_part_object_contains_gc_root_note_; | 1363 unsigned diag_part_object_contains_gc_root_note_; |
1344 unsigned diag_field_contains_gc_root_note_; | 1364 unsigned diag_field_contains_gc_root_note_; |
1345 unsigned diag_finalized_field_note_; | 1365 unsigned diag_finalized_field_note_; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1388 | 1408 |
1389 private: | 1409 private: |
1390 BlinkGCPluginOptions options_; | 1410 BlinkGCPluginOptions options_; |
1391 }; | 1411 }; |
1392 | 1412 |
1393 } // namespace | 1413 } // namespace |
1394 | 1414 |
1395 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( | 1415 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( |
1396 "blink-gc-plugin", | 1416 "blink-gc-plugin", |
1397 "Check Blink GC invariants"); | 1417 "Check Blink GC invariants"); |
OLD | NEW |