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 |