d: Merge upstream dmd 0450061c8
authorIain Buclaw <ibuclaw@gdcproject.org>
Thu, 8 Apr 2021 18:24:07 +0000 (20:24 +0200)
committerIain Buclaw <ibuclaw@gdcproject.org>
Sat, 10 Apr 2021 13:02:07 +0000 (15:02 +0200)
D front-end changes:

 - Fix ICE in forward referenced type members of structs.

 - Fix ICE passing a member template mixin identifier as alias argument.

 - Fix ICE when `__traits' prints error involving a Parameter.

 - Fix bugs found in `__traits(allMembers)' returning wrong result.

 - Detect and shortcut Alias and AliasSeq template patterns.

Reviewed-on: https://github.com/dlang/dmd/pull/12405
     https://github.com/dlang/dmd/pull/12411

gcc/d/ChangeLog:

* dmd/MERGE: Merge upstream dmd 0450061c8.

23 files changed:
gcc/d/dmd/MERGE
gcc/d/dmd/dstruct.c
gcc/d/dmd/dsymbol.h
gcc/d/dmd/dsymbolsem.c
gcc/d/dmd/dtemplate.c
gcc/d/dmd/hdrgen.c
gcc/d/dmd/mtype.c
gcc/d/dmd/template.h
gcc/d/dmd/traits.c
gcc/d/dmd/typesem.c
gcc/d/dmd/version.h
gcc/testsuite/gdc.test/compilable/imports/pkg16044/package.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/imports/pkg16044/sub/package.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/issue16044.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/issue20915.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/issue21813a.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/issue21813b.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test19145.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test20894.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test21812.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/diag19196.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/test16228.d
gcc/testsuite/gdc.test/fail_compilation/test20919.d [new file with mode: 0644]

index 98c229d..86fb308 100644 (file)
@@ -1,4 +1,4 @@
-d16195406e1795ee91f2acb8f522fcb4ec698f47
+0450061c8de71328815da9323bd35c92b37d51d2
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
index 40c67ce..9862159 100644 (file)
@@ -260,6 +260,8 @@ void AggregateDeclaration::setScope(Scope *sc)
  */
 bool AggregateDeclaration::determineFields()
 {
+    if (_scope)
+        dsymbolSemantic(this, NULL);
     if (sizeok != SIZEOKnone)
         return true;
 
index 4aabb5d..ce0ce45 100644 (file)
@@ -266,6 +266,8 @@ public:
     virtual UnitTestDeclaration *isUnitTestDeclaration() { return NULL; }
     virtual NewDeclaration *isNewDeclaration() { return NULL; }
     virtual VarDeclaration *isVarDeclaration() { return NULL; }
+    virtual VersionSymbol *isVersionSymbol() { return NULL; }
+    virtual DebugSymbol *isDebugSymbol() { return NULL; }
     virtual ClassDeclaration *isClassDeclaration() { return NULL; }
     virtual StructDeclaration *isStructDeclaration() { return NULL; }
     virtual UnionDeclaration *isUnionDeclaration() { return NULL; }
index 7e1a858..33f74ed 100644 (file)
@@ -570,7 +570,7 @@ public:
                     ti = dsym->_init ? dsym->_init->syntaxCopy() : NULL;
 
                 VarDeclaration *v = new VarDeclaration(dsym->loc, arg->type, id, ti);
-                v->storage_class |= STCtemp | dsym->storage_class;
+                v->storage_class |= STCtemp | STClocal | dsym->storage_class;
                 if (arg->storageClass & STCparameter)
                     v->storage_class |= arg->storageClass;
                 //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars());
@@ -4843,6 +4843,54 @@ public:
     }
 };
 
