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

Reply via email to