| Index: tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
|
| diff --git a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
|
| index 31a83e8f2ddbf9054228b86344ac9785510dfca7..bdc5ca64c2913a2d3d9e4e297912e26527060535 100644
|
| --- a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
|
| +++ b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
|
| @@ -68,10 +68,13 @@ const char kStackAllocatedFieldNote[] =
|
| const char kMemberInUnmanagedClassNote[] =
|
| "[blink-gc] Member field %0 in unmanaged class declared here:";
|
|
|
| -const char kPartObjectContainsGCRoot[] =
|
| +const char kPartObjectToGCDerivedClassNote[] =
|
| + "[blink-gc] Part-object field %0 to a GC derived class declared here:";
|
| +
|
| +const char kPartObjectContainsGCRootNote[] =
|
| "[blink-gc] Field %0 with embedded GC root in %1 declared here:";
|
|
|
| -const char kFieldContainsGCRoot[] =
|
| +const char kFieldContainsGCRootNote[] =
|
| "[blink-gc] Field %0 defining a GC root declared here:";
|
|
|
| const char kOverriddenNonVirtualTrace[] =
|
| @@ -445,11 +448,22 @@ class CheckGCRootsVisitor : public RecursiveEdgeVisitor {
|
|
|
| // This visitor checks that the fields of a class are "well formed".
|
| // - OwnPtr, RefPtr and RawPtr must not point to a GC derived types.
|
| +// - Part objects must not be GC derived types.
|
| // - An on-heap class must never contain GC roots.
|
| // - Only stack-allocated types may point to stack-allocated types.
|
| class CheckFieldsVisitor : public RecursiveEdgeVisitor {
|
| public:
|
| - typedef std::vector<std::pair<FieldPoint*, Edge*> > Errors;
|
| +
|
| + enum Error {
|
| + kRawPtrToGCManaged,
|
| + kRefPtrToGCManaged,
|
| + kOwnPtrToGCManaged,
|
| + kMemberInUnmanaged,
|
| + kPtrFromHeapToStack,
|
| + kGCDerivedPartObject
|
| + };
|
| +
|
| + typedef std::vector<std::pair<FieldPoint*, Error> > Errors;
|
|
|
| CheckFieldsVisitor(const BlinkGCPluginOptions& options)
|
| : options_(options), current_(0), stack_allocated_host_(false) {}
|
| @@ -482,7 +496,7 @@ class CheckFieldsVisitor : public RecursiveEdgeVisitor {
|
| if ((*it)->Kind() == Edge::kRoot)
|
| return;
|
| }
|
| - invalid_fields_.push_back(std::make_pair(current_, edge));
|
| + invalid_fields_.push_back(std::make_pair(current_, kMemberInUnmanaged));
|
| }
|
|
|
| void VisitValue(Value* edge) override {
|
| @@ -491,7 +505,14 @@ class CheckFieldsVisitor : public RecursiveEdgeVisitor {
|
| return;
|
|
|
| if (!stack_allocated_host_ && edge->value()->IsStackAllocated()) {
|
| - invalid_fields_.push_back(std::make_pair(current_, edge));
|
| + invalid_fields_.push_back(std::make_pair(current_, kPtrFromHeapToStack));
|
| + return;
|
| + }
|
| +
|
| + if (!Parent() &&
|
| + edge->value()->IsGCDerived() &&
|
| + !edge->value()->IsGCMixin()) {
|
| + invalid_fields_.push_back(std::make_pair(current_, kGCDerivedPartObject));
|
| return;
|
| }
|
|
|
| @@ -504,7 +525,8 @@ class CheckFieldsVisitor : public RecursiveEdgeVisitor {
|
| if (Parent()->IsOwnPtr() ||
|
| Parent()->IsRawPtrClass() ||
|
| (stack_allocated_host_ && Parent()->IsRawPtr())) {
|
| - invalid_fields_.push_back(std::make_pair(current_, Parent()));
|
| + invalid_fields_.push_back(std::make_pair(
|
| + current_, InvalidSmartPtr(Parent())));
|
| return;
|
| }
|
|
|
| @@ -512,12 +534,23 @@ class CheckFieldsVisitor : public RecursiveEdgeVisitor {
|
| }
|
|
|
| if (Parent()->IsRawPtr() || Parent()->IsRefPtr() || Parent()->IsOwnPtr()) {
|
| - invalid_fields_.push_back(std::make_pair(current_, Parent()));
|
| + invalid_fields_.push_back(std::make_pair(
|
| + current_, InvalidSmartPtr(Parent())));
|
| return;
|
| }
|
| }
|
|
|
| private:
|
| + Error InvalidSmartPtr(Edge* ptr) {
|
| + if (ptr->IsRawPtr())
|
| + return kRawPtrToGCManaged;
|
| + if (ptr->IsRefPtr())
|
| + return kRefPtrToGCManaged;
|
| + if (ptr->IsOwnPtr())
|
| + return kOwnPtrToGCManaged;
|
| + assert(false && "Unknown smart pointer kind");
|
| + }
|
| +
|
| const BlinkGCPluginOptions& options_;
|
| FieldPoint* current_;
|
| bool stack_allocated_host_;
|
| @@ -595,10 +628,12 @@ class BlinkGCPluginConsumer : public ASTConsumer {
|
| DiagnosticsEngine::Note, kStackAllocatedFieldNote);
|
| diag_member_in_unmanaged_class_note_ = diagnostic_.getCustomDiagID(
|
| DiagnosticsEngine::Note, kMemberInUnmanagedClassNote);
|
| + diag_part_object_to_gc_derived_class_note_ = diagnostic_.getCustomDiagID(
|
| + DiagnosticsEngine::Note, kPartObjectToGCDerivedClassNote);
|
| diag_part_object_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
|
| - DiagnosticsEngine::Note, kPartObjectContainsGCRoot);
|
| + DiagnosticsEngine::Note, kPartObjectContainsGCRootNote);
|
| diag_field_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
|
| - DiagnosticsEngine::Note, kFieldContainsGCRoot);
|
| + DiagnosticsEngine::Note, kFieldContainsGCRootNote);
|
| diag_finalized_field_note_ = diagnostic_.getCustomDiagID(
|
| DiagnosticsEngine::Note, kFinalizedFieldNote);
|
| diag_user_declared_destructor_note_ = diagnostic_.getCustomDiagID(
|
| @@ -717,12 +752,13 @@ class BlinkGCPluginConsumer : public ASTConsumer {
|
| }
|
|
|
| if (info->IsGCDerived()) {
|
| - CheckLeftMostDerived(info);
|
|
|
| - CheckDispatch(info);
|
| -
|
| - if (CXXMethodDecl* newop = info->DeclaresNewOperator())
|
| - ReportClassOverridesNew(info, newop);
|
| + if (!info->IsGCMixin()) {
|
| + CheckLeftMostDerived(info);
|
| + CheckDispatch(info);
|
| + if (CXXMethodDecl* newop = info->DeclaresNewOperator())
|
| + ReportClassOverridesNew(info, newop);
|
| + }
|
|
|
| {
|
| CheckGCRootsVisitor visitor;
|
| @@ -1149,17 +1185,23 @@ class BlinkGCPluginConsumer : public ASTConsumer {
|
| for (CheckFieldsVisitor::Errors::iterator it = errors->begin();
|
| it != errors->end();
|
| ++it) {
|
| - if (it->second->IsRawPtr()) {
|
| - NoteField(it->first, diag_raw_ptr_to_gc_managed_class_note_);
|
| - } else if (it->second->IsRefPtr()) {
|
| - NoteField(it->first, diag_ref_ptr_to_gc_managed_class_note_);
|
| - } else if (it->second->IsOwnPtr()) {
|
| - NoteField(it->first, diag_own_ptr_to_gc_managed_class_note_);
|
| - } else if (it->second->IsMember()) {
|
| - NoteField(it->first, diag_member_in_unmanaged_class_note_);
|
| - } else if (it->second->IsValue()) {
|
| - NoteField(it->first, diag_stack_allocated_field_note_);
|
| + unsigned error;
|
| + if (it->second == CheckFieldsVisitor::kRawPtrToGCManaged) {
|
| + error = diag_raw_ptr_to_gc_managed_class_note_;
|
| + } else if (it->second == CheckFieldsVisitor::kRefPtrToGCManaged) {
|
| + error = diag_ref_ptr_to_gc_managed_class_note_;
|
| + } else if (it->second == CheckFieldsVisitor::kOwnPtrToGCManaged) {
|
| + error = diag_own_ptr_to_gc_managed_class_note_;
|
| + } else if (it->second == CheckFieldsVisitor::kMemberInUnmanaged) {
|
| + error = diag_member_in_unmanaged_class_note_;
|
| + } else if (it->second == CheckFieldsVisitor::kPtrFromHeapToStack) {
|
| + error = diag_stack_allocated_field_note_;
|
| + } else if (it->second == CheckFieldsVisitor::kGCDerivedPartObject) {
|
| + error = diag_part_object_to_gc_derived_class_note_;
|
| + } else {
|
| + assert(false && "Unknown field error");
|
| }
|
| + NoteField(it->first, error);
|
| }
|
| }
|
|
|
| @@ -1383,6 +1425,7 @@ class BlinkGCPluginConsumer : public ASTConsumer {
|
| unsigned diag_own_ptr_to_gc_managed_class_note_;
|
| unsigned diag_stack_allocated_field_note_;
|
| unsigned diag_member_in_unmanaged_class_note_;
|
| + unsigned diag_part_object_to_gc_derived_class_note_;
|
| unsigned diag_part_object_contains_gc_root_note_;
|
| unsigned diag_field_contains_gc_root_note_;
|
| unsigned diag_finalized_field_note_;
|
|
|