+/******************************************************
+ * Do template instance semantic for isAliasSeq templates.
+ * This is a greatly simplified version of TemplateInstance::semantic().
+ */
+static void aliasSeqInstanceSemantic(TemplateInstance *tempinst, Scope *sc, TemplateDeclaration *tempdecl)
+{
+    //printf("[%s] aliasSeqInstanceSemantic('%s')\n", tempinst->loc.toChars(), tempinst->toChars());
+    Scope *paramscope = sc->push();
+    paramscope->stc = 0;
+    paramscope->protection = Prot(Prot::public_);
+
+    TemplateTupleParameter *ttp = (*tempdecl->parameters)[0]->isTemplateTupleParameter();
+    Tuple *va = isTuple(tempinst->tdtypes[0]);
+    Declaration *d = new TupleDeclaration(tempinst->loc, ttp->ident, &va->objects);
+    d->storage_class |= STCtemplateparameter;
+    dsymbolSemantic(d, sc);
+
+    paramscope->pop();
+
+    tempinst->aliasdecl = d;
+
+    tempinst->semanticRun = PASSsemanticdone;
+}
+
+/******************************************************
+ * Do template instance semantic for isAlias templates.
+ * This is a greatly simplified version of TemplateInstance::semantic().
+ */
+static void aliasInstanceSemantic(TemplateInstance *tempinst, Scope *sc, TemplateDeclaration *tempdecl)
+{
+    //printf("[%s] aliasInstanceSemantic('%s')\n", tempinst->loc.toChars(), tempinst->toChars());
+    Scope *paramscope = sc->push();
+    paramscope->stc = 0;
+    paramscope->protection = Prot(Prot::public_);
+
+    TemplateTypeParameter *ttp = (*tempdecl->parameters)[0]->isTemplateTypeParameter();
+    Type *ta = isType(tempinst->tdtypes[0]);
+    Declaration *d = new AliasDeclaration(tempinst->loc, ttp->ident, ta->addMod(tempdecl->onemember->isAliasDeclaration()->type->mod));
+    d->storage_class |= STCtemplateparameter;
+    dsymbolSemantic(d, sc);
+
+    paramscope->pop();
+
+    tempinst->aliasdecl = d;
+
+    tempinst->semanticRun = PASSsemanticdone;
+}
+
 void templateInstanceSemantic(TemplateInstance *tempinst, Scope *sc, Expressions *fargs)
 {
     //printf("[%s] TemplateInstance::semantic('%s', this=%p, gag = %d, sc = %p)\n", tempinst->loc.toChars(), tempinst->toChars(), tempinst, global.gag, sc);
@@ -4913,6 +4961,21 @@ Lerror:
     if (tempinst->errors)
         goto Lerror;
 
+    /* Greatly simplified semantic processing for AliasSeq templates
+     */
+    if (tempdecl->isTrivialAliasSeq)
+    {
+        tempinst->inst = tempinst;
+        return aliasSeqInstanceSemantic(tempinst, sc, tempdecl);
+    }
+    /* Greatly simplified semantic processing for Alias templates
+     */
+    else if (tempdecl->isTrivialAlias)
+    {
+        tempinst->inst = tempinst;
+        return aliasInstanceSemantic(tempinst, sc, tempdecl);
+    }
+
     /* See if there is an existing TemplateInstantiation that already
      * implements the typeargs. If so, just refer to that one instead.
      */
index 208b064..20036f2 100644 (file)
@@ -222,7 +222,8 @@ bool definitelyValueParameter(Expression *e)
         e->op == TOKtype || e->op == TOKdottype ||
         e->op == TOKtemplate ||  e->op == TOKdottd ||
         e->op == TOKfunction || e->op == TOKerror ||
-        e->op == TOKthis || e->op == TOKsuper)
+        e->op == TOKthis || e->op == TOKsuper ||
+        e->op == TOKdot)
         return false;
 
     if (e->op != TOKdotvar)
@@ -531,6 +532,8 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
     this->literal = literal;
     this->ismixin = ismixin;
     this->isstatic = true;
