| 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 bc6674a28a8ab35602561aec91846b4821065065..89f0bd419bb94037deb240e7fb10e41ca09637a4 100644
|
| --- a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
|
| +++ b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
|
| @@ -56,6 +56,9 @@ const char kRefPtrToGCManagedClassNote[] =
|
| const char kOwnPtrToGCManagedClassNote[] =
|
| "[blink-gc] OwnPtr field %0 to a GC managed class declared here:";
|
|
|
| +const char kStackAllocatedFieldNote[] =
|
| + "[blink-gc] Stack-allocated field %0 declared here:";
|
| +
|
| const char kPartObjectContainsGCRoot[] =
|
| "[blink-gc] Field %0 with embedded GC root in %1 declared here:";
|
|
|
| @@ -102,6 +105,10 @@ const char kFieldRequiresFinalizationNote[] =
|
| const char kManualDispatchMethodNote[] =
|
| "[blink-gc] Manual dispatch %0 declared here:";
|
|
|
| +const char kDerivesNonStackAllocated[] =
|
| + "[blink-gc] Stack-allocated class %0 derives class %1"
|
| + " which is not stack allocated.";
|
| +
|
| struct BlinkGCPluginOptions {
|
| BlinkGCPluginOptions() : enable_oilpan(false) {}
|
| bool enable_oilpan;
|
| @@ -424,11 +431,12 @@ class CheckFieldsVisitor : public RecursiveEdgeVisitor {
|
| typedef std::vector<std::pair<FieldPoint*, Edge*> > Errors;
|
|
|
| CheckFieldsVisitor(const BlinkGCPluginOptions& options)
|
| - : options_(options), current_(0) {}
|
| + : options_(options), current_(0), stack_allocated_host_(false) {}
|
|
|
| Errors& invalid_fields() { return invalid_fields_; }
|
|
|
| bool ContainsInvalidFields(RecordInfo* info) {
|
| + stack_allocated_host_ = info->IsStackAllocated();
|
| for (RecordInfo::Fields::iterator it = info->GetFields().begin();
|
| it != info->GetFields().end();
|
| ++it) {
|
| @@ -444,6 +452,9 @@ class CheckFieldsVisitor : public RecursiveEdgeVisitor {
|
| if (edge->value()->record()->isUnion())
|
| return;
|
|
|
| + if (!stack_allocated_host_ && edge->value()->IsStackAllocated())
|
| + invalid_fields_.push_back(std::make_pair(current_, edge));
|
| +
|
| if (!Parent() || !edge->value()->IsGCAllocated())
|
| return;
|
|
|
| @@ -454,13 +465,15 @@ class CheckFieldsVisitor : public RecursiveEdgeVisitor {
|
| if (options_.enable_oilpan)
|
| return;
|
|
|
| - if (Parent()->IsRawPtr() || Parent()->IsRefPtr())
|
| + if ((!stack_allocated_host_ && Parent()->IsRawPtr()) ||
|
| + Parent()->IsRefPtr())
|
| invalid_fields_.push_back(std::make_pair(current_, Parent()));
|
| }
|
|
|
| private:
|
| const BlinkGCPluginOptions& options_;
|
| FieldPoint* current_;
|
| + bool stack_allocated_host_;
|
| Errors invalid_fields_;
|
| };
|
|
|
| @@ -510,6 +523,8 @@ class BlinkGCPluginConsumer : public ASTConsumer {
|
| getErrorLevel(), kMissingTraceDispatch);
|
| diag_missing_finalize_dispatch_ = diagnostic_.getCustomDiagID(
|
| getErrorLevel(), kMissingFinalizeDispatch);
|
| + diag_derives_non_stack_allocated_ = diagnostic_.getCustomDiagID(
|
| + getErrorLevel(), kDerivesNonStackAllocated);
|
|
|
| // Register note messages.
|
| diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID(
|
| @@ -520,6 +535,8 @@ class BlinkGCPluginConsumer : public ASTConsumer {
|
| DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote);
|
| diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
|
| DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote);
|
| + diag_stack_allocated_field_note_ = diagnostic_.getCustomDiagID(
|
| + DiagnosticsEngine::Note, kStackAllocatedFieldNote);
|
| diag_part_object_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
|
| DiagnosticsEngine::Note, kPartObjectContainsGCRoot);
|
| diag_field_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
|
| @@ -585,10 +602,19 @@ class BlinkGCPluginConsumer : public ASTConsumer {
|
|
|
| // Check a class-like object (eg, class, specialization, instantiation).
|
| void CheckClass(RecordInfo* info) {
|
| - // Don't enforce tracing of stack allocated objects.
|
| - if (!info || info->IsStackAllocated())
|
| + if (!info)
|
| return;
|
|
|
| + // Check consistency of stack-allocated hierarchies.
|
| + if (info->IsStackAllocated()) {
|
| + for (RecordInfo::Bases::iterator it = info->GetBases().begin();
|
| + it != info->GetBases().end();
|
| + ++it) {
|
| + if (!it->second.info()->IsStackAllocated())
|
| + ReportDerivesNonStackAllocated(info, &it->second);
|
| + }
|
| + }
|
| +
|
| if (info->RequiresTraceMethod() && !info->GetTraceMethod())
|
| ReportClassRequiresTraceMethod(info);
|
|
|
| @@ -894,6 +920,8 @@ class BlinkGCPluginConsumer : public ASTConsumer {
|
| 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->IsValue()) {
|
| + NoteField(it->first, diag_stack_allocated_field_note_);
|
| }
|
| }
|
| }
|
| @@ -997,6 +1025,14 @@ class BlinkGCPluginConsumer : public ASTConsumer {
|
| diagnostic_.Report(full_loc, error) << receiver->record();
|
| }
|
|
|
| + void ReportDerivesNonStackAllocated(RecordInfo* info, BasePoint* base) {
|
| + SourceLocation loc = base->spec().getLocStart();
|
| + SourceManager& manager = instance_.getSourceManager();
|
| + FullSourceLoc full_loc(loc, manager);
|
| + diagnostic_.Report(full_loc, diag_derives_non_stack_allocated_)
|
| + << info->record() << base->info()->record();
|
| + }
|
| +
|
| void NoteManualDispatchMethod(CXXMethodDecl* dispatch) {
|
| SourceLocation loc = dispatch->getLocStart();
|
| SourceManager& manager = instance_.getSourceManager();
|
| @@ -1075,11 +1111,13 @@ class BlinkGCPluginConsumer : public ASTConsumer {
|
| unsigned diag_virtual_and_manual_dispatch_;
|
| unsigned diag_missing_trace_dispatch_;
|
| unsigned diag_missing_finalize_dispatch_;
|
| + unsigned diag_derives_non_stack_allocated_;
|
|
|
| unsigned diag_field_requires_tracing_note_;
|
| unsigned diag_raw_ptr_to_gc_managed_class_note_;
|
| unsigned diag_ref_ptr_to_gc_managed_class_note_;
|
| unsigned diag_own_ptr_to_gc_managed_class_note_;
|
| + unsigned diag_stack_allocated_field_note_;
|
| unsigned diag_part_object_contains_gc_root_note_;
|
| unsigned diag_field_contains_gc_root_note_;
|
| unsigned diag_finalized_field_note_;
|
|
|