Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1168)

Side by Side Diff: tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp

Issue 292743006: Blink GC plugin: disallow GC derived types as part-object fields. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: support for mixin part objects Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | tools/clang/blink_gc_plugin/tests/part_object_to_gc_derived_class.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 61
62 const char kOwnPtrToGCManagedClassNote[] = 62 const char kOwnPtrToGCManagedClassNote[] =
63 "[blink-gc] OwnPtr field %0 to a GC managed class declared here:"; 63 "[blink-gc] OwnPtr field %0 to a GC managed class declared here:";
64 64
65 const char kStackAllocatedFieldNote[] = 65 const char kStackAllocatedFieldNote[] =
66 "[blink-gc] Stack-allocated field %0 declared here:"; 66 "[blink-gc] Stack-allocated field %0 declared here:";
67 67
68 const char kMemberInUnmanagedClassNote[] = 68 const char kMemberInUnmanagedClassNote[] =
69 "[blink-gc] Member field %0 in unmanaged class declared here:"; 69 "[blink-gc] Member field %0 in unmanaged class declared here:";
70 70
71 const char kPartObjectContainsGCRoot[] = 71 const char kPartObjectToGCDerivedClassNote[] =
72 "[blink-gc] Part-object field %0 to a GC derived class declared here:";
73
74 const char kPartObjectContainsGCRootNote[] =
72 "[blink-gc] Field %0 with embedded GC root in %1 declared here:"; 75 "[blink-gc] Field %0 with embedded GC root in %1 declared here:";
73 76
74 const char kFieldContainsGCRoot[] = 77 const char kFieldContainsGCRootNote[] =
75 "[blink-gc] Field %0 defining a GC root declared here:"; 78 "[blink-gc] Field %0 defining a GC root declared here:";
76 79
77 const char kOverriddenNonVirtualTrace[] = 80 const char kOverriddenNonVirtualTrace[] =
78 "[blink-gc] Class %0 overrides non-virtual trace of base class %1."; 81 "[blink-gc] Class %0 overrides non-virtual trace of base class %1.";
79 82
80 const char kOverriddenNonVirtualTraceNote[] = 83 const char kOverriddenNonVirtualTraceNote[] =
81 "[blink-gc] Non-virtual trace method declared here:"; 84 "[blink-gc] Non-virtual trace method declared here:";
82 85
83 const char kMissingTraceDispatchMethod[] = 86 const char kMissingTraceDispatchMethod[] =
84 "[blink-gc] Class %0 is missing manual trace dispatch."; 87 "[blink-gc] Class %0 is missing manual trace dispatch.";
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after
438 gc_roots_.push_back(current_); 441 gc_roots_.push_back(current_);
439 } 442 }
440 443
441 protected: 444 protected:
442 RootPath current_; 445 RootPath current_;
443 Errors gc_roots_; 446 Errors gc_roots_;
444 }; 447 };
445 448
446 // This visitor checks that the fields of a class are "well formed". 449 // This visitor checks that the fields of a class are "well formed".
447 // - OwnPtr, RefPtr and RawPtr must not point to a GC derived types. 450 // - OwnPtr, RefPtr and RawPtr must not point to a GC derived types.
451 // - Part objects must not be GC derived types.
448 // - An on-heap class must never contain GC roots. 452 // - An on-heap class must never contain GC roots.
449 // - Only stack-allocated types may point to stack-allocated types. 453 // - Only stack-allocated types may point to stack-allocated types.
450 class CheckFieldsVisitor : public RecursiveEdgeVisitor { 454 class CheckFieldsVisitor : public RecursiveEdgeVisitor {
451 public: 455 public:
452 typedef std::vector<std::pair<FieldPoint*, Edge*> > Errors; 456
457 enum Error {
458 kRawPtrToGCManaged,
459 kRefPtrToGCManaged,
460 kOwnPtrToGCManaged,
461 kMemberInUnmanaged,
462 kPtrFromHeapToStack,
463 kGCDerivedPartObject
464 };
465
466 typedef std::vector<std::pair<FieldPoint*, Error> > Errors;
453 467
454 CheckFieldsVisitor(const BlinkGCPluginOptions& options) 468 CheckFieldsVisitor(const BlinkGCPluginOptions& options)
455 : options_(options), current_(0), stack_allocated_host_(false) {} 469 : options_(options), current_(0), stack_allocated_host_(false) {}
456 470
457 Errors& invalid_fields() { return invalid_fields_; } 471 Errors& invalid_fields() { return invalid_fields_; }
458 472
459 bool ContainsInvalidFields(RecordInfo* info) { 473 bool ContainsInvalidFields(RecordInfo* info) {
460 stack_allocated_host_ = info->IsStackAllocated(); 474 stack_allocated_host_ = info->IsStackAllocated();
461 managed_host_ = stack_allocated_host_ || 475 managed_host_ = stack_allocated_host_ ||
462 info->IsGCAllocated() || 476 info->IsGCAllocated() ||
(...skipping 12 matching lines...) Expand all
475 void VisitMember(Member* edge) override { 489 void VisitMember(Member* edge) override {
476 if (managed_host_) 490 if (managed_host_)
477 return; 491 return;
478 // A member is allowed to appear in the context of a root. 492 // A member is allowed to appear in the context of a root.
479 for (Context::iterator it = context().begin(); 493 for (Context::iterator it = context().begin();
480 it != context().end(); 494 it != context().end();
481 ++it) { 495 ++it) {
482 if ((*it)->Kind() == Edge::kRoot) 496 if ((*it)->Kind() == Edge::kRoot)
483 return; 497 return;
484 } 498 }
485 invalid_fields_.push_back(std::make_pair(current_, edge)); 499 invalid_fields_.push_back(std::make_pair(current_, kMemberInUnmanaged));
486 } 500 }
487 501
488 void VisitValue(Value* edge) override { 502 void VisitValue(Value* edge) override {
489 // TODO: what should we do to check unions? 503 // TODO: what should we do to check unions?
490 if (edge->value()->record()->isUnion()) 504 if (edge->value()->record()->isUnion())
491 return; 505 return;
492 506
493 if (!stack_allocated_host_ && edge->value()->IsStackAllocated()) { 507 if (!stack_allocated_host_ && edge->value()->IsStackAllocated()) {
494 invalid_fields_.push_back(std::make_pair(current_, edge)); 508 invalid_fields_.push_back(std::make_pair(current_, kPtrFromHeapToStack));
495 return; 509 return;
496 } 510 }
497 511
512 if (!Parent() &&
513 edge->value()->IsGCDerived() &&
514 !edge->value()->IsGCMixin()) {
515 invalid_fields_.push_back(std::make_pair(current_, kGCDerivedPartObject));
516 return;
517 }
518
498 if (!Parent() || !edge->value()->IsGCAllocated()) 519 if (!Parent() || !edge->value()->IsGCAllocated())
499 return; 520 return;
500 521
501 // In transition mode, disallow OwnPtr<T>, RawPtr<T> to GC allocated T's, 522 // In transition mode, disallow OwnPtr<T>, RawPtr<T> to GC allocated T's,
502 // also disallow T* in stack-allocated types. 523 // also disallow T* in stack-allocated types.
503 if (options_.enable_oilpan) { 524 if (options_.enable_oilpan) {
504 if (Parent()->IsOwnPtr() || 525 if (Parent()->IsOwnPtr() ||
505 Parent()->IsRawPtrClass() || 526 Parent()->IsRawPtrClass() ||
506 (stack_allocated_host_ && Parent()->IsRawPtr())) { 527 (stack_allocated_host_ && Parent()->IsRawPtr())) {
507 invalid_fields_.push_back(std::make_pair(current_, Parent())); 528 invalid_fields_.push_back(std::make_pair(
529 current_, InvalidSmartPtr(Parent())));
508 return; 530 return;
509 } 531 }
510 532
511 return; 533 return;
512 } 534 }
513 535
514 if (Parent()->IsRawPtr() || Parent()->IsRefPtr() || Parent()->IsOwnPtr()) { 536 if (Parent()->IsRawPtr() || Parent()->IsRefPtr() || Parent()->IsOwnPtr()) {
515 invalid_fields_.push_back(std::make_pair(current_, Parent())); 537 invalid_fields_.push_back(std::make_pair(
538 current_, InvalidSmartPtr(Parent())));
516 return; 539 return;
517 } 540 }
518 } 541 }
519 542
520 private: 543 private:
544 Error InvalidSmartPtr(Edge* ptr) {
545 if (ptr->IsRawPtr())
546 return kRawPtrToGCManaged;
547 if (ptr->IsRefPtr())
548 return kRefPtrToGCManaged;
549 if (ptr->IsOwnPtr())
550 return kOwnPtrToGCManaged;
551 assert(false && "Unknown smart pointer kind");
552 }
553
521 const BlinkGCPluginOptions& options_; 554 const BlinkGCPluginOptions& options_;
522 FieldPoint* current_; 555 FieldPoint* current_;
523 bool stack_allocated_host_; 556 bool stack_allocated_host_;
524 bool managed_host_; 557 bool managed_host_;
525 Errors invalid_fields_; 558 Errors invalid_fields_;
526 }; 559 };
527 560
528 // Main class containing checks for various invariants of the Blink 561 // Main class containing checks for various invariants of the Blink
529 // garbage collection infrastructure. 562 // garbage collection infrastructure.
530 class BlinkGCPluginConsumer : public ASTConsumer { 563 class BlinkGCPluginConsumer : public ASTConsumer {
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( 621 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
589 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); 622 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote);
590 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( 623 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
591 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); 624 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote);
592 diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( 625 diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
593 DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote); 626 DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote);
594 diag_stack_allocated_field_note_ = diagnostic_.getCustomDiagID( 627 diag_stack_allocated_field_note_ = diagnostic_.getCustomDiagID(
595 DiagnosticsEngine::Note, kStackAllocatedFieldNote); 628 DiagnosticsEngine::Note, kStackAllocatedFieldNote);
596 diag_member_in_unmanaged_class_note_ = diagnostic_.getCustomDiagID( 629 diag_member_in_unmanaged_class_note_ = diagnostic_.getCustomDiagID(
597 DiagnosticsEngine::Note, kMemberInUnmanagedClassNote); 630 DiagnosticsEngine::Note, kMemberInUnmanagedClassNote);
631 diag_part_object_to_gc_derived_class_note_ = diagnostic_.getCustomDiagID(
632 DiagnosticsEngine::Note, kPartObjectToGCDerivedClassNote);
598 diag_part_object_contains_gc_root_note_ = diagnostic_.getCustomDiagID( 633 diag_part_object_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
599 DiagnosticsEngine::Note, kPartObjectContainsGCRoot); 634 DiagnosticsEngine::Note, kPartObjectContainsGCRootNote);
600 diag_field_contains_gc_root_note_ = diagnostic_.getCustomDiagID( 635 diag_field_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
601 DiagnosticsEngine::Note, kFieldContainsGCRoot); 636 DiagnosticsEngine::Note, kFieldContainsGCRootNote);
602 diag_finalized_field_note_ = diagnostic_.getCustomDiagID( 637 diag_finalized_field_note_ = diagnostic_.getCustomDiagID(
603 DiagnosticsEngine::Note, kFinalizedFieldNote); 638 DiagnosticsEngine::Note, kFinalizedFieldNote);
604 diag_user_declared_destructor_note_ = diagnostic_.getCustomDiagID( 639 diag_user_declared_destructor_note_ = diagnostic_.getCustomDiagID(
605 DiagnosticsEngine::Note, kUserDeclaredDestructorNote); 640 DiagnosticsEngine::Note, kUserDeclaredDestructorNote);
606 diag_user_declared_finalizer_note_ = diagnostic_.getCustomDiagID( 641 diag_user_declared_finalizer_note_ = diagnostic_.getCustomDiagID(
607 DiagnosticsEngine::Note, kUserDeclaredFinalizerNote); 642 DiagnosticsEngine::Note, kUserDeclaredFinalizerNote);
608 diag_base_requires_finalization_note_ = diagnostic_.getCustomDiagID( 643 diag_base_requires_finalization_note_ = diagnostic_.getCustomDiagID(
609 DiagnosticsEngine::Note, kBaseRequiresFinalizationNote); 644 DiagnosticsEngine::Note, kBaseRequiresFinalizationNote);
610 diag_field_requires_finalization_note_ = diagnostic_.getCustomDiagID( 645 diag_field_requires_finalization_note_ = diagnostic_.getCustomDiagID(
611 DiagnosticsEngine::Note, kFieldRequiresFinalizationNote); 646 DiagnosticsEngine::Note, kFieldRequiresFinalizationNote);
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 ReportClassRequiresTraceMethod(info); 745 ReportClassRequiresTraceMethod(info);
711 } 746 }
712 747
713 { 748 {
714 CheckFieldsVisitor visitor(options_); 749 CheckFieldsVisitor visitor(options_);
715 if (visitor.ContainsInvalidFields(info)) 750 if (visitor.ContainsInvalidFields(info))
716 ReportClassContainsInvalidFields(info, &visitor.invalid_fields()); 751 ReportClassContainsInvalidFields(info, &visitor.invalid_fields());
717 } 752 }
718 753
719 if (info->IsGCDerived()) { 754 if (info->IsGCDerived()) {
720 CheckLeftMostDerived(info);
721 755
722 CheckDispatch(info); 756 if (!info->IsGCMixin()) {
723 757 CheckLeftMostDerived(info);
724 if (CXXMethodDecl* newop = info->DeclaresNewOperator()) 758 CheckDispatch(info);
725 ReportClassOverridesNew(info, newop); 759 if (CXXMethodDecl* newop = info->DeclaresNewOperator())
760 ReportClassOverridesNew(info, newop);
761 }
726 762
727 { 763 {
728 CheckGCRootsVisitor visitor; 764 CheckGCRootsVisitor visitor;
729 if (visitor.ContainsGCRoots(info)) 765 if (visitor.ContainsGCRoots(info))
730 ReportClassContainsGCRoots(info, &visitor.gc_roots()); 766 ReportClassContainsGCRoots(info, &visitor.gc_roots());
731 } 767 }
732 768
733 if (info->NeedsFinalization()) 769 if (info->NeedsFinalization())
734 CheckFinalization(info); 770 CheckFinalization(info);
735 } 771 }
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after
1142 void ReportClassContainsInvalidFields(RecordInfo* info, 1178 void ReportClassContainsInvalidFields(RecordInfo* info,
1143 CheckFieldsVisitor::Errors* errors) { 1179 CheckFieldsVisitor::Errors* errors) {
1144 SourceLocation loc = info->record()->getLocStart(); 1180 SourceLocation loc = info->record()->getLocStart();
1145 SourceManager& manager = instance_.getSourceManager(); 1181 SourceManager& manager = instance_.getSourceManager();
1146 FullSourceLoc full_loc(loc, manager); 1182 FullSourceLoc full_loc(loc, manager);
1147 diagnostic_.Report(full_loc, diag_class_contains_invalid_fields_) 1183 diagnostic_.Report(full_loc, diag_class_contains_invalid_fields_)
1148 << info->record(); 1184 << info->record();
1149 for (CheckFieldsVisitor::Errors::iterator it = errors->begin(); 1185 for (CheckFieldsVisitor::Errors::iterator it = errors->begin();
1150 it != errors->end(); 1186 it != errors->end();
1151 ++it) { 1187 ++it) {
1152 if (it->second->IsRawPtr()) { 1188 unsigned error;
1153 NoteField(it->first, diag_raw_ptr_to_gc_managed_class_note_); 1189 if (it->second == CheckFieldsVisitor::kRawPtrToGCManaged) {
1154 } else if (it->second->IsRefPtr()) { 1190 error = diag_raw_ptr_to_gc_managed_class_note_;
1155 NoteField(it->first, diag_ref_ptr_to_gc_managed_class_note_); 1191 } else if (it->second == CheckFieldsVisitor::kRefPtrToGCManaged) {
1156 } else if (it->second->IsOwnPtr()) { 1192 error = diag_ref_ptr_to_gc_managed_class_note_;
1157 NoteField(it->first, diag_own_ptr_to_gc_managed_class_note_); 1193 } else if (it->second == CheckFieldsVisitor::kOwnPtrToGCManaged) {
1158 } else if (it->second->IsMember()) { 1194 error = diag_own_ptr_to_gc_managed_class_note_;
1159 NoteField(it->first, diag_member_in_unmanaged_class_note_); 1195 } else if (it->second == CheckFieldsVisitor::kMemberInUnmanaged) {
1160 } else if (it->second->IsValue()) { 1196 error = diag_member_in_unmanaged_class_note_;
1161 NoteField(it->first, diag_stack_allocated_field_note_); 1197 } else if (it->second == CheckFieldsVisitor::kPtrFromHeapToStack) {
1198 error = diag_stack_allocated_field_note_;
1199 } else if (it->second == CheckFieldsVisitor::kGCDerivedPartObject) {
1200 error = diag_part_object_to_gc_derived_class_note_;
1201 } else {
1202 assert(false && "Unknown field error");
1162 } 1203 }
1204 NoteField(it->first, error);
1163 } 1205 }
1164 } 1206 }
1165 1207
1166 void ReportClassContainsGCRoots(RecordInfo* info, 1208 void ReportClassContainsGCRoots(RecordInfo* info,
1167 CheckGCRootsVisitor::Errors* errors) { 1209 CheckGCRootsVisitor::Errors* errors) {
1168 SourceLocation loc = info->record()->getLocStart(); 1210 SourceLocation loc = info->record()->getLocStart();
1169 SourceManager& manager = instance_.getSourceManager(); 1211 SourceManager& manager = instance_.getSourceManager();
1170 FullSourceLoc full_loc(loc, manager); 1212 FullSourceLoc full_loc(loc, manager);
1171 for (CheckGCRootsVisitor::Errors::iterator it = errors->begin(); 1213 for (CheckGCRootsVisitor::Errors::iterator it = errors->begin();
1172 it != errors->end(); 1214 it != errors->end();
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
1376 unsigned diag_class_overrides_new_; 1418 unsigned diag_class_overrides_new_;
1377 unsigned diag_class_declares_pure_virtual_trace_; 1419 unsigned diag_class_declares_pure_virtual_trace_;
1378 1420
1379 unsigned diag_base_requires_tracing_note_; 1421 unsigned diag_base_requires_tracing_note_;
1380 unsigned diag_field_requires_tracing_note_; 1422 unsigned diag_field_requires_tracing_note_;
1381 unsigned diag_raw_ptr_to_gc_managed_class_note_; 1423 unsigned diag_raw_ptr_to_gc_managed_class_note_;
1382 unsigned diag_ref_ptr_to_gc_managed_class_note_; 1424 unsigned diag_ref_ptr_to_gc_managed_class_note_;
1383 unsigned diag_own_ptr_to_gc_managed_class_note_; 1425 unsigned diag_own_ptr_to_gc_managed_class_note_;
1384 unsigned diag_stack_allocated_field_note_; 1426 unsigned diag_stack_allocated_field_note_;
1385 unsigned diag_member_in_unmanaged_class_note_; 1427 unsigned diag_member_in_unmanaged_class_note_;
1428 unsigned diag_part_object_to_gc_derived_class_note_;
1386 unsigned diag_part_object_contains_gc_root_note_; 1429 unsigned diag_part_object_contains_gc_root_note_;
1387 unsigned diag_field_contains_gc_root_note_; 1430 unsigned diag_field_contains_gc_root_note_;
1388 unsigned diag_finalized_field_note_; 1431 unsigned diag_finalized_field_note_;
1389 unsigned diag_user_declared_destructor_note_; 1432 unsigned diag_user_declared_destructor_note_;
1390 unsigned diag_user_declared_finalizer_note_; 1433 unsigned diag_user_declared_finalizer_note_;
1391 unsigned diag_base_requires_finalization_note_; 1434 unsigned diag_base_requires_finalization_note_;
1392 unsigned diag_field_requires_finalization_note_; 1435 unsigned diag_field_requires_finalization_note_;
1393 unsigned diag_overridden_non_virtual_trace_note_; 1436 unsigned diag_overridden_non_virtual_trace_note_;
1394 unsigned diag_manual_dispatch_method_note_; 1437 unsigned diag_manual_dispatch_method_note_;
1395 1438
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1431 1474
1432 private: 1475 private:
1433 BlinkGCPluginOptions options_; 1476 BlinkGCPluginOptions options_;
1434 }; 1477 };
1435 1478
1436 } // namespace 1479 } // namespace
1437 1480
1438 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( 1481 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X(
1439 "blink-gc-plugin", 1482 "blink-gc-plugin",
1440 "Check Blink GC invariants"); 1483 "Check Blink GC invariants");
OLDNEW
« no previous file with comments | « no previous file | tools/clang/blink_gc_plugin/tests/part_object_to_gc_derived_class.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698