]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
d: Field access in parentheses causes error: need 'this' for 'field' of type 'type'
authorIain Buclaw <ibuclaw@gdcproject.org>
Tue, 21 Jul 2020 17:32:54 +0000 (19:32 +0200)
committerIain Buclaw <ibuclaw@gdcproject.org>
Thu, 20 Aug 2020 17:00:47 +0000 (19:00 +0200)
1. Fixes an ICE in the front-end if a struct symbol were to appear twice
in the compilation unit.

2. Fixes a rejects-valid bug in the front-end where `(symbol)' was being
resolved as a `var' expression, instead of `this.var'.

gcc/d/ChangeLog:

PR d/96250
* dmd/dstruct.c (StructDeclaration::semantic): Error if redefinition
of struct exists in compilation.
* dmd/expressionsem.c (ExpressionSemanticVisitor::visit(TypeExp)):
Rewrite resolved field variables as 'this.var' before semantic.
* dmd/parse.c (Parser::parseUnaryExp): Mark '(type) una_exp' as a
parenthesized expression.

gcc/testsuite/ChangeLog:

PR d/96250
* gdc.test/fail_compilation/fail17492.d: New test.
* gdc.test/compilable/b9490.d: New test.
* gdc.test/compilable/ice14739.d: New test.
* gdc.test/fail_compilation/ice21060.d: New test.
* gdc.test/fail_compilation/imports/ice21060a/package.d: New file.
* gdc.test/fail_compilation/imports/ice21060b/package.d: New file.
* gdc.test/fail_compilation/imports/ice21060c/package.d: New file.
* gdc.test/fail_compilation/imports/ice21060d/package.d: New file.
* gdc.test/runnable/b16278.d: New test.

12 files changed:
gcc/d/dmd/dstruct.c
gcc/d/dmd/expressionsem.c
gcc/d/dmd/parse.c
gcc/testsuite/gdc.test/compilable/b9490.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/ice14739.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/fail17492.d
gcc/testsuite/gdc.test/fail_compilation/ice21060.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/imports/ice21060a/package.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/imports/ice21060b/package.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/imports/ice21060c/package.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/imports/ice21060d/package.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/b16278.d [new file with mode: 0644]

index 0a33cc23935595826d55945630491e6c569d9ece..7da94c1aba85537d48e3033ad92cd85427dcb88d 100644 (file)
@@ -1206,6 +1206,13 @@ void StructDeclaration::semantic(Scope *sc)
         }
     }
 
+    if (type->ty == Tstruct && ((TypeStruct *)type)->sym != this)
+    {
+        // https://issues.dlang.org/show_bug.cgi?id=19024
+        StructDeclaration *sd = ((TypeStruct *)type)->sym;
+        error("already exists at %s. Perhaps in another function with the same name?", sd->loc.toChars());
+    }
+
     if (global.errors != errors)
     {
         // The type is no good.
@@ -1220,8 +1227,6 @@ void StructDeclaration::semantic(Scope *sc)
         deferred->semantic2(sc);
         deferred->semantic3(sc);
     }
-
-    assert(type->ty != Tstruct || ((TypeStruct *)type)->sym == this);
 }
 
 Dsymbol *StructDeclaration::search(const Loc &loc, Identifier *ident, int flags)
index 3221a8ae1121cfd3f07e4994ec56e82a53f9b186..562c2a60426cdb91fdce31b44191820df43d01d2 100644 (file)
@@ -812,6 +812,16 @@ public:
         exp->type->resolve(exp->loc, sc, &e, &t, &s, true);
         if (e)
         {
+            // `(Type)` is actually `(var)` so if `(var)` is a member requiring `this`
+            // then rewrite as `(this.var)` in case it would be followed by a DotVar
+            // to fix https://issues.dlang.org/show_bug.cgi?id=9490
+            VarExp *ve = e->isVarExp();
+            if (ve && ve->var && exp->parens && !ve->var->isStatic() && !(sc->stc & STCstatic) &&
+                sc->func && sc->func->needThis() && ve->var->toParent2()->isAggregateDeclaration())
+            {
+                // printf("apply fix for issue 9490: add `this.` to `%s`...\n", e->toChars());
+                e = new DotVarExp(exp->loc, new ThisExp(exp->loc), ve->var, false);
+            }
             //printf("e = %s %s\n", Token::toChars(e->op), e->toChars());
             e = semantic(e, sc);
         }
index b66bddb8ef87aa996832bcd75edd91bdb5db975a..df18034a0033701bf028d2d16fd8739a4eeb8e57 100644 (file)
@@ -7527,6 +7527,7 @@ Expression *Parser::parseUnaryExp()
                                 return NULL;
                             }
                             e = new TypeExp(loc, t);
+                            e->parens = 1;
                             e = parsePostExp(e);
                         }
                         else
