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: Implement -Wenum-compare for C


This patch enables -Wenum-compare for C.  It permits the C compiler to
warn about comparisons between two different enum types.

Such comparisons are almost invariably a mistake.  Therefore, with this
patch the warning is enabled by default when using -Wall.

Previously, this warning was only supported for C++, and was enabled by
default.  I have reatined that behaviour for C++.  Because it is enabled
by default for C++, this patch makes -Wc++-compat enable the warning for
C.

I posted an earlier version of this patch here, back when we went into
stage 3:

http://gcc.gnu.org/ml/gcc-patches/2008-09/msg00303.html

(There are two separate patches in that post).  This version of the
patch has been tested in my own tree for a while.  I just updated it to
the current sources and bootstrapped and tested it on i686-pc-linux-gnu.

Joseph approved the patch earlier:

http://gcc.gnu.org/ml/gcc-patches/2008-09/msg00309.html

but that was quite a while ago now.

Is that patch OK to commit to mainline?

Ian


gcc/ChangeLog:

2009-03-31  Ian Lance Taylor  <iant@google.com>

	* c.opt (Wenum-compare): Enable for C and Objc.  Initialize to -1.
	* c-opts.c (c_common_handle_option): For C, set warn_enum_compare
	for -Wall and for -Wc++-compat.
	(c_common_post_options): For C++, set warn_enum_compare if not
	already set.
	* c-tree.h (struct c_expr): Add field original_type.
	(build_external_ref): Update declaration.
	* c-parser.c (c_parser_braced_init): Set original_type.
	(c_parser_initelt): Likewise.
	(c_parser_expr_no_commas): Likewise.
	(c_parser_conditional_expression): Likewise.
	(c_parser_cast_expression): Likewise.
	(c_parser_unary_expression): Likewise.  Pull setting of
	original_code to top of function.
	(c_parser_sizeof_expression): Set original_type.
	(c_parser_alignof_expression): Likewise.
	(c_parser_postfix_expression): Likewise.  Pull setting of
	original_code to top of function.
	(c_parser_postfix_expression_after_paren_type): Set
	original_type.
	(c_parser_postfix_expression_after_primary): Likewise.
	(c_parser_expression): Likewise.
	* c-typeck.c (build_external_ref): Add type parameter.  Change all
	callers.
	(c_expr_sizeof_expr): Set original_type field.
	(parser_build_unary_op): Likewise.
	(parser_build_binary_op): Likewise.  Optionally warn about
	comparisons of enums of different types.
	(digest_init): Set original_type field.
	(really_start_incremental_init): Likewise.
	(push_init_level, pop_init_level): Likewise.
	* doc/invoke.texi (Warning Options): -Wenum-compare now
	supported in C.

gcc/testsuite/ChangeLog:

2009-03-31  Ian Lance Taylor  <iant@google.com>

	* gcc.dg/Wenum-compare-1.c: New testcase.


Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi	(revision 145363)
+++ doc/invoke.texi	(working copy)
@@ -2731,6 +2731,7 @@
 -Warray-bounds @r{(only with} @option{-O2}@r{)}  @gol
 -Wc++0x-compat  @gol
 -Wchar-subscripts  @gol
+-Wenum-compare @r{(in C/Objc; this is on by default in C++)} @gol
 -Wimplicit-int  @gol
 -Wimplicit-function-declaration  @gol
 -Wcomment  @gol
@@ -3716,11 +3717,12 @@
 Warn if an empty body occurs in an @samp{if}, @samp{else} or @samp{do
 while} statement.  This warning is also enabled by @option{-Wextra}.
 
-@item -Wenum-compare @r{(C++ and Objective-C++ only)}
+@item -Wenum-compare
 @opindex Wenum-compare
 @opindex Wno-enum-compare
-Warn about a comparison between values of different enum types. This
-warning is enabled by default.
+Warn about a comparison between values of different enum types. In C++
+this warning is enabled by default.  In C this warning is enabled by
+@option{-Wall}.
 
 @item -Wsign-compare
 @opindex Wsign-compare
