Hi,
This patch fixes 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.
Regstrapped on x86_64-linux-gnu, committed to mainline.
Regards,
Iain.
---
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 | 10 +++++-----
gcc/d/expr.cc | 2 +-
gcc/d/runtime.cc | 5 +++++
gcc/d/runtime.def | 18 ++++++++++--------
gcc/d/toir.cc | 2 +-
gcc/testsuite/gdc.dg/pr123995.d | 16 ++++++++++++++++
6 files changed, 38 insertions(+), 15 deletions(-)
create mode 100644 gcc/testsuite/gdc.dg/pr123995.d
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);
+}
--
2.43.0