Commit f691be3b authored by zerny's avatar zerny Committed by Commit bot

Blink GC plugin: Check polymorphic requirements on all GC-derived classes.

Prior to this change we only checked the polymorphic requirements on classes
that declared a trace method. Also, this fixes a typo in condition (2) where we
checked on the derived class instead of the left-most class.

R=ager@chromium.org
BUG=

Review URL: https://codereview.chromium.org/564453002

Cr-Commit-Position: refs/heads/master@{#294360}
parent a41817cd
...@@ -951,12 +951,17 @@ class BlinkGCPluginConsumer : public ASTConsumer { ...@@ -951,12 +951,17 @@ class BlinkGCPluginConsumer : public ASTConsumer {
if (CXXMethodDecl* trace = info->GetTraceMethod()) { if (CXXMethodDecl* trace = info->GetTraceMethod()) {
if (trace->isPure()) if (trace->isPure())
ReportClassDeclaresPureVirtualTrace(info, trace); ReportClassDeclaresPureVirtualTrace(info, trace);
if (info->record()->isPolymorphic())
CheckPolymorphicClass(info, trace);
} else if (info->RequiresTraceMethod()) { } else if (info->RequiresTraceMethod()) {
ReportClassRequiresTraceMethod(info); ReportClassRequiresTraceMethod(info);
} }
// Check polymorphic classes that are GC-derived or have a trace method.
if (info->record()->hasDefinition() && info->record()->isPolymorphic()) {
CXXMethodDecl* trace = info->GetTraceMethod();
if (trace || info->IsGCDerived())
CheckPolymorphicClass(info, trace);
}
{ {
CheckFieldsVisitor visitor(options_); CheckFieldsVisitor visitor(options_);
if (visitor.ContainsInvalidFields(info)) if (visitor.ContainsInvalidFields(info))
...@@ -1010,8 +1015,8 @@ class BlinkGCPluginConsumer : public ASTConsumer { ...@@ -1010,8 +1015,8 @@ class BlinkGCPluginConsumer : public ASTConsumer {
// hold to satisfy that assumption: // hold to satisfy that assumption:
// //
// 1. If trace is virtual, then it must be defined in the left-most base. // 1. If trace is virtual, then it must be defined in the left-most base.
// This ensures that if the vtable is initialized and it contains a pointer to // This ensures that if the vtable is initialized then it contains a pointer
// the trace method. // to the trace method.
// //
// 2. If trace is non-virtual, then the trace method is defined and we must // 2. If trace is non-virtual, then the trace method is defined and we must
// ensure that the left-most base defines a vtable. This ensures that the // ensure that the left-most base defines a vtable. This ensures that the
...@@ -1041,7 +1046,7 @@ class BlinkGCPluginConsumer : public ASTConsumer { ...@@ -1041,7 +1046,7 @@ class BlinkGCPluginConsumer : public ASTConsumer {
return; return;
// Stop with the left-most prior to a safe polymorphic base (a safe base // Stop with the left-most prior to a safe polymorphic base (a safe base
// is non-polymorphic and contains no fields that need tracing). // is non-polymorphic and contains no fields).
if (Config::IsSafePolymorphicBase(name)) if (Config::IsSafePolymorphicBase(name))
break; break;
...@@ -1052,7 +1057,7 @@ class BlinkGCPluginConsumer : public ASTConsumer { ...@@ -1052,7 +1057,7 @@ class BlinkGCPluginConsumer : public ASTConsumer {
if (RecordInfo* left_most_info = cache_.Lookup(left_most)) { if (RecordInfo* left_most_info = cache_.Lookup(left_most)) {
// Check condition (1): // Check condition (1):
if (trace->isVirtual()) { if (trace && trace->isVirtual()) {
if (CXXMethodDecl* trace = left_most_info->GetTraceMethod()) { if (CXXMethodDecl* trace = left_most_info->GetTraceMethod()) {
if (trace->isVirtual()) if (trace->isVirtual())
return; return;
...@@ -1062,7 +1067,7 @@ class BlinkGCPluginConsumer : public ASTConsumer { ...@@ -1062,7 +1067,7 @@ class BlinkGCPluginConsumer : public ASTConsumer {
} }
// Check condition (2): // Check condition (2):
if (DeclaresVirtualMethods(info->record())) if (DeclaresVirtualMethods(left_most))
return; return;
if (left_most_base) { if (left_most_base) {
++it; // Get the base next to the "safe polymorphic base" ++it; // Get the base next to the "safe polymorphic base"
......
In file included from class_does_not_require_finalization.cpp:5: In file included from class_does_not_require_finalization.cpp:5:
./class_does_not_require_finalization.h:18:1: warning: [blink-gc] Class 'DoesNotNeedFinalizer' may not require finalization. ./class_does_not_require_finalization.h:18:1: warning: [blink-gc] Class 'DoesNotNeedFinalizer' may not require finalization.
class DoesNotNeedFinalizer : public GarbageCollectedFinalized<DoesNotNeedFinalizer> { class DoesNotNeedFinalizer
^ ^
./class_does_not_require_finalization.h:23:1: warning: [blink-gc] Class 'DoesNotNeedFinalizer2' may not require finalization. ./class_does_not_require_finalization.h:24:1: warning: [blink-gc] Class 'DoesNotNeedFinalizer2' may not require finalization.
class DoesNotNeedFinalizer2 : public GarbageCollectedFinalized<DoesNotNeedFinalizer2> { class DoesNotNeedFinalizer2
^ ^
./class_does_not_require_finalization.h:34:1: warning: [blink-gc] Class 'DoesNotNeedFinalizer3' may not require finalization. ./class_does_not_require_finalization.h:36:1: warning: [blink-gc] Class 'DoesNotNeedFinalizer3' may not require finalization.
class DoesNotNeedFinalizer3 : public GarbageCollectedFinalized<DoesNotNeedFinalizer3>, public HasEmptyDtor { class DoesNotNeedFinalizer3
^ ^
3 warnings generated. 3 warnings generated.
...@@ -41,6 +41,21 @@ private: ...@@ -41,6 +41,21 @@ private:
Member<HeapObject> m_obj; Member<HeapObject> m_obj;
}; };
template<typename T>
class TemplatedNonPolymorphicBase
: public GarbageCollected<TemplatedNonPolymorphicBase<T> > {
public:
void trace(Visitor* visitor) { visitor->trace(m_obj); }
private:
Member<HeapObject> m_obj;
};
// Looks OK, but will result in an incorrect object pointer when marking.
class TemplatedIsNotLeftMostPolymorphic
: public TemplatedNonPolymorphicBase<TemplatedIsNotLeftMostPolymorphic>,
public PolymorphicBase {
};
} }
#endif #endif
...@@ -2,4 +2,7 @@ In file included from polymorphic_class_with_non_virtual_trace.cpp:5: ...@@ -2,4 +2,7 @@ In file included from polymorphic_class_with_non_virtual_trace.cpp:5:
./polymorphic_class_with_non_virtual_trace.h:17:1: warning: [blink-gc] Left-most base class 'NonPolymorphicBase' of derived class 'IsNotLeftMostPolymorphic' must be polymorphic. ./polymorphic_class_with_non_virtual_trace.h:17:1: warning: [blink-gc] Left-most base class 'NonPolymorphicBase' of derived class 'IsNotLeftMostPolymorphic' must be polymorphic.
class NonPolymorphicBase { class NonPolymorphicBase {
^ ^
1 warning generated. ./polymorphic_class_with_non_virtual_trace.h:45:1: warning: [blink-gc] Left-most base class 'TemplatedNonPolymorphicBase<blink::TemplatedIsNotLeftMostPolymorphic>' of derived class 'TemplatedIsNotLeftMostPolymorphic' must be polymorphic.
class TemplatedNonPolymorphicBase
^
2 warnings generated.
In file included from virtual_and_trace_after_dispatch.cpp:5: In file included from virtual_and_trace_after_dispatch.cpp:5:
./virtual_and_trace_after_dispatch.h:12:1: warning: [blink-gc] Left-most base class 'A' of derived class 'B' must be polymorphic.
class A : public GarbageCollected<A> {
^
./virtual_and_trace_after_dispatch.h:23:1: warning: [blink-gc] Class 'B' contains or inherits virtual methods but implements manual dispatching. ./virtual_and_trace_after_dispatch.h:23:1: warning: [blink-gc] Class 'B' contains or inherits virtual methods but implements manual dispatching.
class B : public A { class B : public A {
^ ^
./virtual_and_trace_after_dispatch.h:14:5: note: [blink-gc] Manual dispatch 'trace' declared here: ./virtual_and_trace_after_dispatch.h:14:5: note: [blink-gc] Manual dispatch 'trace' declared here:
void trace(Visitor*); void trace(Visitor*);
^ ^
1 warning generated. 2 warnings generated.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment