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 warning about ++/-- with enum value


In C++, the ++ and -- operators may not be used with variables of enum
type, unless they have been explicitly declared via operator++ or
operator--.  The first patch in this message changes the C frontend to
issue a warning about uses of ++ or -- with variables of enum type (for
the purposes of -Wc++-compat I think we can disregard the possibility of
defining the operator functions).

The second patch in this message corrects the various instances in gcc
which assume that it is OK to use ++ or -- with a variable of enum
type.  In general I simply change the type of the variable to int or
unsigned int.  In a few cases I then had to add a cast back to the enum
type.

I built the arm, ia64, mips, pa, rs6000, s390, sh, sparc, and spu
backends with the new compiler to see if there were any new warnings.
Only the ia64 backend required changes, which are included in the second
patch, and tested by verifying that some .i files generated the same .s
files.

Bootstrapped and tested on i686-pc-linux-gnu.  OK for mainline?

The second patch requires approval from the C++ and Fortran maintainers.
(Actually I think the C++ changes count as obvious, but I would like the
Fortran maintainers to take a look.)

Ian


gcc/ChangeLog:

2009-05-14  Ian Lance Taylor  <iant@google.com>

	* c-typeck.c (build_unary_op): If -Wc++-compat, warn about using
	++ or -- with a variable of enum type.

gcc/testsuite/ChangeLog:

2009-05-14  Ian Lance Taylor  <iant@google.com>

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


Index: c-typeck.c
===================================================================
--- c-typeck.c	(revision 147509)
+++ c-typeck.c	(working copy)
@@ -3267,6 +3267,11 @@ build_unary_op (location_t location,
 				 : lv_decrement)))
 	return error_mark_node;
 
+      if (warn_cxx_compat && TREE_CODE (TREE_TYPE (arg)) == ENUMERAL_TYPE)
+	warning_at (location, OPT_Wc___compat,
+		    ("pre/post increment/decrement of enumeration value "
+		     "is invalid in C++"));
+
       /* Ensure the argument is fully folded inside any SAVE_EXPR.  */
       arg = c_fully_fold (arg, false, NULL);
 
Index: testsuite/gcc.dg/Wcxx-compat-9.c
===================================================================
--- testsuite/gcc.dg/Wcxx-compat-9.c	(revision 0)
+++ testsuite/gcc.dg/Wcxx-compat-9.c	(revision 0)
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-Wc++-compat" } */
+
+enum e { FIRST, LAST };
+
+extern void f2 (enum e);
+
+void
+f1 ()
+{
+  enum e v;
+
+  for (v = FIRST; v < LAST; ++v)  /* { dg-warning "invalid in C\[+\]\[+\]" } */
+    f2 (v);
+  for (v = FIRST; v < LAST; v++)  /* { dg-warning "invalid in C\[+\]\[+\]" } */
+    f2 (v);
+  for (v = LAST; v > FIRST; --v)  /* { dg-warning "invalid in C\[+\]\[+\]" } */
+    f2 (v);
+  for (v = LAST; v > FIRST; v--)  /* { dg-warning "invalid in C\[+\]\[+\]" } */
+    f2 (v);
+}


==================================================

Second patch.

gcc/ChangeLog:

2009-05-14  Ian Lance Taylor  <iant@google.com>

	* passes.c (finish_optimization_passes): Change i to int.
	* plugin.c (plugins_active_p): Change event to int.
	(dump_active_plugins): Likewise.
	* reginfo.c (invalid_mode_change_p): Change to to unsigned int.
	Add cast.
	* tree.c (tree_range_check_failed): Change c to unsigned int.
	(omp_clause_range_check_failed): Likewise.
	(build_common_builtin_nodes): Change mode to int.  Add cast.
	* config/ia64/ia64.c (is_emitted): Change r to unsigned int.
	(ia64_hard_regno_rename_ok, ia64_eh_uses): Likewise.

gcc/cp/ChangeLog:

2009-05-14  Ian Lance Taylor  <iant@google.com>

	* class.c (layout_class_type): Change itk to unsigned int.
	* decl.c (finish_enum): Change itk to unsigned int.
	* parser.c (cp_parser_check_decl_spec): Change ds to int.  Remove
	casts.

gcc/fortran/ChangeLog:

2009-05-14  Ian Lance Taylor  <iant@google.com>

	* decl.c (match_attr_spec): Change d to unsigned int.
	* dump-parse-tree.c (show_namespace): Change op to int.  Add cast.
	* interface.c (gfc_check_interfaces): Change i to int.  Add casts.
	* module.c (read_module): Change i to int.  Add cast.
	(write_module): Change i to int.
	* symbol.c (gfc_get_namespace): Change in to int.
	(gfc_free_namespace): Change i to int.
	* trans-io.c (gfc_build_io_library_fndecls): Change ptype to
	unsigned int.  Add cast.
	* trans-types.c (gfc_init_kinds): Change mode to unsigned int.
	Add casts.