+    this->isTrivialAliasSeq = false;
+    this->isTrivialAlias = false;
     this->previous = NULL;
     this->protection = Prot(Prot::undefined);
     this->inuse = 0;
@@ -538,13 +541,46 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
 
     // Compute in advance for Ddoc's use
     // Bugzilla 11153: ident could be NULL if parsing fails.
-    if (members && ident)
+    if (!members || !ident)
+        return;
+
+    Dsymbol *s;
+    if (!Dsymbol::oneMembers(members, &s, ident) || !s)
+        return;
+
+    onemember = s;
+    s->parent = this;
+
+    /* Set isTrivialAliasSeq if this fits the pattern:
+     *   template AliasSeq(T...) { alias AliasSeq = T; }
+     * or set isTrivialAlias if this fits the pattern:
+     *   template Alias(T) { alias Alias = qualifiers(T); }
+     */
+    if (!(parameters && parameters->length == 1))
+        return;
+
+    AliasDeclaration *ad = s->isAliasDeclaration();
+    if (!ad || !ad->type)
+        return;
+
+    TypeIdentifier *ti = ad->type->isTypeIdentifier();
+    if (!ti || ti->idents.length != 0)
+        return;
+
+    if (TemplateTupleParameter *ttp = (*parameters)[0]->isTemplateTupleParameter())
     {
-        Dsymbol *s;
-        if (Dsymbol::oneMembers(members, &s, ident) && s)
+        if (ti->ident == ttp->ident && ti->mod == 0)
+        {
+            //printf("found isAliasSeq %s %s\n", s->toChars(), ad->type->toChars());
+            isTrivialAliasSeq = true;
+        }
+    }
+    else if (TemplateTypeParameter *ttp = (*parameters)[0]->isTemplateTypeParameter())
+    {
+        if (ti->ident == ttp->ident)
         {
-            onemember = s;
-            s->parent = this;
+            //printf("found isAlias %s %s\n", s->toChars(), ad->type->toChars());
+            isTrivialAlias = true;
         }
     }
 }
@@ -6223,6 +6259,14 @@ bool TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
                 sa = ((DotTemplateExp *)ea)->td;
                 goto Ldsym;
             }
