d: Merge upstream dmd cb4a96fae
authorIain Buclaw <ibuclaw@gdcproject.org>
Tue, 25 Aug 2020 09:44:48 +0000 (11:44 +0200)
committerIain Buclaw <ibuclaw@gdcproject.org>
Wed, 26 Aug 2020 08:03:55 +0000 (10:03 +0200)
Fixes both a bug where compilation would hang, and an issue where recursive
template limits are hit too early.

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

gcc/d/ChangeLog:

* dmd/MERGE: Merge upstream dmd cb4a96fae

gcc/d/dmd/MERGE
gcc/d/dmd/dmacro.c
gcc/d/dmd/dtemplate.c
gcc/d/dmd/expressionsem.c
gcc/d/dmd/globals.h
gcc/d/dmd/mtype.c
gcc/d/dmd/optimize.c
gcc/testsuite/gdc.test/compilable/ice20092.d [new file with mode: 0644]

index 8445bfaf343365f1e32da5db28d873d9e72f1927..2dc2ef3d6223a5e302ebf43e5784343856cf7424 100644 (file)
@@ -1,4 +1,4 @@
-2cc25c2191928f865e1b711f30b6a4268d6a0d9a
+cb4a96faecb6b521ac4749581bcfa39f61143db0
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
index 07187612616dfcdb51b1639d294eab63480232bb..cefd3b037aa77f2281a32e6b1914d78820a498b3 100644 (file)
@@ -226,11 +226,10 @@ void Macro::expand(OutBuffer *buf, size_t start, size_t *pend,
 {
     // limit recursive expansion
     static int nest;
-    static const int nestLimit = 1000;
-    if (nest > nestLimit)
+    if (nest > global.recursionLimit)
     {
-        error(Loc(), "DDoc macro expansion limit exceeded; more than %d "
-            "expansions.", nestLimit);
+        error(Loc(), "DDoc macro expansion limit exceeded; more than %d expansions.",
+              global.recursionLimit);
         return;
     }
     nest++;
index a35721cc9cd795d5417fee68bdb2435d31c19699..a86daeee6336f88b2b7532298b05592d8c266d27 100644 (file)
@@ -4337,6 +4337,13 @@ MATCH deduceType(RootObject *o, Scope *sc, Type *tparam, TemplateParameters *par
 
         void visit(ArrayLiteralExp *e)
         {
+            // https://issues.dlang.org/show_bug.cgi?id=20092
+            if (e->elements && e->elements->length &&
+                e->type->toBasetype()->nextOf()->ty == Tvoid)
+            {
+                result = deduceEmptyArrayElement();
+                return;
+            }
             if ((!e->elements || !e->elements->length) &&
                 e->type->toBasetype()->nextOf()->ty == Tvoid &&
                 tparam->ty == Tarray)
@@ -5932,10 +5939,10 @@ void TemplateInstance::tryExpandMembers(Scope *sc2)
     static int nest;
     // extracted to a function to allow windows SEH to work without destructors in the same function
     //printf("%d\n", nest);
-    if (++nest > 500)
+    if (++nest > global.recursionLimit)
     {
         global.gag = 0;                 // ensure error message gets printed
-        error("recursive expansion");
+        error("recursive expansion exceeded allowed nesting limit");
         fatal();
     }
 
@@ -5949,10 +5956,10 @@ void TemplateInstance::trySemantic3(Scope *sc2)
     // extracted to a function to allow windows SEH to work without destructors in the same function
     static int nest;
     //printf("%d\n", nest);
-    if (++nest > 300)
+    if (++nest > global.recursionLimit)
     {
         global.gag = 0;            // ensure error message gets printed
-        error("recursive expansion");
+        error("recursive expansion exceeded allowed nesting limit");
         fatal();
     }
     semantic3(sc2);
@@ -6353,7 +6360,7 @@ Lerror:
         while (ti && !ti->deferred && ti->tinst)
         {
             ti = ti->tinst;
-            if (++nest > 500)
+            if (++nest > global.recursionLimit)
             {
                 global.gag = 0;            // ensure error message gets printed
                 error("recursive expansion");
@@ -8440,7 +8447,7 @@ void TemplateMixin::semantic(Scope *sc)
 
     static int nest;
     //printf("%d\n", nest);
-    if (++nest > 500)
+    if (++nest > global.recursionLimit)
     {
         global.gag = 0;                 // ensure error message gets printed
         error("recursive expansion");
index 9f21dabb7e4db4c6fca2e0709a6be0ee6b9379ad..d2519969a2ce48b299a4cdbf2323430f41dad19e 100644 (file)
@@ -2896,7 +2896,7 @@ public:
             else
             {
                 static int nest;
-                if (++nest > 500)
+                if (++nest > global.recursionLimit)
                 {
                     exp->error("recursive evaluation of %s", exp->toChars());
                     --nest;
index 9e1a5b2d15a49b9915f3b5f000ad67ff8527c7e9..9d6e1ec37a90bff5d07c8e55d9f2cd110dc6a343 100644 (file)
@@ -244,6 +244,8 @@ struct Global
     Array<class Identifier*>* versionids; // command line versions and predefined versions
     Array<class Identifier*>* debugids;   // command line debug versions and predefined versions
 
+    enum { recursionLimit = 500 }; // number of recursive template expansions before abort
+
     /* Start gagging. Return the current number of gagged errors
      */
     unsigned startGagging();
index de39ecb02b282a512a21bd2735f5e859b81cd2e3..36471557dfcd6bbe586f25ab59cc492a63a4fa16 100644 (file)
@@ -2189,7 +2189,7 @@ Expression *Type::noMember(Scope *sc, Expression *e, Identifier *ident, int flag
 
     static int nest;      // https://issues.dlang.org/show_bug.cgi?id=17380
 
-    if (++nest > 500)
+    if (++nest > global.recursionLimit)
     {
       ::error(e->loc, "cannot resolve identifier `%s`", ident->toChars());
       --nest;
@@ -5536,7 +5536,7 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
 
     bool errors = false;
 
-    if (inuse > 500)
+    if (inuse > global.recursionLimit)
     {
         inuse = 0;
         ::error(loc, "recursive type");
index e907229be4c40bb41aeb55d17d6baf00b4e2bd26..45d94df577d08cc29057c2923474aaf39daa3576 100644 (file)
@@ -19,6 +19,7 @@
 #include "init.h"
 #include "enum.h"
 #include "ctfe.h"
+#include "errors.h"
 
 Expression *semantic(Expression *e, Scope *sc);
 
@@ -1214,10 +1215,18 @@ Expression *Expression_optimize(Expression *e, int result, bool keepLvalue)
     v.ret = e;
 
     // Optimize the expression until it can no longer be simplified.
-    while (ex != v.ret)
+    size_t b = 0;
+    while (1)
     {
+        if (b++ == global.recursionLimit)
+        {
+            e->error("infinite loop while optimizing expression");
+            fatal();
+        }
         ex = v.ret;
         ex->accept(&v);
+        if (ex == v.ret)
+            break;
     }
     return ex;
 }
diff --git a/gcc/testsuite/gdc.test/compilable/ice20092.d b/gcc/testsuite/gdc.test/compilable/ice20092.d
new file mode 100644 (file)
index 0000000..ff2be37
--- /dev/null
@@ -0,0 +1,10 @@
+void foo()
+{
+    (void[1]).init.front;
+}
+
+void front(T)(T[] a)
+{
+    static assert(is(T == void));
+}
+