re PR fortran/17758 (gfortran_abort and some others should be marked as noreturn)
authorThomas Koenig <Thomas.Koenig@online.de>
Wed, 24 Aug 2005 20:04:20 +0000 (20:04 +0000)
committerThomas Koenig <tkoenig@gcc.gnu.org>
Wed, 24 Aug 2005 20:04:20 +0000 (20:04 +0000)
2005-08-24  Thomas Koenig  <Thomas.Koenig@online.de>

PR fortran/17758
* gfortran.h (symbol_attribute):  Add noreturn to the structure.
(gfc_intrinsic_sym):  Add noreturn to the structure.
* intrinsic.c (make_noreturn):  New function.
(add_subroutines):  Mark subroutines abort and exit as noreturn.
(gfc_intrinsic_sub_interface):  Copy noreturn attribute from
isym to the resolved symbol.
* trans-decl.c (gfc_get_extern_function_decl): Set function
as VOLATILE (== noreturn) if the noreturn attribute is set.

2005-08-24  Thomas Koenig  <Thomas.Koenig@online.de>

PR fortran/17758
gfortran.dg/nonreturning_statements.f90: New test.

From-SVN: r103449

gcc/fortran/ChangeLog
gcc/fortran/gfortran.h
gcc/fortran/intrinsic.c
gcc/fortran/trans-decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/nonreturning_statements.f90 [new file with mode: 0644]

index 7fcd0ed700d189da8ec2f582ff8c57724616bf3a..271bbc4bb46de521057883b9a5f9bedaf8dcadf7 100644 (file)
@@ -1,3 +1,15 @@
+2005-08-24  Thomas Koenig  <Thomas.Koenig@online.de>
+
+       PR fortran/17758
+       * gfortran.h (symbol_attribute):  Add noreturn to the structure.
+       (gfc_intrinsic_sym):  Add noreturn to the structure.
+       * intrinsic.c (make_noreturn):  New function.
+       (add_subroutines):  Mark subroutines abort and exit as noreturn.
+       (gfc_intrinsic_sub_interface):  Copy noreturn attribute from
+       isym to the resolved symbol.
+       * trans-decl.c (gfc_get_extern_function_decl): Set function
+       as VOLATILE (== noreturn) if the noreturn attribute is set.
+
 2005-08-21  Steven G. Kargl  <kargls@comcast.net>
 
        * decl.c: Typo in comment.
index c692ce24d37844fd536d462251ca77038c882c84..8c4303b1e15126457e5d913f5d3f7042ef2dd65b 100644 (file)
@@ -428,6 +428,10 @@ typedef struct
   unsigned sequence:1, elemental:1, pure:1, recursive:1;
   unsigned unmaskable:1, masked:1, contained:1;
 
+  /* This is set if the subroutine doesn't return.  Currently, this
+     is only possible for intrinsic subroutines.  */
+  unsigned noreturn:1;
+
   /* Set if this procedure is an alternate entry point.  These procedures
      don't have any code associated, and the backend will turn them into
      thunks to the master function.  */
@@ -1032,7 +1036,7 @@ typedef struct gfc_intrinsic_sym
   const char *name, *lib_name;
   gfc_intrinsic_arg *formal;
   gfc_typespec ts;
-  int elemental, pure, generic, specific, actual_ok, standard;
+  int elemental, pure, generic, specific, actual_ok, standard, noreturn;
 
   gfc_simplify_f simplify;
   gfc_check_f check;
index a304fbd667c870579df5180c0c65889ff91fc898..180e7ae36f6650c06d4371e1f1b18d945d94a548 100644 (file)
@@ -843,6 +843,14 @@ make_alias (const char *name, int standard)
     }
 }
 
+/* Make the current subroutine noreturn.  */
+
+static void
+make_noreturn(void)
+{
+  if (sizing == SZ_NOTHING)
+      next_sym[-1].noreturn = 1;
+}
 
 /* Add intrinsic functions.  */
 
@@ -2108,6 +2116,8 @@ add_subroutines (void)
 
   add_sym_0s ("abort", 1, GFC_STD_GNU, NULL);
 
+  make_noreturn();
+
   add_sym_1s ("cpu_time", 0, 1, BT_UNKNOWN, 0, GFC_STD_F95,
              gfc_check_cpu_time, NULL, gfc_resolve_cpu_time,
              tm, BT_REAL, dr, REQUIRED);
@@ -2199,6 +2209,8 @@ add_subroutines (void)
              gfc_check_exit, NULL, gfc_resolve_exit,
              c, BT_INTEGER, di, OPTIONAL);
 
+  make_noreturn();
+
   add_sym_1s ("flush", 0, 1, BT_UNKNOWN, 0, GFC_STD_GNU,
              gfc_check_flush, NULL, gfc_resolve_flush,
              c, BT_INTEGER, di, OPTIONAL);
@@ -3161,6 +3173,7 @@ gfc_intrinsic_sub_interface (gfc_code * c, int error_flag)
       return MATCH_ERROR;
     }
 
+  c->resolved_sym->attr.noreturn = isym->noreturn;
   check_intrinsic_standard (name, isym->standard, &c->loc);
 
   return MATCH_YES;
index 3488cde9096c8baeeb83fa0fb24a193dcb430be6..aaa4006da635ddb459fc17257fb6bac75a5e2a34 100644 (file)
@@ -1001,6 +1001,10 @@ gfc_get_extern_function_decl (gfc_symbol * sym)
       TREE_SIDE_EFFECTS (fndecl) = 0;
     }
 
+  /* Mark non-returning functions.  */
+  if (sym->attr.noreturn)
+      TREE_THIS_VOLATILE(fndecl) = 1;
+
   sym->backend_decl = fndecl;
 
   if (DECL_CONTEXT (fndecl) == NULL_TREE)
index e787eaa4c1c040dc39b9ee9954ad2f5a57ba4aaf..80b184e802642361d6a51b471661506418c8e63d 100644 (file)
@@ -1,3 +1,8 @@
+2005-08-24  Thomas Koenig  <Thomas.Koenig@online.de>
+
+       PR fortran/17758
+       gfortran.dg/nonreturning_statements.f90: New test.
+
 2005-08-24  Nathan Sidwell  <nathan@codesourcery.com>
 
        PR c++/22454
        PR c++/23337
        * g++.dg/ext/vector2.C: New.
 
+2005-08-16  Thomas Koenig  <Thomas.Koenig@online.de>
+
+       * gfortran.dg/inquire-complex.f90:  Correct mangled testcase.
+
 2005-08-16  Thomas Koenig  <Thomas.Koenig@online.de>
 
        PR libfortran/23428
diff --git a/gcc/testsuite/gfortran.dg/nonreturning_statements.f90 b/gcc/testsuite/gfortran.dg/nonreturning_statements.f90
new file mode 100644 (file)
index 0000000..6268f72
--- /dev/null
@@ -0,0 +1,25 @@
+! { dg-final { scan-assembler-not "should_be_noreturn" } }
+! PR 17758
+! This checks that non-returning subroutines and statements
+! really don't return by calling non-existing subroutines
+! afterwards.  These calls are supposed to be optimized away, so
+! they won't show up in the generated assembly.
+program main
+  character(len=5) :: c
+  c = '12345'
+  read(unit=c,fmt='(A)') i
+  select case(i)
+     case(1)
+        call abort
+        call abort_should_be_noreturn
+     case(2)
+        stop 65
+        call stop_numeric_should_be_noreturn
+     case(3)
+        stop "foobar"
+        call stop_string_should_be_noreturn
+     case(4)
+        call exit
+        call exit_should_be_noreturn
+     end select
+end program main