+            if (ea->op == TOKdot)
+            {
+                if (ScopeExp *se = ((DotExp *)ea)->e2->isScopeExp())
+                {
+                    sa = se->sds;
+                    goto Ldsym;
+                }
+            }
         }
         else if (sa)
         {
@@ -6770,8 +6814,7 @@ Dsymbols *TemplateInstance::appendToModuleMember()
 {
     Module *mi = minst;     // instantiated -> inserted module
 
-    if (global.params.useUnitTests ||
-        global.params.debuglevel)
+    if (global.params.useUnitTests)
     {
         // Turn all non-root instances to speculative
         if (mi && !mi->isRoot())
index 9eba88f..9397b1e 100644 (file)
@@ -1714,6 +1714,10 @@ public:
                 objectToBuffer(arg);
             }
         }
+        else if (Parameter *p = isParameter(oarg))
+        {
+            p->accept(this);
+        }
         else if (!oarg)
         {
             buf->writestring("NULL");
index 1c73f50..9ef8ab4 100644 (file)
@@ -7039,7 +7039,10 @@ Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident, int
          */
         e = expressionSemantic(e, sc);  // do this before turning on noaccesscheck
 
-        sym->size(e->loc);      // do semantic of type
+        if (!sym->determineFields())
+        {
+            error(e->loc, "unable to determine fields of `%s` because of forward references", toChars());
+        }
 
         Expression *e0 = NULL;
         Expression *ev = e->op == TOKtype ? NULL : e;
@@ -7373,7 +7376,9 @@ bool TypeStruct::hasPointers()
     // Probably should cache this information in sym rather than recompute
     StructDeclaration *s = sym;
 
-    sym->size(Loc());               // give error for forward references
+    if (sym->members && !sym->determineFields() && sym->type != Type::terror)
+        error(sym->loc, "no size because of forward references");
+
     for (size_t i = 0; i < s->fields.length; i++)
     {
         Declaration *d = s->fields[i];
index fb842ac..086ec72 100644 (file)
@@ -77,6 +77,8 @@ public:
     bool literal;               // this template declaration is a literal
     bool ismixin;               // template declaration is only to be used as a mixin
     bool isstatic;              // this is static template declaration
+    bool isTrivialAliasSeq;     // matches `template AliasSeq(T...) { alias AliasSeq = T; }
+    bool isTrivialAlias;        // matches `template Alias(T) { alias Alias = T; }
     Prot protection;
     int inuse;                  // for recursive expansion detection
 
index 99b5457..5a9f58b 100644 (file)
@@ -1560,6 +1560,13 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
             s = imp->mod;
         }
 
+        // https://issues.dlang.org/show_bug.cgi?id=16044
+        if (Package *p = s->isPackage())
+        {
+            if (Module *pm = p->isPackageMod())
+                s = pm;
+        }
+
         ScopeDsymbol *sds = s->isScopeDsymbol();
         if (!sds || sds->isTemplateDeclaration())
         {
@@ -1587,6 +1594,11 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
                     }
                 }
 
+                // https://issues.dlang.org/show_bug.cgi?id=20915
+                // skip version and debug identifiers
+                if (sm->isVersionSymbol() || sm->isDebugSymbol())
+                    return 0;
+
                 //printf("\t[%i] %s %s\n", i, sm->kind(), sm->toChars());
                 if (sm->ident)
                 {
index 670144d..31e93c2 100644 (file)
@@ -797,7 +797,7 @@ Type *typeSemantic(Type *type, const Loc &loc, Scope *sc)
 
                 if (tf->isreturn && !tf->isref && !tf->next->hasPointers())
                 {
-                    ::error(loc, "function type `%s` has `return` but does not return any indirections", tf->toChars());
+                    tf->isreturn = false;
                 }
             }
 
@@ -872,7 +872,7 @@ Type *typeSemantic(Type *type, const Loc &loc, Scope *sc)
                             if (0 && !tf->isref)
                             {
                                 StorageClass stc = fparam->storageClass & (STCref | STCout);
-                                ::error(loc, "parameter %s is `return %s` but function does not return by ref",
+                                ::error(loc, "parameter `%s` is `return %s` but function does not return by `ref`",
                                     fparam->ident ? fparam->ident->toChars() : "",
                                     stcToChars(stc));
                                 errors = true;
@@ -886,9 +886,7 @@ Type *typeSemantic(Type *type, const Loc &loc, Scope *sc)
                             }
                             else if (!tf->isref && tf->next && !tf->next->hasPointers())
                             {
-                                ::error(loc, "parameter %s is `return` but function does not return any indirections",
-                                    fparam->ident ? fparam->ident->toChars() : "");
-                                errors = true;
+                                fparam->storageClass &= STCreturn;   // https://issues.dlang.org/show_bug.cgi?id=18963
                             }
                         }
                     }
index 9e7fd5e..33811ee 100644 (file)
@@ -24,6 +24,7 @@ public:
     const char *toChars();
     void addMember(Scope *sc, ScopeDsymbol *sds);
     const char *kind() const;
+    DebugSymbol *isDebugSymbol() { return this; }
     void accept(Visitor *v) { v->visit(this); }
 };
 
@@ -39,5 +40,6 @@ public:
     const char *toChars();
     void addMember(Scope *sc, ScopeDsymbol *sds);
     const char *kind() const;
+    VersionSymbol *isVersionSymbol() { return this; }
     void accept(Visitor *v) { v->visit(this); }
 };
