diff mbox series

[committed] d: Merge upstream dmd 313d28b3d, druntime e361d200.

Message ID 20220428110842.371285-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] d: Merge upstream dmd 313d28b3d, druntime e361d200. | expand

Commit Message

Iain Buclaw April 28, 2022, 11:08 a.m. UTC
Hi,

This patches merges the D front-end with upstream dmd 313d28b3d, and the
D runtime library with upstream druntime e361d200.

D front-end changes:

    - Import latest bug fixes from the 2.100 release branch.
    - Fix signatures of extern C++ functions that have size_t
      parameters.

Bootstrapped and regression tested on x86_64-linux-gnu, and
i686-apple-darwin14.  Committed to mainline.

Regards,
Iain.

---
gcc/d/ChangeLog:

	* dmd/MERGE: Merge upstream dmd 313d28b3d.
	* d-port.cc (Port::memicmp): Use d_size_t instead of size_t.
	(Port::valcpy): Likewise.

libphobos/ChangeLog:

	* libdruntime/MERGE: Merge upstream druntime e361d200.
---
 gcc/d/d-port.cc                               |  8 +-
 gcc/d/dmd/MERGE                               |  2 +-
 gcc/d/dmd/cparse.d                            | 95 +++++++++++++++----
 gcc/d/dmd/dscope.d                            |  2 +
 gcc/d/dmd/expression.h                        |  6 +-
 gcc/d/dmd/expressionsem.d                     | 29 ++++--
 gcc/d/dmd/root/port.h                         |  5 +-
 .../gdc.test/compilable/revert_dip1000.d      |  7 ++
 libphobos/libdruntime/MERGE                   |  2 +-
 9 files changed, 121 insertions(+), 35 deletions(-)
 create mode 100644 gcc/testsuite/gdc.test/compilable/revert_dip1000.d
diff mbox series

Patch

diff --git a/gcc/d/d-port.cc b/gcc/d/d-port.cc
index a0e06b37683..a908cc8dbb0 100644
--- a/gcc/d/d-port.cc
+++ b/gcc/d/d-port.cc
@@ -31,11 +31,11 @@  along with GCC; see the file COPYING3.  If not see
 /* Compare the first N bytes of S1 and S2 without regard to the case.  */
 
 int