Index: testsuite/gcc.dg/Wenum-compare-1.c
===================================================================
--- testsuite/gcc.dg/Wenum-compare-1.c	(revision 0)
+++ testsuite/gcc.dg/Wenum-compare-1.c	(revision 0)
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-Wenum-compare" } */
+enum E1 { A, B, C };
+enum E2 { D, E, F };
+extern void f2 ();
+void
+f1 ()
+{
+  int a = A;
+  int d = D;
+  enum E1 e1 = A;
+  enum E2 e2 = D;
+  if (A > D)	/* { dg-warning "comparison between .enum E1. and .enum E2." } */
+    f2 ();
+  if (e1 > e2)  /* { dg-warning "comparison between .enum E1. and .enum E2." } */
+    f2 ();
+  if (e1 > e2 + 1)
+    f2 ();
+  if (A > 0)
+    f2 ();
+  if (e1 > 0)
+    f2 ();
+  if (A + D > 0)
+    f2 ();
+  if (e1 > 0)
+    f2 ();
+  if (A + D > 0)
+    f2 ();
+  if ((int) A > D)
+    f2 ();
+  if ((int) e1 > e2)
+    f2 ();
+}
Index: c-tree.h
===================================================================
--- c-tree.h	(revision 145363)
+++ c-tree.h	(working copy)
@@ -163,6 +163,11 @@
      initializers, or ERROR_MARK for other expressions (including
      parenthesized expressions).  */
   enum tree_code original_code;
+  /* If not NULL, the original type of an expression.  This will
+     differ from the type of the value field for an enum constant.
+     The type of an enum constant is a plain integer type, but this
+     field will be the enum type.  */
+  tree original_type;
 };
 
 /* A kind of type specifier.  Note that this information is currently
@@ -577,7 +582,7 @@
 extern tree composite_type (tree, tree);
 extern tree build_component_ref (tree, tree);
 extern tree build_array_ref (tree, tree, location_t);
-extern tree build_external_ref (tree, int, location_t);
+extern tree build_external_ref (tree, int, location_t, tree *);
 extern void pop_maybe_used (bool);
 extern struct c_expr c_expr_sizeof_expr (struct c_expr);
 extern struct c_expr c_expr_sizeof_type (struct c_type_name *);
Index: c.opt
===================================================================
--- c.opt	(revision 145363)
+++ c.opt	(working copy)
@@ -204,7 +204,7 @@
 Warn about stray tokens after #elif and #endif
 
 Wenum-compare
-C++ ObjC++ Var(warn_enum_compare) Init(1) Warning
+C ObjC C++ ObjC++ Var(warn_enum_compare) Init(-1) Warning
 Warn about comparison of different enum types
 
 Werror
Index: c-typeck.c
===================================================================
--- c-typeck.c	(revision 145363)
+++ c-typeck.c	(working copy)
@@ -2188,9 +2188,12 @@
 
 /* Build an external reference to identifier ID.  FUN indicates
    whether this will be used for a function call.  LOC is the source
-   location of the identifier.  */
+   location of the identifier.  This sets *TYPE to the type of the
+   identifier, which is not the same as the type of the returned value
+   for CONST_DECLs defined as enum constants.  If the type of the
+   identifier is not available, *TYPE is set to NULL.  */
 tree
