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]

PR 40989: Fix Wimplicit


The problem here is that group options (options that enable other
options) are not handled correctly when enabled by -Werror=. The
following patch fixes this issue for Wimplicit but also adds the
infrastructure to fix it for all other options. When
enabling/disabling an option, we should always use the new
process_option function.

In the future, we should be able to generate the calls to
process_option automatically from the .opt files.

Bootstrapped and regression tested on x86_64-linux-gnu. OK?


2010-05-01  Manuel López-Ibáñez  <manu@gcc.gnu.org>

	PR 40989
	* opts.c (common_handle_option): Add argument kind.
	(handle_option): Factor out code to...
	(process_option): ... here. New.
	(set_option): Use option index instead of option pointer. Classify
	diagnostics correctly.
	(enable_warning_as_error): Call process_option.
	* opts.h (set_option): Update declaration.
	(process_option): Declare.
	* langhooks.h (struct lang_hooks): Add argument kind to
	handle_option.
	* c.opt (Wimplicit,Wimplicit-int): Initialize to -1.
	* c-opts.c (set_Wimplicit): Delete.
	(lang_mask): New static constant.
	(c_common_handle_option): Add argument kind. Use process_option
	instead of set_Wimplicit.
	(c_common_post_options): warn_implicit and warn_implicit_int
	are disabled by default.
	* c-common.c (warn_implicit): Do not define here.
	* c-common.h (warn_implicit): Do not declare here.
	(c_common_handle_option): Update declaration.
	* lto-opts.c (lto_reissue_options): Update call to set_option.
java/
	* lang.c (java_handle_option): Add argument kind.
fortran/	
	* options.c (gfc_handle_option): Add argument kind.
	* gfortran.h (gfc_handle_option): Update declaration.
testsuite/
	* gcc.dg/pr40989.c: New.
Index: gcc/java/lang.c
===================================================================
--- gcc/java/lang.c	(revision 158909)
+++ gcc/java/lang.c	(working copy)
@@ -50,11 +50,11 @@ The Free Software Foundation is independ
 static bool java_init (void);
 static void java_finish (void);
 static unsigned int java_init_options (unsigned int, const char **);
 static bool java_post_options (const char **);
 
-static int java_handle_option (size_t scode, const char *arg, int value);
+static int java_handle_option (size_t scode, const char *arg, int value, int kind);
 static void put_decl_string (const char *, int);
 static void put_decl_node (tree, int);
 static void java_print_error_function (diagnostic_context *, const char *,
 				       diagnostic_info *);
 static int merge_init_test_initialization (void * *, void *);
@@ -173,11 +173,12 @@ struct lang_hooks lang_hooks = LANG_HOOK
 /*
  * process java-specific compiler command-line options
  * return 0, but do not complain if the option is not recognized.
  */
 static int
-java_handle_option (size_t scode, const char *arg, int value)
+java_handle_option (size_t scode, const char *arg, int value,
+		    int kind ATTRIBUTE_UNUSED)
 {
   enum opt_code code = (enum opt_code) scode;
 
   switch (code)
     {
Index: gcc/testsuite/gcc.dg/pr40989.c
===================================================================
--- gcc/testsuite/gcc.dg/pr40989.c	(revision 0)
+++ gcc/testsuite/gcc.dg/pr40989.c	(revision 0)
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-Werror=implicit" } */
+int main() {
+  return pippo(); /* { dg-error "" } */
+}
+/* { dg-message "warnings being treated as errors" "" { target *-*-* } 0 } */
Index: gcc/opts.c
===================================================================
--- gcc/opts.c	(revision 158909)
+++ gcc/opts.c	(working copy)
@@ -370,11 +370,11 @@ bool flag_warn_unused_result = false;
 /* Input file names.  */
 const char **in_fnames;
 unsigned num_in_fnames;
 
 static int common_handle_option (size_t scode, const char *arg, int value,
-				 unsigned int lang_mask);
+				 unsigned int lang_mask, int kind);
 static void handle_param (const char *);
 static unsigned int handle_option (const char **argv, unsigned int lang_mask);
 static char *write_langs (unsigned int lang_mask);
 static void complain_wrong_lang (const char *, const struct cl_option *,
 				 unsigned int lang_mask);
@@ -483,10 +483,51 @@ void print_ignored_options (void)
     }
 
   input_location = saved_loc;
 }
 
