This changes from: pragma-diag-3.c:2:9: warning: missing [error|warning|ignored] after ‘#pragma GCC diagnostic’ [-Wpragmas] #pragma GCC diagnostic /* { dg-warning "24:missing" "missing" { xfail *-*-* } } */ ^ pragma-diag-3.c:4:9: warning: expected [error|warning|ignored|push|pop] after ‘#pragma GCC diagnostic’ [-Wpragmas] #pragma GCC diagnostic warn /* { dg-warning "24:expected" } */ ^ pragma-diag-3.c:6:9: warning: unknown option after ‘#pragma GCC diagnostic’ kind [-Wpragmas] #pragma GCC diagnostic ignored "-Wfoo" /* { dg-warning "32:unknown" } */ ^
to: pragma-diag-3.c:2:83: warning: missing [error|warning|ignored|push|pop] after ‘#pragma GCC diagnostic’ [-Wpragmas] pragma-diag-3.c:4:24: warning: expected [error|warning|ignored|push|pop] after ‘#pragma GCC diagnostic’ [-Wpragmas] #pragma GCC diagnostic warn /* { dg-warning "24:expected" } */ ^ pragma-diag-3.c:6:32: warning: unknown option after ‘#pragma GCC diagnostic’ kind [-Wpragmas] #pragma GCC diagnostic ignored "-Wfoo" /* { dg-warning "32:unknown" } */ ^ which is a clear improvement except for the fact that CPP_PRAGMA_EOL tokens do not have a valid location. I think this is a bug and will open a PR. Of course, this opens the door to giving better locations for all diagnostics in c-pragma.c, but I'll leave that for the future. Bootstrapped and regression tested on x86_64-linux-gnu. OK? gcc/cp/ChangeLog: 2015-05-25 Manuel López-Ibáñez <m...@gcc.gnu.org> * parser.c (pragma_lex): Add loc argument. Rearrange the code to make it more similar to the C version. gcc/c-family/ChangeLog: 2015-05-25 Manuel López-Ibáñez <m...@gcc.gnu.org> * c-pragma.c (handle_pragma_diagnostic): Use explicit location when warning. * c-pragma.h (pragma_lex): Add optional loc argument. gcc/c/ChangeLog: 2015-05-25 Manuel López-Ibáñez <m...@gcc.gnu.org> * c-parser.c (pragma_lex): Add loc argument. gcc/testsuite/ChangeLog: 2015-05-25 Manuel López-Ibáñez <m...@gcc.gnu.org> * gcc.dg/pragma-diag-3.c: New test.
Index: gcc/c-family/c-pragma.c =================================================================== --- gcc/c-family/c-pragma.c (revision 223596) +++ gcc/c-family/c-pragma.c (working copy) @@ -725,14 +725,20 @@ handle_pragma_diagnostic(cpp_reader *ARG unsigned int option_index; enum cpp_ttype token; diagnostic_t kind; tree x; struct cl_option_handlers handlers; + location_t loc; - token = pragma_lex (&x); + token = pragma_lex (&x, &loc); if (token != CPP_NAME) - GCC_BAD ("missing [error|warning|ignored] after %<#pragma GCC diagnostic%>"); + { + warning_at (loc, OPT_Wpragmas, + "missing [error|warning|ignored|push|pop] after %<#pragma GCC diagnostic%>"); + return; + } + kind_string = IDENTIFIER_POINTER (x); if (strcmp (kind_string, "error") == 0) kind = DK_ERROR; else if (strcmp (kind_string, "warning") == 0) kind = DK_WARNING; @@ -747,15 +753,23 @@ handle_pragma_diagnostic(cpp_reader *ARG { diagnostic_pop_diagnostics (global_dc, input_location); return; } else - GCC_BAD ("expected [error|warning|ignored|push|pop] after %<#pragma GCC diagnostic%>"); + { + warning_at (loc, OPT_Wpragmas, + "expected [error|warning|ignored|push|pop] after %<#pragma GCC diagnostic%>"); + return; + } - token = pragma_lex (&x); + token = pragma_lex (&x, &loc); if (token != CPP_STRING) - GCC_BAD ("missing option after %<#pragma GCC diagnostic%> kind"); + { + warning_at (loc, OPT_Wpragmas, + "missing option after %<#pragma GCC diagnostic%> kind"); + return; + } option_string = TREE_STRING_POINTER (x); set_default_handlers (&handlers); for (option_index = 0; option_index < cl_options_count; option_index++) if (strcmp (cl_options[option_index].opt_text, option_string) == 0) { @@ -763,11 +777,12 @@ handle_pragma_diagnostic(cpp_reader *ARG input_location, c_family_lang_mask, &handlers, &global_options, &global_options_set, global_dc); return; } - GCC_BAD ("unknown option after %<#pragma GCC diagnostic%> kind"); + warning_at (loc, OPT_Wpragmas, + "unknown option after %<#pragma GCC diagnostic%> kind"); } /* Parse #pragma GCC target (xxx) to set target specific options. */ static void handle_pragma_target(cpp_reader *ARG_UNUSED(dummy)) Index: gcc/c-family/c-pragma.h =================================================================== --- gcc/c-family/c-pragma.h (revision 223596) +++ gcc/c-family/c-pragma.h (working copy) @@ -211,11 +211,11 @@ extern void c_invoke_pragma_handler (uns extern void maybe_apply_pragma_weak (tree); extern void maybe_apply_pending_pragma_weaks (void); extern tree maybe_apply_renaming_pragma (tree, tree); extern void add_to_renaming_pragma_list (tree, tree); -extern enum cpp_ttype pragma_lex (tree *); +extern enum cpp_ttype pragma_lex (tree *, location_t *loc = NULL); /* Flags for use with c_lex_with_flags. The values here were picked so that 0 means to translate and join strings. */ #define C_LEX_STRING_NO_TRANSLATE 1 /* Do not lex strings into execution character set. */ Index: gcc/c/c-parser.c =================================================================== --- gcc/c/c-parser.c (revision 223596) +++ gcc/c/c-parser.c (working copy) @@ -9835,16 +9835,19 @@ c_parser_pragma (c_parser *parser, enum } /* The interface the pragma parsers have to the lexer. */ enum cpp_ttype -pragma_lex (tree *value) +pragma_lex (tree *value, location_t *loc) { c_token *tok = c_parser_peek_token (the_parser); enum cpp_ttype ret = tok->type; *value = tok->value; + if (loc) + *loc = tok->location; + if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF) ret = CPP_EOF; else { if (ret == CPP_KEYWORD) Index: gcc/testsuite/gcc.dg/pragma-diag-3.c =================================================================== --- gcc/testsuite/gcc.dg/pragma-diag-3.c (revision 0) +++ gcc/testsuite/gcc.dg/pragma-diag-3.c (revision 0) @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +#pragma GCC diagnostic /* { dg-warning "24:missing" "missing" { xfail *-*-* } } */ + +#pragma GCC diagnostic warn /* { dg-warning "24:expected" } */ + +#pragma GCC diagnostic ignored "-Wfoo" /* { dg-warning "32:unknown" } */ Index: gcc/cp/parser.c =================================================================== --- gcc/cp/parser.c (revision 223596) +++ gcc/cp/parser.c (working copy) @@ -33175,29 +33175,28 @@ cp_parser_pragma (cp_parser *parser, enu } /* The interface the pragma parsers have to the lexer. */ enum cpp_ttype -pragma_lex (tree *value) +pragma_lex (tree *value, location_t *loc) { - cp_token *tok; - enum cpp_ttype ret; + cp_token *tok = cp_lexer_peek_token (the_parser->lexer); + enum cpp_ttype ret = tok->type; - tok = cp_lexer_peek_token (the_parser->lexer); - - ret = tok->type; *value = tok->u.value; + if (loc) + *loc = tok->location; if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF) ret = CPP_EOF; else if (ret == CPP_STRING) *value = cp_parser_string_literal (the_parser, false, false); else { - cp_lexer_consume_token (the_parser->lexer); if (ret == CPP_KEYWORD) ret = CPP_NAME; + cp_lexer_consume_token (the_parser->lexer); } return ret; }