-build_external_ref (tree id, int fun, location_t loc)
+build_external_ref (tree id, int fun, location_t loc, tree *type)
 {
   tree ref;
   tree decl = lookup_name (id);
@@ -2199,8 +2202,12 @@
      whatever lookup_name() found.  */
   decl = objc_lookup_ivar (decl, id);
 
+  *type = NULL;
   if (decl && decl != error_mark_node)
-    ref = decl;
+    {
+      ref = decl;
+      *type = TREE_TYPE (ref);
+    }
   else if (fun)
     /* Implicit function declaration.  */
     ref = implicitly_declare (id);
@@ -2332,6 +2339,7 @@
     {
       ret.value = error_mark_node;
       ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
       pop_maybe_used (false);
     }
   else
@@ -2341,6 +2349,7 @@
 				       &expr_const_operands);
       ret.value = c_sizeof (TREE_TYPE (folded_expr));
       ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
       if (c_vla_type_p (TREE_TYPE (folded_expr)))
 	{
 	  /* sizeof is evaluated when given a vla (C99 6.5.3.4p2).  */
@@ -2366,6 +2375,7 @@
   type = groktypename (t, &type_expr, &type_expr_const);
   ret.value = c_sizeof (type);
   ret.original_code = ERROR_MARK;
+  ret.original_type = NULL;
   if (type_expr && c_vla_type_p (type))
     {
       ret.value = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (ret.value),
@@ -2842,7 +2852,8 @@
 
   result.value = build_unary_op (loc, code, arg.value, 0);
   result.original_code = code;
-  
+  result.original_type = NULL;
+
   if (TREE_OVERFLOW_P (result.value) && !TREE_OVERFLOW_P (arg.value))
     overflow_warning (result.value);
 
@@ -2865,10 +2876,17 @@
 
   enum tree_code code1 = arg1.original_code;
   enum tree_code code2 = arg2.original_code;
+  tree type1 = (arg1.original_type
+                ? arg1.original_type
+                : TREE_TYPE (arg1.value));
+  tree type2 = (arg2.original_type
+                ? arg2.original_type
+                : TREE_TYPE (arg2.value));
 
   result.value = build_binary_op (location, code,
 				  arg1.value, arg2.value, 1);
   result.original_code = code;
+  result.original_type = NULL;
 
   if (TREE_CODE (result.value) == ERROR_MARK)
     return result;
@@ -2901,6 +2919,16 @@
       && !TREE_OVERFLOW_P (arg2.value))
     overflow_warning (result.value);
 
+  /* Warn about comparisons of different enum types.  */
+  if (warn_enum_compare
+      && TREE_CODE_CLASS (code) == tcc_comparison
+      && TREE_CODE (type1) == ENUMERAL_TYPE
+      && TREE_CODE (type2) == ENUMERAL_TYPE
+      && TYPE_MAIN_VARIANT (type1) != TYPE_MAIN_VARIANT (type2))
+    warning (OPT_Wenum_compare,
+	     "comparison between %qT and %qT",
+	     type1, type2);
+
   return result;
 }
 
@@ -5138,6 +5166,7 @@
 	  tree typ2 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)));
 	  expr.value = inside_init;
 	  expr.original_code = (strict_string ? STRING_CST : ERROR_MARK);
+	  expr.original_type = NULL;
 	  maybe_warn_string_init (type, expr);
 
 	  if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
@@ -5657,6 +5686,7 @@
   p->depth = constructor_depth;
   p->replacement_value.value = 0;
   p->replacement_value.original_code = ERROR_MARK;
+  p->replacement_value.original_type = NULL;
   p->implicit = 0;
   p->range_stack = 0;
   p->outer = 0;
@@ -5800,6 +5830,7 @@
   p->depth = constructor_depth;
   p->replacement_value.value = 0;
   p->replacement_value.original_code = ERROR_MARK;
+  p->replacement_value.original_type = NULL;
   p->implicit = implicit;
   p->outer = 0;
   p->incremental = constructor_incremental;
@@ -5956,6 +5987,7 @@
   struct c_expr ret;
   ret.value = 0;
   ret.original_code = ERROR_MARK;
