aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/c-parser.c3
-rw-r--r--gcc/c-tree.h3
-rw-r--r--gcc/c-typeck.c17
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/Wcxx-compat-18.c15
-rw-r--r--gcc/tree-cfg.c2
7 files changed, 52 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 695547c..6b76ed3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+2009-06-19 Ian Lance Taylor <ian@airs.com>
+
+ * tree-cfg.c (gimple_redirect_edge_and_branch): Change ERROR_MARK
+ to GIMPLE_ERROR_MARK.
+
+ * c-typeck.c (build_conditional_expr): Add op1_original_type and
+ op2_original_type parameters. Warn about using different enum
+ types.
+ * c-parser.c (c_parser_conditional_expression): Pass original
+ types to build_conditional_expr.
+ * c-tree.h (build_conditional_expr): Update declaration.
+
2009-06-19 Ian Lance Taylor <iant@google.com>
* config/i386/i386.c (ix86_function_specific_save): Test that
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index 0fc1abb..29e399f 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -4597,7 +4597,8 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
ret.value = build_conditional_expr (colon_loc, cond.value,
cond.original_code == C_MAYBE_CONST_EXPR,
- exp1.value, exp2.value);
+ exp1.value, exp1.original_type,
+ exp2.value, exp2.original_type);
ret.original_code = ERROR_MARK;
if (exp1.value == error_mark_node || exp2.value == error_mark_node)
ret.original_type = NULL;
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index 9d3d2f3..c01cc66 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -556,7 +556,8 @@ extern struct c_expr parser_build_unary_op (location_t, enum tree_code,
extern struct c_expr parser_build_binary_op (location_t,
enum tree_code, struct c_expr,
struct c_expr);
-extern tree build_conditional_expr (location_t, tree, bool, tree, tree);
+extern tree build_conditional_expr (location_t, tree, bool, tree, tree,
+ tree, tree);
extern tree build_compound_expr (location_t, tree, tree);
extern tree c_cast_expr (location_t, struct c_type_name *, tree);
extern tree build_c_cast (location_t, tree, tree);
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 0a40a88..df1e171 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -3770,7 +3770,8 @@ c_mark_addressable (tree exp)
tree
build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
- tree op1, tree op2)
+ tree op1, tree op1_original_type, tree op2,
+ tree op2_original_type)
{
tree type1;
tree type2;
@@ -3843,6 +3844,20 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
}
}
+ if (warn_cxx_compat)
+ {
+ tree t1 = op1_original_type ? op1_original_type : TREE_TYPE (orig_op1);
+ tree t2 = op2_original_type ? op2_original_type : TREE_TYPE (orig_op2);
+
+ if (TREE_CODE (t1) == ENUMERAL_TYPE
+ && TREE_CODE (t2) == ENUMERAL_TYPE
+ && TYPE_MAIN_VARIANT (t1) != TYPE_MAIN_VARIANT (t2))
+ warning_at (colon_loc, OPT_Wc___compat,
+ ("different enum types in conditional is "
+ "invalid in C++: %qT vs %qT"),
+ t1, t2);
+ }
+
/* Quickly detect the usual case where op1 and op2 have the same type
after promotion. */
if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e1ea0a33..4a1a8d3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2009-06-19 Ian Lance Taylor <iant@google.com>
+
+ * gcc.dg/Wcxx-compat-18.c: New testcase.
+
2009-06-19 Richard Guenther <rguenther@suse.de>
* gcc.c-torture/execute/20090618-1.c: New testcase.
diff --git a/gcc/testsuite/gcc.dg/Wcxx-compat-18.c b/gcc/testsuite/gcc.dg/Wcxx-compat-18.c
new file mode 100644
index 0000000..9ae2d77
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wcxx-compat-18.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-Wc++-compat" } */
+enum E1 { A };
+enum E2 { B };
+int
+f1 (int i)
+{
+ return (int) (i ? A : B); /* { dg-warning "invalid in C\[+\]\[+\]" } */
+}
+extern enum E1 f2();
+int
+f3 (int i)
+{
+ return (int) (i ? f2 () : B); /* { dg-warning "invalid in C\[+\]\[+\]" } */
+}
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 8470d76..4c7c0db 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -4947,7 +4947,7 @@ gimple_redirect_edge_and_branch (edge e, basic_block dest)
gsi = gsi_last_bb (bb);
stmt = gsi_end_p (gsi) ? NULL : gsi_stmt (gsi);
- switch (stmt ? gimple_code (stmt) : ERROR_MARK)
+ switch (stmt ? gimple_code (stmt) : GIMPLE_ERROR_MARK)
{
case GIMPLE_COND:
/* For COND_EXPR, we only need to redirect the edge. */