Skip to content

Commit d538348

Browse files
Lewis HyattLewis Hyatt
authored andcommitted
libcpp: Improve locations for macros defined prior to PCH include [PR105608]
It is permissible to define macros prior to including a PCH, as long as these definitions are disjoint from or identical to the macros in the PCH. The PCH loading process replaces all libcpp data structures with those from the PCH, so it is necessary to remember the extra macros separately and then restore them after loading the PCH, which all is handled by cpp_save_state() and cpp_read_state() in libcpp/pch.cc. The restoration process consists of pushing a buffer containing the macro definition and then lexing it from there, similar to how a command-line -D option is processed. The current implementation does not attempt to set up the line_map for this process, and so the locations assigned to the macros are often not meaningful. (Similar to what happened in the past with lexing the tokens out of a _Pragma string, lexing out of a buffer rather than a file produces "sorta" reasonable locations that are often close enough, but not reliably correct.) Fix that up by remembering enough additional information (more or less, an expanded_location for each macro definition) to produce a reasonable location for the newly restored macros. One issue that came up is the treatment of command-line-defined macros. From the perspective of the generic line_map data structures, the command-line location is not distinguishable from other locations; it's just an ordinary location created by the front ends with a fake file name by convention. (At the moment, it is always the string `<command-line>', subject to translation.) Since libcpp needs to assign macros to that location, it needs to know what location to use, so I added a new member line_maps::cmdline_location for the front ends to set, similar to how line_maps::builtin_location is handled. This revealed a small issue, in c-opts.cc we have: /* All command line defines must have the same location. */ cpp_force_token_locations (parse_in, line_table->highest_line); But contrary to the comment, all command line defines don't actually end up with the same location anymore. This is because libcpp/lex.cc has been expanded (r6-4873) to include range information on the returned locations. That logic has never been respecting the request of cpp_force_token_locations. I believe this was not intentional, and so I have corrected that here. Prior to this patch, the range logic has been leading to command-line macros all having similar locations in the same line map (or ad-hoc locations based from there for sufficiently long tokens); with this change, they all have exactly the same location and that location is recorded in line_maps::cmdline_location. With that change, then it works fine for pch.cc to restore macros whether they came from the command-line or from the main file. gcc/c-family/ChangeLog: PR preprocessor/105608 * c-opts.cc (c_finish_options): Set new member line_table->cmdline_location. * c-pch.cc (c_common_read_pch): Adapt linemap usage to changes in libcpp pch.cc; it is now possible that the linemap is in a different file after returning from cpp_read_state(). libcpp/ChangeLog: PR preprocessor/105608 * include/line-map.h: Add new member CMDLINE_LOCATION. * lex.cc (get_location_for_byte_range_in_cur_line): Do not expand the token location to include range information if token location override was requested. (warn_about_normalization): Likewise. (_cpp_lex_direct): Likewise. * pch.cc (struct saved_macro): New local struct. (struct save_macro_data): Change DEFNS vector to hold saved_macro rather than uchar*. (save_macros): Adapt to remember the location information for each saved macro in addition to the definition. (cpp_prepare_state): Likewise. (cpp_read_state): Use the saved location information to generate proper locations for the restored macros. gcc/testsuite/ChangeLog: PR preprocessor/105608 * g++.dg/pch/line-map-3.C: Remove xfails. * g++.dg/pch/line-map-4.C: New test. * g++.dg/pch/line-map-4.Hs: New test.
1 parent f8881d5 commit d538348

File tree

8 files changed

+132
-50
lines changed

8 files changed

+132
-50
lines changed

gcc/c-family/c-opts.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1700,6 +1700,7 @@ c_finish_options (void)
17001700
bool cxx_assert_seen_p = false;
17011701