+  ret.original_type = NULL;
 
   if (implicit == 0)
     {
Index: c-opts.c
===================================================================
--- c-opts.c	(revision 145363)
+++ c-opts.c	(working copy)
@@ -412,6 +412,12 @@
 	     can turn it off only if it's not explicit.  */
 	  if (warn_main == -1)
 	    warn_main = (value ? 2 : 0);
+
+	  /* In C, -Wall turns on -Wenum-compare, which we do here.
+	     In C++ it is on by default, which is done in
+	     c_common_post_options.  */
+          if (warn_enum_compare == -1)
+            warn_enum_compare = value;
 	}
       else
 	{
@@ -438,6 +444,13 @@
       cpp_opts->warn_comments = value;
       break;
 
+    case OPT_Wc___compat:
+      /* Because -Wenum-compare is the default in C++, -Wc++-compat
+	 implies -Wenum-compare.  */
+      if (warn_enum_compare == -1 && value)
+	warn_enum_compare = value;
+      break;
+
     case OPT_Wdeprecated:
       cpp_opts->warn_deprecated = value;
       break;
@@ -1095,6 +1108,12 @@
   if (warn_sign_conversion == -1)
     warn_sign_conversion =  (c_dialect_cxx ()) ? 0 : warn_conversion;
 
+  /* In C, -Wall and -Wc++-compat enable -Wenum-compare, which we do
+     in c_common_handle_option; if it has not yet been set, it is
+     disabled by default.  In C++, it is enabled by default.  */
+  if (warn_enum_compare == -1)
+    warn_enum_compare = c_dialect_cxx () ? 1 : 0;
+
   /* -Wpacked-bitfield-compat is on by default for the C languages.  The
      warning is issued in stor-layout.c which is not part of the front-end so
      we need to selectively turn it on here.  */
Index: c-parser.c
===================================================================
--- c-parser.c	(revision 145363)
+++ c-parser.c	(working copy)
@@ -3042,6 +3042,7 @@
       struct c_expr ret;
       ret.value = error_mark_node;
       ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
       c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, "expected %<}%>");
       pop_init_level (0);
       return ret;
@@ -3098,6 +3099,7 @@
 		  struct c_expr init;
 		  init.value = error_mark_node;
 		  init.original_code = ERROR_MARK;
+		  init.original_type = NULL;
 		  c_parser_error (parser, "expected identifier");
 		  c_parser_skip_until_found (parser, CPP_COMMA, NULL);
 		  process_init_element (init, false);
@@ -3172,6 +3174,7 @@
 		  mexpr.value
 		    = objc_build_message_expr (build_tree_list (rec, args));
 		  mexpr.original_code = ERROR_MARK;
+		  mexpr.original_type = NULL;
 		  /* Now parse and process the remainder of the
 		     initializer, starting with this message
 		     expression as a primary-expression.  */
@@ -3221,6 +3224,7 @@
 		  struct c_expr init;
 		  init.value = error_mark_node;
 		  init.original_code = ERROR_MARK;
+		  init.original_type = NULL;
 		  c_parser_error (parser, "expected %<=%>");
 		  c_parser_skip_until_found (parser, CPP_COMMA, NULL);
 		  process_init_element (init, false);
@@ -4430,6 +4434,7 @@
       TREE_NO_WARNING (ret.value) = 1;
       ret.original_code = ERROR_MARK;
     }
+  ret.original_type = NULL;
   return ret;
 }
 
@@ -4477,6 +4482,7 @@
       exp1.value = c_save_expr (default_conversion (cond.value));
       if (eptype)
 	exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value);
+      exp1.original_type = NULL;
       cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value);
       skip_evaluation += cond.value == truthvalue_true_node;
     }
@@ -4495,6 +4501,7 @@
       skip_evaluation -= cond.value == truthvalue_true_node;
       ret.value = error_mark_node;
       ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
       return ret;
     }
   exp2 = c_parser_conditional_expression (parser, NULL);
@@ -4504,6 +4511,24 @@
 				      cond.original_code == C_MAYBE_CONST_EXPR,
 				      exp1.value, exp2.value);
   ret.original_code = ERROR_MARK;
+  if (exp1.value == error_mark_node || exp2.value == error_mark_node)
+    ret.original_type = NULL;
+  else
+    {
+      tree t1, t2;
+
+      /* If both sides are enum type, the default conversion will have
+	 made the type of the result be an integer type.  We want to
+	 remember the enum types we started with.  */
+      t1 = exp1.original_type ? exp1.original_type : TREE_TYPE (exp1.value);
+      t2 = exp2.original_type ? exp2.original_type : TREE_TYPE (exp2.value);
+      ret.original_type = ((t1 != error_mark_node
+			    && t2 != error_mark_node
+			    && (TYPE_MAIN_VARIANT (t1)
+				== TYPE_MAIN_VARIANT (t2)))
+			   ? t1
+			   : NULL);
+    }
   return ret;
 }
 
