]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
d: Fix error when passing assert(0) as argument [PR123995]
authorIain Buclaw <ibuclaw@gdcproject.org>
Sun, 8 Feb 2026 17:31:50 +0000 (18:31 +0100)
committerIain Buclaw <ibuclaw@gdcproject.org>
Sun, 8 Feb 2026 19:55:39 +0000 (20:55 +0100)
Library routines that either throw or halt execution already have the
call flag ECF_NORETURN.  Make their internal type `noreturn' as well, so
that they can be "passed" to functions accepting noreturn arguments.

PR d/123995

gcc/d/ChangeLog:

* d-codegen.cc (build_assert_call): Cast libcall result to `noreturn'.
(build_array_bounds_call):  Likewise.
(build_bounds_index_condition): Likewise.
(build_bounds_slice_condition): Likewise.
* expr.cc (ExprVisitor::visit (ThrowExp *)): Likewise.
* toir.cc (IRVisitor::visit (ThrowStatement *)): Likewise.
* runtime.cc (enum d_libcall_type): Add LCT_NORETURN.
(get_libcall_type): Handle LCT_NORETURN.
* runtime.def (ASSERTP): Change return type to `noreturn'.
(ASSERT_MSG): Likewise.
(UNITTESTP): Likewise.
(UNITTEST_MSG): Likewise.
(ARRAYBOUNDSP): Likewise.
(ARRAYBOUNDS_SLICEP): Likewise.
(ARRAYBOUNDS_INDEXP): Likewise.
(THROW): Likewise.

gcc/testsuite/ChangeLog:

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

gcc/d/d-codegen.cc
gcc/d/expr.cc
gcc/d/runtime.cc
gcc/d/runtime.def
gcc/d/toir.cc
gcc/testsuite/gdc.dg/pr123995.d [new file with mode: 0644]

index 04fc63bda75883446727f04f5ead192fce489ff8..b22bdef77ce4060373bb67c5b625fc3428a3466c 100644 (file)
@@ -1994,9 +1994,9 @@ build_assert_call (const Loc &loc, libcall_fn libcall, tree msg)
 
 
   if (msg != NULL_TREE)
-    return build_libcall (libcall, Type::tvoid, 3, msg, file, line);
+    return build_libcall (libcall, Type::tnoreturn, 3, msg, file, line);
   else
-    return build_libcall (libcall, Type::tvoid, 2, file, line);
+    return build_libcall (libcall, Type::tnoreturn, 2, file, line);
 }
 
 /* Builds a CALL_EXPR at location LOC in the source file to execute when an
@@ -2010,7 +2010,7 @@ build_array_bounds_call (const Loc &loc)
     return build_call_expr (builtin_decl_explicit (BUILT_IN_TRAP), 0);
   else
     {
-      return build_libcall (LIBCALL_ARRAYBOUNDSP, Type::tvoid, 2,
+      return build_libcall (LIBCALL_ARRAYBOUNDSP, Type::tnoreturn, 2,
                            build_filename_from_loc (loc),
                            size_int (loc.linnum ()));
     }
@@ -2039,7 +2039,7 @@ build_bounds_index_condition (IndexExp *ie, tree index, tree length)
     boundserr = build_call_expr (builtin_decl_explicit (BUILT_IN_TRAP), 0);
   else
     {
-      boundserr = build_libcall (LIBCALL_ARRAYBOUNDS_INDEXP, Type::tvoid, 4,
+      boundserr = build_libcall (LIBCALL_ARRAYBOUNDS_INDEXP, Type::tnoreturn, 4,
                                 build_filename_from_loc (ie->e2->loc),
                                 size_int (ie->e2->loc.linnum ()),
                                 index, length);
@@ -2089,7 +2089,7 @@ build_bounds_slice_condition (SliceExp *se, tree lower, tree upper, tree length)
          else
            {
              boundserr = build_libcall (LIBCALL_ARRAYBOUNDS_SLICEP,
-                                        Type::tvoid, 5,
+                                        Type::tnoreturn, 5,
                                         build_filename_from_loc (se->loc),
                                         size_int (se->loc.linnum ()),
                                         lower, upper, length);
index 6a5059bba899c420e4a053e794130ffbfab6a3d5..d05a12d5d090cfdb4b6bd3140006369347797dcd 100644 (file)
@@ -1005,7 +1005,7 @@ public:
   void visit (ThrowExp *e) final override
   {
     tree arg = build_expr_dtor (e->e1);
-    this->result_ = build_libcall (LIBCALL_THROW, Type::tvoid, 1, arg);
+    this->result_ = build_libcall (LIBCALL_THROW, Type::tnoreturn, 1, arg);
   }
 
   /* Build a postfix expression.  */
index fa291d8fd13c14c3eba48d3d7d1044e993054e63..4fb63f85b5bcc5a908f1bce2c832339cf3fed5b8 100644 (file)
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3.  If not see
 
 enum d_libcall_type
 {
+  LCT_NORETURN,                    /* typeof(*null)        */
   LCT_VOID,                /* void                 */
   LCT_BYTE,                /* byte                 */
   LCT_INT,                 /* int                  */
@@ -89,6 +90,10 @@ get_libcall_type (d_libcall_type type)
 
   switch (type)
     {
+    case LCT_NORETURN:
+      libcall_types[type] = Type::tnoreturn;
+      break;
+
     case LCT_VOID:
       libcall_types[type] = Type::tvoid;
       break;
index 9651c07dc8ba71fef01a57e6ff1737e0c0140822..016f58756bfd7a6e9b4f2813c945381e8042c165 100644 (file)
@@ -39,24 +39,26 @@ along with GCC; see the file COPYING3.  If not see
 #define RT(T1) LCT_ ## T1
 
 /* Used when an assert() contract fails.  */
-DEF_D_RUNTIME (ASSERTP, "_d_assertp", RT(VOID), P2(IMMUTABLE_CHARPTR, UINT),
+DEF_D_RUNTIME (ASSERTP, "_d_assertp", RT(NORETURN), P2(IMMUTABLE_CHARPTR, UINT),
               ECF_NORETURN)
-DEF_D_RUNTIME (ASSERT_MSG, "_d_assert_msg", RT(VOID), P3(STRING, STRING, UINT),
+DEF_D_RUNTIME (ASSERT_MSG, "_d_assert_msg", RT(NORETURN),
+              P3(STRING, STRING, UINT),
               ECF_NORETURN)
 
 /* Used when an assert() contract fails in a unittest function.  */
-DEF_D_RUNTIME (UNITTESTP, "_d_unittestp", RT(VOID), P2(IMMUTABLE_CHARPTR, UINT),
+DEF_D_RUNTIME (UNITTESTP, "_d_unittestp", RT(NORETURN),
+              P2(IMMUTABLE_CHARPTR, UINT),
               ECF_NORETURN)
-DEF_D_RUNTIME (UNITTEST_MSG, "_d_unittest_msg", RT(VOID),
+DEF_D_RUNTIME (UNITTEST_MSG, "_d_unittest_msg", RT(NORETURN),
               P3(STRING, STRING, UINT), ECF_NORETURN)
 
 /* Used when an array index outside the bounds of its range.  */
-DEF_D_RUNTIME (ARRAYBOUNDSP, "_d_arrayboundsp", RT(VOID),
+DEF_D_RUNTIME (ARRAYBOUNDSP, "_d_arrayboundsp", RT(NORETURN),
               P2(IMMUTABLE_CHARPTR, UINT), ECF_NORETURN)
-DEF_D_RUNTIME (ARRAYBOUNDS_SLICEP, "_d_arraybounds_slicep", RT(VOID),
+DEF_D_RUNTIME (ARRAYBOUNDS_SLICEP, "_d_arraybounds_slicep", RT(NORETURN),
               P5(IMMUTABLE_CHARPTR, UINT, SIZE_T, SIZE_T, SIZE_T),
               ECF_NORETURN)
-DEF_D_RUNTIME (ARRAYBOUNDS_INDEXP, "_d_arraybounds_indexp", RT(VOID),
+DEF_D_RUNTIME (ARRAYBOUNDS_INDEXP, "_d_arraybounds_indexp", RT(NORETURN),
               P4(IMMUTABLE_CHARPTR, UINT, SIZE_T, SIZE_T), ECF_NORETURN)
 
 /* Used when calling delete on a stack-allocated class or interface.  */
@@ -92,7 +94,7 @@ DEF_D_RUNTIME (ARRAYAPPENDWD, "_d_arrayappendwd", RT(ARRAY_VOID),
               P2(ARRAYPTR_BYTE, DCHAR), 0)
 
 /* Used for throw() expressions.  */
-DEF_D_RUNTIME (THROW, "_d_throw", RT(VOID), P1(OBJECT), ECF_NORETURN)
+DEF_D_RUNTIME (THROW, "_d_throw", RT(NORETURN), P1(OBJECT), ECF_NORETURN)
 DEF_D_RUNTIME (BEGIN_CATCH, "__gdc_begin_catch", RT(VOIDPTR), P1(VOIDPTR), 0)
 
 /* C++ exception handlers.  */
index eb4e825ce1c8fb483cc419b506ebe8525bf932e8..1ad41cf93689ab67ba495ce2b571cf5be383f9d5 100644 (file)
@@ -1241,7 +1241,7 @@ public:
     else
       arg = build_nop (build_ctype (get_object_type ()), arg);
 
-    add_stmt (build_libcall (LIBCALL_THROW, Type::tvoid, 1, arg));
+    add_stmt (build_libcall (LIBCALL_THROW, Type::tnoreturn, 1, arg));
   }
 
   /* Build a try-catch statement, one of the building blocks for exception
diff --git a/gcc/testsuite/gdc.dg/pr123995.d b/gcc/testsuite/gdc.dg/pr123995.d
new file mode 100644 (file)
index 0000000..c3e3b83
--- /dev/null
@@ -0,0 +1,16 @@
+// { dg-do compile }
+int fn123995(const typeof(*null) val)
+{
+    return 0;
+}
+
+int pr123995a()
+{
+    return fn123995(assert(0));
+}
+
+int pr123995b()
+{
+    static Exception ex;
+    return fn123995(throw ex);
+}