aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2020-05-16 23:33:15 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2020-05-17 00:20:09 +0200
commit7d505b0ed8565b8c120ddd2b0b4630c93eecdec5 (patch)
treea560a194b1496c53f2f5e5d1bd82e293ed9fe685
parent866f7405707dd2970868941635a32bd9197cd731 (diff)
d: Fix wrong vtable offset in virtual function call
The Semantic (pass 1) analysis for classes is handled by ClassDeclaration::semantic. For a given class, this method may be ran multiple times in order to resolve forward references. The method incrementally tries to resolve the types referred to by the members of the class. The subsequent calls to this method are short-circuited if the class members have been fully analyzed. For this the code tests that it is not the first/main call to the method (semanticRun == PASS.init else branch), scx is not set, and that the this->symtab is already set. If all these conditions are met, the method returns. But before returning, the method was setting this->semanticRun to PASSsemanticdone. It should not set semanticRun since the class has not been fully analyzed yet. The base class analysis for this class could be pending and as a result vtable may not have been fully created. This fake setting of semanticRun results in the semantic analyzer to believe that the class has been fully analyzed. As exposed by the issues in upstream, it may result in compile time errors when a derived type class is getting analyzed and because of this fake semanticdone on the base class, the semantic analysis construes that an overriden method is not defined in the base class. PR95155 exposes anoter scenario where a buggy vtable may be created and a call to a class method may result in execution of some adhoc code. gcc/d/ChangeLog: PR d/95155 * dmd/dclass.c (ClassDeclaration::semantic): Don't prematurely set done on semantic analysis. gcc/testsuite/ChangeLog: PR d/95155 * gdc.test/compilable/imports/pr9471a.d: New test. * gdc.test/compilable/imports/pr9471b.d: New test. * gdc.test/compilable/imports/pr9471c.d: New test. * gdc.test/compilable/imports/pr9471d.d: New test. * gdc.test/compilable/pr9471.d: New test.
-rw-r--r--gcc/d/ChangeLog6
-rw-r--r--gcc/d/dmd/dclass.c1
-rw-r--r--gcc/testsuite/ChangeLog9
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/pr9471a.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/pr9471b.d5
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/pr9471c.d18
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/pr9471d.d1
-rw-r--r--gcc/testsuite/gdc.test/compilable/pr9471.d6
8 files changed, 47 insertions, 1 deletions
diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog
index 9cc59c8ad1d..c3f56590298 100644
--- a/gcc/d/ChangeLog
+++ b/gcc/d/ChangeLog
@@ -1,3 +1,9 @@
+2020-05-16 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/95155
+ * dmd/dclass.c (ClassDeclaration::semantic): Don't prematurely
+ set done on semantic analysis.
+
2020-04-07 Iain Buclaw <ibuclaw@gdcproject.org>
PR d/94240
diff --git a/gcc/d/dmd/dclass.c b/gcc/d/dmd/dclass.c
index 572b3e24387..66869361dcb 100644
--- a/gcc/d/dmd/dclass.c
+++ b/gcc/d/dmd/dclass.c
@@ -395,7 +395,6 @@ void ClassDeclaration::semantic(Scope *sc)
}
else if (symtab && !scx)
{
- semanticRun = PASSsemanticdone;
return;
}
semanticRun = PASSsemantic;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b69958e23d0..0b70f660fb8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,12 @@
+2020-05-16 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/95155
+ * gdc.test/compilable/imports/pr9471a.d: New test.
+ * gdc.test/compilable/imports/pr9471b.d: New test.
+ * gdc.test/compilable/imports/pr9471c.d: New test.
+ * gdc.test/compilable/imports/pr9471d.d: New test.
+ * gdc.test/compilable/pr9471.d: New test.
+
2020-05-14 Szabolcs Nagy <szabolcs.nagy@arm.com>
Backport from mainline.
diff --git a/gcc/testsuite/gdc.test/compilable/imports/pr9471a.d b/gcc/testsuite/gdc.test/compilable/imports/pr9471a.d
new file mode 100644
index 00000000000..79b78e1e52a
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/pr9471a.d
@@ -0,0 +1,2 @@
+import imports.pr9471c;
+class AggregateDeclaration : ScopeDsymbol { }
diff --git a/gcc/testsuite/gdc.test/compilable/imports/pr9471b.d b/gcc/testsuite/gdc.test/compilable/imports/pr9471b.d
new file mode 100644
index 00000000000..a46a12c496f
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/pr9471b.d
@@ -0,0 +1,5 @@
+import imports.pr9471a;
+class ClassDeclaration : AggregateDeclaration
+{
+ void isBaseOf();
+}
diff --git a/gcc/testsuite/gdc.test/compilable/imports/pr9471c.d b/gcc/testsuite/gdc.test/compilable/imports/pr9471c.d
new file mode 100644
index 00000000000..d80a61480ce
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/pr9471c.d
@@ -0,0 +1,18 @@
+import imports.pr9471b;
+
+struct Array(T)
+{
+ static if (is(typeof(T.opCmp))) { }
+}
+alias ClassDeclarations = Array!ClassDeclaration;
+
+class Dsymbol
+{
+ void addObjcSymbols(ClassDeclarations);
+}
+
+class ScopeDsymbol : Dsymbol
+{
+ import imports.pr9471d;
+ void importScope();
+}
diff --git a/gcc/testsuite/gdc.test/compilable/imports/pr9471d.d b/gcc/testsuite/gdc.test/compilable/imports/pr9471d.d
new file mode 100644
index 00000000000..187b9083294
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/pr9471d.d
@@ -0,0 +1 @@
+// Module needs to be imported to trigger bug.
diff --git a/gcc/testsuite/gdc.test/compilable/pr9471.d b/gcc/testsuite/gdc.test/compilable/pr9471.d
new file mode 100644
index 00000000000..37ff32e4957
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/pr9471.d
@@ -0,0 +1,6 @@
+// PERMUTE_ARGS:
+// EXTRA_FILES: imports/pr9471a.d imports/pr9471b.d imports/pr9471c.d imports/pr9471d.d
+import imports.pr9471a;
+import imports.pr9471b;
+
+static assert (__traits(getVirtualIndex, ClassDeclaration.isBaseOf) == 7);