@@ -4792,6 +4817,7 @@
 	{
 	  ret.value = error_mark_node;
 	  ret.original_code = ERROR_MARK;
+	  ret.original_type = NULL;
 	  return ret;
 	}
 
@@ -4805,6 +4831,7 @@
       expr = default_function_array_conversion (expr);
       ret.value = c_cast_expr (type_name, expr.value);
       ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
       return ret;
     }
   else
@@ -4844,6 +4871,8 @@
   int ext;
   struct c_expr ret, op;
   location_t loc = c_parser_peek_token (parser)->location;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL;
   switch (c_parser_peek_token (parser)->type)
     {
     case CPP_PLUS_PLUS:
@@ -4866,7 +4895,6 @@
       op = c_parser_cast_expression (parser, NULL);
       op = default_function_array_conversion (op);
       ret.value = build_indirect_ref (loc, op.value, "unary *");
-      ret.original_code = ERROR_MARK;
       return ret;
     case CPP_PLUS:
       if (!c_dialect_objc () && !in_system_header)
@@ -4906,7 +4934,6 @@
 	  c_parser_error (parser, "expected identifier");
 	  ret.value = error_mark_node;
 	}
-	ret.original_code = ERROR_MARK;
 	return ret;
     case CPP_KEYWORD:
       switch (c_parser_peek_token (parser)->keyword)
@@ -4967,6 +4994,7 @@
 	  in_sizeof--;
 	  ret.value = error_mark_node;
 	  ret.original_code = ERROR_MARK;
+	  ret.original_type = NULL;
 	  return ret;
 	}
       if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
@@ -5021,6 +5049,7 @@
 	  in_alignof--;
 	  ret.value = error_mark_node;
 	  ret.original_code = ERROR_MARK;
+	  ret.original_type = NULL;
 	  return ret;
 	}
       if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
@@ -5034,6 +5063,7 @@
       in_alignof--;
       ret.value = c_alignof (groktypename (type_name, NULL, NULL));
       ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
       return ret;
     }
   else
@@ -5045,6 +5075,7 @@
       in_alignof--;
       ret.value = c_alignof_expr (expr.value);
       ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
       return ret;
     }
 }
@@ -5108,11 +5139,12 @@
   struct c_expr expr, e1, e2, e3;
   struct c_type_name *t1, *t2;
   location_t loc;
+  expr.original_code = ERROR_MARK;
+  expr.original_type = NULL;
   switch (c_parser_peek_token (parser)->type)
     {
     case CPP_NUMBER:
       expr.value = c_parser_peek_token (parser)->value;
-      expr.original_code = ERROR_MARK;
       loc = c_parser_peek_token (parser)->location;
       c_parser_consume_token (parser);
       if (TREE_CODE (expr.value) == FIXED_CST
@@ -5127,7 +5159,6 @@
     case CPP_CHAR32:
     case CPP_WCHAR:
       expr.value = c_parser_peek_token (parser)->value;
-      expr.original_code = ERROR_MARK;
       c_parser_consume_token (parser);
       break;
     case CPP_STRING:
@@ -5142,7 +5173,6 @@
       gcc_assert (c_dialect_objc ());
       expr.value
 	= objc_build_string_object (c_parser_peek_token (parser)->value);
-      expr.original_code = ERROR_MARK;
       c_parser_consume_token (parser);
       break;
     case CPP_NAME:
@@ -5150,7 +5180,6 @@
 	{
 	  c_parser_error (parser, "expected expression");
 	  expr.value = error_mark_node;
-	  expr.original_code = ERROR_MARK;
 	  break;
 	}
       {
@@ -5159,8 +5188,8 @@
 	c_parser_consume_token (parser);
 	expr.value = build_external_ref (id,
 					 (c_parser_peek_token (parser)->type
-					  == CPP_OPEN_PAREN), loc);
-	expr.original_code = ERROR_MARK;
+					  == CPP_OPEN_PAREN), loc,
+					 &expr.original_type);
       }
       break;
     case CPP_OPEN_PAREN:
