+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
#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"
/* 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;
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);
/* 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));
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;
}