trans.c: Include tree-flow.h.
authorEric Botcazou <ebotcazou@adacore.com>
Sun, 27 Jun 2010 08:47:23 +0000 (08:47 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Sun, 27 Jun 2010 08:47:23 +0000 (08:47 +0000)
* gcc-interface/trans.c: Include tree-flow.h.
(gnu_switch_label_stack): Delete.
(Case_Statement_to_gnu): Do not emit the goto at the end of a case if
its associated block cannot fall through.  Do not emit the final label
if no cases branche to it.
* gcc-interface/Make-lang.in (ada/trans.o): Add $(TREE_FLOW_H).

From-SVN: r161461

gcc/ada/ChangeLog
gcc/ada/gcc-interface/Make-lang.in
gcc/ada/gcc-interface/trans.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/noreturn3.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/noreturn3.ads [new file with mode: 0644]

index 56f0a06..021a07a 100644 (file)
@@ -1,3 +1,12 @@
+2010-06-27  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc-interface/trans.c: Include tree-flow.h.
+       (gnu_switch_label_stack): Delete.
+       (Case_Statement_to_gnu): Do not emit the goto at the end of a case if
+       its associated block cannot fall through.  Do not emit the final label
+       if no cases branche to it.
+       * gcc-interface/Make-lang.in (ada/trans.o): Add $(TREE_FLOW_H).
+
 2010-06-23  Thomas Quinot  <quinot@adacore.com>
 
        * exp_attr.adb (Expand_Access_To_Protected_Op): When rewriting a
index 9bf7a47..d4f37fe 100644 (file)
@@ -1260,7 +1260,7 @@ ada/targtyps.o : ada/gcc-interface/targtyps.c $(CONFIG_H) $(SYSTEM_H) \
        $(COMPILER) -c $(ALL_COMPILERFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
 
 ada/trans.o : ada/gcc-interface/trans.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
-   $(TM_H) $(TREE_H) $(FLAGS_H) output.h tree-iterator.h \
+   $(TM_H) $(TREE_H) $(FLAGS_H) output.h tree-iterator.h $(TREE_FLOW_H) \
    $(GIMPLE_H) ada/gcc-interface/ada.h ada/adadecode.h ada/types.h \
    ada/atree.h ada/elists.h ada/namet.h ada/nlists.h ada/snames.h \
    ada/stringt.h ada/uintp.h ada/urealp.h ada/fe.h ada/sinfo.h ada/einfo.h \
index aec94b0..b79b4f0 100644 (file)
@@ -33,6 +33,7 @@
 #include "output.h"
 #include "libfuncs.h"  /* For set_stack_check_libfunc.  */
 #include "tree-iterator.h"
+#include "tree-flow.h"
 #include "gimple.h"
 
 #include "ada.h"
@@ -168,9 +169,6 @@ static GTY(()) VEC(tree,gc) *gnu_return_label_stack;
 /* Stack of LOOP_STMT nodes.  */
 static GTY(()) VEC(tree,gc) *gnu_loop_label_stack;
 
-/* Stack of labels for switch statements.  */
-static GTY(()) VEC(tree,gc) *gnu_switch_label_stack;
-
 /* The stacks for N_{Push,Pop}_*_Label.  */
 static GTY(()) VEC(tree,gc) *gnu_constraint_error_label_stack;
 static GTY(()) VEC(tree,gc) *gnu_storage_error_label_stack;
@@ -1908,9 +1906,9 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
 static tree
 Case_Statement_to_gnu (Node_Id gnat_node)
 {
-  tree gnu_result;
-  tree gnu_expr;
+  tree gnu_result, gnu_expr, gnu_label;
   Node_Id gnat_when;
+  bool may_fallthru = false;
 
   gnu_expr = gnat_to_gnu (Expression (gnat_node));
   gnu_expr = convert (get_base_type (TREE_TYPE (gnu_expr)), gnu_expr);
@@ -1933,8 +1931,7 @@ Case_Statement_to_gnu (Node_Id gnat_node)
 
   /* We build a SWITCH_EXPR that contains the code with interspersed
      CASE_LABEL_EXPRs for each label.  */
-  VEC_safe_push (tree, gc, gnu_switch_label_stack,
-                create_artificial_label (input_location));
+  gnu_label = create_artificial_label (input_location);
   start_stmt_group ();
 
   for (gnat_when = First_Non_Pragma (Alternatives (gnat_node));
@@ -2014,18 +2011,22 @@ Case_Statement_to_gnu (Node_Id gnat_node)
         containing the Case statement.  */
       if (choices_added_p)
        {
-         add_stmt (build_stmt_group (Statements (gnat_when), true));
-         add_stmt (build1 (GOTO_EXPR, void_type_node,
-                           VEC_last (tree, gnu_switch_label_stack)));
+         tree group = build_stmt_group (Statements (gnat_when), true);
+         bool group_may_fallthru = block_may_fallthru (group);
+         add_stmt (group);
+         if (group_may_fallthru)
+           {
+             add_stmt (build1 (GOTO_EXPR, void_type_node, gnu_label));
+             may_fallthru = true;
+           }
        }
     }
 
-  /* Now emit a definition of the label all the cases branched to.  */
-  add_stmt (build1 (LABEL_EXPR, void_type_node,
-                   VEC_last (tree, gnu_switch_label_stack)));
+  /* Now emit a definition of the label the cases branche to, if any.  */
+  if (may_fallthru)
+    add_stmt (build1 (LABEL_EXPR, void_type_node, gnu_label));
   gnu_result = build3 (SWITCH_EXPR, TREE_TYPE (gnu_expr), gnu_expr,
                       end_stmt_group (), NULL_TREE);
-  VEC_pop (tree, gnu_switch_label_stack);
 
   return gnu_result;
 }
index ea6169e..04fad30 100644 (file)
@@ -1,3 +1,7 @@
+2010-06-27  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/noreturn3.ad[sb]: New test.
+
 2010-06-26  Jason Merrill  <jason@redhat.com>
 
        * g++.dg/cpp0x/explicit5.C: New.
diff --git a/gcc/testsuite/gnat.dg/noreturn3.adb b/gcc/testsuite/gnat.dg/noreturn3.adb
new file mode 100644 (file)
index 0000000..4457373
--- /dev/null
@@ -0,0 +1,27 @@
+-- { dg-do compile }
+
+with Ada.Exceptions;
+
+package body Noreturn3 is
+
+  procedure Raise_Error (E : Enum; ErrorMessage : String) is
+
+    function Msg return String is
+    begin
+      return "Error :" & ErrorMessage;
+    end;
+
+  begin
+    case E is
+       when One =>
+         Ada.Exceptions.Raise_Exception (Exc1'Identity, Msg);
+
+       when Two =>
+         Ada.Exceptions.Raise_Exception (Exc2'Identity, Msg);
+
+       when others =>
+         Ada.Exceptions.Raise_Exception (Exc3'Identity, Msg);
+    end case;
+  end;
+
+end Noreturn3;
diff --git a/gcc/testsuite/gnat.dg/noreturn3.ads b/gcc/testsuite/gnat.dg/noreturn3.ads
new file mode 100644 (file)
index 0000000..d830a14
--- /dev/null
@@ -0,0 +1,12 @@
+package Noreturn3 is
+
+  Exc1 : Exception;
+  Exc2 : Exception;
+  Exc3 : Exception;
+
+  type Enum is (One, Two, Three);
+
+  procedure Raise_Error (E : Enum; ErrorMessage : String);
+  pragma No_Return (Raise_Error);
+
+end Noreturn3;