@@ -5181,7 +5210,6 @@
 	      c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
 	      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
 	      expr.value = error_mark_node;
-	      expr.original_code = ERROR_MARK;
 	      break;
 	    }
 	  stmt = c_begin_stmt_expr ();
@@ -5191,7 +5219,6 @@
 	  pedwarn (here, OPT_pedantic, 
 		   "ISO C forbids braced-groups within expressions");
 	  expr.value = c_finish_stmt_expr (stmt);
-	  expr.original_code = ERROR_MARK;
 	}
       else if (c_token_starts_typename (c_parser_peek_2nd_token (parser)))
 	{
@@ -5207,7 +5234,6 @@
 	  if (type_name == NULL)
 	    {
 	      expr.value = error_mark_node;
-	      expr.original_code = ERROR_MARK;
 	    }
 	  else
 	    expr = c_parser_postfix_expression_after_paren_type (parser,
@@ -5222,6 +5248,7 @@
 	    TREE_NO_WARNING (expr.value) = 1;
 	  if (expr.original_code != C_MAYBE_CONST_EXPR)
 	    expr.original_code = ERROR_MARK;
+	  /* Don't change EXPR.ORIGINAL_TYPE.  */
 	  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
 				     "expected %<)%>");
 	}
@@ -5235,7 +5262,6 @@
 	  expr.value = fname_decl (c_parser_peek_token (parser)->location,
 				   c_parser_peek_token (parser)->keyword,
 				   c_parser_peek_token (parser)->value);
-	  expr.original_code = ERROR_MARK;
 	  c_parser_consume_token (parser);
 	  break;
 	case RID_VA_ARG:
@@ -5243,7 +5269,6 @@
 	  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
 	    {
 	      expr.value = error_mark_node;
-	      expr.original_code = ERROR_MARK;
 	      break;
 	    }
 	  e1 = c_parser_expr_no_commas (parser, NULL);
@@ -5252,7 +5277,6 @@
 	    {
 	      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
 	      expr.value = error_mark_node;
-	      expr.original_code = ERROR_MARK;
 	      break;
 	    }
 	  t1 = c_parser_type_name (parser);
@@ -5261,7 +5285,6 @@
 	  if (t1 == NULL)
 	    {
 	      expr.value = error_mark_node;
-	      expr.original_code = ERROR_MARK;
 	    }
 	  else
 	    {
@@ -5276,7 +5299,6 @@
 				       expr.value);
 		  C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true;
 		}
-	      expr.original_code = ERROR_MARK;
 	    }
 	  break;
 	case RID_OFFSETOF:
@@ -5284,21 +5306,18 @@
 	  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
 	    {
 	      expr.value = error_mark_node;
-	      expr.original_code = ERROR_MARK;
 	      break;
 	    }
 	  t1 = c_parser_type_name (parser);
 	  if (t1 == NULL)
 	    {
 	      expr.value = error_mark_node;
-	      expr.original_code = ERROR_MARK;
 	      break;
 	    }
 	  if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
 	    {
 	      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
 	      expr.value = error_mark_node;
-	      expr.original_code = ERROR_MARK;
 	      break;
 	    }
 	  {
@@ -5363,7 +5382,6 @@
 	    c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
 				       "expected %<)%>");
 	    expr.value = fold_offsetof (offsetof_ref, NULL_TREE);
-	    expr.original_code = ERROR_MARK;
 	  }
 	  break;
 	case RID_CHOOSE_EXPR:
@@ -5371,7 +5389,6 @@
 	  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
 	    {
 	      expr.value = error_mark_node;
-	      expr.original_code = ERROR_MARK;
 	      break;
 	    }
 	  loc = c_parser_peek_token (parser)->location;
