[c-family/49654/49655] reject invalid options in pragma diagnostic
diff mbox

Message ID CAESRpQA4dqsofvikBJuHKNFBQR1PkZMc0434gE8yqSiK5-r6Ag@mail.gmail.com
State New
Headers show

Commit Message

Manuel López-Ibáñez Sept. 22, 2015, 6:08 p.m. UTC
Use find_opt instead of linear search through options in
handle_pragma_diagnostic (PR 49654) and reject non-warning options and
options not valid for the current language (PR 49655).

Boot&tested on x86_64-linux-gnu.

OK?

gcc/testsuite/ChangeLog:

2015-09-22  Manuel López-Ibáñez  <manu@gcc.gnu.org>

    PR c/49655
    * gcc.dg/pragma-diag-6.c: New test.

gcc/ChangeLog:

2015-09-22  Manuel López-Ibáñez  <manu@gcc.gnu.org>

    PR c/49655
    * opts.h (write_langs): Declare.
    * opts-global.c (write_langs): Make it extern.

gcc/c-family/ChangeLog:

2015-09-22  Manuel López-Ibáñez  <manu@gcc.gnu.org>

    PR c/49654
    PR c/49655
    * c-pragma.c (handle_pragma_diagnostic): Detect non-warning
    options and options not valid for the current language.

Comments

Bernd Schmidt Sept. 23, 2015, 11:19 a.m. UTC | #1
On 09/22/2015 08:08 PM, Manuel López-Ibáñez wrote:
> Use find_opt instead of linear search through options in
> handle_pragma_diagnostic (PR 49654) and reject non-warning options and
> options not valid for the current language (PR 49655).

> +  /* option_string + 1 to skip the initial '-' */
> +  unsigned int lang_mask = c_common_option_lang_mask () | CL_COMMON;
> +  unsigned int option_index = find_opt (option_string + 1, lang_mask);

Swap the first two lines to have the comment in the right spot.

> +  else if (!(cl_options[option_index].flags & lang_mask))
> +    {
> +      char * ok_langs = write_langs (cl_options[option_index].flags);
> +      char * bad_lang = write_langs (c_common_option_lang_mask ());
> +      warning_at (loc, OPT_Wpragmas,
> +		  "option %qs is valid for %s but not for %s",
> +		  option_string, ok_langs, bad_lang);
> +      free (ok_langs);
> +      free (bad_lang);
> +      return;
> +    }

Slightly surprising, but I checked and find_opt is documented to return 
an option for a different front end if it can't find a valid one 
matching lang_mask.

Patch is ok.


Bernd
Marek Polacek Sept. 23, 2015, 11:31 a.m. UTC | #2
On Tue, Sep 22, 2015 at 08:08:28PM +0200, Manuel López-Ibáñez wrote:
> +  else if (!(cl_options[option_index].flags & lang_mask))
> +    {
> +      char * ok_langs = write_langs (cl_options[option_index].flags);
> +      char * bad_lang = write_langs (c_common_option_lang_mask ());

Please remove the spaces after * when you commit the patch.

Thanks,

	Marek

Patch
diff mbox

Index: gcc/c-family/c-pragma.c
===================================================================
--- gcc/c-family/c-pragma.c	(revision 227965)
+++ gcc/c-family/c-pragma.c	(working copy)
@@ -747,26 +747,44 @@  handle_pragma_diagnostic(cpp_reader *ARG
       warning_at (loc, OPT_Wpragmas,
 		  "missing option after %<#pragma GCC diagnostic%> kind");
       return;
     }
 
+  const char *option_string = TREE_STRING_POINTER (x);
+  /* option_string + 1 to skip the initial '-' */
+  unsigned int lang_mask = c_common_option_lang_mask () | CL_COMMON;
+  unsigned int option_index = find_opt (option_string + 1, lang_mask);
+  if (option_index == OPT_SPECIAL_unknown)
+    {
+      warning_at (loc, OPT_Wpragmas,
+		  "unknown option after %<#pragma GCC diagnostic%> kind");
+      return;
+    }
+  else if (!(cl_options[option_index].flags & CL_WARNING))
+    {
+      warning_at (loc, OPT_Wpragmas,
+		  "%qs is not an option that controls warnings", option_string);
+      return;
+    }
+  else if (!(cl_options[option_index].flags & lang_mask))
+    {
+      char * ok_langs = write_langs (cl_options[option_index].flags);
+      char * bad_lang = write_langs (c_common_option_lang_mask ());
+      warning_at (loc, OPT_Wpragmas,
+		  "option %qs is valid for %s but not for %s",
+		  option_string, ok_langs, bad_lang);
+      free (ok_langs);
+      free (bad_lang);
+      return;
+    }
+
   struct cl_option_handlers handlers;
   set_default_handlers (&handlers);
-
-  unsigned int option_index;
-  const char *option_string = TREE_STRING_POINTER (x);
-  for (option_index = 0; option_index < cl_options_count; option_index++)
-    if (strcmp (cl_options[option_index].opt_text, option_string) == 0)
-      {
-	control_warning_option (option_index, (int) kind, kind != DK_IGNORED,
-				input_location, c_family_lang_mask, &handlers,
-				&global_options, &global_options_set,
-				global_dc);
-	return;
-      }
-  warning_at (loc, OPT_Wpragmas,
-	      "unknown option after %<#pragma GCC diagnostic%> kind");
+  control_warning_option (option_index, (int) kind, kind != DK_IGNORED,
+			  loc, lang_mask, &handlers,
+			  &global_options, &global_options_set,
+			  global_dc);
 }
 
 /*  Parse #pragma GCC target (xxx) to set target specific options.  */
 static void
 handle_pragma_target(cpp_reader *ARG_UNUSED(dummy))
Index: gcc/testsuite/gcc.dg/pragma-diag-6.c
===================================================================
--- gcc/testsuite/gcc.dg/pragma-diag-6.c	(revision 0)
+++ gcc/testsuite/gcc.dg/pragma-diag-6.c	(revision 0)
@@ -0,0 +1,5 @@ 
+/* { dg-do compile } */
+#pragma GCC diagnostic error "-Wnoexcept" /* { dg-warning "is valid for C../ObjC.. but not for C" } */
+#pragma GCC diagnostic error "-fstrict-aliasing" /* { dg-warning "not an option that controls warnings" } */
+#pragma GCC diagnostic error "-Werror" /* { dg-warning "not an option that controls warnings" } */
+int i;
Index: gcc/opts.h
===================================================================
--- gcc/opts.h	(revision 227965)
+++ gcc/opts.h	(working copy)
@@ -366,10 +366,11 @@  extern void control_warning_option (unsi
 				    unsigned int lang_mask,
 				    const struct cl_option_handlers *handlers,
 				    struct gcc_options *opts,
 				    struct gcc_options *opts_set,
 				    diagnostic_context *dc);
+extern char *write_langs (unsigned int mask);
 extern void print_ignored_options (void);
 extern void handle_common_deferred_options (void);
 extern bool common_handle_option (struct gcc_options *opts,
 				  struct gcc_options *opts_set,
 				  const struct cl_decoded_option *decoded,
Index: gcc/opts-global.c
===================================================================
--- gcc/opts-global.c	(revision 227965)
+++ gcc/opts-global.c	(working copy)
@@ -52,11 +52,11 @@  static vec<const_char_p> ignored_options
 const char **in_fnames;
 unsigned num_in_fnames;
 
 /* Return a malloced slash-separated list of languages in MASK.  */
 
-static char *
+char *
 write_langs (unsigned int mask)
 {
   unsigned int n = 0, len = 0;
   const char *lang_name;
   char *result;