diff --git a/gcc/testsuite/gdc.test/compilable/b9490.d b/gcc/testsuite/gdc.test/compilable/b9490.d
new file mode 100644 (file)
index 0000000..d0148b1
--- /dev/null
@@ -0,0 +1,39 @@
+// https://issues.dlang.org/show_bug.cgi?id=9490
+class A
+{
+    int[1] arr;
+
+    this()
+    {
+        assert(arr.length);
+        assert((arr).length);
+    }
+}
+
+class C
+{
+    struct Foo { int a; void funcToo(){} }
+    Foo foo;
+
+    auto get(){return foo;}
+
+    void test()
+    {
+        // Error: need 'this' to access member a
+        (foo).a = 1;
+        (foo).funcToo();
+        (get()).a = 2;
+    }
+}
+
+struct S { int i; }
+struct S1 { S s; }
+void f(int) { }
+
+void main()
+{
+    S1 s1;
+    f(s1.s.tupleof); // OK
+    f((s1.s).tupleof); // Error: need 'this' to access member s
+}
+
diff --git a/gcc/testsuite/gdc.test/compilable/ice14739.d b/gcc/testsuite/gdc.test/compilable/ice14739.d
new file mode 100644 (file)
index 0000000..cc90da6
--- /dev/null
@@ -0,0 +1,19 @@
+// REQUIRED_ARGS: -o-
+
+void main(string[] args)
+{
+    immutable int a;
+    immutable int b;
+    S!a sa;
+    S!b sb;
+    C!a ca;
+    C!b cb;
+}
+
+struct S(alias a)
+{
+}
+
+class C(alias a)
+{
+}
index e45c2e59359e4bcf61a214f0c5295ec903fb18ab..80e9e2a2c4aafc8e68315c2b974c2f9dd55b15cb 100644 (file)
@@ -1,6 +1,7 @@
 /* TEST_OUTPUT:
 ---
-fail_compilation/fail17492.d(19): Error: class fail17492.C.testE.I already exists at fail_compilation/fail17492.d(12). Perhaps in another function with the same name?
+fail_compilation/fail17492.d(20): Error: class `fail17492.C.testE.I` already exists at fail17492.d(13). Perhaps in another function with the same name?
+fail_compilation/fail17492.d(37): Error: struct `fail17492.S.testE.I` already exists at fail17492.d(30). Perhaps in another function with the same name?
 ---
 https://issues.dlang.org/show_bug.cgi?id=17492
 */
@@ -21,3 +22,20 @@ class C
         }
     }
 }
+
+class S
+{
+    void testE()
+    {
+        struct I
+        {
+        }
+    }
+
+    void testE()
+    {
+        struct I
+        {
+        }
+    }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice21060.d b/gcc/testsuite/gdc.test/fail_compilation/ice21060.d
new file mode 100644 (file)
index 0000000..d33889c
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+EXTRA_FILES: imports/ice21060a/package.d imports/ice21060b/package.d imports/ice21060c/package.d imports/ice21060d/package.d
+TEST_OUTPUT:
+---
+fail_compilation/imports/ice21060b/package.d(3): Error: struct `imports.ice21060d.P21060` already exists at fail_compilation/imports/ice21060d/package.d(3). Perhaps in another function with the same name?
+---
+*/
+struct S21060
+{
+    void print()
+    {
+        import imports.ice21060a;
+        import imports.ice21060b;
+    }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/ice21060a/package.d b/gcc/testsuite/gdc.test/fail_compilation/imports/ice21060a/package.d
new file mode 100644 (file)
index 0000000..b046aeb
--- /dev/null
@@ -0,0 +1 @@
+import imports.ice21060c;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/ice21060b/package.d b/gcc/testsuite/gdc.test/fail_compilation/imports/ice21060b/package.d
new file mode 100644 (file)
index 0000000..a806fd0
--- /dev/null
@@ -0,0 +1,5 @@
+module imports.ice21060d;
+
+struct P21060
+{
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/ice21060c/package.d b/gcc/testsuite/gdc.test/fail_compilation/imports/ice21060c/package.d
new file mode 100644 (file)
index 0000000..cc6f74e
--- /dev/null
@@ -0,0 +1 @@
+import imports.ice21060d;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/ice21060d/package.d b/gcc/testsuite/gdc.test/fail_compilation/imports/ice21060d/package.d
new file mode 100644 (file)
index 0000000..a806fd0
--- /dev/null
@@ -0,0 +1,5 @@
+module imports.ice21060d;
+
+struct P21060
+{
+}
diff --git a/gcc/testsuite/gdc.test/runnable/b16278.d b/gcc/testsuite/gdc.test/runnable/b16278.d
new file mode 100644 (file)
index 0000000..a0a422d
--- /dev/null
@@ -0,0 +1,6 @@
+// REQUIRED_ARGS: -main
+class A()
+{
+    static struct S { A a; }
+}
+enum e = is(A!());