+
+/* Process an option OPTION, with option index OPT_INDEX, and argument
+   ARG, for the language indicated by LANG_MASK.  VALUE is true,
+   unless no- form of an -f or -W option was given.  KIND is the
+   diagnostic_t if this is a diagnostics option, DK_UNSPECIFIED
+   otherwise.  Returns false if the switch was invalid.  */
+bool
+process_option (int opt_index, int value, const char *arg,
+		unsigned int lang_mask, int kind)
+{
+  const struct cl_option *option = &cl_options[opt_index];
+
+  if (option->flag_var)
+    set_option (opt_index, value, arg, kind);
+  
+  if (option->flags & lang_mask)
+    {
+      if (lang_hooks.handle_option (opt_index, arg, value, kind) == 0)
+	return false;
+      else
+	lto_register_user_option (opt_index, arg, value, lang_mask);
+    }
+
+  if (option->flags & CL_COMMON)
+    {
+      if (common_handle_option (opt_index, arg, value, lang_mask, kind) == 0)
+	return false;
+      else
+	lto_register_user_option (opt_index, arg, value, CL_COMMON);
+    }
+
+  if (option->flags & CL_TARGET)
+    {
+      if (!targetm.handle_option (opt_index, arg, value))
+	return false;
+      else
+	lto_register_user_option (opt_index, arg, value, CL_TARGET);
+    }
+  return true;
+}
+
 /* Handle the switch beginning at ARGV for the language indicated by
    LANG_MASK.  Returns the number of switches consumed.  */
 static unsigned int
 handle_option (const char **argv, unsigned int lang_mask)
 {
@@ -607,36 +648,12 @@ handle_option (const char **argv, unsign
 		 option->opt_text);
 	  goto done;
 	}
     }
 
-  if (option->flag_var)
-    set_option (option, value, arg);
-
-  if (option->flags & lang_mask)
-    {
-      if (lang_hooks.handle_option (opt_index, arg, value) == 0)
-	result = 0;
-      else
-	lto_register_user_option (opt_index, arg, value, lang_mask);
-    }
-
-  if (result && (option->flags & CL_COMMON))
-    {
-      if (common_handle_option (opt_index, arg, value, lang_mask) == 0)
-	result = 0;
-      else
-	lto_register_user_option (opt_index, arg, value, CL_COMMON);
-    }
-
-  if (result && (option->flags & CL_TARGET))
-    {
-      if (!targetm.handle_option (opt_index, arg, value))
-	result = 0;
-      else
-	lto_register_user_option (opt_index, arg, value, CL_TARGET);
-    }
+  if (!process_option (opt_index, value, arg, lang_mask, DK_UNSPECIFIED))
+    result = 0;
 
  done:
   if (dup)
     free (dup);
   return result;
