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 |
11 #include "Config.h" | 11 #include "Config.h" |
12 #include "JsonWriter.h" | 12 #include "JsonWriter.h" |
13 #include "RecordInfo.h" | 13 #include "RecordInfo.h" |
14 | 14 |
15 #include "clang/AST/AST.h" | 15 #include "clang/AST/AST.h" |
16 #include "clang/AST/ASTConsumer.h" | 16 #include "clang/AST/ASTConsumer.h" |
17 #include "clang/AST/RecursiveASTVisitor.h" | 17 #include "clang/AST/RecursiveASTVisitor.h" |
18 #include "clang/Frontend/CompilerInstance.h" | 18 #include "clang/Frontend/CompilerInstance.h" |
19 #include "clang/Frontend/FrontendPluginRegistry.h" | 19 #include "clang/Frontend/FrontendPluginRegistry.h" |
20 | 20 |
21 using namespace clang; | 21 using namespace clang; |
22 using std::string; | 22 using std::string; |
23 | 23 |
24 namespace { | 24 namespace { |
25 | 25 |
26 const char kClassMustLeftMostlyDeriveGC[] = | 26 const char kClassMustLeftMostlyDeriveGC[] = |
27 "[blink-gc] Class %0 must derive its GC base in the left-most position."; | 27 "[blink-gc] Class %0 must derive its GC base in the left-most position."; |
28 | 28 |
29 const char kClassRequiresTraceMethod[] = | 29 const char kClassRequiresTraceMethod[] = |
30 "[blink-gc] Class %0 requires a trace method" | 30 "[blink-gc] Class %0 requires a trace method."; |
31 " because it contains fields that require tracing."; | |
32 | 31 |
33 const char kBaseRequiresTracing[] = | 32 const char kBaseRequiresTracing[] = |
34 "[blink-gc] Base class %0 of derived class %1 requires tracing."; | 33 "[blink-gc] Base class %0 of derived class %1 requires tracing."; |
35 | 34 |
| 35 const char kBaseRequiresTracingNote[] = |
| 36 "[blink-gc] Untraced base class %0 declared here:"; |
| 37 |
36 const char kFieldsRequireTracing[] = | 38 const char kFieldsRequireTracing[] = |
37 "[blink-gc] Class %0 has untraced fields that require tracing."; | 39 "[blink-gc] Class %0 has untraced fields that require tracing."; |
38 | 40 |
39 const char kFieldRequiresTracingNote[] = | 41 const char kFieldRequiresTracingNote[] = |
40 "[blink-gc] Untraced field %0 declared here:"; | 42 "[blink-gc] Untraced field %0 declared here:"; |
41 | 43 |
42 const char kClassContainsInvalidFields[] = | 44 const char kClassContainsInvalidFields[] = |
43 "[blink-gc] Class %0 contains invalid fields."; | 45 "[blink-gc] Class %0 contains invalid fields."; |
44 | 46 |
45 const char kClassContainsGCRoot[] = | 47 const char kClassContainsGCRoot[] = |
(...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
571 diag_missing_finalize_dispatch_ = | 573 diag_missing_finalize_dispatch_ = |
572 diagnostic_.getCustomDiagID(getErrorLevel(), kMissingFinalizeDispatch); | 574 diagnostic_.getCustomDiagID(getErrorLevel(), kMissingFinalizeDispatch); |
573 diag_derives_non_stack_allocated_ = | 575 diag_derives_non_stack_allocated_ = |
574 diagnostic_.getCustomDiagID(getErrorLevel(), kDerivesNonStackAllocated); | 576 diagnostic_.getCustomDiagID(getErrorLevel(), kDerivesNonStackAllocated); |
575 diag_class_overrides_new_ = | 577 diag_class_overrides_new_ = |
576 diagnostic_.getCustomDiagID(getErrorLevel(), kClassOverridesNew); | 578 diagnostic_.getCustomDiagID(getErrorLevel(), kClassOverridesNew); |
577 diag_class_declares_pure_virtual_trace_ = diagnostic_.getCustomDiagID( | 579 diag_class_declares_pure_virtual_trace_ = diagnostic_.getCustomDiagID( |
578 getErrorLevel(), kClassDeclaresPureVirtualTrace); | 580 getErrorLevel(), kClassDeclaresPureVirtualTrace); |
579 | 581 |
580 // Register note messages. | 582 // Register note messages. |
| 583 diag_base_requires_tracing_note_ = diagnostic_.getCustomDiagID( |
| 584 DiagnosticsEngine::Note, kBaseRequiresTracingNote); |
581 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID( | 585 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID( |
582 DiagnosticsEngine::Note, kFieldRequiresTracingNote); | 586 DiagnosticsEngine::Note, kFieldRequiresTracingNote); |
583 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 587 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
584 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); | 588 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); |
585 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 589 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
586 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); | 590 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); |
587 diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 591 diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
588 DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote); | 592 DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote); |
589 diag_stack_allocated_field_note_ = diagnostic_.getCustomDiagID( | 593 diag_stack_allocated_field_note_ = diagnostic_.getCustomDiagID( |
590 DiagnosticsEngine::Note, kStackAllocatedFieldNote); | 594 DiagnosticsEngine::Note, kStackAllocatedFieldNote); |
(...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1086 diagnostic_.Report(full_loc, diag_class_must_left_mostly_derive_gc_) | 1090 diagnostic_.Report(full_loc, diag_class_must_left_mostly_derive_gc_) |
1087 << info->record(); | 1091 << info->record(); |
1088 } | 1092 } |
1089 | 1093 |
1090 void ReportClassRequiresTraceMethod(RecordInfo* info) { | 1094 void ReportClassRequiresTraceMethod(RecordInfo* info) { |
1091 SourceLocation loc = info->record()->getInnerLocStart(); | 1095 SourceLocation loc = info->record()->getInnerLocStart(); |
1092 SourceManager& manager = instance_.getSourceManager(); | 1096 SourceManager& manager = instance_.getSourceManager(); |
1093 FullSourceLoc full_loc(loc, manager); | 1097 FullSourceLoc full_loc(loc, manager); |
1094 diagnostic_.Report(full_loc, diag_class_requires_trace_method_) | 1098 diagnostic_.Report(full_loc, diag_class_requires_trace_method_) |
1095 << info->record(); | 1099 << info->record(); |
| 1100 |
| 1101 for (RecordInfo::Bases::iterator it = info->GetBases().begin(); |
| 1102 it != info->GetBases().end(); |
| 1103 ++it) { |
| 1104 if (it->second.NeedsTracing().IsNeeded()) |
| 1105 NoteBaseRequiresTracing(&it->second); |
| 1106 } |
| 1107 |
1096 for (RecordInfo::Fields::iterator it = info->GetFields().begin(); | 1108 for (RecordInfo::Fields::iterator it = info->GetFields().begin(); |
1097 it != info->GetFields().end(); | 1109 it != info->GetFields().end(); |
1098 ++it) { | 1110 ++it) { |
1099 if (!it->second.IsProperlyTraced()) | 1111 if (!it->second.IsProperlyTraced()) |
1100 NoteFieldRequiresTracing(info, it->first); | 1112 NoteFieldRequiresTracing(info, it->first); |
1101 } | 1113 } |
1102 } | 1114 } |
1103 | 1115 |
1104 void ReportBaseRequiresTracing(RecordInfo* derived, | 1116 void ReportBaseRequiresTracing(RecordInfo* derived, |
1105 CXXMethodDecl* trace, | 1117 CXXMethodDecl* trace, |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1271 << info->record(); | 1283 << info->record(); |
1272 } | 1284 } |
1273 | 1285 |
1274 void NoteManualDispatchMethod(CXXMethodDecl* dispatch) { | 1286 void NoteManualDispatchMethod(CXXMethodDecl* dispatch) { |
1275 SourceLocation loc = dispatch->getLocStart(); | 1287 SourceLocation loc = dispatch->getLocStart(); |
1276 SourceManager& manager = instance_.getSourceManager(); | 1288 SourceManager& manager = instance_.getSourceManager(); |
1277 FullSourceLoc full_loc(loc, manager); | 1289 FullSourceLoc full_loc(loc, manager); |
1278 diagnostic_.Report(full_loc, diag_manual_dispatch_method_note_) << dispatch; | 1290 diagnostic_.Report(full_loc, diag_manual_dispatch_method_note_) << dispatch; |
1279 } | 1291 } |
1280 | 1292 |
| 1293 void NoteBaseRequiresTracing(BasePoint* base) { |
| 1294 SourceLocation loc = base->spec().getLocStart(); |
| 1295 SourceManager& manager = instance_.getSourceManager(); |
| 1296 FullSourceLoc full_loc(loc, manager); |
| 1297 diagnostic_.Report(full_loc, diag_base_requires_tracing_note_) |
| 1298 << base->info()->record(); |
| 1299 } |
| 1300 |
1281 void NoteFieldRequiresTracing(RecordInfo* holder, FieldDecl* field) { | 1301 void NoteFieldRequiresTracing(RecordInfo* holder, FieldDecl* field) { |
1282 NoteField(field, diag_field_requires_tracing_note_); | 1302 NoteField(field, diag_field_requires_tracing_note_); |
1283 } | 1303 } |
1284 | 1304 |
1285 void NotePartObjectContainsGCRoot(FieldPoint* point) { | 1305 void NotePartObjectContainsGCRoot(FieldPoint* point) { |
1286 FieldDecl* field = point->field(); | 1306 FieldDecl* field = point->field(); |
1287 SourceLocation loc = field->getLocStart(); | 1307 SourceLocation loc = field->getLocStart(); |
1288 SourceManager& manager = instance_.getSourceManager(); | 1308 SourceManager& manager = instance_.getSourceManager(); |
1289 FullSourceLoc full_loc(loc, manager); | 1309 FullSourceLoc full_loc(loc, manager); |
1290 diagnostic_.Report(full_loc, diag_part_object_contains_gc_root_note_) | 1310 diagnostic_.Report(full_loc, diag_part_object_contains_gc_root_note_) |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1347 unsigned diag_overridden_non_virtual_trace_; | 1367 unsigned diag_overridden_non_virtual_trace_; |
1348 unsigned diag_missing_trace_dispatch_method_; | 1368 unsigned diag_missing_trace_dispatch_method_; |
1349 unsigned diag_missing_finalize_dispatch_method_; | 1369 unsigned diag_missing_finalize_dispatch_method_; |
1350 unsigned diag_virtual_and_manual_dispatch_; | 1370 unsigned diag_virtual_and_manual_dispatch_; |
1351 unsigned diag_missing_trace_dispatch_; | 1371 unsigned diag_missing_trace_dispatch_; |
1352 unsigned diag_missing_finalize_dispatch_; | 1372 unsigned diag_missing_finalize_dispatch_; |
1353 unsigned diag_derives_non_stack_allocated_; | 1373 unsigned diag_derives_non_stack_allocated_; |
1354 unsigned diag_class_overrides_new_; | 1374 unsigned diag_class_overrides_new_; |
1355 unsigned diag_class_declares_pure_virtual_trace_; | 1375 unsigned diag_class_declares_pure_virtual_trace_; |
1356 | 1376 |
| 1377 unsigned diag_base_requires_tracing_note_; |
1357 unsigned diag_field_requires_tracing_note_; | 1378 unsigned diag_field_requires_tracing_note_; |
1358 unsigned diag_raw_ptr_to_gc_managed_class_note_; | 1379 unsigned diag_raw_ptr_to_gc_managed_class_note_; |
1359 unsigned diag_ref_ptr_to_gc_managed_class_note_; | 1380 unsigned diag_ref_ptr_to_gc_managed_class_note_; |
1360 unsigned diag_own_ptr_to_gc_managed_class_note_; | 1381 unsigned diag_own_ptr_to_gc_managed_class_note_; |
1361 unsigned diag_stack_allocated_field_note_; | 1382 unsigned diag_stack_allocated_field_note_; |
1362 unsigned diag_member_in_unmanaged_class_note_; | 1383 unsigned diag_member_in_unmanaged_class_note_; |
1363 unsigned diag_part_object_contains_gc_root_note_; | 1384 unsigned diag_part_object_contains_gc_root_note_; |
1364 unsigned diag_field_contains_gc_root_note_; | 1385 unsigned diag_field_contains_gc_root_note_; |
1365 unsigned diag_finalized_field_note_; | 1386 unsigned diag_finalized_field_note_; |
1366 unsigned diag_user_declared_destructor_note_; | 1387 unsigned diag_user_declared_destructor_note_; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1408 | 1429 |
1409 private: | 1430 private: |
1410 BlinkGCPluginOptions options_; | 1431 BlinkGCPluginOptions options_; |
1411 }; | 1432 }; |
1412 | 1433 |
1413 } // namespace | 1434 } // namespace |
1414 | 1435 |
1415 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( | 1436 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( |
1416 "blink-gc-plugin", | 1437 "blink-gc-plugin", |
1417 "Check Blink GC invariants"); | 1438 "Check Blink GC invariants"); |
OLD | NEW |