@@ -5380,7 +5397,6 @@
 	    {
 	      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
 	      expr.value = error_mark_node;
-	      expr.original_code = ERROR_MARK;
 	      break;
 	    }
 	  e2 = c_parser_expr_no_commas (parser, NULL);
@@ -5388,7 +5404,6 @@
 	    {
 	      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
 	      expr.value = error_mark_node;
-	      expr.original_code = ERROR_MARK;
 	      break;
 	    }
 	  e3 = c_parser_expr_no_commas (parser, NULL);
@@ -5412,28 +5427,24 @@
 	  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
 	    {
 	      expr.value = error_mark_node;
-	      expr.original_code = ERROR_MARK;
 	      break;
 	    }
 	  t1 = c_parser_type_name (parser);
 	  if (t1 == NULL)
 	    {
 	      expr.value = error_mark_node;
-	      expr.original_code = ERROR_MARK;
 	      break;
 	    }
 	  if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
 	    {
 	      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
 	      expr.value = error_mark_node;
-	      expr.original_code = ERROR_MARK;
 	      break;
 	    }
 	  t2 = c_parser_type_name (parser);
 	  if (t2 == NULL)
 	    {
 	      expr.value = error_mark_node;
-	      expr.original_code = ERROR_MARK;
 	      break;
 	    }
 	  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
@@ -5447,7 +5458,6 @@
 	    expr.value = comptypes (e1, e2)
 	      ? build_int_cst (NULL_TREE, 1)
 	      : build_int_cst (NULL_TREE, 0);
-	    expr.original_code = ERROR_MARK;
 	  }
 	  break;
 	case RID_AT_SELECTOR:
@@ -5456,7 +5466,6 @@
 	  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
 	    {
 	      expr.value = error_mark_node;
-	      expr.original_code = ERROR_MARK;
 	      break;
 	    }
 	  {
@@ -5464,7 +5473,6 @@
 	    c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
 				       "expected %<)%>");
 	    expr.value = objc_build_selector_expr (sel);
-	    expr.original_code = ERROR_MARK;
 	  }
 	  break;
 	case RID_AT_PROTOCOL:
@@ -5473,7 +5481,6 @@
 	  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
 	    {
 	      expr.value = error_mark_node;
-	      expr.original_code = ERROR_MARK;
 	      break;
 	    }
 	  if (c_parser_next_token_is_not (parser, CPP_NAME))
@@ -5481,7 +5488,6 @@
 	      c_parser_error (parser, "expected identifier");
 	      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
 	      expr.value = error_mark_node;
-	      expr.original_code = ERROR_MARK;
 	      break;
 	    }
 	  {
@@ -5490,7 +5496,6 @@
 	    c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
 				       "expected %<)%>");
 	    expr.value = objc_build_protocol_expr (id);
-	    expr.original_code = ERROR_MARK;
 	  }
 	  break;
 	case RID_AT_ENCODE:
@@ -5500,14 +5505,12 @@
 	  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
 	    {
 	      expr.value = error_mark_node;
-	      expr.original_code = ERROR_MARK;
 	      break;
 	    }
 	  t1 = c_parser_type_name (parser);
 	  if (t1 == NULL)
 	    {
 	      expr.value = error_mark_node;
-	      expr.original_code = ERROR_MARK;
 	      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
 	      break;
 	    }
@@ -5516,13 +5519,11 @@
 	  {
 	    tree type = groktypename (t1, NULL, NULL);
 	    expr.value = objc_build_encode_expr (type);
-	    expr.original_code = ERROR_MARK;
 	  }
 	  break;
 	default:
 	  c_parser_error (parser, "expected expression");
 	  expr.value = error_mark_node;
-	  expr.original_code = ERROR_MARK;
 	  break;
 	}
       break;
@@ -5537,14 +5538,12 @@
 				     "expected %<]%>");
 	  expr.value = objc_build_message_expr (build_tree_list (receiver,
 								 args));
