This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH RFA: C frontend: Generate SWITCH_EXPR rather than SWITCH_STMT
- From: Ian Lance Taylor <ian at airs dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: 03 Apr 2005 10:59:08 -0400
- Subject: PATCH RFA: C frontend: Generate SWITCH_EXPR rather than SWITCH_STMT
This patch changes the C frontend to generate SWITCH_EXPR rather than
SWITCH_STMT. SWITCH_EXPR is GENERIC, unlike SWITCH_STMT which is
specific to the C/C++ frontends. Generating SWITCH_EXPR directly
saves a call to gimplify_switch_stmt for each switch statement.
The real point of this patch is that, once it is accepted, it should
be straightforward to move the various loop constructs out of the
C/C++ common code into the C++ frontend. The C frontend no longer
generates FOR_STMT, WHILE_STMT, etc. Having it no longer generate
SWITCH_STMT makes it a little easier to move these all into the C++
frontend, as SWITCH_STMT is the last tree generated by the C frontend
which (when used by the C++ frontend) requires handling of BREAK_STMT
and CONTINUE_STMT.
It would also be possible to change the C++ frontend to no longer
generate these looping constructs, but to emit GENERIC directly.
However, my present understanding is that the C++ frontend maintainers
would prefer to continue to generate them. This is evidently not the
case for the C frontend, which stopped generating them via a patch by
RTH last June.
Tested using a bootstrap and testsuite run on i686-pc-linux-gnu. OK
for mainline?
Ian
2005-04-03 Ian Lance Taylor <ian@airs.com>
* c-typeck.c (struct c_switch): Rename switch_stmt field to
switch_expr.
(c_start_case): Build SWITCH_EXPR, not SWITCH_STMT.
(do_case): Use SWITCH_COND rather than SWITCH_STMT_COND.
(c_finish_case): Use SWITCH_BODY rather than SWITCH_STMT_BODY.
Call c_do_switch_expr_warnings rather than c_do_switch_warnings.
* c-common.c (c_do_switch_warnings_1): New static function broken
out of c_do_switch_warnings.
(c_do_switch_warnings): Call c_do_switch_warnings_1.
(c_do_switch_expr_warnings): New function.
* c-common.h (c_do_switch_expr_warnings): Declare.
Index: c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.618
diff -p -u -r1.618 c-common.c
--- c-common.c 30 Mar 2005 01:35:01 -0000 1.618
+++ c-common.c 3 Apr 2005 14:42:19 -0000
@@ -3708,32 +3708,17 @@ match_case_to_enum (splay_tree_node node
return 0;
}
-/* Handle -Wswitch*. Called from the front end after parsing the switch
- construct. */
-/* ??? Should probably be somewhere generic, since other languages besides
- C and C++ would want this. We'd want to agree on the data structure,
- however, which is a problem. Alternately, we operate on gimplified
- switch_exprs, which I don't especially like. At the moment, however,
- C/C++ are the only tree-ssa languages that support enumerations at all,
- so the point is moot. */
+/* Common code for -Wswitch*. */
-void
-c_do_switch_warnings (splay_tree cases, tree switch_stmt)
+static void
+c_do_switch_warnings_1 (splay_tree cases, location_t switch_location,
+ tree type, tree cond)
{
splay_tree_node default_node;
- location_t switch_location;
- tree type;
if (!warn_switch && !warn_switch_enum && !warn_switch_default)
return;
- if (EXPR_HAS_LOCATION (switch_stmt))
- switch_location = EXPR_LOCATION (switch_stmt);
- else
- switch_location = input_location;
-
- type = SWITCH_STMT_TYPE (switch_stmt);
-
default_node = splay_tree_lookup (cases, (splay_tree_key) NULL);
if (warn_switch_default && !default_node)
warning ("%Hswitch missing default case", &switch_location);
@@ -3744,7 +3729,7 @@ c_do_switch_warnings (splay_tree cases,
default case, or when -Wswitch-enum was specified. */
if (((warn_switch && !default_node) || warn_switch_enum)
&& type && TREE_CODE (type) == ENUMERAL_TYPE
- && TREE_CODE (SWITCH_STMT_COND (switch_stmt)) != INTEGER_CST)
+ && TREE_CODE (cond) != INTEGER_CST)
{
tree chain;
@@ -3788,6 +3773,45 @@ c_do_switch_warnings (splay_tree cases,
}
}
+/* Handle -Wswitch* for a SWITCH_STMT. Called from the front end
+ after parsing the switch construct. */
+/* ??? Should probably be somewhere generic, since other languages besides
+ C and C++ would want this. We'd want to agree on the data structure,
+ however, which is a problem. Alternately, we operate on gimplified
+ switch_exprs, which I don't especially like. At the moment, however,
+ C/C++ are the only tree-ssa languages that support enumerations at all,
+ so the point is moot. */
+
+void
+c_do_switch_warnings (splay_tree cases, tree switch_stmt)
+{
+ location_t switch_location;
+
+ if (EXPR_HAS_LOCATION (switch_stmt))
+ switch_location = EXPR_LOCATION (switch_stmt);
+ else
+ switch_location = input_location;
+ c_do_switch_warnings_1 (cases, switch_location,
+ SWITCH_STMT_TYPE (switch_stmt),
+ SWITCH_STMT_COND (switch_stmt));
+}
+
+/* Like c_do_switch_warnings, but takes a SWITCH_EXPR rather than a
+ SWITCH_STMT. */
+
+void
+c_do_switch_expr_warnings (splay_tree cases, tree switch_expr)
+{
+ location_t switch_location;
+
+ if (EXPR_HAS_LOCATION (switch_expr))
+ switch_location = EXPR_LOCATION (switch_expr);
+ else
+ switch_location = input_location;
+ c_do_switch_warnings_1 (cases, switch_location, TREE_TYPE (switch_expr),
+ SWITCH_COND (switch_expr));
+}
+
/* Finish an expression taking the address of LABEL (an
IDENTIFIER_NODE). Returns an expression for the address. */
Index: c-common.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.h,v
retrieving revision 1.280
diff -p -u -r1.280 c-common.h
--- c-common.h 30 Mar 2005 01:35:02 -0000 1.280
+++ c-common.h 3 Apr 2005 14:42:19 -0000
@@ -825,6 +825,7 @@ extern int case_compare (splay_tree_key,
extern tree c_add_case_label (splay_tree, tree, tree, tree, tree);
extern void c_do_switch_warnings (splay_tree, tree);
+extern void c_do_switch_expr_warnings (splay_tree, tree);
extern tree build_function_call (tree, tree);
Index: c-typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.429
diff -p -u -r1.429 c-typeck.c
--- c-typeck.c 30 Mar 2005 19:56:30 -0000 1.429
+++ c-typeck.c 3 Apr 2005 14:42:20 -0000
@@ -6609,8 +6609,8 @@ c_finish_return (tree retval)
}
struct c_switch {
- /* The SWITCH_STMT being built. */
- tree switch_stmt;
+ /* The SWITCH_EXPR being built. */
+ tree switch_expr;
/* The original type of the testing expression, i.e. before the
default conversion is applied. */
@@ -6641,7 +6641,7 @@ struct c_switch {
struct c_switch *c_switch_stack;
/* Start a C switch statement, testing expression EXP. Return the new
- SWITCH_STMT. */
+ SWITCH_EXPR. */
tree
c_start_case (tree exp)
@@ -6677,16 +6677,16 @@ c_start_case (tree exp)
}
}
- /* Add this new SWITCH_STMT to the stack. */
+ /* Add this new SWITCH_EXPR to the stack. */
cs = XNEW (struct c_switch);
- cs->switch_stmt = build_stmt (SWITCH_STMT, exp, NULL_TREE, orig_type);
+ cs->switch_expr = build3 (SWITCH_EXPR, orig_type, exp, NULL_TREE, NULL_TREE);
cs->orig_type = orig_type;
cs->cases = splay_tree_new (case_compare, NULL, NULL);
cs->blocked_stmt_expr = 0;
cs->next = c_switch_stack;
c_switch_stack = cs;
- return add_stmt (cs->switch_stmt);
+ return add_stmt (cs->switch_expr);
}
/* Process a case label. */
@@ -6699,7 +6699,7 @@ do_case (tree low_value, tree high_value
if (c_switch_stack && !c_switch_stack->blocked_stmt_expr)
{
label = c_add_case_label (c_switch_stack->cases,
- SWITCH_STMT_COND (c_switch_stack->switch_stmt),
+ SWITCH_COND (c_switch_stack->switch_expr),
c_switch_stack->orig_type,
low_value, high_value);
if (label == error_mark_node)
@@ -6729,12 +6729,12 @@ c_finish_case (tree body)
{
struct c_switch *cs = c_switch_stack;
- SWITCH_STMT_BODY (cs->switch_stmt) = body;
+ SWITCH_BODY (cs->switch_expr) = body;
gcc_assert (!cs->blocked_stmt_expr);
/* Emit warnings as needed. */
- c_do_switch_warnings (cs->cases, cs->switch_stmt);
+ c_do_switch_expr_warnings (cs->cases, cs->switch_expr);
/* Pop the stack. */
c_switch_stack = cs->next;