On 01/17/2016 07:09 AM, David Malcolm wrote:
Our code for handling the "_Pragma" builtin macro is implemented in
libcpp/directives.c:destringize_and_run.
It handles _Pragma by creating a one-line buffer containing the _Pragma
content, then sending it to do_pragma, which tokenizes it and handles
the input as if it were spelled as #pragma.
Unfortunately the tokens it generates have bogus location values; the
values are in the current highest ordinary map at the time of expansion,
and this determines the effective location of the synthesized #pragma.
Hence for PR preprocessor/69126:
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
#pragma GCC diagnostic push
#define MACRO \
_Pragma("GCC diagnostic ignored \"-Wunused-variable\"") \
int x;
int g()
{
MACRO;
return 0;
}
#pragma GCC diagnostic pop
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
although -save-temps looks sane:
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
#pragma GCC diagnostic push
int g()
{
# 19 "../../src/gcc/testsuite/c-c++-common/pr69126.c"
#pragma GCC diagnostic ignored "-Wunused-variable"
# 19 "../../src/gcc/testsuite/c-c++-common/pr69126.c"
int x;;
return 0;
}
#pragma GCC diagnostic pop
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
the "ignored" directive is treated as if it occured in this
bogus location:
(gdb) call inform (226930, "pre, the location of the ignore")
/tmp/test.cc:17:24: note: pre, the location of the ignore
MACRO;
^
which is effectively *after* the
int x;;
line.
I believe this is a long-standing bug, but the cleanup of the
C++ FE's impl of -Wunused-variable in r226234 (to avoid using
%q+D) has exposed this as a regression (since the -Wunused-variable
warning is now emitted for this location:
int x;
^
rather than at input_location:
return 0;
^
and hence isn't suppressed by the _Pragma.
The function destringize_and_run is full of comments like
/* Ugh; an awful kludge. We are really not set up to be lexing
and:
/* ??? Antique Disgusting Hack. What does this do? */
and similar "???" lines.
I believe it predates macro maps (I believe they were added in
r180081 on 2011-10-15); as far as I can tell, the code is set
up for *line* maps, i.e. it may even predate column information
(it gets the line right, but not the column).
To minimize the change to destringize_and_run at this stage, the
following patch papers over the problem by fixing up the locations
for the tokens synthesized for _Pragma, setting them all to be at the
expansion point of the _Pragma directive, rather than some columns
after it.
This fixes the location of the synthesized #pragma and hence
fixes the regression seen in the PR. The -save-temps output (which
was already correct) is unaffected.
Successfully bootstrapped®rtested on x86_64-pc-linux-gnu;
adds 3 PASS results to g++.sum and 1 to gcc.sum
(although the regression currently only affects C++, I put the new
test case into c-c++-common for good measure).
OK for trunk in stage 3?
gcc/testsuite/ChangeLog:
PR preprocessor/69126
* c-c++-common/pr69126.c: New test case.
libcpp/ChangeLog:
PR preprocessor/69126
* directives.c (destringize_and_run): Add expansion_loc param; use
it when handling unexpanded pragmas to fixup the locations of the
synthesized tokens.
(_cpp_do__Pragma): Add expansion_loc param and use it when calling
destringize_and_run.
* internal.h (_cpp_do__Pragma): Add expansion_loc param.
* macro.c (builtin_macro): Pass expansion location of _Pragma to
_cpp_do__Pragma.
It's a hack, but OK.
This would be precisely the kind of thing that ideally we'd cover the
existing behaviour with unit tests before trying to clean up the layers
of hackery in this code.
jeff