@@ -1462,11 +1479,11 @@ print_specific_help (unsigned int includ
    extra handling need to be listed here; if you simply want
    VALUE assigned to a variable, it happens automatically.  */
 
 static int
 common_handle_option (size_t scode, const char *arg, int value,
-		      unsigned int lang_mask)
+		      unsigned int lang_mask, int kind ATTRIBUTE_UNUSED)
 {
   static bool verbose = false;
   enum opt_code code = (enum opt_code) scode;
 
   switch (code)
@@ -2371,12 +2388,14 @@ get_option_state (int option, struct cl_
 }
 
 /* Set *OPTION according to VALUE and ARG.  */
 
 void
-set_option (const struct cl_option *option, int value, const char *arg)
+set_option (int opt_index, int value, const char *arg, int kind)
 {
+  const struct cl_option *option = &cl_options[opt_index];
+
   if (!option->flag_var)
     return;
 
   switch (option->var_type)
     {
@@ -2402,10 +2421,13 @@ set_option (const struct cl_option *opti
 
     case CLVC_STRING:
 	*(const char **) option->flag_var = arg;
 	break;
     }
+
+  if ((diagnostic_t)kind != DK_UNSPECIFIED)
+    diagnostic_classify_diagnostic (global_dc, opt_index, (diagnostic_t)kind);
 }
 
 
 /* Callback function, called when -Werror= enables a warning.  */
 
@@ -2445,12 +2467,12 @@ enable_warning_as_error (const char *arg
       if (kind == DK_ERROR)
 	{
 	  const struct cl_option * const option = cl_options + option_index;
 
 	  /* -Werror=foo implies -Wfoo.  */
-	  if (option->var_type == CLVC_BOOLEAN && option->flag_var)
-	    *(int *) option->flag_var = 1;
+	  if (option->var_type == CLVC_BOOLEAN)
+	    process_option (option_index, value, arg, lang_mask, (int)kind);
 
 	  if (warning_as_error_callback)
 	    warning_as_error_callback (option_index);
 	}
     }
Index: gcc/opts.h
===================================================================
--- gcc/opts.h	(revision 158909)
+++ gcc/opts.h	(working copy)
@@ -101,12 +101,13 @@ extern unsigned num_in_fnames;
 size_t find_opt (const char *input, int lang_mask);
 extern void prune_options (int *argcp, char ***argvp);
 extern void decode_options (unsigned int argc, const char **argv);
 extern int option_enabled (int opt_idx);
 extern bool get_option_state (int, struct cl_option_state *);
-extern void set_option (const struct cl_option *, int, const char *);
-
+extern void set_option (int opt_index, int value, const char *arg, int);
+bool process_option (int opt_index, int value, const char *arg,
+		     unsigned int lang_mask, int kind);
 extern void register_warning_as_error_callback (void (*callback) (int));
 extern void enable_warning_as_error (const char *arg, int value,
 				     unsigned int lang_mask);
 extern void print_ignored_options (void);
 #endif
Index: gcc/fortran/gfortran.h
===================================================================
--- gcc/fortran/gfortran.h	(revision 158909)
+++ gcc/fortran/gfortran.h	(working copy)
@@ -2321,11 +2321,11 @@ void gfc_done_2 (void);
 
 int get_c_kind (const char *, CInteropKind_t *);
 
 /* options.c */
 unsigned int gfc_init_options (unsigned int, const char **);
-int gfc_handle_option (size_t, const char *, int);
+int gfc_handle_option (size_t, const char *, int, int);
 bool gfc_post_options (const char **);
 
 /* f95-lang.c */
 void gfc_maybe_initialize_eh (void);
 
Index: gcc/fortran/options.c
===================================================================
--- gcc/fortran/options.c	(revision 158909)
+++ gcc/fortran/options.c	(working copy)
@@ -530,11 +530,12 @@ gfc_handle_runtime_check_option (const c
 
 /* Handle command-line options.  Returns 0 if unrecognized, 1 if
    recognized and handled.  */
 
 int
-gfc_handle_option (size_t scode, const char *arg, int value)
+gfc_handle_option (size_t scode, const char *arg, int value,
+		   int kind ATTRIBUTE_UNUSED)
 {
   int result = 1;
   enum opt_code code = (enum opt_code) scode;
 
   /* Ignore file names.  */
Index: gcc/langhooks.h
===================================================================
--- gcc/langhooks.h	(revision 158909)
+++ gcc/langhooks.h	(working copy)
@@ -281,11 +281,11 @@ struct lang_hooks
      was in fact supplied.  For -f and -W switches, VALUE is 1 or 0
      for the positive and negative forms respectively.
 
      Return 1 if the switch is valid, 0 if invalid, and -1 if it's
      valid and should not be treated as language-independent too.  */
-  int (*handle_option) (size_t code, const char *arg, int value);
+  int (*handle_option) (size_t code, const char *arg, int value, int kind);
 
   /* Return false to use the default complaint about a missing
      argument, otherwise output a complaint and return true.  */
   bool (*missing_argument) (const char *opt, size_t code);
 
Index: gcc/c.opt
===================================================================
--- gcc/c.opt	(revision 158909)
+++ gcc/c.opt	(working copy)
@@ -261,18 +261,19 @@ Warn whenever type qualifiers are ignore
 Winit-self
 C ObjC C++ ObjC++ Var(warn_init_self) Warning
 Warn about variables which are initialized to themselves
 
 Wimplicit
-C ObjC C++ ObjC++ Warning
+C ObjC C++ ObjC++ Var(warn_implicit) Init(-1) Warning
+Warn about implicit declarations
 
 Wimplicit-function-declaration
 C ObjC Var(warn_implicit_function_declaration) Init(-1) Warning
 Warn about implicit function declarations
 
 Wimplicit-int
-C ObjC Var(warn_implicit_int) Warning
+C ObjC Var(warn_implicit_int) Init(-1) Warning
 Warn when a declaration does not specify a type
 
 Wimport
 C ObjC C++ ObjC++ Undocumented
 
Index: gcc/c-opts.c
===================================================================
--- gcc/c-opts.c	(revision 158909)
+++ gcc/c-opts.c	(working copy)
@@ -104,11 +104,10 @@ static bool warn_variadic_macros = true;
 static size_t deferred_count;
 
 /* Number of deferred options scanned for -include.  */
 static size_t include_cursor;
 
-static void set_Wimplicit (int);
 static void handle_OPT_d (const char *);
 static void set_std_cxx98 (int);
 static void set_std_cxx0x (int);
 static void set_std_c89 (int, int);
 static void set_std_c99 (int);
@@ -133,10 +132,13 @@ static struct deferred_opt
 {
   enum opt_code code;
   const char *arg;
 } *deferred_opts;
 
+
+static const unsigned int lang_mask = (CL_C | CL_CXX | CL_ObjC | CL_ObjCXX);
+
 /* Complain that switch CODE expects an argument but none was
    provided.  OPT was the command-line option.  Return FALSE to get
    the default message in opts.c, TRUE if we provide a specialized
    one.  */
 bool
@@ -347,11 +349,12 @@ c_common_init_options (unsigned int argc
 /* Handle switch SCODE with argument ARG.  VALUE is true, unless no-
    form of an -f or -W option was given.  Returns 0 if the switch was
    invalid, a negative number to prevent language-independent
    processing in toplev.c (a hack necessary for the short-term).  */
 int
-c_common_handle_option (size_t scode, const char *arg, int value)
+c_common_handle_option (size_t scode, const char *arg, int value,
+			int kind)
 {
   const struct cl_option *option = &cl_options[scode];
   enum opt_code code = (enum opt_code) scode;
   int result = 1;
 
@@ -360,11 +363,11 @@ c_common_handle_option (size_t scode, co
   bool preprocessing_asm_p = (cpp_get_options (parse_in)->lang == CLK_ASM);
 
   switch (code)
     {
     default:
-      if (cl_options[code].flags & (CL_C | CL_CXX | CL_ObjC | CL_ObjCXX))
+      if (cl_options[code].flags & lang_mask)
 	{
 	  if ((option->flags & CL_TARGET)
 	      && ! targetcm.handle_c_option (scode, arg, value))
 	    result = 0;
 	  break;
@@ -469,11 +472,11 @@ c_common_handle_option (size_t scode, co
       break;
 
     case OPT_Wall:
       warn_unused = value;
       set_Wformat (value);
-      set_Wimplicit (value);
+      process_option (OPT_Wimplicit, value, NULL, lang_mask, kind);
       warn_char_subscripts = value;
       warn_missing_braces = value;
       warn_parentheses = value;
       warn_return_type = value;
       warn_sequence_point = value;	/* Was C only.  */
@@ -567,11 +570,15 @@ c_common_handle_option (size_t scode, co
     case OPT_Wformat_:
       set_Wformat (atoi (arg));
       break;
 
     case OPT_Wimplicit:
-      set_Wimplicit (value);
+      gcc_assert (value == 0 || value == 1);
+      if (warn_implicit_int == -1)
+	process_option (OPT_Wimplicit_int, value, NULL, lang_mask, kind);
+      if (warn_implicit_function_declaration == -1)
+	process_option (OPT_Wimplicit_function_declaration, value, NULL, lang_mask, kind);
       break;
 
     case OPT_Wimport:
       /* Silently ignore for now.  */
       break;
@@ -1244,10 +1251,16 @@ c_common_post_options (const char **pfil
 	       "-Wformat-contains-nul ignored without -Wformat");
       warning (OPT_Wformat_security,
 	       "-Wformat-security ignored without -Wformat");
     }
 
+  if (warn_implicit == -1) 
+    warn_implicit = 0;
+      
+  if (warn_implicit_int == -1)
+    warn_implicit_int = 0;
+
   /* -Wimplicit-function-declaration is enabled by default for C99.  */
   if (warn_implicit_function_declaration == -1)
     warn_implicit_function_declaration = flag_isoc99;
 
   /* If we're allowing C++0x constructs, don't warn about C++0x
@@ -1764,19 +1777,10 @@ set_std_cxx0x (int iso)
   flag_no_nonansi_builtin = iso;
   flag_iso = iso;
   cxx_dialect = cxx0x;
 }
 
-/* Handle setting implicit to ON.  */
-static void
-set_Wimplicit (int on)
-{
-  warn_implicit = on;
-  warn_implicit_int = on;
-  warn_implicit_function_declaration = on;
-}
-
 /* Args to -d specify what to dump.  Silently ignore
    unrecognized options; they may be aimed at toplev.c.  */
 static void
 handle_OPT_d (const char *arg)
 {
Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c	(revision 158909)
+++ gcc/c-common.c	(working copy)
@@ -426,14 +426,10 @@ int flag_threadsafe_statics = 1;
 /* Nonzero if we want to pretty-print template specializations as the
    template signature followed by the arguments.  */
 
 int flag_pretty_templates = 1;
 
-/* Nonzero means warn about implicit declarations.  */
-
-int warn_implicit = 1;
-
 /* Maximum template instantiation depth.  This limit exists to limit the
    time it takes to notice infinite template instantiations; the default
    value of 1024 is likely to be in the next C++ standard.  */
 
 int max_tinst_depth = 1024;
Index: gcc/c-common.h
===================================================================
--- gcc/c-common.h	(revision 158909)
+++ gcc/c-common.h	(working copy)
@@ -748,14 +748,10 @@ extern int flag_threadsafe_statics;
 /* Nonzero if we want to pretty-print template specializations as the
    template signature followed by the arguments.  */
 
 extern int flag_pretty_templates;
 
-/* Nonzero means warn about implicit declarations.  */
-
-extern int warn_implicit;
-
 /* Warn about using __null (as NULL in C++) as sentinel.  For code compiled
    with GCC this doesn't matter as __null is guaranteed to have the right
    size.  */
 
 extern int warn_strict_null_sentinel;
@@ -825,11 +821,11 @@ extern bool check_builtin_function_argum
 extern void check_function_format (tree, int, tree *);
 extern void set_Wformat (int);
 extern tree handle_format_attribute (tree *, tree, tree, int, bool *);
 extern tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
 extern bool attribute_takes_identifier_p (tree);
-extern int c_common_handle_option (size_t code, const char *arg, int value);
+extern int c_common_handle_option (size_t code, const char *arg, int value, int kind);
 extern bool c_common_missing_argument (const char *opt, size_t code);
 extern tree c_common_type_for_mode (enum machine_mode, int);
 extern tree c_common_type_for_size (unsigned int, int);
 extern tree c_common_fixed_point_type_for_size (unsigned int, unsigned int,
 						int, int);
Index: gcc/lto-opts.c
===================================================================
--- gcc/lto-opts.c	(revision 158909)
+++ gcc/lto-opts.c	(working copy)
@@ -381,11 +381,11 @@ lto_reissue_options (void)
   for (i = 0; VEC_iterate (opt_t, opts, i, o); i++)
     {
       const struct cl_option *option = &cl_options[o->code];
 
       if (option->flag_var)
-	set_option (option, o->value, o->arg);
+	set_option (o->code, o->value, o->arg, 0 /*DK_UNSPECIFIED*/);
 
       if (o->type == CL_TARGET)
 	targetm.handle_option (o->code, o->arg, o->value);
       else if (o->type == CL_COMMON)
 	gcc_assert (option->flag_var);

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