Index: tree.c
===================================================================
--- tree.c	(revision 147509)
+++ tree.c	(working copy)
@@ -7147,7 +7147,7 @@ tree_range_check_failed (const_tree node
 {
   char *buffer;
   unsigned length = 0;
-  enum tree_code c;
+  unsigned int c;
 
   for (c = c1; c <= c2; ++c)
     length += 4 + strlen (tree_code_name[c]);
@@ -7208,7 +7208,7 @@ omp_clause_range_check_failed (const_tre
 {
   char *buffer;
   unsigned length = 0;
-  enum omp_clause_code c;
+  unsigned int c;
 
   for (c = c1; c <= c2; ++c)
     length += 4 + strlen (omp_clause_code_name[c]);
@@ -7811,7 +7811,7 @@ build_common_builtin_nodes (void)
      complex.  Further, we can do slightly better with folding these 
      beasties if the real and complex parts of the arguments are separate.  */
   {
-    enum machine_mode mode;
+    int mode;
 
     for (mode = MIN_MODE_COMPLEX_FLOAT; mode <= MAX_MODE_COMPLEX_FLOAT; ++mode)
       {
@@ -7820,7 +7820,7 @@ build_common_builtin_nodes (void)
 	enum built_in_function mcode, dcode;
 	tree type, inner_type;
 
-	type = lang_hooks.types.type_for_mode (mode, 0);
+	type = lang_hooks.types.type_for_mode ((enum machine_mode) mode, 0);
 	if (type == NULL)
 	  continue;
 	inner_type = TREE_TYPE (type);
Index: cp/class.c
===================================================================
--- cp/class.c	(revision 147509)
+++ cp/class.c	(working copy)
@@ -4864,7 +4864,7 @@ layout_class_type (tree t, tree *virtual
       if (DECL_C_BIT_FIELD (field)
 	  && INT_CST_LT (TYPE_SIZE (type), DECL_SIZE (field)))
 	{
-	  integer_type_kind itk;
+	  unsigned int itk;
 	  tree integer_type;
 	  bool was_unnamed_p = false;
 	  /* We must allocate the bits as if suitably aligned for the
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 147509)
+++ cp/decl.c	(working copy)
@@ -11022,7 +11022,7 @@ finish_enum (tree enumtype)
   int lowprec;
   int highprec;
   int precision;
-  integer_type_kind itk;
+  int itk;
   tree underlying_type = NULL_TREE;
   bool fixed_underlying_type_p 
     = ENUM_UNDERLYING_TYPE (enumtype) != NULL_TREE;
Index: cp/parser.c
===================================================================
--- cp/parser.c	(revision 147509)
+++ cp/parser.c	(working copy)
@@ -2149,11 +2149,11 @@ static void
 cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs,
 			   location_t location)
 {
-  cp_decl_spec ds;
+  int ds;
 
   for (ds = ds_first; ds != ds_last; ++ds)
     {
-      unsigned count = decl_specs->specs[(int)ds];
+      unsigned count = decl_specs->specs[ds];
       if (count < 2)
 	continue;
       /* The "long" specifier is a special case because of "long long".  */
@@ -2183,7 +2183,7 @@ cp_parser_check_decl_spec (cp_decl_speci
 	    "__complex",
 	    "__thread"
 	  };
-	  error ("%Hduplicate %qs", &location, decl_spec_names[(int)ds]);
+	  error ("%Hduplicate %qs", &location, decl_spec_names[ds]);
 	}
     }
 }
Index: fortran/interface.c
===================================================================
--- fortran/interface.c	(revision 147509)
+++ fortran/interface.c	(working copy)
@@ -1175,7 +1175,7 @@ gfc_check_interfaces (gfc_namespace *ns)
 {
   gfc_namespace *old_ns, *ns2;
   char interface_name[100];
-  gfc_intrinsic_op i;
+  int i;
 
   old_ns = gfc_current_ns;
   gfc_current_ns = ns;
@@ -1193,12 +1193,12 @@ gfc_check_interfaces (gfc_namespace *ns)
 	strcpy (interface_name, "intrinsic assignment operator");
       else
 	sprintf (interface_name, "intrinsic '%s' operator",
-		 gfc_op2string (i));
+		 gfc_op2string ((gfc_intrinsic_op) i));
 
       if (check_interface0 (ns->op[i], interface_name))
 	continue;
 
-      check_operator_interface (ns->op[i], i);
+      check_operator_interface (ns->op[i], (gfc_intrinsic_op) i);
 
       for (ns2 = ns; ns2; ns2 = ns2->parent)
 	{
Index: fortran/symbol.c
===================================================================
--- fortran/symbol.c	(revision 147509)
+++ fortran/symbol.c	(working copy)
@@ -2198,7 +2198,7 @@ gfc_get_namespace (gfc_namespace *parent
 {
   gfc_namespace *ns;
   gfc_typespec *ts;
-  gfc_intrinsic_op in;
+  int in;
   int i;
 
   ns = XCNEW (gfc_namespace);
@@ -3089,7 +3089,7 @@ void
 gfc_free_namespace (gfc_namespace *ns)
 {
   gfc_namespace *p, *q;
-  gfc_intrinsic_op i;
+  int i;
 
   if (ns == NULL)
     return;
@@ -4495,4 +4495,3 @@ gfc_get_tbp_symtree (gfc_symtree **root,
 
   return result;
 }
-
Index: fortran/decl.c
===================================================================
--- fortran/decl.c	(revision 147509)
+++ fortran/decl.c	(working copy)
@@ -2815,7 +2815,7 @@ match_attr_spec (void)
 
   locus start, seen_at[NUM_DECL];
   int seen[NUM_DECL];
-  decl_types d;
+  unsigned int d;
   const char *attr;
   match m;
   gfc_try t;
Index: fortran/dump-parse-tree.c
===================================================================
--- fortran/dump-parse-tree.c	(revision 147509)
+++ fortran/dump-parse-tree.c	(working copy)
@@ -1,5 +1,5 @@
 /* Parse tree dumper
-   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
    Contributed by Steven Bosscher
 
@@ -1973,7 +1973,7 @@ show_namespace (gfc_namespace *ns)
 {
   gfc_interface *intr;
   gfc_namespace *save;
-  gfc_intrinsic_op op;
+  int op;
   gfc_equiv *eq;
   int i;
 
@@ -2023,7 +2023,7 @@ show_namespace (gfc_namespace *ns)
 
 	  show_indent ();
 	  fprintf (dumpfile, "Operator interfaces for %s:",
-		   gfc_op2string (op));
+		   gfc_op2string ((gfc_intrinsic_op) op));
 
 	  for (; intr; intr = intr->next)
 	    fprintf (dumpfile, " %s", intr->sym->name);
Index: fortran/module.c
===================================================================
--- fortran/module.c	(revision 147509)
+++ fortran/module.c	(working copy)
@@ -4017,7 +4017,7 @@ read_module (void)
   module_locus operator_interfaces, user_operators;
   const char *p;
   char name[GFC_MAX_SYMBOL_LEN + 1];
-  gfc_intrinsic_op i;
+  int i;
   int ambiguous, j, nuse, symbol;
   pointer_info *info, *q;
   gfc_use_rename *u;
@@ -4225,7 +4225,7 @@ read_module (void)
 
       if (only_flag)
 	{
-	  u = find_use_operator (i);
+	  u = find_use_operator ((gfc_intrinsic_op) i);
 
 	  if (u == NULL)
 	    {
@@ -4677,7 +4677,7 @@ write_symtree (gfc_symtree *st)
 static void
 write_module (void)
 {
-  gfc_intrinsic_op i;
+  int i;
 
   /* Write the operator interfaces.  */
   mio_lparen ();
Index: fortran/trans-types.c
===================================================================
--- fortran/trans-types.c	(revision 147509)
+++ fortran/trans-types.c	(working copy)
@@ -252,7 +252,7 @@ void init_c_interop_kinds (void)
 void
 gfc_init_kinds (void)
 {
-  enum machine_mode mode;
+  unsigned int mode;
   int i_index, r_index, kind;
   bool saw_i4 = false, saw_i8 = false;
   bool saw_r4 = false, saw_r8 = false, saw_r16 = false;
@@ -261,7 +261,7 @@ gfc_init_kinds (void)
     {
       int kind, bitsize;
 
-      if (!targetm.scalar_mode_supported_p (mode))
+      if (!targetm.scalar_mode_supported_p ((enum machine_mode) mode))
 	continue;
 
       /* The middle end doesn't support constants larger than 2*HWI.
@@ -309,12 +309,13 @@ gfc_init_kinds (void)
 
   for (r_index = 0, mode = MIN_MODE_FLOAT; mode <= MAX_MODE_FLOAT; mode++)
     {
-      const struct real_format *fmt = REAL_MODE_FORMAT (mode);
+      const struct real_format *fmt =
+	REAL_MODE_FORMAT ((enum machine_mode) mode);
       int kind;
 
       if (fmt == NULL)
 	continue;
-      if (!targetm.scalar_mode_supported_p (mode))
+      if (!targetm.scalar_mode_supported_p ((enum machine_mode) mode))
 	continue;
 
       /* Only let float/double/long double go through because the fortran
Index: fortran/trans-io.c
===================================================================
--- fortran/trans-io.c	(revision 147509)
+++ fortran/trans-io.c	(working copy)
@@ -279,7 +279,7 @@ gfc_build_io_library_fndecls (void)
   tree gfc_intio_type_node;
   tree parm_type, dt_parm_type;
   HOST_WIDE_INT pad_size;
-  enum ioparam_type ptype;
+  unsigned int ptype;
 
   types[IOPARM_type_int4] = gfc_int4_type_node = gfc_get_int_type (4);
   types[IOPARM_type_intio] = gfc_intio_type_node
@@ -302,7 +302,7 @@ gfc_build_io_library_fndecls (void)
 		     TYPE_ALIGN (gfc_get_int_type (gfc_intio_kind)));
 
   for (ptype = IOPARM_ptype_common; ptype < IOPARM_ptype_num; ptype++)
-    gfc_build_st_parameter (ptype, types);
+    gfc_build_st_parameter ((enum ioparam_type) ptype, types);
 
   /* Define the transfer functions.  */
 
Index: plugin.c
===================================================================
--- plugin.c	(revision 147509)
+++ plugin.c	(working copy)
@@ -765,7 +765,7 @@ print_plugins_help (FILE *file, const ch
 bool
 plugins_active_p (void)
 {
-  enum plugin_event event;
+  int event;
 
   for (event = PLUGIN_PASS_MANAGER_SETUP; event < PLUGIN_EVENT_LAST; event++)
     if (plugin_callbacks[event])
@@ -781,7 +781,7 @@ plugins_active_p (void)
 void
 dump_active_plugins (FILE *file)
 {
-  enum plugin_event event;
+  int event;
 
   if (!plugins_active_p ())
     return;
Index: reginfo.c
===================================================================
--- reginfo.c	(revision 147509)
+++ reginfo.c	(working copy)
@@ -1322,7 +1322,7 @@ invalid_mode_change_p (unsigned int regn
 		       enum machine_mode from)
 {
   struct subregs_of_mode_node dummy, *node;
-  enum machine_mode to;
+  unsigned int to;
   unsigned char mask;
 
   gcc_assert (subregs_of_mode);
@@ -1335,7 +1335,7 @@ invalid_mode_change_p (unsigned int regn
   mask = 1 << (regno & 7);
   for (to = VOIDmode; to < NUM_MACHINE_MODES; to++)
     if (node->modes[to] & mask)
-      if (CANNOT_CHANGE_MODE_CLASS (from, to, rclass))
+      if (CANNOT_CHANGE_MODE_CLASS (from, (enum machine_mode) to, rclass))
 	return true;
 
   return false;
Index: passes.c
===================================================================
--- passes.c	(revision 147509)
+++ passes.c	(working copy)
@@ -239,7 +239,7 @@ rest_of_type_compilation (tree type, int
 void
 finish_optimization_passes (void)
 {
-  enum tree_dump_index i;
+  int i;
   struct dump_file_info *dfi;
   char *name;
 
Index: config/ia64/ia64.c
===================================================================
--- config/ia64/ia64.c	(revision 147509)
+++ config/ia64/ia64.c	(working copy)
@@ -1943,7 +1943,7 @@ get_reg (enum ia64_frame_regs r)
 static bool
 is_emitted (int regno)
 {
-  enum ia64_frame_regs r;
+  unsigned int r;
 
   for (r = reg_fp; r < number_of_ia64_frame_regs; r++)
     if (emitted_frame_related_regs[r] == regno)
@@ -3657,7 +3657,7 @@ int
 ia64_hard_regno_rename_ok (int from, int to)
 {
   /* Don't clobber any of the registers we reserved for the prologue.  */
-  enum ia64_frame_regs r;
+  unsigned int r;
 
   for (r = reg_fp; r <= reg_save_ar_lc; r++)
     if (to == current_frame_info.r[r] 
@@ -9317,7 +9317,7 @@ ia64_epilogue_uses (int regno)
 int
 ia64_eh_uses (int regno)
 {
-  enum ia64_frame_regs r;
+  unsigned int r;
 
   if (! reload_completed)
     return 0;

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