]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
d: Fix ICE in gimplify_expr with const ref noreturn parameters [PR123046]
authorIain Buclaw <ibuclaw@gdcproject.org>
Thu, 29 Jan 2026 13:06:14 +0000 (14:06 +0100)
committerIain Buclaw <ibuclaw@gdcproject.org>
Thu, 29 Jan 2026 14:27:18 +0000 (15:27 +0100)
The ICE was caused by references to const/immutable qualified `noreturn'
declarations that were being leaked to the code generation when they
should have been omitted or replaced with `assert(0)'.

PR d/123046

gcc/d/ChangeLog:

* d-codegen.cc (build_address): Return `null' when generating the
address of a `noreturn' declaration.
(d_build_call): Compare TYPE_MAIN_VARIANT of type with `noreturn'.
* decl.cc (get_fndecl_arguments): Likewise.
* types.cc (finish_aggregate_mode): Likewise.
(TypeVisitor::visit (TypeFunction *)): Likewise.

gcc/testsuite/ChangeLog:

* gdc.dg/pr123046.d: New test.

gcc/d/d-codegen.cc
gcc/d/decl.cc
gcc/d/types.cc
gcc/testsuite/gdc.dg/pr123046.d [new file with mode: 0644]

index 9ec23546b4add10be0c7e01853777c36b8ce64bb..3ff3d0628ab97d25339ac654e9758f7ec8b64942 100644 (file)
@@ -705,6 +705,11 @@ build_address (tree exp)
   if (TREE_CODE (exp) == CONST_DECL)
     exp = DECL_INITIAL (exp);
 
+  /* Type `noreturn' has no storage, return `null' for the expression.  */
+  if (DECL_P (exp) && TREE_CODE (exp) != FIELD_DECL
+      && TYPE_MAIN_VARIANT (TREE_TYPE (exp)) == noreturn_type_node)
+    return compound_expr (init, null_pointer_node);
+
   /* Some expression lowering may request an address of a compile-time constant,
      or other non-lvalue expression.  Make sure it is assigned to a location we
      can reference.  */
@@ -2361,7 +2366,7 @@ d_build_call (TypeFunction *tf, tree callable, tree object,
 
          /* Type `noreturn` is a terminator, as no other arguments can possibly
             be evaluated after it.  */
-         if (TREE_TYPE (targ) == noreturn_type_node)
+         if (TYPE_MAIN_VARIANT (TREE_TYPE (targ)) == noreturn_type_node)
            noreturn_call = true;
 
          vec_safe_push (args, targ);
@@ -2381,7 +2386,12 @@ d_build_call (TypeFunction *tf, tree callable, tree object,
       unsigned int ix;
 
       FOR_EACH_VEC_SAFE_ELT (args, ix, arg)
-       saved_args = compound_expr (saved_args, arg);
+       {
+         saved_args = compound_expr (saved_args, arg);
+
+         if (TYPE_MAIN_VARIANT (TREE_TYPE (arg)) == noreturn_type_node)
+           break;
+       }
 
       /* Add a stub result type for the expression.  */
       tree result = build_zero_cst (TREE_TYPE (ctype));
index b4e7fb21c222ccde719340e7c0d7639eecf68d62..b1f232616fcc3c239d4139f4001ff0de44fa4c23 100644 (file)
@@ -184,7 +184,7 @@ get_fndecl_arguments (FuncDeclaration *decl)
 
          /* Type `noreturn` is a terminator, as no other arguments can possibly
             be evaluated after it.  */
-         if (TREE_TYPE (parm_decl) == noreturn_type_node)
+         if (TYPE_MAIN_VARIANT (TREE_TYPE (parm_decl)) == noreturn_type_node)
            break;
 
          /* Chain them in the correct order.  */
index e6f1bcbb9047f500d2ba3c170a754740ba542dfc..b09c262fc86f1f5c4fd2bfd229cc2cdc51adae31 100644 (file)
@@ -963,7 +963,7 @@ public:
 
        /* Type `noreturn` is a terminator, as no other arguments can possibly
           be evaluated after it.  */
-       if (type == noreturn_type_node)
+       if (TYPE_MAIN_VARIANT (type) == noreturn_type_node)
          break;
 
        fnparams = chainon (fnparams, build_tree_list (0, type));
@@ -989,7 +989,7 @@ public:
     d_keep (t->ctype);
 
     /* Qualify function types that have the type `noreturn` as volatile.  */
-    if (fntype == noreturn_type_node)
+    if (TYPE_MAIN_VARIANT (fntype) == noreturn_type_node)
       t->ctype = build_qualified_type (t->ctype, TYPE_QUAL_VOLATILE);
 
     /* Handle any special support for calling conventions.  */
diff --git a/gcc/testsuite/gdc.dg/pr123046.d b/gcc/testsuite/gdc.dg/pr123046.d
new file mode 100644 (file)
index 0000000..1a3cb23
--- /dev/null
@@ -0,0 +1,10 @@
+// { dg-do compile }
+ulong pure_hashOf(const ref typeof(*null) key)
+{
+    return hashOf(key);
+}
+
+ulong hashOf(const typeof(*null) val)
+{
+    return 0;
+}