On Fri, 2017-11-17 at 12:10 +0200, Boris Kolpackov wrote: > The below patch adds the -fmacro-prefix-map option that allows > remapping > of file names in __FILE__, __BASE_FILE__, and __builtin_FILE(), > similar > to how -fdebug-prefix-map allows to do the same for debug > information. > > Additionally, the patch adds -ffile-prefix-map which can be used to > specify both mappings with a single option (and, should we need to > add more -f*-prefix-map options in the future, those as well). > > There is PR other/70268 with more details/motivation: > > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70268 > > Note that a patch has been proposed earlier by Hongxu Jia. This patch > offers a significantly different implementation though I used the > original patch as a reference to make sure I've covered all the areas > (e.g., __builtin_FILE()). > > Copyright assignment is on file.
Thanks for posting this patch. To my naive eyes this seems like a useful addition, but I'm hoping someone with more knowledge of the standards around the preprocessor can comment. Does any other compiler implement something similar? Some notes inline follow... > libcpp/ChangeLog: > > 2017-11-17 Boris Kolpackov <bo...@codesynthesis.com> > > PR other/70268 > * include/cpplib.h (cpp_callbacks::remap_filename): New > callback. > * libcpp/macro.c (_cpp_builtin_macro_text): Call remap_filename > for > __FILE__ and __BASE_FILE__. > > > gcc/ChangeLog: > > 2017-11-17 Boris Kolpackov <bo...@codesynthesis.com> > > PR other/70268 > * common.opt: (-ffile-prefix-map): New option. > * opts.c (common_handle_option): Deffer it. (spelling of "Defer") > * opts-global.c (handle_common_deferred_options): Handle it. > * debug.h (remap_debug_filename, add_debug_prefix_map): Move > to... > * file-prefix-map.h: New file. > (remap_debug_filename, add_debug_prefix_map): ...here. > (add_macro_prefix_map, add_file_prefix_map, > remap_macro_filename): New. > * final.c (debug_prefix_map, add_debug_prefix_map > remap_debug_filename): Move to... > * file-prefix-map.c: New file. IIRC, new files should have a .cc suffix. > (file_prefix_map, add_prefix_map, remap_filename) ...here and > rename, > generalize, get rid of alloca() call. > (add_macro_prefix_map, add_debug_prefix_map, > add_file_prefix_map): > Implement in terms of add_prefix_map(). > (remap_macro_filename, remap_debug_filename): Implement in term > of > remap_filename(). > * Makefile.in (OBJS, PLUGIN_HEADERS): Add new files. > * builtins.c (fold_builtin_FILE): Call > remap_macro_filename(). > * dbxout.c: Include file-prefix-map.h. Are there some spaces vs tabs issues in the ChangeLog? (it might be just my email client though). > * varasm.c: Likewise. > * vmsdbgout.c: Likewise. > * xcoffout.c: Likewise. > * dwarf2out.c: Likewise plus omit new options from > DW_AT_producer. > * doc/cppopts.texi: Document -fmacro-prefix-map. > * doc/invoke.texi: Document -ffile-prefix-map. > > > gcc/c-family/ChangeLog: > > 2017-11-17 Boris Kolpackov <bo...@codesynthesis.com> > > PR other/70268 > * c-family/c.opt (-fmacro-prefix-map): New option. > * c-family/c-opts.c (c_common_handle_option): Handle it. > * c-family/c-lex.c (init_c_lex): Set remap_filename cpp > callback. > * c-family/c-ppoutput.c (init_pp_output): Likewise. > > > gcc/testsuite/ChangeLog: > > 2017-11-17 Boris Kolpackov <bo...@codesynthesis.com> > > PR other/70268 > * c-c++-common/ffile-prefix-map.c: New test. > * c-c++-common/fmacro-prefix-map.c: New test. > * c-c++-common/cpp/ffile-prefix-map.c: New test. > * c-c++-common/cpp/fmacro-prefix-map.c: New test. > > > diff --git a/gcc/Makefile.in b/gcc/Makefile.in > index 5db78558c0c..ba09b747b02 100644 > --- a/gcc/Makefile.in > +++ b/gcc/Makefile.in > @@ -1280,6 +1280,7 @@ OBJS = \ > expmed.o \ > expr.o \ > fibonacci_heap.o \ > + file-prefix-map.o \ I believe you used spaces rather than a tab here. > final.o \ > fixed-value.o \ > fold-const.o \ > @@ -3486,8 +3487,8 @@ PLUGIN_HEADERS = $(TREE_H) $(CONFIG_H) > $(SYSTEM_H) coretypes.h $(TM_H) \ > tree-ssa-loop-niter.h tree-ssa-ter.h tree-ssa-threadedge.h \ > tree-ssa-threadupdate.h inchash.h wide-int.h signop.h hash-map.h \ > hash-set.h dominance.h cfg.h cfgrtl.h cfganal.h cfgbuild.h > cfgcleanup.h \ > - lcm.h cfgloopmanip.h builtins.def chkp-builtins.def pass- > instances.def \ > - params.list > + lcm.h cfgloopmanip.h file-prefix-map.h builtins.def chkp- > builtins.def \ > + pass-instances.def params.list > > # generate the 'build fragment' b-header-vars > s-header-vars: Makefile > diff --git a/gcc/builtins.c b/gcc/builtins.c > index 650de0d9aca..14016fe6312 100644 > --- a/gcc/builtins.c > +++ b/gcc/builtins.c > @@ -70,6 +70,7 @@ along with GCC; see the file COPYING3. If not see > #include "case-cfn-macros.h" > #include "gimple-fold.h" > #include "intl.h" > +#include "file-prefix-map.h" /* remap_macro_filename() */ > > struct target_builtins default_target_builtins; > #if SWITCHABLE_TARGET > @@ -8784,7 +8785,13 @@ static inline tree > fold_builtin_FILE (location_t loc) > { > if (const char *fname = LOCATION_FILE (loc)) > + { > + /* The documentation says this builtin is equivalent to the > preprocessor > + __FILE__ macro so it appears appropriate to use the same file > prefix > + mappings. */ > + fname = remap_macro_filename (fname); > return build_string_literal (strlen (fname) + 1, fname); > + } Formatting nit: should be: if () { body } rather than: if () { body } What "owns" the memory returned by remap_macro_filename? I see later on that this calls remap_filename, and hence the result is either ggc-allocated, or is the input pointer, and hence "fname" is temporary memory that goes away when the GC runs; build_string_literal takes a copy. (This is different from Hongxu Jia's patch attached to PR 70268, which calls xstrdup *or* returns the input pointer). > > return build_string_literal (1, ""); > } > diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c > index 8342800303a..9d61abe545d 100644 > --- a/gcc/c-family/c-lex.c > +++ b/gcc/c-family/c-lex.c > @@ -27,6 +27,7 @@ along with GCC; see the file COPYING3. If not see > #include "stor-layout.h" > #include "c-pragma.h" > #include "debug.h" > +#include "file-prefix-map.h" /* remap_macro_filename() */ > > #include "attribs.h" > > @@ -82,6 +83,7 @@ init_c_lex (void) > cb->has_attribute = c_common_has_attribute; > cb->get_source_date_epoch = cb_get_source_date_epoch; > cb->get_suggestion = cb_get_suggestion; > + cb->remap_filename = remap_macro_filename; > > /* Set the debug callbacks if we can use them. */ > if ((debug_info_level == DINFO_LEVEL_VERBOSE > diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c > index cead15e7a63..04b8c6cd40a 100644 > --- a/gcc/c-family/c-opts.c > +++ b/gcc/c-family/c-opts.c > @@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see > #include "plugin.h" /* For PLUGIN_INCLUDE_FILE > event. */ > #include "mkdeps.h" > #include "dumpfile.h" > +#include "file-prefix-map.h" /* add_*_prefix_map() */ > > #ifndef DOLLARS_IN_IDENTIFIERS > # define DOLLARS_IN_IDENTIFIERS true > @@ -448,6 +449,10 @@ c_common_handle_option (size_t scode, const char > *arg, int value, > cpp_opts->dollars_in_ident = value; > break; > > + case OPT_fmacro_prefix_map_: > + add_macro_prefix_map (arg); > + break; > + > case OPT_ffreestanding: > value = !value; > /* Fall through. */ > diff --git a/gcc/c-family/c-ppoutput.c b/gcc/c-family/c-ppoutput.c > index d1c92379f62..949a4955923 100644 > --- a/gcc/c-family/c-ppoutput.c > +++ b/gcc/c-family/c-ppoutput.c > @@ -22,6 +22,7 @@ > #include "c-common.h" /* For flags. */ > #include "../libcpp/internal.h" > #include "c-pragma.h" /* For parse_in. */ > +#include "file-prefix-map.h" /* remap_macro_filename() */ > > /* Encapsulates state used to convert a stream of tokens into a text > file. */ > @@ -151,6 +152,7 @@ init_pp_output (FILE *out_stream) > > cb->has_attribute = c_common_has_attribute; > cb->get_source_date_epoch = cb_get_source_date_epoch; > + cb->remap_filename = remap_macro_filename; > > /* Initialize the print structure. */ > print.src_line = 1; > diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt > index 479ae63bb0e..9c6b8113ebf 100644 > --- a/gcc/c-family/c.opt > +++ b/gcc/c-family/c.opt > @@ -1386,6 +1386,10 @@ fdollars-in-identifiers > C ObjC C++ ObjC++ > Permit '$' as an identifier character. > > +fmacro-prefix-map= > +C ObjC C++ ObjC++ Joined RejectNegative > +-fmacro-prefix-map=<old>=<new> Map one directory name to another in > __FILE__, __BASE_FILE__, and __builtin_FILE(). > + > fdump-ada-spec > C ObjC C++ ObjC++ RejectNegative Var(flag_dump_ada_spec) > Write all declarations as Ada code transitively. > diff --git a/gcc/common.opt b/gcc/common.opt > index f8f2ed3db8a..31524e1e4fd 100644 > --- a/gcc/common.opt > +++ b/gcc/common.opt > @@ -1175,7 +1175,11 @@ Common RejectNegative Joined > Var(common_deferred_options) Defer > > fdebug-prefix-map= > Common Joined RejectNegative Var(common_deferred_options) Defer > -Map one directory name to another in debug information. > +-fdebug-prefix-map=<old>=<new> Map one directory name to another in > debug information. > + > +ffile-prefix-map= > +Common Joined RejectNegative Var(common_deferred_options) Defer > +-ffile-prefix-map=<old>=<new> Map one directory name to another in > compilation result. > fdebug-types-section > Common Report Var(flag_debug_types_section) Init(0) > diff --git a/gcc/dbxout.c b/gcc/dbxout.c > index 49a858339f8..e4aa16f635a 100644 > --- a/gcc/dbxout.c > +++ b/gcc/dbxout.c > @@ -91,6 +91,7 @@ along with GCC; see the file COPYING3. If not see > #include "common/common-target.h" > #include "langhooks.h" > #include "expr.h" > +#include "file-prefix-map.h" /* remap_debug_filename() */ > > #ifdef XCOFF_DEBUGGING_INFO > #include "xcoffout.h" > diff --git a/gcc/debug.h b/gcc/debug.h > index 277d990c20f..22fc7e7ab20 100644 > --- a/gcc/debug.h > +++ b/gcc/debug.h > @@ -246,9 +246,6 @@ extern bool dwarf2out_do_frame (void); > extern bool dwarf2out_do_cfi_asm (void); > extern void dwarf2out_switch_text_section (void); > > -const char *remap_debug_filename (const char *); > -void add_debug_prefix_map (const char *); > - > /* For -fdump-go-spec. */ > > extern const struct gcc_debug_hooks * > diff --git a/gcc/doc/cppopts.texi b/gcc/doc/cppopts.texi > index 16bf22a6f38..09eb88fff97 100644 > --- a/gcc/doc/cppopts.texi > +++ b/gcc/doc/cppopts.texi > @@ -287,6 +287,16 @@ When this option is given no argument, the > default parameter value is > > Note that @code{-ftrack-macro-expansion=2} is activated by default. > > +@item -fmacro-prefix-map=@var{old}=@var{new} > +@opindex fmacro-prefix-map > +When preprocessing files in directory @file{@var{old}}, expand the > +@code{__FILE__} and @code{__BASE_FILE__} macros as in @file{@var{new > }} > +instead. This can be used to change an absolute path to a relative > +path by using @file{.} for @var{new} which can result in more > +reproducible builds that are location independent. This option also > +affects @code{__builtin_FILE()} during compilation. See also > +@option{-ffile-prefix-map}. I'm not a fan of the name "-fmacro-prefix-map" as it makes me wonder "what macros are affected?"; it doesn't immediately suggest __FILE__ to me (and __BASE_FILE__). I wonder if "-f__FILE__-prefix-map" is sane and implementable? (sorry to "bikeshed" this). Do other compilers implement similar options? > @item -fexec-charset=@var{charset} > @opindex fexec-charset > @cindex character set, execution > @@ -534,4 +544,3 @@ token in the output is preceded by the dump of > the map its location > belongs to. > > When used from GCC without @option{-E}, this option has no effect. > - > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi > index 85c980bdfc9..a5edd9fa092 100644 > --- a/gcc/doc/invoke.texi > +++ b/gcc/doc/invoke.texi > @@ -172,7 +172,8 @@ in the following sections. > @gccoptlist{-c -S -E -o @var{file} -x @var{language} @gol > -v -### --help@r{[}=@var{class}@r{[},@dots{}@r{]]} --target- > help --version @gol > -pass-exit-codes -pipe -specs=@var{file} -wrapper @gol > -@@@var{file} -fplugin=@var{file} -fplugin-arg-@var{name}=@var{arg} > @gol > +@@@var{file} -ffile-prefix-map=@var{old}=@var{new} @gol > +-fplugin=@var{file} -fplugin-arg-@var{name}=@var{arg} @gol > -fdump-ada-spec@r{[}-slim@r{]} -fada-spec-parent=@var{unit} -fdump- > go-spec=@var{file}} > > @item C Language Options > @@ -480,9 +481,9 @@ Objective-C and Objective-C++ Dialects}. > -dD -dI -dM -dN -dU @gol > -fdebug-cpp -fdirectives-only -fdollars-in-identifiers @gol > -fexec-charset=@var{charset} -fextended-identifiers @gol > --finput-charset=@var{charset} -fno-canonical-system-headers @gol > --fpch-deps -fpch-preprocess -fpreprocessed @gol > --ftabstop=@var{width} -ftrack-macro-expansion @gol > +-finput-charset=@var{charset} -fmacro-prefix-map=@var{old}=@var{new} > @gol > +-fno-canonical-system-headers @gol -fpch-deps -fpch- > preprocess @gol > +-fpreprocessed -ftabstop=@var{width} -ftrack-macro-expansion @gol > -fwide-exec-charset=@var{charset} -fworking-directory @gol > -H -imacros @var{file} -include @var{file} @gol > -M -MD -MF -MG -MM -MMD -MP -MQ -MT @gol > @@ -1652,6 +1653,15 @@ This invokes all subprograms of @command{gcc} > under > @samp{gdb --args}, thus the invocation of @command{cc1} is > @samp{gdb --args cc1 @dots{}}. > > +@item -ffile-prefix-map=@var{old}=@var{new} > +@opindex ffile-prefix-map > +When compiling files in directory @file{@var{old}}, record any > references > +to them in the result of the compilation as in @file{@var{new}} > instead. > +Specifying this option is equivalent to specifying all the > individual > +@option{-f*-prefix-map} options. This can be used to make > reproducible You say "all the individual...options"; am I right in thinking there are just two of them: -fmacro-prefix-map and -fdebug-prefix-map? If so, wouldn't it better to say "both of the options" and list them there. Similar comments apply to the .opt text for this above. > +builds that are location independent. See also @option{-fmacro- > prefix-map} > +and @option{-fdebug-prefix-map}. > + > @item -fplugin=@var{name}.so > @opindex fplugin > Load the plugin code in file @var{name}.so, assumed to be a > @@ -7059,7 +7069,7 @@ used to replace a build-time path with an > install-time path in the debug info. > It can also be used to change an absolute path to a relative path by > using > @file{.} for @var{new}. This can give more reproducible builds, > which are > location independent, but may require an extra command to tell GDB > where to > -find the source files. > +find the source files. See also @option{-ffile-prefix-map}. > > @item -fvar-tracking > @opindex fvar-tracking > diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c > index 76a538f1ff9..83aec7d7f3d 100644 > --- a/gcc/dwarf2out.c > +++ b/gcc/dwarf2out.c > @@ -94,6 +94,7 @@ along with GCC; see the file COPYING3. If not see > #include "rtl-iter.h" > #include "stringpool.h" > #include "attribs.h" > +#include "file-prefix-map.h" /* remap_debug_filename() */ > > static void dwarf2out_source_line (unsigned int, unsigned int, const > char *, > int, bool); > @@ -23408,6 +23409,8 @@ gen_producer_string (void) > case OPT_fltrans_output_list_: > case OPT_fresolution_: > case OPT_fdebug_prefix_map_: > + case OPT_fmacro_prefix_map_: > + case OPT_ffile_prefix_map_: > case OPT_fcompare_debug: > /* Ignore these. */ > continue; > diff --git a/gcc/file-prefix-map.c b/gcc/file-prefix-map.c > new file mode 100644 > index 00000000000..c8b6af51d40 > --- /dev/null > +++ b/gcc/file-prefix-map.c > @@ -0,0 +1,127 @@ > +/* Implementation of file prefix remapping support (-f*-prefix-map > options). > + Copyright (C) 2017 Free Software Foundation, Inc. > + > + This program is free software; you can redistribute it and/or > modify it > + under the terms of the GNU General Public License as published by > the > + Free Software Foundation; either version 3, or (at your option) > any > + later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program; see the file COPYING3. If not see > + <http://www.gnu.org/licenses/>. */ > + > +#include "config.h" > +#include "system.h" > +#include "coretypes.h" > +#include "diagnostic.h" > +#include "file-prefix-map.h" > + > +/* Structure recording the mapping from source file and directory > names at > + compile time to those to be embedded in the compilation result > (debug > + information, the __FILE__ macro expansion, etc). */ > +struct file_prefix_map > +{ > + const char *old_prefix; > + const char *new_prefix; > + size_t old_len; > + size_t new_len; > + struct file_prefix_map *next; > +}; > + > +/* Record a file prefix mapping in the specified map. ARG is the > argument to > + -f*-prefix-map and must be of the form OLD=NEW. OPT is the > option name > + for diagnostics. */ > +static void > +add_prefix_map (file_prefix_map *&maps, const char *arg, const char > *opt) > +{ > + file_prefix_map *map; > + const char *p; > + > + p = strchr (arg, '='); > + if (!p) > + { > + error ("invalid argument %qs to %s", arg, opt); I think both of these should be %qs, so that the option is quoted (the old code in final.c didn't do that, but I think it should have). > + return; > + } > + map = XNEW (file_prefix_map); > + map->old_prefix = xstrndup (arg, p - arg); > + map->old_len = p - arg; > + p++; > + map->new_prefix = xstrdup (p); > + map->new_len = strlen (p); > + map->next = maps; > + maps = map; > +} Anytime I see an XNEW I wonder if this ought to be a constructor, and the struct ought to become a class, but given that this code is basically just moved from final.c, maybe leave that for a separate cleanup to help preserve history. > +/* Perform user-specified mapping of filename prefixes. Return the > new name > + corresponding to FILENAME. */ > +static const char * > +remap_filename (file_prefix_map *maps, const char *filename) > +{ > + file_prefix_map *map; > + char *s; > + const char *name; > + size_t name_len; > + > + for (map = maps; map; map = map->next) > + if (filename_ncmp (filename, map->old_prefix, map->old_len) == > 0) > + break; > + if (!map) > + return filename; > + name = filename + map->old_len; > + name_len = strlen (name) + 1; > + > + s = (char *) ggc_alloc_atomic (name_len + map->new_len); > + memcpy (s, map->new_prefix, map->new_len); > + memcpy (s + map->new_len, name, name_len); > + return s; > +} You've moved this code from final.c, where the memory is allocated on stack and then copied via ggc_strdup, but with an early exit for : > - s = (char *) alloca (name_len + map->new_len); > - memcpy (s, map->new_prefix, map->new_len); > - memcpy (s + map->new_len, name, name_len); > - return ggc_strdup (s); so I guess the ggc_alloc_atomic avoids a strlen. Please can you add a note to the function's header documenting that the return value is either a pointer to a GC-allocated buffer, or is FILENAME (when no remapping occurs). > +/* NOTE: if adding another -f*-prefix-map option then don't forget > to > + ignore it in DW_AT_producer (dwarf2out.c). */ > + > +/* Linked lists of file_prefix_map structures. */ > +static file_prefix_map *macro_prefix_maps; /* -fmacro-prefix-map */ > +static file_prefix_map *debug_prefix_maps; /* -fdebug-prefix-map */ > + > +/* Record a file prefix mapping for -fmacro-prefix-map. */ > +void > +add_macro_prefix_map (const char *arg) > +{ > + add_prefix_map (macro_prefix_maps, arg, "-fmacro-prefix-map"); > +} > + > +/* Record a file prefix mapping for -fdebug-prefix-map. */ > +void > +add_debug_prefix_map (const char *arg) > +{ > + add_prefix_map (debug_prefix_maps, arg, "-fdebug-prefix-map"); > +} > + > +/* Record a file prefix mapping for all -f*-prefix-map. */ > +void > +add_file_prefix_map (const char *arg) > +{ > + add_prefix_map (macro_prefix_maps, arg, "-ffile-prefix-map"); > + add_prefix_map (debug_prefix_maps, arg, "-ffile-prefix-map"); > +} > + > +/* Remap using -fmacro-prefix-map. */ Please can you add a note to this comment documenting the "ownership" of the buffer (as above). > +const char * > +remap_macro_filename (const char *filename) > +{ > + return remap_filename (macro_prefix_maps, filename); > +} > + > +/* Remap using -fdebug-prefix-map. */ Likewise. > +const char * > +remap_debug_filename (const char *filename) > +{ > + return remap_filename (debug_prefix_maps, filename); > +} > diff --git a/gcc/file-prefix-map.h b/gcc/file-prefix-map.h > new file mode 100644 > index 00000000000..3309eeed646 > --- /dev/null > +++ b/gcc/file-prefix-map.h > @@ -0,0 +1,28 @@ > +/* Declarations for file prefix remapping support (-f*-prefix-map > options). > + Copyright (C) 2017 Free Software Foundation, Inc. > + > + This program is free software; you can redistribute it and/or > modify it > + under the terms of the GNU General Public License as published by > the > + Free Software Foundation; either version 3, or (at your option) > any > + later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program; see the file COPYING3. If not see > + <http://www.gnu.org/licenses/>. */ > + > +#ifndef GCC_FILE_PREFIX_MAP_H > +#define GCC_FILE_PREFIX_MAP_H > + > +void add_macro_prefix_map (const char *); > +void add_debug_prefix_map (const char *); > +void add_file_prefix_map (const char *); > + > +const char *remap_macro_filename (const char *); > +const char *remap_debug_filename (const char *); > + > +#endif /* !GCC_FILE_PREFIX_MAP_H */ > diff --git a/gcc/final.c b/gcc/final.c > index fe35a36dbbf..edba0d42697 100644 > --- a/gcc/final.c > +++ b/gcc/final.c > @@ -1501,71 +1501,6 @@ asm_str_count (const char *templ) > return count; > } > > -/* ??? This is probably the wrong place for these. */ > -/* Structure recording the mapping from source file and directory > - names at compile time to those to be embedded in debug > - information. */ > -struct debug_prefix_map > -{ > - const char *old_prefix; > - const char *new_prefix; > - size_t old_len; > - size_t new_len; > - struct debug_prefix_map *next; > -}; > - > -/* Linked list of such structures. */ > -static debug_prefix_map *debug_prefix_maps; > - > - > -/* Record a debug file prefix mapping. ARG is the argument to > - -fdebug-prefix-map and must be of the form OLD=NEW. */ > - > -void > -add_debug_prefix_map (const char *arg) > -{ > - debug_prefix_map *map; > - const char *p; > - > - p = strchr (arg, '='); > - if (!p) > - { > - error ("invalid argument %qs to -fdebug-prefix-map", arg); > - return; > - } > - map = XNEW (debug_prefix_map); > - map->old_prefix = xstrndup (arg, p - arg); > - map->old_len = p - arg; > - p++; > - map->new_prefix = xstrdup (p); > - map->new_len = strlen (p); > - map->next = debug_prefix_maps; > - debug_prefix_maps = map; > -} > - > -/* Perform user-specified mapping of debug filename > prefixes. Return > - the new name corresponding to FILENAME. */ > - > -const char * > -remap_debug_filename (const char *filename) > -{ > - debug_prefix_map *map; > - char *s; > - const char *name; > - size_t name_len; > - > - for (map = debug_prefix_maps; map; map = map->next) > - if (filename_ncmp (filename, map->old_prefix, map->old_len) == > 0) > - break; > - if (!map) > - return filename; > - name = filename + map->old_len; > - name_len = strlen (name) + 1; > - s = (char *) alloca (name_len + map->new_len); > - memcpy (s, map->new_prefix, map->new_len); > - memcpy (s + map->new_len, name, name_len); > - return ggc_strdup (s); > -} > > /* Return true if DWARF2 debug info can be emitted for DECL. */ > > diff --git a/gcc/opts-global.c b/gcc/opts-global.c > index 343dbd3ac2c..aadc2ef880b 100644 > --- a/gcc/opts-global.c > +++ b/gcc/opts-global.c > @@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see > #include "stringpool.h" > #include "attribs.h" > #include "asan.h" > +#include "file-prefix-map.h" /* add_*_prefix_map() */ > > typedef const char *const_char_p; /* For DEF_VEC_P. */ > > @@ -365,6 +366,10 @@ handle_common_deferred_options (void) > add_debug_prefix_map (opt->arg); > break; > > + case OPT_ffile_prefix_map_: > + add_file_prefix_map (opt->arg); > + break; > + > case OPT_fdump_: > if (!g->get_dumps ()->dump_switch_p (opt->arg)) > error ("unrecognized command line option %<-fdump-%s%>", > opt->arg); > diff --git a/gcc/opts.c b/gcc/opts.c > index ac383d48ec1..9b9a9e2e734 100644 > --- a/gcc/opts.c > +++ b/gcc/opts.c > @@ -2075,6 +2075,7 @@ common_handle_option (struct gcc_options *opts, > break; > > case OPT_fdebug_prefix_map_: > + case OPT_ffile_prefix_map_: > /* Deferred. */ > break; > > diff --git a/gcc/testsuite/c-c++-common/cpp/ffile-prefix-map.c > b/gcc/testsuite/c-c++-common/cpp/ffile-prefix-map.c > new file mode 100644 > index 00000000000..cf14de84a0d > --- /dev/null > +++ b/gcc/testsuite/c-c++-common/cpp/ffile-prefix-map.c > @@ -0,0 +1,5 @@ > +/* { dg-do compile } */ > +/* { dg-options "-ffile-prefix-map==FILE-PREFIX" } */ What's up with this "=="? (as opposed to "="). Is this being interpreted as an argument of "=FILE-PREFIX" to the option? If so what does this mean? (and if it's a meaningful special- case, please can you document this in the .texi) > +#pragma message __FILE__ /* { dg-message "FILE-PREFIX" } */ > +#pragma message __BASE_FILE__ /* { dg-message "FILE-PREFIX" } */ Please add some before/after text to the #pragma message and to the dg- message so that the dg-message is verifying the exact value of __FILE__, and not just a substring match. > diff --git a/gcc/testsuite/c-c++-common/cpp/fmacro-prefix-map.c > b/gcc/testsuite/c-c++-common/cpp/fmacro-prefix-map.c > new file mode 100644 > index 00000000000..2618146247b > --- /dev/null > +++ b/gcc/testsuite/c-c++-common/cpp/fmacro-prefix-map.c > @@ -0,0 +1,5 @@ > +/* { dg-do compile } */ > +/* { dg-options "-fmacro-prefix-map==MACRO-PREFIX" } */ > + > +#pragma message __FILE__ /* { dg-message "MACRO-PREFIX" } */ > +#pragma message __BASE_FILE__ /* { dg-message "MACRO-PREFIX" } */ (likewise, obviously) > diff --git a/gcc/testsuite/c-c++-common/ffile-prefix-map.c > b/gcc/testsuite/c-c++-common/ffile-prefix-map.c > new file mode 100644 > index 00000000000..9b22eb6f06a > --- /dev/null > +++ b/gcc/testsuite/c-c++-common/ffile-prefix-map.c > @@ -0,0 +1,12 @@ > +/* Test __builtin_FILE(). */ > +/* { dg-do run } */ > +/* { dg-options "-ffile-prefix-map==FILE-PREFIX" } */ > + > +#include <stdio.h> > + > +int main () > +{ > + printf ("%s\n", __builtin_FILE ()); > +} > + > +/* { dg-output "FILE-PREFIX" } */ Likewise to the printf, e.g.: printf ("__builtin_FILE is '%s'\n", __builtin_FILE ()); and: /* { dg-output "__builtin_FILE is 'FILE-PREFIX'" } */ > diff --git a/gcc/testsuite/c-c++-common/fmacro-prefix-map.c > b/gcc/testsuite/c-c++-common/fmacro-prefix-map.c > new file mode 100644 > index 00000000000..e3dee68d8a7 > --- /dev/null > +++ b/gcc/testsuite/c-c++-common/fmacro-prefix-map.c > @@ -0,0 +1,12 @@ > +/* Test __builtin_FILE(). */ > +/* { dg-do run } */ > +/* { dg-options "-fmacro-prefix-map==MACRO-PREFIX" } */ > + > +#include <stdio.h> > + > +int main () > +{ > + printf ("%s\n", __builtin_FILE ()); > +} > + > +/* { dg-output "MACRO-PREFIX" } */ Likewise. > diff --git a/gcc/varasm.c b/gcc/varasm.c > index 1b35a99d688..cac338711ee 100644 > --- a/gcc/varasm.c > +++ b/gcc/varasm.c > @@ -55,6 +55,7 @@ along with GCC; see the file COPYING3. If not see > #include "attribs.h" > #include "asan.h" > #include "rtl-iter.h" > +#include "file-prefix-map.h" /* remap_debug_filename() */ > > #ifdef XCOFF_DEBUGGING_INFO > #include "xcoffout.h" /* Needed for external data > declarations. */ > diff --git a/gcc/vmsdbgout.c b/gcc/vmsdbgout.c > index 580dd284016..a0958e0f971 100644 > --- a/gcc/vmsdbgout.c > +++ b/gcc/vmsdbgout.c > @@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see > #include "langhooks.h" > #include "function.h" > #include "target.h" > +#include "file-prefix-map.h" /* remap_debug_filename() */ > > /* Difference in seconds between the VMS Epoch and the Unix Epoch */ > static const long long vms_epoch_offset = 3506716800ll; > diff --git a/gcc/xcoffout.c b/gcc/xcoffout.c > index cf2064d5ba5..afda2f83e82 100644 > --- a/gcc/xcoffout.c > +++ b/gcc/xcoffout.c > @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see > #include "varasm.h" > #include "output.h" > #include "debug.h" > +#include "file-prefix-map.h" /* remap_debug_filename() */ > > #ifdef XCOFF_DEBUGGING_INFO > > diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h > index 101b33aef48..ea3bb36fd1b 100644 > --- a/libcpp/include/cpplib.h > +++ b/libcpp/include/cpplib.h > @@ -622,6 +622,10 @@ struct cpp_callbacks > C++-style comments it does not include the terminating > newline. */ > void (*comment) (cpp_reader *, source_location, const unsigned > char *, > size_t); > + > + /* Callback for filename remapping in __FILE__ and __BASE_FILE__ > macro > + expansions. */ > + const char *(*remap_filename) (const char*); > }; > > #ifdef VMS > diff --git a/libcpp/macro.c b/libcpp/macro.c > index bf473eae358..35c98aaf4c9 100644 > --- a/libcpp/macro.c > +++ b/libcpp/macro.c > @@ -450,6 +450,8 @@ _cpp_builtin_macro_text (cpp_reader *pfile, > cpp_hashnode *node, > if (!name) > abort (); > } > + if (pfile->cb.remap_filename) > + name = pfile->cb.remap_filename (name); > len = strlen (name); > buf = _cpp_unaligned_alloc (pfile, len * 2 + 3); > result = buf; This made me nervous, since "name" is now GC-allocated (or is the old value of "name", which IIRC is owned by the linemap). However, the code effectively takes a copy in: buf = cpp_quote_string (buf + 1, (const unsigned char *) name, len); so that's OK and "name" falls out of scope, with the buffer eventually to be GC-ed, which seems reasonable given this only happens for __FILE__ and __BASE_FILE__. Thanks for the patch; hope this is constructive Dave