From c1822f9c9b169c9588a110522dd60d579edaf6d1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Manuel=20L=C3=B3pez-Ib=C3=A1=C3=B1ez?= Date: Wed, 23 Sep 2015 13:07:07 +0000 Subject: [PATCH] [c-family/49654/49655] reject invalid options in pragma diagnostic MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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). gcc/testsuite/ChangeLog: 2015-09-23 Manuel López-Ibáñez PR c/49655 * gcc.dg/pragma-diag-6.c: New test. gcc/ChangeLog: 2015-09-23 Manuel López-Ibáñez PR c/49655 * opts.h (write_langs): Declare. * opts-global.c (write_langs): Make it extern. gcc/c-family/ChangeLog: 2015-09-23 Manuel López-Ibáñez PR c/49654 PR c/49655 * c-pragma.c (handle_pragma_diagnostic): Detect non-warning options and options not valid for the current language. From-SVN: r228049 --- gcc/ChangeLog | 6 ++++ gcc/c-family/ChangeLog | 7 +++++ gcc/c-family/c-pragma.c | 46 +++++++++++++++++++--------- gcc/opts-global.c | 2 +- gcc/opts.h | 1 + gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gcc.dg/pragma-diag-6.c | 5 +++ 7 files changed, 57 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pragma-diag-6.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2ec3abeb601..eba5f94c573 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2015-09-23 Manuel López-Ibáñez + + PR c/49655 + * opts.h (write_langs): Declare. + * opts-global.c (write_langs): Make it extern. + 2015-09-23 Oleg Endo PR target/67391 diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index e887735f58b..8d4df7654b7 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,10 @@ +2015-09-23 Manuel López-Ibáñez + + PR c/49654 + PR c/49655 + * c-pragma.c (handle_pragma_diagnostic): Detect non-warning + options and options not valid for the current language. + 2015-09-22 Patrick Palka * c-indentation.c (should_warn_for_misleading_indentation): diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c index de2304e788e..3c348009cea 100644 --- a/gcc/c-family/c-pragma.c +++ b/gcc/c-family/c-pragma.c @@ -749,22 +749,40 @@ handle_pragma_diagnostic(cpp_reader *ARG_UNUSED(dummy)) return; } + const char *option_string = TREE_STRING_POINTER (x); + unsigned int lang_mask = c_common_option_lang_mask () | CL_COMMON; + /* option_string + 1 to skip the initial '-' */ + 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. */ diff --git a/gcc/opts-global.c b/gcc/opts-global.c index 9f5050b1cab..05e2e37aed6 100644 --- a/gcc/opts-global.c +++ b/gcc/opts-global.c @@ -54,7 +54,7 @@ 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; diff --git a/gcc/opts.h b/gcc/opts.h index 3cfd151fb62..38b38370fb5 100644 --- a/gcc/opts.h +++ b/gcc/opts.h @@ -368,6 +368,7 @@ extern void control_warning_option (unsigned int opt_index, int kind, 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, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3e722c2c89c..46d4f053130 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-09-23 Manuel López-Ibáñez + + PR c/49655 + * gcc.dg/pragma-diag-6.c: New test. + 2015-09-23 James Greenhalgh * gcc.target/aarch64/advsimd-intrinsics/vcvt_high_1.c: New. diff --git a/gcc/testsuite/gcc.dg/pragma-diag-6.c b/gcc/testsuite/gcc.dg/pragma-diag-6.c new file mode 100644 index 00000000000..6ce76d9e49b --- /dev/null +++ b/gcc/testsuite/gcc.dg/pragma-diag-6.c @@ -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; -- 2.30.2