-	  expr.original_code = ERROR_MARK;
 	  break;
 	}
       /* Else fall through to report error.  */
     default:
       c_parser_error (parser, "expected expression");
       expr.value = error_mark_node;
-      expr.original_code = ERROR_MARK;
       break;
     }
   return c_parser_postfix_expression_after_primary (parser, expr);
@@ -5589,6 +5588,7 @@
   non_const |= !type_expr_const;
   expr.value = build_compound_literal (type, init.value, non_const);
   expr.original_code = ERROR_MARK;
+  expr.original_type = NULL;
   if (type_expr)
     {
       if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR)
@@ -5629,6 +5629,7 @@
 				     "expected %<]%>");
 	  expr.value = build_array_ref (expr.value, idx, loc);
 	  expr.original_code = ERROR_MARK;
+	  expr.original_type = NULL;
 	  break;
 	case CPP_OPEN_PAREN:
 	  /* Function call.  */
@@ -5647,6 +5648,7 @@
 	      && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL
 	      && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P)
 	    expr.original_code = C_MAYBE_CONST_EXPR;
+	  expr.original_type = NULL;
 	  break;
 	case CPP_DOT:
 	  /* Structure element reference.  */
@@ -5659,11 +5661,23 @@
 	      c_parser_error (parser, "expected identifier");
 	      expr.value = error_mark_node;
 	      expr.original_code = ERROR_MARK;
+              expr.original_type = NULL;
 	      return expr;
 	    }
 	  c_parser_consume_token (parser);
 	  expr.value = build_component_ref (expr.value, ident);
 	  expr.original_code = ERROR_MARK;
+	  if (TREE_CODE (expr.value) != COMPONENT_REF)
+	    expr.original_type = NULL;
+	  else
+	    {
+	      /* Remember the original type of a bitfield.  */
+	      tree field = TREE_OPERAND (expr.value, 1);
+	      if (TREE_CODE (field) != FIELD_DECL)
+		expr.original_type = NULL;
+	      else
+		expr.original_type = DECL_BIT_FIELD_TYPE (field);
+	    }
 	  break;
 	case CPP_DEREF:
 	  /* Structure element reference.  */
@@ -5676,6 +5690,7 @@
 	      c_parser_error (parser, "expected identifier");
 	      expr.value = error_mark_node;
 	      expr.original_code = ERROR_MARK;
+	      expr.original_type = NULL;
 	      return expr;
 	    }
 	  c_parser_consume_token (parser);
@@ -5684,6 +5699,17 @@
 								"->"),
 					    ident);
 	  expr.original_code = ERROR_MARK;
+	  if (TREE_CODE (expr.value) != COMPONENT_REF)
+	    expr.original_type = NULL;
+	  else
+	    {
+	      /* Remember the original type of a bitfield.  */
+	      tree field = TREE_OPERAND (expr.value, 1);
+	      if (TREE_CODE (field) != FIELD_DECL)
+		expr.original_type = NULL;
+	      else
+		expr.original_type = DECL_BIT_FIELD_TYPE (field);
+	    }
 	  break;
 	case CPP_PLUS_PLUS:
 	  /* Postincrement.  */
@@ -5692,6 +5718,7 @@
 	  expr.value = build_unary_op (loc,
 				       POSTINCREMENT_EXPR, expr.value, 0);
 	  expr.original_code = ERROR_MARK;
+	  expr.original_type = NULL;
 	  break;
 	case CPP_MINUS_MINUS:
 	  /* Postdecrement.  */
@@ -5700,6 +5727,7 @@
 	  expr.value = build_unary_op (loc,
 				       POSTDECREMENT_EXPR, expr.value, 0);
 	  expr.original_code = ERROR_MARK;
+	  expr.original_type = NULL;
 	  break;
 	default:
 	  return expr;
@@ -5727,6 +5755,7 @@
       next = default_function_array_conversion (next);
       expr.value = build_compound_expr (expr.value, next.value);
       expr.original_code = COMPOUND_EXPR;
+      expr.original_type = NULL;
     }
   return expr;
 }

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