| 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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 const char kFieldRequiresFinalizationNote[] = | 109 const char kFieldRequiresFinalizationNote[] = |
| 110 "[blink-gc] Field %0 requiring finalization declared here:"; | 110 "[blink-gc] Field %0 requiring finalization declared here:"; |
| 111 | 111 |
| 112 const char kManualDispatchMethodNote[] = | 112 const char kManualDispatchMethodNote[] = |
| 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[] = |
| 120 "[blink-gc] Garbage collected class %0" |
| 121 " is not permitted to override its new operator."; |
| 122 |
| 119 struct BlinkGCPluginOptions { | 123 struct BlinkGCPluginOptions { |
| 120 BlinkGCPluginOptions() : enable_oilpan(false), dump_graph(false) {} | 124 BlinkGCPluginOptions() : enable_oilpan(false), dump_graph(false) {} |
| 121 bool enable_oilpan; | 125 bool enable_oilpan; |
| 122 bool dump_graph; | 126 bool dump_graph; |
| 123 std::set<std::string> ignored_classes; | 127 std::set<std::string> ignored_classes; |
| 124 std::set<std::string> checked_namespaces; | 128 std::set<std::string> checked_namespaces; |
| 125 std::vector<std::string> ignored_directories; | 129 std::vector<std::string> ignored_directories; |
| 126 }; | 130 }; |
| 127 | 131 |
| 128 typedef std::vector<CXXRecordDecl*> RecordVector; | 132 typedef std::vector<CXXRecordDecl*> RecordVector; |
| (...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 557 diag_missing_finalize_dispatch_method_ = diagnostic_.getCustomDiagID( | 561 diag_missing_finalize_dispatch_method_ = diagnostic_.getCustomDiagID( |
| 558 getErrorLevel(), kMissingFinalizeDispatchMethod); | 562 getErrorLevel(), kMissingFinalizeDispatchMethod); |
| 559 diag_virtual_and_manual_dispatch_ = | 563 diag_virtual_and_manual_dispatch_ = |
| 560 diagnostic_.getCustomDiagID(getErrorLevel(), kVirtualAndManualDispatch); | 564 diagnostic_.getCustomDiagID(getErrorLevel(), kVirtualAndManualDispatch); |
| 561 diag_missing_trace_dispatch_ = | 565 diag_missing_trace_dispatch_ = |
| 562 diagnostic_.getCustomDiagID(getErrorLevel(), kMissingTraceDispatch); | 566 diagnostic_.getCustomDiagID(getErrorLevel(), kMissingTraceDispatch); |
| 563 diag_missing_finalize_dispatch_ = | 567 diag_missing_finalize_dispatch_ = |
| 564 diagnostic_.getCustomDiagID(getErrorLevel(), kMissingFinalizeDispatch); | 568 diagnostic_.getCustomDiagID(getErrorLevel(), kMissingFinalizeDispatch); |
| 565 diag_derives_non_stack_allocated_ = | 569 diag_derives_non_stack_allocated_ = |
| 566 diagnostic_.getCustomDiagID(getErrorLevel(), kDerivesNonStackAllocated); | 570 diagnostic_.getCustomDiagID(getErrorLevel(), kDerivesNonStackAllocated); |
| 571 diag_class_overrides_new_ = |
| 572 diagnostic_.getCustomDiagID(getErrorLevel(), kClassOverridesNew); |
| 567 | 573 |
| 568 // Register note messages. | 574 // Register note messages. |
| 569 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID( | 575 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID( |
| 570 DiagnosticsEngine::Note, kFieldRequiresTracingNote); | 576 DiagnosticsEngine::Note, kFieldRequiresTracingNote); |
| 571 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 577 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
| 572 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); | 578 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); |
| 573 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 579 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
| 574 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); | 580 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); |
| 575 diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 581 diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
| 576 DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote); | 582 DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote); |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 693 CheckFieldsVisitor visitor(options_); | 699 CheckFieldsVisitor visitor(options_); |
| 694 if (visitor.ContainsInvalidFields(info)) | 700 if (visitor.ContainsInvalidFields(info)) |
| 695 ReportClassContainsInvalidFields(info, &visitor.invalid_fields()); | 701 ReportClassContainsInvalidFields(info, &visitor.invalid_fields()); |
| 696 } | 702 } |
| 697 | 703 |
| 698 if (info->IsGCDerived()) { | 704 if (info->IsGCDerived()) { |
| 699 CheckLeftMostDerived(info); | 705 CheckLeftMostDerived(info); |
| 700 | 706 |
| 701 CheckDispatch(info); | 707 CheckDispatch(info); |
| 702 | 708 |
| 709 if (CXXMethodDecl* newop = info->DeclaresNewOperator()) |
| 710 ReportClassOverridesNew(info, newop); |
| 711 |
| 703 // TODO: Remove this exception once TreeShared is properly traced. | 712 // TODO: Remove this exception once TreeShared is properly traced. |
| 704 if (!info->IsTreeShared()) { | 713 if (!info->IsTreeShared()) { |
| 705 CheckGCRootsVisitor visitor; | 714 CheckGCRootsVisitor visitor; |
| 706 if (visitor.ContainsGCRoots(info)) | 715 if (visitor.ContainsGCRoots(info)) |
| 707 ReportClassContainsGCRoots(info, &visitor.gc_roots()); | 716 ReportClassContainsGCRoots(info, &visitor.gc_roots()); |
| 708 } | 717 } |
| 709 | 718 |
| 710 if (info->NeedsFinalization()) | 719 if (info->NeedsFinalization()) |
| 711 CheckFinalization(info); | 720 CheckFinalization(info); |
| 712 } | 721 } |
| (...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1229 } | 1238 } |
| 1230 | 1239 |
| 1231 void ReportDerivesNonStackAllocated(RecordInfo* info, BasePoint* base) { | 1240 void ReportDerivesNonStackAllocated(RecordInfo* info, BasePoint* base) { |
| 1232 SourceLocation loc = base->spec().getLocStart(); | 1241 SourceLocation loc = base->spec().getLocStart(); |
| 1233 SourceManager& manager = instance_.getSourceManager(); | 1242 SourceManager& manager = instance_.getSourceManager(); |
| 1234 FullSourceLoc full_loc(loc, manager); | 1243 FullSourceLoc full_loc(loc, manager); |
| 1235 diagnostic_.Report(full_loc, diag_derives_non_stack_allocated_) | 1244 diagnostic_.Report(full_loc, diag_derives_non_stack_allocated_) |
| 1236 << info->record() << base->info()->record(); | 1245 << info->record() << base->info()->record(); |
| 1237 } | 1246 } |
| 1238 | 1247 |
| 1248 void ReportClassOverridesNew(RecordInfo* info, CXXMethodDecl* newop) { |
| 1249 SourceLocation loc = newop->getLocStart(); |
| 1250 SourceManager& manager = instance_.getSourceManager(); |
| 1251 FullSourceLoc full_loc(loc, manager); |
| 1252 diagnostic_.Report(full_loc, diag_class_overrides_new_) << info->record(); |
| 1253 } |
| 1254 |
| 1239 void NoteManualDispatchMethod(CXXMethodDecl* dispatch) { | 1255 void NoteManualDispatchMethod(CXXMethodDecl* dispatch) { |
| 1240 SourceLocation loc = dispatch->getLocStart(); | 1256 SourceLocation loc = dispatch->getLocStart(); |
| 1241 SourceManager& manager = instance_.getSourceManager(); | 1257 SourceManager& manager = instance_.getSourceManager(); |
| 1242 FullSourceLoc full_loc(loc, manager); | 1258 FullSourceLoc full_loc(loc, manager); |
| 1243 diagnostic_.Report(full_loc, diag_manual_dispatch_method_note_) << dispatch; | 1259 diagnostic_.Report(full_loc, diag_manual_dispatch_method_note_) << dispatch; |
| 1244 } | 1260 } |
| 1245 | 1261 |
| 1246 void NoteFieldRequiresTracing(RecordInfo* holder, FieldDecl* field) { | 1262 void NoteFieldRequiresTracing(RecordInfo* holder, FieldDecl* field) { |
| 1247 NoteField(field, diag_field_requires_tracing_note_); | 1263 NoteField(field, diag_field_requires_tracing_note_); |
| 1248 } | 1264 } |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1309 unsigned diag_class_contains_gc_root_; | 1325 unsigned diag_class_contains_gc_root_; |
| 1310 unsigned diag_class_requires_finalization_; | 1326 unsigned diag_class_requires_finalization_; |
| 1311 unsigned diag_finalizer_accesses_finalized_field_; | 1327 unsigned diag_finalizer_accesses_finalized_field_; |
| 1312 unsigned diag_overridden_non_virtual_trace_; | 1328 unsigned diag_overridden_non_virtual_trace_; |
| 1313 unsigned diag_missing_trace_dispatch_method_; | 1329 unsigned diag_missing_trace_dispatch_method_; |
| 1314 unsigned diag_missing_finalize_dispatch_method_; | 1330 unsigned diag_missing_finalize_dispatch_method_; |
| 1315 unsigned diag_virtual_and_manual_dispatch_; | 1331 unsigned diag_virtual_and_manual_dispatch_; |
| 1316 unsigned diag_missing_trace_dispatch_; | 1332 unsigned diag_missing_trace_dispatch_; |
| 1317 unsigned diag_missing_finalize_dispatch_; | 1333 unsigned diag_missing_finalize_dispatch_; |
| 1318 unsigned diag_derives_non_stack_allocated_; | 1334 unsigned diag_derives_non_stack_allocated_; |
| 1335 unsigned diag_class_overrides_new_; |
| 1319 | 1336 |
| 1320 unsigned diag_field_requires_tracing_note_; | 1337 unsigned diag_field_requires_tracing_note_; |
| 1321 unsigned diag_raw_ptr_to_gc_managed_class_note_; | 1338 unsigned diag_raw_ptr_to_gc_managed_class_note_; |
| 1322 unsigned diag_ref_ptr_to_gc_managed_class_note_; | 1339 unsigned diag_ref_ptr_to_gc_managed_class_note_; |
| 1323 unsigned diag_own_ptr_to_gc_managed_class_note_; | 1340 unsigned diag_own_ptr_to_gc_managed_class_note_; |
| 1324 unsigned diag_stack_allocated_field_note_; | 1341 unsigned diag_stack_allocated_field_note_; |
| 1325 unsigned diag_member_in_unmanaged_class_note_; | 1342 unsigned diag_member_in_unmanaged_class_note_; |
| 1326 unsigned diag_part_object_contains_gc_root_note_; | 1343 unsigned diag_part_object_contains_gc_root_note_; |
| 1327 unsigned diag_field_contains_gc_root_note_; | 1344 unsigned diag_field_contains_gc_root_note_; |
| 1328 unsigned diag_finalized_field_note_; | 1345 unsigned diag_finalized_field_note_; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1371 | 1388 |
| 1372 private: | 1389 private: |
| 1373 BlinkGCPluginOptions options_; | 1390 BlinkGCPluginOptions options_; |
| 1374 }; | 1391 }; |
| 1375 | 1392 |
| 1376 } // namespace | 1393 } // namespace |
| 1377 | 1394 |
| 1378 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( | 1395 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( |
| 1379 "blink-gc-plugin", | 1396 "blink-gc-plugin", |
| 1380 "Check Blink GC invariants"); | 1397 "Check Blink GC invariants"); |
| OLD | NEW |