This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH RFA: -Wc++-compat: different enums in ?:


When doing the big -Wc++-compat enum fixes a while back, I overlooked a
case.  In C++, the ?: operator does not permit the second and third
operands to have different enum types.  This patch adds a warning for
this case for -Wc++-compat.  This patch requires approval from the C
frontend maintainers.

This patch also fixes the single case in the gcc sources where this
problem arises.

Bootstrapped and tested on x86_64-unknown-linux-gnu.  OK for mainline?

Ian


gcc/ChangeLog:

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.

gcc/testsuite/ChangeLog:

2009-06-19  Ian Lance Taylor  <iant@google.com>

	* gcc.dg/Wcxx-compat-18.c: New testcase.


Index: c-tree.h
===================================================================
--- c-tree.h	(revision 148685)
+++ c-tree.h	(working copy)
@@ -552,7 +552,8 @@ extern struct c_expr parser_build_unary_
 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);
Index: c-typeck.c
===================================================================
--- c-typeck.c	(revision 148685)
+++ c-typeck.c	(working copy)
@@ -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
 	}
     }
 
+  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))
Index: c-parser.c
===================================================================
--- c-parser.c	(revision 148685)
+++ c-parser.c	(working copy)
@@ -4599,7 +4599,8 @@ c_parser_conditional_expression (c_parse
   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;
Index: tree-cfg.c
===================================================================
--- tree-cfg.c	(revision 148685)
+++ tree-cfg.c	(working copy)
@@ -4947,7 +4947,7 @@ gimple_redirect_edge_and_branch (edge e,
   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.  */
Index: testsuite/gcc.dg/Wcxx-compat-18.c
===================================================================
--- testsuite/gcc.dg/Wcxx-compat-18.c	(revision 0)
+++ testsuite/gcc.dg/Wcxx-compat-18.c	(revision 0)
@@ -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\[+\]\[+\]" } */
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]