-Port::memicmp (const char *s1, const char *s2, size_t n)
+Port::memicmp (const char *s1, const char *s2, d_size_t n)
 {
   int result = 0;
 
-  for (size_t i = 0; i < n; i++)
+  for (d_size_t i = 0; i < n; i++)
     {
       char c1 = s1[i];
       char c2 = s2[i];
@@ -143,9 +143,9 @@  Port::readlongBE (const void *buffer)
 /* Write an SZ-byte sized VALUE to BUFFER, ignoring endian-ness.  */
 
 void
-Port::valcpy (void *buffer, uint64_t value, size_t sz)
+Port::valcpy (void *buffer, uint64_t value, d_size_t sz)
 {
-  gcc_assert (((size_t) buffer) % sz == 0);
+  gcc_assert (((d_size_t) buffer) % sz == 0);
 
   switch (sz)
     {
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 2bc9b95b5e2..d18119193d4 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@ 
-eb7bee331a13026eeb4dcbf9d43d5d4e744a4d26
+313d28b3db7523e67880ae3baf8ef28ce9abe9bd
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index 53bf26ec927..2b2046f3da3 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -213,16 +213,12 @@  final class CParser(AST) : Parser!AST
                     goto Lexp;
 
                 case TOK.leftParenthesis:
-                {
-                    /* If tokens look like a function call, assume it is one,
-                     * As any type-name won't be resolved until semantic, this
-                     * could be rewritten later.
-                     */
-                    auto tk = &token;
-                    if (isFunctionCall(tk))
-                        goto Lexp;
-                    goto default;
-                }
+                    if (auto pt = lookupTypedef(token.ident))
+                    {
+                        if (*pt)
+                            goto Ldeclaration;
+                    }
+                    goto Lexp;  // function call
 
                 default:
                 {
@@ -1626,10 +1622,21 @@  final class CParser(AST) : Parser!AST
          */
         if (token.value == TOK.semicolon)
         {
-            nextToken();
             if (!tspec)
+            {
+                nextToken();
                 return;         // accept empty declaration as an extension
+            }
+
+            if (auto ti = tspec.isTypeIdentifier())
+            {
+                // C11 6.7.2-2
+                error("type-specifier missing for declaration of `%s`", ti.ident.toChars());
+                nextToken();
+                return;
+            }
 
+            nextToken();
             auto tt = tspec.isTypeTag();
             if (!tt ||
                 !tt.id && (tt.tok == TOK.struct_ || tt.tok == TOK.union_))
@@ -1661,6 +1668,22 @@  final class CParser(AST) : Parser!AST
             specifier.mod &= ~MOD.xnone;          // 'used' it
         }
 
+        void scanPastSemicolon()
+        {
+            while (token.value != TOK.semicolon && token.value != TOK.endOfFile)
+                nextToken();
+            nextToken();
+        }
+
+        if (token.value == TOK.assign && tspec && tspec.isTypeIdentifier())
+        {
+            /* C11 6.7.2-2
+             * Special check for `const b = 1;` because some compilers allow it
+             */
+            error("type-specifier omitted for declaration of `%s`", tspec.isTypeIdentifier().ident.toChars());
+            return scanPastSemicolon();
+        }
+
         bool first = true;
         while (1)
         {
@@ -1880,10 +1903,7 @@  final class CParser(AST) : Parser!AST
                 default:
                     error("`=`, `;` or `,` expected to end declaration instead of `%s`", token.toChars());
                 Lend:
-                    while (token.value != TOK.semicolon && token.value != TOK.endOfFile)
-                        nextToken();
-                    nextToken();
-                    return;
+                    return scanPastSemicolon();
             }
         }
     }
@@ -2528,7 +2548,14 @@  final class CParser(AST) : Parser!AST
                 default:
                     if (declarator == DTR.xdirect)
                     {
-                        error("identifier or `(` expected"); // )
+                        if (!t || t.isTypeIdentifier())
+                        {
+                            // const arr[1];
+                            error("no type-specifier for declarator");
+                            t = AST.Type.tint32;
+                        }
+                        else
+                            error("identifier or `(` expected"); // )
                         panic();
                     }
                     ts = t;
@@ -2744,6 +2771,11 @@  final class CParser(AST) : Parser!AST
         Specifier specifier;
         specifier.packalign.setDefault();
         auto tspec = cparseSpecifierQualifierList(LVL.global, specifier);
+        if (!tspec)
+        {
+            error("type-specifier is missing");
+            tspec = AST.Type.tint32;
+        }
         if (tspec && specifier.mod & MOD.xconst)
         {
             tspec = toConst(tspec);
@@ -2829,8 +2861,18 @@  final class CParser(AST) : Parser!AST
             Specifier specifier;
             specifier.packalign.setDefault();
             auto tspec = cparseDeclarationSpecifiers(LVL.prototype, specifier);
-            if (tspec && specifier.mod & MOD.xconst)
+            if (!tspec)
             {
+                error("no type-specifier for parameter");
+                tspec = AST.Type.tint32;
+            }
+
+            if (specifier.mod & MOD.xconst)
+            {
+                if ((token.value == TOK.rightParenthesis || token.value == TOK.comma) &&
+                    tspec.isTypeIdentifier())
+                    error("type-specifier omitted for parameter `%s`", tspec.isTypeIdentifier().ident.toChars());
+
                 tspec = toConst(tspec);
                 specifier.mod = MOD.xnone;      // 'used' it
             }
@@ -3400,7 +3442,12 @@  final class CParser(AST) : Parser!AST
         Specifier specifier;
         specifier.packalign = this.packalign;
         auto tspec = cparseSpecifierQualifierList(LVL.member, specifier);
-        if (tspec && specifier.mod & MOD.xconst)
+        if (!tspec)
+        {
+            error("no type-specifier for struct member");
+            tspec = AST.Type.tint32;
+        }
+        if (specifier.mod & MOD.xconst)
         {
             tspec = toConst(tspec);
             specifier.mod = MOD.xnone;          // 'used' it
@@ -3413,7 +3460,13 @@  final class CParser(AST) : Parser!AST
             nextToken();
             auto tt = tspec.isTypeTag();
             if (!tt)
+            {
+                if (auto ti = tspec.isTypeIdentifier())
+                {
+                    error("type-specifier omitted before declaration of `%s`", ti.ident.toChars());
+                }
                 return; // legal but meaningless empty declaration
+            }
 
             /* If anonymous struct declaration
              *   struct { ... members ... };
@@ -3453,6 +3506,12 @@  final class CParser(AST) : Parser!AST
             AST.Type dt;
             if (token.value == TOK.colon)
             {
+                if (auto ti = tspec.isTypeIdentifier())
+                {
+                    error("type-specifier omitted before bit field declaration of `%s`", ti.ident.toChars());
+                    tspec = AST.Type.tint32;
+                }
+
                 // C11 6.7.2.1-12 unnamed bit-field
                 id = Identifier.generateAnonymousId("BitField");
                 dt = tspec;
diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d
index c3a1d05cd7b..6339a9e36ba 100644
--- a/gcc/d/dmd/dscope.d
+++ b/gcc/d/dmd/dscope.d
@@ -457,6 +457,8 @@  struct Scope
 
                 if (sc.scopesym.isModule())
                     flags |= SearchUnqualifiedModule;        // tell Module.search() that SearchLocalsOnly is to be obeyed
+                else if (sc.flags & SCOPE.Cfile && sc.scopesym.isStructDeclaration())
+                    continue;                                // C doesn't have struct scope
 
                 if (Dsymbol s = sc.scopesym.search(loc, ident, flags))
                 {
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index a0d63e0023d..330dcdb77ec 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -373,11 +373,11 @@  public:
     OwnedBy ownedByCtfe;
 
     static StringExp *create(const Loc &loc, const char *s);
-    static StringExp *create(const Loc &loc, const void *s, size_t len);
+    static StringExp *create(const Loc &loc, const void *s, d_size_t len);
     static void emplace(UnionExp *pue, const Loc &loc, const char *s);
     bool equals(const RootObject *o) const;
-    char32_t getCodeUnit(size_t i) const;
-    void setCodeUnit(size_t i, char32_t c);
+    char32_t getCodeUnit(d_size_t i) const;
+    void setCodeUnit(d_size_t i, char32_t c);
     StringExp *toStringExp();
     StringExp *toUTF8(Scope *sc);
     Optional<bool> toBool();
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index 22a1f45f4e8..d4e96bb0f09 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -5216,13 +5216,30 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
         if (s.ident)
         {
             VarDeclaration v = s.isVarDeclaration();
-            if (v && !(sc.flags & SCOPE.Cfile))
+            if (v)
             {
-                /* Do semantic() on initializer first so this will be illegal:
-                 *      int a = a;
-                 */
-                e.declaration.dsymbolSemantic(sc);
-                s.parent = sc.parent;
+                if (sc.flags & SCOPE.Cfile)
+                {
+                    /* Do semantic() on the type before inserting v into the symbol table
+                     */
+                    if (!v.originalType)
+                        v.originalType = v.type.syntaxCopy();
+                    Scope* sc2 = sc.push();
+                    sc2.stc |= v.storage_class & STC.FUNCATTR;
+                    sc2.linkage = LINK.c;       // account for the extern(C) in front of the declaration
+                    v.inuse++;
+                    v.type = v.type.typeSemantic(v.loc, sc2);
+                    v.inuse--;
+                    sc2.pop();
+                }
+                else
+                {
+                    /* Do semantic() on initializer first so this will be illegal:
+                     *      int a = a;
+                     */
+                    e.declaration.dsymbolSemantic(sc);
+                    s.parent = sc.parent;
+                }
             }
 
             if (!sc.insert(s))
diff --git a/gcc/d/dmd/root/port.h b/gcc/d/dmd/root/port.h
index 069a365addf..66a67605b5c 100644
--- a/gcc/d/dmd/root/port.h
+++ b/gcc/d/dmd/root/port.h
@@ -13,12 +13,13 @@ 
 // The idea is to minimize #ifdef's in the app code.
 
 #include "dsystem.h"
+#include "dcompat.h"
 
 typedef unsigned char utf8_t;
 
 struct Port
 {
-    static int memicmp(const char *s1, const char *s2, size_t n);
+    static int memicmp(const char *s1, const char *s2, d_size_t n);
     static char *strupr(char *s);
 
     static bool isFloat32LiteralOutOfRange(const char *s);
@@ -30,5 +31,5 @@  struct Port
     static unsigned readlongBE(const void *buffer);
     static unsigned readwordLE(const void *buffer);
     static unsigned readwordBE(const void *buffer);
-    static void valcpy(void *dst, uint64_t val, size_t size);
+    static void valcpy(void *dst, uint64_t val, d_size_t size);
 };
diff --git a/gcc/testsuite/gdc.test/compilable/revert_dip1000.d b/gcc/testsuite/gdc.test/compilable/revert_dip1000.d
new file mode 100644
index 00000000000..ad6a6d8aade
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/revert_dip1000.d
@@ -0,0 +1,7 @@ 
+/*
+REQUIRED_ARGS: -revert=dip1000
+TEST_OUTPUT:
+---
+---
+*/
+int* oops(scope int* p) @safe { return p; }
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index e08d9cdc0fd..c94634f4770 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@ 
-27834edb5e1613e3abd43e09880c36d9fc961938
+e361d200b287a68344095f306cf5ea3a63c080e1
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/druntime repository.