| 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 6603d6e6b804d31dc32ff4864621a53058fe0c1b..1c74e05056b5db448fee6041d9cab7384f189876 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:";
|
|
|
| @@ -97,6 +100,14 @@ const char kBaseRequiresFinalizationNote[] =
|
| const char kFieldRequiresFinalizationNote[] =
|
| "[blink-gc] Field %0 requiring finalization declared here:";
|
|
|
| +const char kDerivesNonStackAllocated[] =
|
| + "[blink-gc] Stack-allocated class %0 derives class %1"
|
| + " which is not stack allocated.";
|
| +
|
| +const char kDerivesStackAllocated[] =
|
| + "[blink-gc] Class %0 derives stack-allocated class %1"
|
| + " but is not itself stack allocated";
|
| +
|
| struct BlinkGCPluginOptions {
|
| BlinkGCPluginOptions() : enable_oilpan(false) {}
|
| bool enable_oilpan;
|
| @@ -419,11 +430,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) {
|
| @@ -439,6 +451,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;
|
|
|
| @@ -449,13 +464,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_;
|
| };
|
|
|
| @@ -503,6 +520,10 @@ class BlinkGCPluginConsumer : public ASTConsumer {
|
| getErrorLevel(), kMissingFinalize);
|
| diag_missing_finalize_dispatch_ = diagnostic_.getCustomDiagID(
|
| getErrorLevel(), kMissingFinalizeDispatch);
|
| + diag_derives_non_stack_allocated_ = diagnostic_.getCustomDiagID(
|
| + getErrorLevel(), kDerivesNonStackAllocated);
|
| + diag_derives_stack_allocated_ = diagnostic_.getCustomDiagID(
|
| + getErrorLevel(), kDerivesStackAllocated);
|
|
|
| // Register note messages.
|
| diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID(
|
| @@ -513,6 +534,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(
|
| @@ -574,10 +597,22 @@ 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.
|
| + bool stack_allocated = info->IsStackAllocated();
|
| + for (RecordInfo::Bases::iterator it = info->GetBases().begin();
|
| + it != info->GetBases().end();
|
| + ++it) {
|
| + bool stack_allocated_base = it->second.info()->IsStackAllocated();
|
| + if (stack_allocated && !stack_allocated_base)
|
| + ReportDerivesNonStackAllocated(info, &it->second);
|
| +
|
| + if (!stack_allocated && stack_allocated_base)
|
| + ReportDerivesStackAllocated(info, &it->second);
|
| + }
|
| +
|
| if (info->RequiresTraceMethod() && !info->GetTraceMethod())
|
| ReportClassRequiresTraceMethod(info);
|
|
|
| @@ -880,6 +915,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_);
|
| }
|
| }
|
| }
|
| @@ -973,6 +1010,22 @@ 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 ReportDerivesStackAllocated(RecordInfo* info, BasePoint* base) {
|
| + SourceLocation loc = base->spec().getLocStart();
|
| + SourceManager& manager = instance_.getSourceManager();
|
| + FullSourceLoc full_loc(loc, manager);
|
| + diagnostic_.Report(full_loc, diag_derives_stack_allocated_)
|
| + << info->record() << base->info()->record();
|
| + }
|
| +
|
| void NoteFieldRequiresTracing(RecordInfo* holder, FieldDecl* field) {
|
| NoteField(field, diag_field_requires_tracing_note_);
|
| }
|
| @@ -1036,11 +1089,14 @@ class BlinkGCPluginConsumer : public ASTConsumer {
|
| unsigned diag_missing_trace_dispatch_;
|
| unsigned diag_missing_finalize_;
|
| unsigned diag_missing_finalize_dispatch_;
|
| + unsigned diag_derives_non_stack_allocated_;
|
| + unsigned diag_derives_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_;
|
|
|