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

Reply via email to