17021702
/* All command line defines must have the same location. */
1703+
line_table->cmdline_location = line_table->highest_line;
17031704
cpp_force_token_locations (parse_in, line_table->highest_line);
17041705
for (size_t i = 0; i < deferred_count; i++)
17051706
{

gcc/c-family/c-pch.cc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -347,18 +347,18 @@ c_common_read_pch (cpp_reader *pfile, const char *name,
347347
rebuild_location_adhoc_htab (line_table);
348348
line_table->trace_includes = saved_trace_includes;
349349

350-
/* Set the current location to the line containing the #include (or the
351-
#pragma GCC pch_preprocess) for the purpose of assigning locations to any
352-
macros that are about to be restored. */
353-
linemap_add (line_table, LC_ENTER, 0, saved_loc.file,
354-
saved_loc.line > 1 ? saved_loc.line - 1 : saved_loc.line);
350+
/* Set the line_map current location to the start of the file, so that things
351+
remain in order after cpp_read_state() re-adds any macros that were defined
352+
prior to calling gt_pch_restore(). */
353+
linemap_add (line_table, LC_ENTER, saved_loc.sysp, saved_loc.file, 0);
355354

356355
timevar_push (TV_PCH_CPP_RESTORE);
357356
cpp_result = cpp_read_state (pfile, name, f, smd);
358357

359358
/* Set the current location to the line following the #include, where we
360359
were prior to processing the PCH. */
361-
linemap_line_start (line_table, saved_loc.line, 0);
360+
linemap_add (line_table, LC_RENAME, saved_loc.sysp, saved_loc.file,
361+
saved_loc.line);
362362

363363
timevar_pop (TV_PCH_CPP_RESTORE);
364364

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,5 @@
1-
#define UNUSED_MACRO /* { dg-error "UNUSED_MACRO" "" { xfail *-*-* } } */
2-
#include "line-map-3.H" /* { dg-bogus "-:UNUSED_MACRO" "" { xfail *-*-* } } */
3-
4-
/* { dg-do compile } */
5-
/* { dg-additional-options "-Werror=unused-macros" } */
6-
71
/* PR preprocessor/105608 */
8-
/* This test case is currently xfailed and requires work in libcpp/pch.cc to
9-
resolve. Currently, the macro location is incorrectly assigned to line 2
10-
of the header file when read via PCH, because libcpp doesn't try to
11-
assign locations relative to the newly loaded line map after restoring
12-
the PCH. */
13-
14-
/* In PCH mode we also complain incorrectly about the command line macro -Dwith_PCH
15-
added by dejagnu; that warning would get suppressed if the macro location were
16-
correctly restored by libcpp to reflect that it was a command line macro. */
17-
/* { dg-bogus "-:with_PCH" "" { xfail *-*-* } 2 } */
18-
19-
/* The reason we used -Werror was to prevent pch.exp from rerunning without PCH;
20-
in that case we would get unnecessary XPASS outputs since the test does work
21-
fine without PCH. Once the bug is fixed, remove the -Werror and switch to
22-
dg-warning. */
23-
/* { dg-regexp {[^[:space:]]*: some warnings being treated as errors} } */
2+
/* { dg-do compile } */
3+
/* { dg-additional-options "-Wunused-macros" } */
4+
#define UNUSED_MACRO /* { dg-warning "-:UNUSED_MACRO" "" } */
5+
#include "line-map-3.H" /* { dg-bogus "-:UNUSED_MACRO" "" } */
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/* PR preprocessor/105608 */
2+
/* { dg-do compile } */
3+
#define INT int /* { dg-error "-:declaration does not declare anything" } */
4+
#include "line-map-4.H"
5+
INT; /* { dg-note "in expansion of macro" } */
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/* This space intentionally left blank. */

libcpp/include/line-map.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,12 @@ class GTY(()) line_maps {
878878
built-in tokens. */
879879
location_t builtin_location;
880880

881+
/* The special location value to be used for tokens originating on the
882+
command line. This is currently only needed by the C-family front ends
883+
for PCH support; if it would be used for another purpose in the future,
884+
then other libcpp-using front ends may need to set it as well. */
885+
location_t cmdline_location;
886+
881887
/* The default value of range_bits in ordinary line maps. */
882888
unsigned int default_range_bits;
883889

libcpp/lex.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1353,6 +1353,8 @@ get_location_for_byte_range_in_cur_line (cpp_reader *pfile,
13531353
const unsigned char *const start,
13541354
size_t num_bytes)
13551355
{
1356+
if (pfile->forced_token_location)
1357+
return pfile->forced_token_location;
13561358
gcc_checking_assert (num_bytes > 0);
13571359

13581360
/* CPP_BUF_COLUMN and linemap_position_for_column both refer
@@ -2035,6 +2037,7 @@ warn_about_normalization (cpp_reader *pfile,
20352037
/* If possible, create a location range for the token. */
20362038
if (loc >= RESERVED_LOCATION_COUNT
20372039
&& token->type != CPP_EOF
2040+
&& !pfile->forced_token_location
20382041
/* There must be no line notes to process. */
20392042
&& (!(pfile->buffer->cur
20402043
>= pfile->buffer->notes[pfile->buffer->cur_note].pos
@@ -4399,7 +4402,8 @@ _cpp_lex_direct (cpp_reader *pfile)
43994402

44004403
/* Potentially convert the location of the token to a range. */
44014404
if (result->src_loc >= RESERVED_LOCATION_COUNT
4402-
&& result->type != CPP_EOF)
4405+
&& result->type != CPP_EOF
4406+
&& !pfile->forced_token_location)
44034407
{
44044408
/* Ensure that any line notes are processed, so that we have the
44054409
correct physical line/column for the end-point of the token even

libcpp/pch.cc

Lines changed: 104 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -730,9 +730,20 @@ cpp_valid_state (cpp_reader *r, const char *name, int fd)
730730

731731
/* Save all the existing macros. */
732732

733+
namespace {
734+
735+
struct saved_macro
736+
{
737+
uchar *defn;
738+
location_t loc;
739+
expanded_location xloc;
740+
};
741+
742+
} /* unnamed namespace */
743+
733744
struct save_macro_data
734745
{
735-
uchar **defns;
746+
saved_macro *defns;
736747
size_t count;
737748
size_t array_size;
738749
char **saved_pragmas;
@@ -762,14 +773,29 @@ save_macros (cpp_reader *r, cpp_hashnode *h, void *data_p)
762773
if (data->count == data->array_size)
763774
{
764775
data->array_size *= 2;
765-
data->defns = XRESIZEVEC (uchar *, data->defns, (data->array_size));
776+
data->defns = XRESIZEVEC (saved_macro, data->defns, data->array_size);
766777
}
767778

768779
const uchar * defn = cpp_macro_definition (r, h);
769780
size_t defnlen = ustrlen (defn);
770781

771-
data->defns[data->count] = (uchar *) xmemdup (defn, defnlen, defnlen + 2);
772-
data->defns[data->count][defnlen] = '\n';
782+
const auto d = data->defns + data->count;
783+
d->defn = (uchar *) xmemdup (defn, defnlen, defnlen + 2);
784+
d->defn[defnlen] = '\n';
785+
d->loc = h->value.macro->line;
786+
d->xloc = {};
787+
if (d->loc == r->line_table->cmdline_location)
788+
{
789+
/* The cmdline_location may be different when it comes time to
790+
restore the macros, so use 0 to indicate this. */
791+
d->loc = 0;
792+
}
793+
else if (d->loc != r->line_table->builtin_location)
794+
{
795+
const auto map = linemap_lookup (r->line_table, d->loc);
796+
gcc_assert (map);
797+
d->xloc = linemap_expand_location (r->line_table, map, d->loc);
798+
}
773799
data->count++;
774800
}
775801

@@ -785,9 +811,22 @@ cpp_prepare_state (cpp_reader *r, struct save_macro_data **data)
785811
struct save_macro_data *d = XNEW (struct save_macro_data);
786812

787813
d->array_size = 512;
788-
d->defns = XNEWVEC (uchar *, d->array_size);
814+
d->defns = XNEWVEC (saved_macro, d->array_size);
789815
d->count = 0;
790816
cpp_forall_identifiers (r, save_macros, d);
817+
818+
/* Sort the saved macros in order, so the line map gets built up
819+
in chronological order as expected when we load them back in. */
820+
static line_maps *line_table;
821+
line_table = r->line_table;
822+
qsort (d->defns, d->count, sizeof (saved_macro),
823+
[] (const void *x1, const void *x2)
824+
{
825+
const auto d1 = static_cast<const saved_macro *> (x1);
826+
const auto d2 = static_cast<const saved_macro *> (x2);
827+
return linemap_compare_locations (line_table, d2->loc, d1->loc);
828+
});
829+
791830
d->saved_pragmas = _cpp_save_pragma_names (r);
792831
*data = d;
793832
}
@@ -820,16 +859,16 @@ cpp_read_state (cpp_reader *r, const char *name, FILE *f,
820859
r->state.prevent_expansion = 1;
821860
r->state.angled_headers = 0;
822861

862+
const auto old_directive_line = r->directive_line;
863+
823864
/* Run through the carefully-saved macros, insert them. */
865+
const char *cur_fname = nullptr;
824866
for (i = 0; i < data->count; i++)
825867
{
826-
cpp_hashnode *h;
827-
size_t namelen;
828-
uchar *defn;
829-
830-
namelen = ustrcspn (data->defns[i], "( \n");
831-
h = cpp_lookup (r, data->defns[i], namelen);
832-
defn = data->defns[i] + namelen;
868+
const auto d = data->defns + i;
869+
const size_t namelen = ustrcspn (d->defn, "( \n");
870+
cpp_hashnode *const h = cpp_lookup (r, d->defn, namelen);
871+
const auto defn = d->defn + namelen;
833872

834873
/* The PCH file is valid, so we know that if there is a definition
835874
from the PCH file it must be the same as the one we had
@@ -839,28 +878,72 @@ cpp_read_state (cpp_reader *r, const char *name, FILE *f,
839878
if (cpp_push_buffer (r, defn, ustrchr (defn, '\n') - defn, true)
840879
!= NULL)
841880
{
842-
_cpp_clean_line (r);
881+
if (d->loc == r->line_table->builtin_location)
882+
r->directive_line = r->line_table->builtin_location;
883+
else if (d->loc == 0)
884+
/* This was a command-line-defined macro, preserve that
885+
aspect now. */
886+
r->directive_line = r->line_table->cmdline_location;
887+
else
888+
{
889+
/* In practice, almost all of the locations ought to be in the
890+
main file, since a PCH cannot be loaded after including
891+
other headers. The (probably sole) exception is that
892+
implicit preincludes can be loaded, so if an implicit
893+
preinclude such as /usr/include/stdc-predef.h has changed
894+
since the PCH was created (in a way not invalidating the
895+
PCH), we can end up here with locations that are not in the
896+
main file. In that case, we may be adding them to the
897+
line_map out of order (the implicit preinclude already
898+
being represented in the line_map we have loaded from the
899+
PCH), but it is probably not going to cause any observable
900+
issue given the constraints on what can appear in a header
901+
before loading a PCH. */
902+
if (!cur_fname || strcmp (cur_fname, d->xloc.file))
903+
{
904+
linemap_add (r->line_table, LC_RENAME, d->xloc.sysp,
905+
d->xloc.file, d->xloc.line);
906+
cur_fname = d->xloc.file;
907+
}
908+
r->directive_line = linemap_line_start (r->line_table,
909+
d->xloc.line, 127);
910+
}
911+
912+
/* Even when the macro was defined in the main file, we have to
913+
use cpp_force_token_locations here, so all tokens in the macro
914+
will have location assigned to the directive line with no
915+
column information. We no longer know even which line the
916+
tokens appeared on originally now, much less the column, since
917+
we only stored the macro definition string after lexing it. */
918+
cpp_force_token_locations (r, r->directive_line);
843919

844-
/* ??? Using r->line_table->highest_line is not ideal here, but we
845-
do need to use some location that is relative to the new line
846-
map just loaded, not the old one that was in effect when these
847-
macros were lexed. The proper fix is to remember the file name
848-
and line number where each macro was defined, and then add
849-
these locations into the new line map. See PR105608. */
850-
if (!_cpp_create_definition (r, h, r->line_table->highest_line))
920+
_cpp_clean_line (r);
921+
if (!_cpp_create_definition (r, h, r->directive_line))
851922
abort ();
923+
cpp_stop_forcing_token_locations (r);
852924
_cpp_pop_buffer (r);
925+
926+
if (d->loc < RESERVED_LOCATION_COUNT)
927+
/* Macros defined on the command line or as builtins are always
928+
implicitly used. It is necessary to note this here or else
929+
-Wunused-macros will complain, because these locations do
930+
return TRUE for MAIN_FILE_P(). For a command line
931+
definition, d->loc was set to 0 when we saved it, so it does
932+
satisfy the check performed here. */
933+
h->value.macro->used = true;
853934
}
854935
else
855936
abort ();
856937
}
857938

858-
free (data->defns[i]);
939+
free (data->defns[i].defn);
859940
}
860941
r->state = old_state;
942+
r->directive_line = old_directive_line;
861943

862944
_cpp_restore_pragma_names (r, data->saved_pragmas);
863945

946+
XDELETEVEC (data->defns);
864947
free (data);
865948

866949
if (deps_restore (r->deps, f, CPP_OPTION (r, restore_pch_deps) ? name : NULL)

0 commit comments

Comments
 (0)