From: Iain Buclaw Date: Sun, 8 Feb 2026 17:31:50 +0000 (+0100) Subject: d: Fix error when passing assert(0) as argument [PR123995] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=815732c2751060c38f0dc872a025632f247dda5c;p=thirdparty%2Fgcc.git d: Fix error when passing assert(0) as argument [PR123995] 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. --- diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc index 04fc63bda75..b22bdef77ce 100644 --- a/gcc/d/d-codegen.cc +++ b/gcc/d/d-codegen.cc @@ -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); diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc index 6a5059bba89..d05a12d5d09 100644 --- a/gcc/d/expr.cc +++ b/gcc/d/expr.cc @@ -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. */ diff --git a/gcc/d/runtime.cc b/gcc/d/runtime.cc index fa291d8fd13..4fb63f85b5b 100644 --- a/gcc/d/runtime.cc +++ b/gcc/d/runtime.cc @@ -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; diff --git a/gcc/d/runtime.def b/gcc/d/runtime.def index 9651c07dc8b..016f58756bf 100644 --- a/gcc/d/runtime.def +++ b/gcc/d/runtime.def @@ -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. */ diff --git a/gcc/d/toir.cc b/gcc/d/toir.cc index eb4e825ce1c..1ad41cf9368 100644 --- a/gcc/d/toir.cc +++ b/gcc/d/toir.cc @@ -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 index 00000000000..c3e3b8327e0 --- /dev/null +++ b/gcc/testsuite/gdc.dg/pr123995.d @@ -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); +}