diff --git a/gcc/testsuite/gdc.test/compilable/imports/pkg16044/package.d b/gcc/testsuite/gdc.test/compilable/imports/pkg16044/package.d
new file mode 100644 (file)
index 0000000..a517957
--- /dev/null
@@ -0,0 +1,4 @@
+module pkg16044;
+
+int test1;
+int test2;
diff --git a/gcc/testsuite/gdc.test/compilable/imports/pkg16044/sub/package.d b/gcc/testsuite/gdc.test/compilable/imports/pkg16044/sub/package.d
new file mode 100644 (file)
index 0000000..4c96e12
--- /dev/null
@@ -0,0 +1,4 @@
+module pkg16044.sub;
+
+int test3;
+int test4;
diff --git a/gcc/testsuite/gdc.test/compilable/issue16044.d b/gcc/testsuite/gdc.test/compilable/issue16044.d
new file mode 100644 (file)
index 0000000..e959e2e
--- /dev/null
@@ -0,0 +1,9 @@
+// REQUIRED_ARGS: -Icompilable/imports
+// EXTRA_FILES: imports/pkg16044/package.d imports/pkg16044/sub/package.d
+module issue16044; // https://issues.dlang.org/show_bug.cgi?id=16044
+
+import pkg16044;
+import pkg16044.sub;
+
+static assert([__traits(allMembers, pkg16044)] == ["object", "test1", "test2"]);
+static assert([__traits(allMembers, pkg16044.sub)] == ["object", "test3", "test4"]);
diff --git a/gcc/testsuite/gdc.test/compilable/issue20915.d b/gcc/testsuite/gdc.test/compilable/issue20915.d
new file mode 100644 (file)
index 0000000..dd8b7b5
--- /dev/null
@@ -0,0 +1,10 @@
+module issue20915;
+
+// prior to the PR adding this test case,
+// locally defined version and debug idents were included.
+version = illegal;
+debug   = illegal;
+
+alias Seq(T...) = T;
+
+static assert (__traits(allMembers, issue20915) == Seq!("object", "Seq"));
diff --git a/gcc/testsuite/gdc.test/compilable/issue21813a.d b/gcc/testsuite/gdc.test/compilable/issue21813a.d
new file mode 100644 (file)
index 0000000..f07b47a
--- /dev/null
@@ -0,0 +1,13 @@
+// https://issues.dlang.org/show_bug.cgi?id=21813
+Target.OS defaultTargetOS()
+{
+    return Target.OS.linux;
+}
+
+struct Target
+{
+    enum OS { linux }
+    OS os = defaultTargetOS();
+    void deinitialize() { this = this.init; }
+    @property isPOSIX() scope @nogc { }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/issue21813b.d b/gcc/testsuite/gdc.test/compilable/issue21813b.d
new file mode 100644 (file)
index 0000000..ef22697
--- /dev/null
@@ -0,0 +1,13 @@
+// https://issues.dlang.org/show_bug.cgi?id=21813
+Target.OS defaultTargetOS()
+{
+    return Target.OS.linux;
+}
+
+struct Target 
+{
+    enum OS { linux }
+    OS os = defaultTargetOS();
+    @property isPOSIX() scope @nogc { }
+}
+
diff --git a/gcc/testsuite/gdc.test/compilable/test19145.d b/gcc/testsuite/gdc.test/compilable/test19145.d
new file mode 100644 (file)
index 0000000..ef5faa8
--- /dev/null
@@ -0,0 +1,14 @@
+// https://issues.dlang.org/show_bug.cgi?id=19415
+
+struct S
+{
+   int x;
+   S foo() return { return S(x); }
+   this(this) @disable;
+}
+
+S bar()
+{
+   S s;
+   return s; // Error: struct `S` is not copyable because it is annotated with @disable
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test20894.d b/gcc/testsuite/gdc.test/compilable/test20894.d
new file mode 100644 (file)
index 0000000..e8dad45
--- /dev/null
@@ -0,0 +1,46 @@
+// https://issues.dlang.org/show_bug.cgi?id=20894
+
+mixin template MT()
+{
+    int   a;
+    alias b = char;
+    void  c() {}
+}
+
+struct S
+{
+    mixin MT mt;
+}
+
+void main()
+{
+    auto r = S();
+    enum c = S();
+
+    foo!(S.mt);
+    foo!(r.mt);
+    foo!(c.mt);          // OK <- ICE
+
+    foo!(mixin("S.mt"));
+    foo!(mixin("r.mt")); // OK <- ICE
+    foo!(mixin("c.mt")); // OK <- ICE
+
+    // some checks
+    foo!(r.mt, c.mt);
+    foo!(mixin("r.mt"), c.mt);
+    foo!(r.mt, mixin("c.mt"));
+    foo!(S.mt, mixin("c.mt"));
+}
+
+alias Tup(T...) = T;
+
+void foo(A...)()
+{
+    static if (A.length == 2)
+    {
+        static assert(__traits(isSame, A[0], A[1]));
+        enum members = __traits(allMembers, A[0]);
+        static assert(members == __traits(allMembers, A[1]));
+        static assert(members == Tup!("a", "b", "c"));
+    }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test21812.d b/gcc/testsuite/gdc.test/compilable/test21812.d
new file mode 100644 (file)
index 0000000..9cf33f5
--- /dev/null
@@ -0,0 +1,10 @@
+// https://issues.dlang.org/show_bug.cgi?id=21812
+
+struct S(A...)
+{
+   A args;
+}
+
+static assert(__traits(allMembers, S!(int, float)) == AliasSeq!("args"));
+
+alias AliasSeq(T...) = T;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag19196.d b/gcc/testsuite/gdc.test/fail_compilation/diag19196.d
new file mode 100644 (file)
index 0000000..857f9a4
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/diag19196.d(11): Error: unable to determine fields of `B` because of forward references
+fail_compilation/diag19196.d(15): Error: template instance `diag19196.Foo!(B)` error instantiating
+---
+*/
+module diag19196;
+struct Foo(T)
+{
+    alias F = typeof(T.tupleof);
+}
+struct B
+{
+    Foo!B b;
+}
index 6aa79a2..63951e6 100644 (file)
@@ -1,13 +1,13 @@
 /* REQUIRED_ARGS: -dip25
    TEST_OUTPUT:
 ---
-fail_compilation/test16228.d(22): Error: function type 'return int()' has 'return' but does not return any indirections
-fail_compilation/test16228.d(23): Error: function test16228.S.foo static member has no 'this' to which 'return' can apply
+fail_compilation/test16228.d(23): Error: function `test16228.S.bar` `static` member has no `this` to which `return` can apply
 ---
 */
 
 
 
+
 // https://issues.dlang.org/show_bug.cgi?id=16228
 
 int* wrap ( return ref int input )
@@ -20,5 +20,16 @@ struct S
     int x;
 
     int foo() return { return 3; }
-    static ref int foo() return { return x; }
+    static ref int bar() return { return x; }
+}
+
+
+// https://issues.dlang.org/show_bug.cgi?id=18963
+
+T Identity(T)(return T t) { return t; }
+
+void bar(int i, void* p)
+{
+    Identity(p);
+    Identity(i);
 }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test20919.d b/gcc/testsuite/gdc.test/fail_compilation/test20919.d
new file mode 100644 (file)
index 0000000..2f1bad1
--- /dev/null
@@ -0,0 +1,13 @@
+/* TEST_OUTPUT:
+---
+fail_compilation/test20919.d(12): Error: `__traits(getAttributes, int a)` does not give a valid type
+---
+*/
+// https://issues.dlang.org/show_bug.cgi?id=20919
+
+void foo(int a) {}
+
+static if (is(typeof(foo) params == __parameters))
+{
+    __traits(getAttributes, params) a;
+}