drop -aux{dir,base}, revamp -dump{dir,base}
Richard Biener
rguenther@suse.de
Mon Jan 20 10:38:00 GMT 2020
On Thu, 16 Jan 2020, Alexandre Oliva wrote:
> On Jan 9, 2020, Alexandre Oliva <oliva@adacore.com> wrote:
>
> > On Jan 9, 2020, Richard Biener <rguenther@suse.de> wrote:
> >> Did I miss the actual (non-documentation) patch?
>
> > No, I didn't post it. It's kind of big, and only yesterday did I get it
> > to work as expected and now extensively documented, passing all of the
> > extensive testsuite I wrote for it.
>
> Here it is, at last, regstrapped on x86_64-linux-gnu. Ok to install?
I'm hesitant to approve it now since we're in stage4 and been too
permissive already. So ...
OK for GCC 11.
And thanks alot for this work!
Thanks,
Richard.
>
> revamp dump and aux output names
>
> This patch simplifies (!!!) the logic governing the naming of dump
> files and auxiliary output files in the driver, in the compiler, and
> in the LTO wrapper. No changes are made to the naming of primary
> outputs, there are often ways to restore past behavior, and a number
> of inconsistencies are fixed. Some internal options are removed
> (-auxbase and -auxbase-strip), sensible existing uses of -dumpdir and
> -dumpbase options remain unchanged, additional useful cases are added,
> making for what is still admittedly quite complex. Extensive
> documentation and testcases provide numerous examples, from normal to
> corner cases.
>
> The most visible changes are:
>
> - aux and dump files now always go in the same directory, that
> defaults to the directory of the primary output, but that can be
> overridden with -dumpdir, -save-temps=*, or, preserving past behavior,
> with a -dumpbase with a directory component.
>
> - driver and compiler now have the same notion of naming of auxiliary
> outputs, e.g. .dwo files will no longer be in one location while the
> debug info suggests they are elsewhere, and -save-temps and .dwo
> auxiliary outputs now go in the same location as .su, .ci and
> coverage data, with consistent naming.
>
> - explicitly-specified primary output names guide not only the
> location of aux and dump outputs: the output base name is also used in
> their base name, as a prefix when also linking (e.g. foo.c bar.c -o
> foobar creates foobar-foo.dwo and foobar-bar.dwo with -gsplit-dwarf),
> or as the base name instead of the input name (foo.c -c -o whatever.o
> creates whatever.su rather than foo.su with -fstack-usage). The
> preference for the input file base name, quite useful for our
> testsuite, can be restored with -dumpbase "".
>
> - naming a -dumpbase when compiling multiple sources used to cause
> dumps from later compiles to overwrite those of earlier ones; it is
> now used as a prefix when compiling multiple sources, like an
> executable name above.
>
> - the dumpbase, explicitly specified or computed from output or input
> names, now also governs the naming of aux outputs; since aux outputs
> usually replaced the suffix from the input name, while dump outputs
> append their own additional suffixes, a -dumpbase-ext option is
> introduced to enable a chosen suffix to be dropped from dumpbase to
> form aux output names.
>
> - LTO dump and aux outputs were quite a mess, sometimes leaking
> temporary output names into -save-temps output names, sometimes
> conversely generating desirable aux outputs in temporary locations.
> They now obey the same logic of compiler aux and dump outputs, landing
> in the expected location and taking the linker output name or an
> explicit dumpbase overrider into account.
>
> - Naming of -fdump-final-insns outputs now follows the dump file
> naming logic for the .gkd files, and the .gk dump files generated in
> the second -fcompare-debug compilation get the .gk inserted before the
> suffix that -dumpbase-ext drops in aux outputs.
>
>
> for gcc/ChangeLog
>
> * common.opt (aux_base_name): Define.
> (dumpbase, dumpdir): Mark as Driver options.
> (-dumpbase, -dumpdir): Likewise.
> (dumpbase-ext, -dumpbase-ext): New.
> (auxbase, auxbase-strip): Drop.
> * doc/invoke.texi (-dumpbase, -dumpbase-ext, -dumpdir):
> Document.
> (-o): Introduce the notion of primary output, mention it
> influences auxiliary and dump output names as well, add
> examples.
> (-save-temps): Adjust, move examples into -dump*.
> (-save-temps=cwd, -save-temps=obj): Likewise.
> (-fdump-final-insns): Adjust.
> * dwarf2out.c (gen_producer_string): Drop auxbase and
> auxbase_strip; add dumpbase_ext.
> * gcc.c (enum save_temps): Add SAVE_TEMPS_DUMP.
> (save_temps_prefix, save_temps_length): Drop.
> (save_temps_overrides_dumpdir): New.
> (dumpdir, dumpbase, dumpbase_ext): New.
> (dumpdir_length, dumpdir_trailing_dash_added): New.
> (outbase, outbase_length): New.
> (The Specs Language): Introduce %". Adjust %b and %B.
> (ASM_FINAL_SPEC): Use %b.dwo for an aux output name always.
> Precede object file with %w when it's the primary output.
> (cpp_debug_options): Do not pass on incoming -dumpdir,
> -dumpbase and -dumpbase-ext options; recompute them with
> %:dumps.
> (cc1_options): Drop auxbase with and without compare-debug;
> use cpp_debug_options instead of dumpbase. Mark asm output
> with %w when it's the primary output.
> (static_spec_functions): Drop %:compare-debug-auxbase-opt and
> %:replace-exception. Add %:dumps.
> (driver_handle_option): Implement -save-temps=*/-dumpdir
> mutual overriding logic. Save dumpdir, dumpbase and
> dumpbase-ext options. Do not save output_file in
> save_temps_prefix.
> (adds_single_suffix_p): New.
> (single_input_file_index): New.
> (process_command): Combine output dir, output base name, and
> dumpbase into dumpdir and outbase.
> (set_collect_gcc_options): Pass a possibly-adjusted -dumpdir.
> (do_spec_1): Optionally dumpdir instead of save_temps_prefix,
> and outbase instead of input_basename in %b, %B and in
> -save-temps aux files. Handle empty argument %".
> (driver::maybe_run_linker): Adjust dumpdir and auxbase.
> (compare_debug_dump_opt_spec_function): Adjust gkd dump file
> naming. Spec-quote the computed -fdump-final-insns file name.
> (debug_auxbase_opt): Drop.
> (compare_debug_self_opt_spec_function): Drop auxbase-strip
> computation.
> (compare_debug_auxbase_opt_spec_function): Drop.
> (not_actual_file_p): New.
> (replace_extension_spec_func): Drop.
> (dumps_spec_func): New.
> (convert_white_space): Split-out parts into...
> (quote_string, whitespace_to_convert_p): ... these. New.
> (quote_spec_char_p, quote_spec, quote_spec_arg): New.
> (driver::finalize): Release and reset new variables; drop
> removed ones.
> * lto-wrapper.c (DUMPBASE_SUFFIX): Drop leading period.
> (debug_objcopy): Use concat.
> (run_gcc): Recognize -save-temps=* as -save-temps too. Obey
> -dumpdir. Pass on empty dumpdir and dumpbase with a directory
> component. Simplify temp file names.
> * opts.c (finish_options): Drop aux base name handling.
> (common_handle_option): Drop auxbase-strip handling.
> * toplev.c (print_switch_values): Drop auxbase, add
> dumpbase-ext.
> (process_options): Derive aux_base_name from dump_base_name
> and dump_base_ext.
> (lang_dependent_init): Compute dump_base_ext along with
> dump_base_name. Disable stack usage and callgraph-info during
> lto generation and compare-debug recompilation.
>
> for gcc/fortran/ChangeLog
>
> * options.c (gfc_get_option_string): Drop auxbase, add
> dumpbase_ext.
>
> for gcc/ada/ChangeLog
>
> * gcc-interface/lang-specs.h: Drop auxbase and auxbase-strip.
> Use %:dumps instead of -dumpbase. Add %w for implicit .s
> primary output.
> * switch.adb (Is_Internal_GCC_Switch): Recognize dumpdir and
> dumpbase-ext. Drop auxbase and auxbase-strip.
>
> for lto-plugin/ChangeLog
>
> * lto-plugin.c (skip_in_suffix): New.
> (exec_lto_wrapper): Use skip_in_suffix and concat to build
> non-temporary output names.
> (onload): Look for -dumpdir in COLLECT_GCC_OPTIONS, and
> override link_output_name with it.
>
> for contrib/ChangeLog
>
> * compare-debug: Adjust for .gkd files named as dump files,
> with the source suffix rather than the object suffix.
>
> for gcc/testsuite/ChangeLog
>
> * gcc.misc-tests/outputs.exp: New.
> * gcc.misc-tests/outputs-0.c: New.
> * gcc.misc-tests/outputs-1.c: New.
> * gcc.misc-tests/outputs-2.c: New.
> * lib/gcc-defs.exp (dg-additional-files-options): Pass
> -dumpbase "" when there are additional sources.
> * lib/profopt.exp (profopt-execute): Pass the executable
> suffix with -dumpbase-ext.
> * lib/scandump.exp (dump-base): Mention -dumpbase "" use.
> * lib/scanltranstree.exp: Adjust dump suffix expectation.
> * lib/scanwpaipa.exp: Likewise.
> ---
> contrib/compare-debug | 26 +
> gcc/ada/gcc-interface/lang-specs.h | 16 -
> gcc/ada/switch.adb | 4
> gcc/common.opt | 27 +
> gcc/doc/invoke.texi | 385 +++++++++++-
> gcc/dwarf2out.c | 3
> gcc/fortran/options.c | 4
> gcc/gcc.c | 938 ++++++++++++++++++++++++------
> gcc/lto-wrapper.c | 153 ++---
> gcc/opts.c | 35 -
> gcc/testsuite/gcc.misc-tests/outputs-0.c | 1
> gcc/testsuite/gcc.misc-tests/outputs-1.c | 4
> gcc/testsuite/gcc.misc-tests/outputs-2.c | 2
> gcc/testsuite/gcc.misc-tests/outputs.exp | 655 +++++++++++++++++++++
> gcc/testsuite/lib/gcc-defs.exp | 4
> gcc/testsuite/lib/profopt.exp | 10
> gcc/testsuite/lib/scandump.exp | 3
> gcc/testsuite/lib/scanltranstree.exp | 20 -
> gcc/testsuite/lib/scanwpaipa.exp | 20 -
> gcc/toplev.c | 62 +-
> lto-plugin/lto-plugin.c | 87 +++
> 21 files changed, 2040 insertions(+), 419 deletions(-)
> create mode 100644 gcc/testsuite/gcc.misc-tests/outputs-0.c
> create mode 100644 gcc/testsuite/gcc.misc-tests/outputs-1.c
> create mode 100644 gcc/testsuite/gcc.misc-tests/outputs-2.c
> create mode 100644 gcc/testsuite/gcc.misc-tests/outputs.exp
>
> diff --git a/contrib/compare-debug b/contrib/compare-debug
> index 22870cf..cf80ae3 100755
> --- a/contrib/compare-debug
> +++ b/contrib/compare-debug
> @@ -2,7 +2,7 @@
>
> # Compare stripped copies of two given object files.
>
> -# Copyright (C) 2007, 2008, 2009, 2010, 2012 Free Software Foundation
> +# Copyright (C) 2007, 2008, 2009, 2010, 2012, 2020 Free Software Foundation
> # Originally by Alexandre Oliva <aoliva@redhat.com>
>
> # This file is part of GCC.
> @@ -183,8 +183,28 @@ $rm "$1.$suf1" "$2.$suf2"
>
> trap "exit $status; exit" 0 1 2 15
>
> -if test -f "$1".gkd || test -f "$2".gkd; then
> - if cmp "$1".gkd "$2".gkd; then
> +# Replace the suffix in $1 and $2 with .*.gkd, compare them if a
> +# single file is found by the globbing.
> +base1=`echo "$1" | sed '$s,\.[^.]*$,,'` gkd1=
> +for f in "$base1".*.gkd; do
> + if test "x$gkd1" != x; then
> + gkd1=
> + break
> + elif test -f "$f"; then
> + gkd1=$f
> + fi
> +done
> +base2=`echo "$2" | sed '$s,\.[^.]*$,,'` gkd2=
> +for f in "$base2".*.gkd; do
> + if test "x$gkd2" != x; then
> + gkd2=
> + break
> + elif test -f "$f"; then
> + gkd2=$f
> + fi
> +done
> +if test "x$gkd1" != x || test "x$gkd2" != x; then
> + if cmp "${gkd1-/dev/null}" "${gkd2-/dev/null}"; then
> :
> else
> status=$?
> diff --git a/gcc/ada/gcc-interface/lang-specs.h b/gcc/ada/gcc-interface/lang-specs.h
> index 374fc1e..5e65cf98 100644
> --- a/gcc/ada/gcc-interface/lang-specs.h
> +++ b/gcc/ada/gcc-interface/lang-specs.h
> @@ -34,17 +34,15 @@
> %{!S:%{!c:%e-c or -S required for Ada}}\
> gnat1 %{I*} %{k8:-gnatk8} %{Wall:-gnatwa} %{w:-gnatws} %{!Q:-quiet}\
> %{nostdinc*} %{nostdlib*}\
> - -dumpbase %{.adb:%b.adb}%{.ads:%b.ads}%{!.adb:%{!.ads:%b.ada}}\
> - %{fcompare-debug-second:%:compare-debug-auxbase-opt(%b) -gnatd_A} \
> - %{!fcompare-debug-second:%{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}%{!c:%{!S:-auxbase %b}}} \
> - %{O*} %{W*} %{w} %{p} %{pg:-p} %{d*} \
> + %{fcompare-debug-second:-gnatd_A} \
> + %{O*} %{W*} %{w} %{p} %{pg:-p} %{d*} %:dumps(%{!.adb:%{!.ads:.ada}}) \
> %{coverage:-fprofile-arcs -ftest-coverage} "
> #if defined(TARGET_VXWORKS_RTP)
> "%{fRTS=rtp|fRTS=rtp-smp|fRTS=ravenscar-cert-rtp:-mrtp} "
> #endif
> "%{gnatea:-gnatez} %{g*&m*&f*} "
> "%1 %{!S:%{o*:%w%*-gnatO}} \
> - %i %{S:%W{o*}%{!o*:-o %b.s}} \
> + %i %{S:%W{o*}%{!o*:-o %w%b.s}} \
> %{gnatc*|gnats*: -o %j} %{-param*} \
> %{!gnatc*:%{!gnats*:%(invoke_as)}}", 0, 0, 0},
>
> @@ -53,9 +51,7 @@
> %{!c:%e-c required for gnat2why}\
> gnat1why %{I*} %{k8:-gnatk8} %{!Q:-quiet}\
> %{nostdinc*} %{nostdlib*}\
> - -dumpbase %{.adb:%b.adb}%{.ads:%b.ads}%{!.adb:%{!.ads:%b.ada}}\
> - %{o*:-auxbase-strip %*}%{!o*:-auxbase %b} \
> - %{a} %{d*} \
> + %{a} %{d*} %:dumps(%{!.adb:%{!.ads:.ada}}) \
> %{gnatea:-gnatez} %{g*&m*&f*} \
> %1 %{o*:%w%*-gnatO} \
> %i \
> @@ -66,9 +62,7 @@
> %{!c:%e-c required for gnat2scil}\
> gnat1scil %{I*} %{k8:-gnatk8} %{!Q:-quiet}\
> %{nostdinc*} %{nostdlib*}\
> - -dumpbase %{.adb:%b.adb}%{.ads:%b.ads}%{!.adb:%{!.ads:%b.ada}}\
> - %{o*:-auxbase-strip %*}%{!o*:-auxbase %b} \
> - %{a} %{d*} \
> + %{a} %{d*} %:dumps(%{!.adb:%{!.ads:.ada}}) \
> %{gnatea:-gnatez} %{g*&m*&f*} \
> %1 %{o*:%w%*-gnatO} \
> %i \
> diff --git a/gcc/ada/switch.adb b/gcc/ada/switch.adb
> index 7cdaa196..b6f4e00 100644
> --- a/gcc/ada/switch.adb
> +++ b/gcc/ada/switch.adb
> @@ -163,9 +163,9 @@ package body Switch is
> return Is_Switch (Switch_Chars)
> and then
> (Switch_Chars (First .. Last) = "-param" or else
> + Switch_Chars (First .. Last) = "dumpdir" or else
> Switch_Chars (First .. Last) = "dumpbase" or else
> - Switch_Chars (First .. Last) = "auxbase-strip" or else
> - Switch_Chars (First .. Last) = "auxbase");
> + Switch_Chars (First .. Last) = "dumpbase-ext");
> end Is_Internal_GCC_Switch;
>
> ---------------
> diff --git a/gcc/common.opt b/gcc/common.opt
> index e9b29fb..9c299cc 100644
> --- a/gcc/common.opt
> +++ b/gcc/common.opt
> @@ -188,6 +188,12 @@ const char *main_input_basename
> Variable
> int main_input_baselength
>
> +; The base name used for auxiliary output files.
> +; dump_base_name minus dump_base_ext.
> +
> +Variable
> +const char *aux_base_name
> +
> ; Which options have been printed by --help.
> Variable
> char *help_printed
> @@ -252,10 +258,13 @@ Common Separate Alias(d)
> Common Joined Alias(d)
>
> -dumpbase
> -Common Separate Alias(dumpbase)
> +Driver Common Separate Alias(dumpbase)
> +
> +-dumpbase-ext
> +Driver Common Separate Alias(dumpbase-ext)
>
> -dumpdir
> -Common Separate Alias(dumpdir)
> +Driver Common Separate Alias(dumpdir)
>
> -entry
> Driver Separate Alias(e)
> @@ -840,12 +849,6 @@ Common Separate Var(aux_info_file_name)
> aux-info=
> Common Joined Alias(aux-info)
>
> -auxbase
> -Common Separate RejectDriver Var(aux_base_name)
> -
> -auxbase-strip
> -Common Separate RejectDriver
> -
> coverage
> Driver
>
> @@ -857,11 +860,15 @@ Common Joined
> -d<letters> Enable dumps from specific passes of the compiler.
>
> dumpbase
> -Common Separate Var(dump_base_name)
> +Driver Common Separate Var(dump_base_name)
> -dumpbase <file> Set the file basename to be used for dumps.
>
> +dumpbase-ext
> +Driver Common Separate Var(dump_base_ext)
> +-dumpbase-ext .<ext> Drop a trailing .<ext> from the dump basename to name auxiliary output files.
> +
> dumpdir
> -Common Separate Var(dump_dir_name)
> +Driver Common Separate Var(dump_dir_name)
> -dumpdir <dir> Set the directory name to be used for dumps.
>
> dumpmachine
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index f2c805c..c679cdf 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -184,7 +184,9 @@ in the following sections.
> @table @emph
> @item Overall Options
> @xref{Overall Options,,Options Controlling the Kind of Output}.
> -@gccoptlist{-c -S -E -o @var{file} -x @var{language} @gol
> +@gccoptlist{-c -S -E -o @var{file} @gol
> +-dumpbase @var{dumpbase} -dumpbase-ext @var{auxdropsuf} @gol
> +-dumpdir @var{dumppfx} -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} -ffile-prefix-map=@var{old}=@var{new} @gol
> @@ -1552,9 +1554,9 @@ Input files that don't require preprocessing are ignored.
> @cindex output file option
> @item -o @var{file}
> @opindex o
> -Place output in file @var{file}. This applies to whatever
> -sort of output is being produced, whether it be an executable file,
> -an object file, an assembler file or preprocessed C code.
> +Place the primary output in file @var{file}. This applies to whatever
> +sort of output is being produced, whether it be an executable file, an
> +object file, an assembler file or preprocessed C code.
>
> If @option{-o} is not specified, the default is to put an executable
> file in @file{a.out}, the object file for
> @@ -1563,6 +1565,314 @@ assembler file in @file{@var{source}.s}, a precompiled header file in
> @file{@var{source}.@var{suffix}.gch}, and all preprocessed C source on
> standard output.
>
> +Though @option{-o} names only the primary output, it also affects the
> +naming of auxiliary and dump outputs. See the examples below. Unless
> +overridden, both auxiliary outputs and dump outputs are placed in the
> +same directory as the primary output. In auxiliary outputs, the suffix
> +of the input file is replaced with that of the auxiliary output file
> +type; in dump outputs, the suffix of the dump file is appended to the
> +input file suffix. In compilation commands, the base name of both
> +auxiliary and dump outputs is that of the primary output; in compile and
> +link commands, the primary output name, minus the executable suffix, is
> +combined with the input file name. If both share the same base name,
> +disregarding the suffix, the result of the combination is that base
> +name, otherwise, they are concatenated, separated by a dash.
> +
> +@smallexample
> +gcc -c foo.c ...
> +@end smallexample
> +
> +will use @file{foo.o} as the primary output, and place aux outputs and
> +dumps next to it, e.g., aux file @file{foo.dwo} for
> +@option{-gsplit-dwarf}, and dump file @file{foo.c.???r.final} for
> +@option{-fdump-rtl-final}.
> +
> +If a non-linker output file is explicitly specified, aux and dump files
> +by default take the same base name:
> +
> +@smallexample
> +gcc -c foo.c -o dir/foobar.o ...
> +@end smallexample
> +
> +will name aux outputs @file{dir/foobar.*} and dump outputs
> +@file{dir/foobar.c.*}.
> +
> +A linker output will instead prefix aux and dump outputs:
> +
> +@smallexample
> +gcc foo.c bar.c -o dir/foobar ...
> +@end smallexample
> +
> +will generally name aux outputs @file{dir/foobar-foo.*} and
> +@file{dir/foobar-bar.*}, and dump outputs @file{dir/foobar-foo.c.*} and
> +@file{dir/foobar-bar.c.*}.
> +
> +The one exception to the above is when the executable shares the base
> +name with the single input:
> +
> +@smallexample
> +gcc foo.c -o dir/foo ...
> +@end smallexample
> +
> +in which case aux outputs are named @file{dir/foo.*} and dump outputs
> +named @file{dir/foo.c.*}.
> +
> +The location and the names of auxiliary and dump outputs can be adjusted
> +by the options @option{-dumpbase}, @option{-dumpbase-ext},
> +@option{-dumpdir}, @option{-save-temps=cwd}, and
> +@option{-save-temps=obj}.
> +
> +
> +@item -dumpbase @var{dumpbase}
> +@opindex dumpbase
> +This option sets the base name for auxiliary and dump output files. It
> +does not affect the name of the primary output file. Intermediate
> +outputs, when preserved, are not regarded as primary outputs, but as
> +auxiliary outputs:
> +
> +@smallexample
> +gcc -save-temps -S foo.c
> +@end smallexample
> +
> +saves the (no longer) temporary preprocessed file in @file{foo.i}, and
> +then compiles to the (implied) output file @file{foo.s}, whereas:
> +
> +@smallexample
> +gcc -save-temps -dumpbase save-foo -c foo.c
> +@end smallexample
> +
> +preprocesses to in @file{save-foo.i}, compiles to @file{save-foo.s} (now
> +an intermediate, thus auxiliary output), and then assembles to the
> +(implied) output file @file{foo.o}.
> +
> +Absent this option, dump and aux files take their names from the input
> +file, or from the (non-linker) output file, if one is explicitly
> +specified: dump output files (e.g. those requested by @option{-fdump-*}
> +options) with the input name suffix, and aux output files (those
> +requested by other non-dump options, e.g. @code{-save-temps},
> +@code{-gsplit-dwarf}, @code{-fcallgraph-info}) without it.
> +
> +Similar suffix differentiation of dump and aux outputs can be attained
> +for explicitly-given @option{-dumpbase basename.suf} by also specifying
> +@option{-dumpbase-ext .suf}.
> +
> +If @var{dumpbase} is explicitly specified with any directory component,
> +any @var{dumppfx} specification (e.g. @option{-dumpdir} or
> +@option{-save-temps=*}) is ignored, and instead of appending to it,
> +@var{dumpbase} fully overrides it:
> +
> +@smallexample
> +gcc foo.c -c -o dir/foo.o -dumpbase alt/foo \
> + -dumpdir pfx- -save-temps=cwd ...
> +@end smallexample
> +
> +creates auxiliary and dump outputs named @file{alt/foo.*}, disregarding
> +@file{dir/} in @option{-o}, the @file{./} prefix implied by
> +@option{-save-temps=cwd}, and @file{pfx-} in @option{-dumpdir}.
> +
> +When @option{-dumpbase} is specified in a command that compiles multiple
> +inputs, or that compiles and then links, it may be combined with
> +@var{dumppfx}, as specified under @option{-dumpdir}. Then, each input
> +file is compiled using the combined @var{dumppfx}, and default values
> +for @var{dumpbase} and @var{auxdropsuf} are computed for each input
> +file:
> +
> +@smallexample
> +gcc foo.c bar.c -c -dumpbase main ...
> +@end smallexample
> +
> +creates @file{foo.o} and @file{bar.o} as primary outputs, and avoids
> +overwriting the auxiliary and dump outputs by using the @var{dumpbase}
> +as a prefix, creating auxiliary and dump outputs named @file{main-foo.*}
> +and @file{main-bar.*}.
> +
> +An empty string specified as @var{dumpbase} avoids the influence of the
> +output basename in the naming of auxiliary and dump outputs during
> +compilation, computing default values :
> +
> +@smallexample
> +gcc -c foo.c -o dir/foobar.o -dumpbase '' ...
> +@end smallexample
> +
> +will name aux outputs @file{dir/foo.*} and dump outputs
> +@file{dir/foo.c.*}. Note how their basenames are taken from the input
> +name, but the directory still defaults to that of the output.
> +
> +The empty-string dumpbase does not prevent the use of the output
> +basename for outputs during linking:
> +
> +@smallexample
> +gcc foo.c bar.c -o dir/foobar -dumpbase '' -flto ...
> +@end smallexample
> +
> +The compilation of the source files will name auxiliary outputs
> +@file{dir/foo.*} and @file{dir/bar.*}, and dump outputs
> +@file{dir/foo.c.*} and @file{dir/bar.c.*}. LTO recompilation during
> +linking will use @file{dir/foobar.} as the prefix for dumps and
> +auxiliary files.
> +
> +
> +@item -dumpbase-ext @var{auxdropsuf}
> +@opindex dumpbase-ext
> +When forming the name of an auxiliary (but not a dump) output file, drop
> +trailing @var{auxdropsuf} from @var{dumpbase} before appending any
> +suffixes. If not specified, this option defaults to the suffix of a
> +default @var{dumpbase}, i.e., the suffix of the input file when
> +@option{-dumpbase} is not present in the command line, or @var{dumpbase}
> +is combined with @var{dumppfx}.
> +
> +@smallexample
> +gcc foo.c -c -o dir/foo.o -dumpbase x-foo.c -dumpbase-ext .c ...
> +@end smallexample
> +
> +creates @file{dir/foo.o} as the main output, and generates auxiliary
> +outputs in @file{dir/x-foo.*}, taking the location of the primary
> +output, and dropping the @file{.c} suffix from the @var{dumpbase}. Dump
> +outputs retain the suffix: @file{dir/x-foo.c.*}.
> +
> +This option is disregarded if it does not match the suffix of a
> +specified @var{dumpbase}, except as an alternative to the executable
> +suffix when appending the linker output base name to @var{dumppfx}, as
> +specified below:
> +
> +@smallexample
> +gcc foo.c bar.c -o main.out -dumpbase-ext .out ...
> +@end smallexample
> +
> +creates @file{main.out} as the primary output, and avoids overwriting
> +the auxiliary and dump outputs by using the executable name minus
> +@var{auxdropsuf} as a prefix, creating auxiliary outputs named
> +@file{main-foo.*} and @file{main-bar.*} and dump outputs named
> +@file{main-foo.c.*} and @file{main-bar.c.*}.
> +
> +
> +@item -dumpdir @var{dumppfx}
> +@opindex dumpdir
> +When forming the name of an auxiliary or dump output file, use
> +@var{dumppfx} as a prefix:
> +
> +@smallexample
> +gcc -dumpdir pfx- -c foo.c ...
> +@end smallexample
> +
> +creates @file{foo.o} as the primary output, and auxiliary outputs named
> +@file{pfx-foo.*}, combining the given @var{dumppfx} with the default
> +@var{dumpbase} derived from the default primary output, derived in turn
> +from the input name. Dump outputs also take the input name suffix:
> +@file{pfx-foo.c.*}.
> +
> +If @var{dumppfx} is to be used as a directory name, it must end with a
> +directory separator:
> +
> +@smallexample
> +gcc -dumpdir dir/ -c foo.c -o obj/bar.o ...
> +@end smallexample
> +
> +creates @file{obj/bar.o} as the primary output, and auxiliary outputs
> +named @file{dir/bar.*}, combining the given @var{dumppfx} with the
> +default @var{dumpbase} derived from the primary output name. Dump
> +outputs also take the input name suffix: @file{dir/bar.c.*}.
> +
> +It defaults to the location of the output file; options
> +@option{-save-temps=cwd} and @option{-save-temps=obj} override this
> +default, just like an explicit @option{-dumpdir} option. In case
> +multiple such options are given, the last one prevails:
> +
> +@smallexample
> +gcc -dumpdir pfx- -c foo.c -save-temps=obj ...
> +@end smallexample
> +
> +outputs @file{foo.o}, with auxiliary outputs named @file{foo.*} because
> +@option{-save-temps=*} overrides the @var{dumppfx} given by the earlier
> +@option{-dumpdir} option. It does not matter that @option{=obj} is the
> +default for @option{-save-temps}, nor that the output directory is
> +implicitly the current directory. Dump outputs are named
> +@file{foo.c.*}.
> +
> +When compiling from multiple input files, if @option{-dumpbase} is
> +specified, @var{dumpbase}, minus a @var{auxdropsuf} suffix, and a dash
> +are appended to (or override, if containing any directory components) an
> +explicit or defaulted @var{dumppfx}, so that each of the multiple
> +compilations gets differently-named aux and dump outputs.
> +
> +@smallexample
> +gcc foo.c bar.c -c -dumpdir dir/pfx- -dumpbase main ...
> +@end smallexample
> +
> +outputs auxiliary dumps to @file{dir/pfx-main-foo.*} and
> +@file{dir/pfx-main-bar.*}, appending @var{dumpbase}- to @var{dumppfx}.
> +Dump outputs retain the input file suffix: @file{dir/pfx-main-foo.c.*}
> +and @file{dir/pfx-main-bar.c.*}, respectively. Contrast with the
> +single-input compilation:
> +
> +@smallexample
> +gcc foo.c -c -dumpdir dir/pfx- -dumpbase main ...
> +@end smallexample
> +
> +that, applying @option{-dumpbase} to a single source, does not compute
> +and append a separate @var{dumpbase} per input file. Its auxiliary and
> +dump outputs go in @file{dir/pfx-main.*}.
> +
> +When compiling and then linking from multiple input files, a defaulted
> +or explicitly specified @var{dumppfx} also undergoes the @var{dumpbase}-
> +transformation above (e.g. the compilation of @file{foo.c} and
> +@file{bar.c} above, but without @option{-c}). If neither
> +@option{-dumpdir} nor @option{-dumpbase} are given, the linker output
> +base name, minus @var{auxdropsuf}, if specified, or the executable
> +suffix otherwise, plus a dash is appended to the default @var{dumppfx}
> +instead. Note, however, that unlike earlier cases of linking:
> +
> +@smallexample
> +gcc foo.c bar.c -dumpdir dir/pfx- -o main ...
> +@end smallexample
> +
> +does not append the output name @file{main} to @var{dumppfx}, because
> +@option{-dumpdir} is explicitly specified. The goal is that the
> +explicitly-specified @var{dumppfx} may contain the specified output name
> +as part of the prefix, if desired; only an explicitly-specified
> +@option{-dumpbase} would be combined with it, in order to avoid simply
> +discarding a meaningful option.
> +
> +When compiling and then linking from a single input file, the linker
> +output base name will only be appended to the default @var{dumppfx} as
> +above if it does not share the base name with the single input file
> +name. This has been covered in single-input linking cases above, but
> +not with an explicit @option{-dumpdir} that inhibits the combination,
> +even if overridden by @option{-save-temps=*}:
> +
> +@smallexample
> +gcc foo.c -dumpdir alt/pfx- -o dir/main.exe -save-temps=cwd ...
> +@end smallexample
> +
> +Auxiliary outputs are named @file{foo.*}, and dump outputs
> +@file{foo.c.*}, in the current working directory as ultimately requested
> +by @option{-save-temps=cwd}.
> +
> +Summing it all up for an intuitive though slightly imprecise data flow:
> +the primary output name is broken into a directory part and a basename
> +part; @var{dumppfx} is set to the former, unless overridden by
> +@option{-dumpdir} or @option{-save-temps=*}, and @var{dumpbase} is set
> +to the latter, unless overriden by @option{-dumpbase}. If there are
> +multiple inputs or linking, this @var{dumpbase} may be combined with
> +@var{dumppfx} and taken from each input file. Auxiliary output names
> +for each input are formed by combining @var{dumppfx}, @var{dumpbase}
> +minus suffix, and the auxiliary output suffix; dump output names are
> +only different in that the suffix from @var{dumpbase} is retained.
> +
> +When it comes to auxiliary and dump outputs created during LTO
> +recompilation, a combination of @var{dumppfx} and @var{dumpbase}, as
> +given or as derived from the linker output name but not from inputs,
> +even in cases in which this combination would not otherwise be used as
> +such, is passed down with a trailing period replacing the compiler-added
> +dash, if any, as a @option{-dumpdir} option to @command{lto-wrapper};
> +being involved in linking, this program does not normally get any
> +@option{-dumpbase} and @option{-dumpbase-ext}, and it ignores them.
> +
> +When running sub-compilers, @command{lto-wrapper} appends LTO stage
> +names to the received @var{dumppfx}, ensures it contains a directory
> +component so that it overrides any @option{-dumpdir}, and passes that as
> +@option{-dumpbase} to sub-compilers.
> +
> @item -v
> @opindex v
> Print (on standard error output) the commands executed to run the stages
> @@ -15644,54 +15954,28 @@ computing CRC32).
> The @var{string} should be different for every file you compile.
>
> @item -save-temps
> -@itemx -save-temps=cwd
> @opindex save-temps
> -Store the usual ``temporary'' intermediate files permanently; place them
> -in the current directory and name them based on the source file. Thus,
> -compiling @file{foo.c} with @option{-c -save-temps} produces files
> -@file{foo.i} and @file{foo.s}, as well as @file{foo.o}. This creates a
> -preprocessed @file{foo.i} output file even though the compiler now
> -normally uses an integrated preprocessor.
> +Store the usual ``temporary'' intermediate files permanently; name them
> +as auxiliary output files, as specified described under
> +@option{-dumpbase} and @option{-dumpdir}.
>
> When used in combination with the @option{-x} command-line option,
> -@option{-save-temps} is sensible enough to avoid over writing an
> +@option{-save-temps} is sensible enough to avoid overwriting an
> input source file with the same extension as an intermediate file.
> The corresponding intermediate file may be obtained by renaming the
> source file before using @option{-save-temps}.
>
> -If you invoke GCC in parallel, compiling several different source
> -files that share a common base name in different subdirectories or the
> -same source file compiled for multiple output destinations, it is
> -likely that the different parallel compilers will interfere with each
> -other, and overwrite the temporary files. For instance:
> -
> -@smallexample
> -gcc -save-temps -o outdir1/foo.o indir1/foo.c&
> -gcc -save-temps -o outdir2/foo.o indir2/foo.c&
> -@end smallexample
> -
> -may result in @file{foo.i} and @file{foo.o} being written to
> -simultaneously by both compilers.
> +@item -save-temps=cwd
> +@opindex save-temps=cwd
> +Equivalent to @option{-save-temps -dumpdir ./}.
>
> @item -save-temps=obj
> @opindex save-temps=obj
> -Store the usual ``temporary'' intermediate files permanently. If the
> -@option{-o} option is used, the temporary files are based on the
> -object file. If the @option{-o} option is not used, the
> -@option{-save-temps=obj} switch behaves like @option{-save-temps}.
> -
> -For example:
> -
> -@smallexample
> -gcc -save-temps=obj -c foo.c
> -gcc -save-temps=obj -c bar.c -o dir/xbar.o
> -gcc -save-temps=obj foobar.c -o dir2/yfoobar
> -@end smallexample
> -
> -@noindent
> -creates @file{foo.i}, @file{foo.s}, @file{dir/xbar.i},
> -@file{dir/xbar.s}, @file{dir2/yfoobar.i}, @file{dir2/yfoobar.s}, and
> -@file{dir2/yfoobar.o}.
> +Equivalent to @option{-save-temps -dumpdir @file{outdir/}}, where
> +@file{outdir/} is the directory of the output file specified after the
> +@option{-o} option, including any directory separators. If the
> +@option{-o} option is not used, the @option{-save-temps=obj} switch
> +behaves like @option{-save-temps=cwd}.
>
> @item -time@r{[}=@var{file}@r{]}
> @opindex time
> @@ -15728,7 +16012,7 @@ can later tell what file was being compiled, and with which options.
> Dump the final internal representation (RTL) to @var{file}. If the
> optional argument is omitted (or if @var{file} is @code{.}), the name
> of the dump file is determined by appending @code{.gkd} to the
> -compilation output file name.
> +dump base name, see @option{-dumpbase}.
>
> @item -fcompare-debug@r{[}=@var{opts}@r{]}
> @opindex fcompare-debug
> @@ -29903,17 +30187,24 @@ together or combine them with constant text in a single argument.
> @item %%
> Substitute one @samp{%} into the program name or argument.
>
> +@item %"
> +Substitute an empty argument.
> +
> @item %i
> Substitute the name of the input file being processed.
>
> @item %b
> -Substitute the basename of the input file being processed.
> -This is the substring up to (and not including) the last period
> -and not including the directory.
> +Substitute the basename for outputs related with the input file being
> +processed. This is often the substring up to (and not including) the
> +last period and not including the directory but, unless %w is active, it
> +expands to the basename for auxiliary outputs, which may be influenced
> +by an explicit output name, and by various other options that control
> +how auxiliary outputs are named.
>
> @item %B
> This is the same as @samp{%b}, but include the file suffix (text after
> -the last period).
> +the last period). Without %w, it expands to the basename for dump
> +outputs.
>
> @item %d
> Marks the argument containing or following the @samp{%d} as a
> diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
> index 70b3fad..1882116 100644
> --- a/gcc/dwarf2out.c
> +++ b/gcc/dwarf2out.c
> @@ -24333,9 +24333,8 @@ gen_producer_string (void)
> case OPT_o:
> case OPT_d:
> case OPT_dumpbase:
> + case OPT_dumpbase_ext:
> case OPT_dumpdir:
> - case OPT_auxbase:
> - case OPT_auxbase_strip:
> case OPT_quiet:
> case OPT_version:
> case OPT_v:
> diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
> index 4cc8a90..d844fa9 100644
> --- a/gcc/fortran/options.c
> +++ b/gcc/fortran/options.c
> @@ -838,8 +838,8 @@ gfc_get_option_string (void)
> case OPT_o:
> case OPT_d:
> case OPT_dumpbase:
> + case OPT_dumpbase_ext:
> case OPT_dumpdir:
> - case OPT_auxbase:
> case OPT_quiet:
> case OPT_version:
> case OPT_fintrinsic_modules_path:
> @@ -864,8 +864,8 @@ gfc_get_option_string (void)
> case OPT_o:
> case OPT_d:
> case OPT_dumpbase:
> + case OPT_dumpbase_ext:
> case OPT_dumpdir:
> - case OPT_auxbase:
> case OPT_quiet:
> case OPT_version:
> case OPT_fintrinsic_modules_path:
> diff --git a/gcc/gcc.c b/gcc/gcc.c
> index effc384f..cc04a20 100644
> --- a/gcc/gcc.c
> +++ b/gcc/gcc.c
> @@ -270,12 +270,36 @@ static const char *target_sysroot_hdrs_suffix = 0;
> static enum save_temps {
> SAVE_TEMPS_NONE, /* no -save-temps */
> SAVE_TEMPS_CWD, /* -save-temps in current directory */
> + SAVE_TEMPS_DUMP, /* -save-temps in dumpdir */
> SAVE_TEMPS_OBJ /* -save-temps in object directory */
> } save_temps_flag;
>
> -/* Output file to use to get the object directory for -save-temps=obj */
> -static char *save_temps_prefix = 0;
> -static size_t save_temps_length = 0;
> +/* Set this iff the dumppfx implied by a -save-temps=* option is to
> + override a -dumpdir option, if any. */
> +static bool save_temps_overrides_dumpdir = false;
> +
> +/* -dumpdir, -dumpbase and -dumpbase-ext flags passed in, possibly
> + rearranged as they are to be passed down, e.g., dumpbase and
> + dumpbase_ext may be cleared if integrated with dumpdir or
> + dropped. */
> +static char *dumpdir, *dumpbase, *dumpbase_ext;
> +
> +/* Usually the length of the string in dumpdir. However, during
> + linking, it may be shortened to omit a driver-added trailing dash,
> + by then replaced with a trailing period, that is still to be passed
> + to sub-processes in -dumpdir, but not to be generally used in spec
> + filename expansions. See maybe_run_linker. */
> +static size_t dumpdir_length = 0;
> +
> +/* Set if the last character in dumpdir is (or was) a dash that the
> + driver added to dumpdir after dumpbase or linker output name. */
> +static bool dumpdir_trailing_dash_added = false;
> +
> +/* Basename of dump and aux outputs, computed from dumpbase (given or
> + derived from output name), to override input_basename in non-%w %b
> + et al. */
> +static char *outbase;
> +static size_t outbase_length = 0;
>
> /* The compiler version. */
>
> @@ -402,13 +426,16 @@ static const char *find_plugindir_spec_function (int, const char **);
> static const char *print_asm_header_spec_function (int, const char **);
> static const char *compare_debug_dump_opt_spec_function (int, const char **);
> static const char *compare_debug_self_opt_spec_function (int, const char **);
> -static const char *compare_debug_auxbase_opt_spec_function (int, const char **);
> static const char *pass_through_libs_spec_func (int, const char **);
> -static const char *replace_extension_spec_func (int, const char **);
> +static const char *dumps_spec_func (int, const char **);
> static const char *greater_than_spec_func (int, const char **);
> static const char *debug_level_greater_than_spec_func (int, const char **);
> static const char *find_fortran_preinclude_file (int, const char **);
> static char *convert_white_space (char *);
> +static char *quote_spec (char *);
> +static char *quote_spec_arg (char *);
> +static bool not_actual_file_p (const char *);
> +
>
> /* The Specs Language
>
> @@ -426,12 +453,19 @@ expanding these sequences; therefore, you can concatenate them together
> or with constant text in a single argument.
>
> %% substitute one % into the program name or argument.
> + %" substitute an empty argument.
> %i substitute the name of the input file being processed.
> - %b substitute the basename of the input file being processed.
> - This is the substring up to (and not including) the last period
> - and not including the directory unless -save-temps was specified
> - to put temporaries in a different location.
> - %B same as %b, but include the file suffix (text after the last period).
> + %b substitute the basename for outputs related with the input file
> + being processed. This is often a substring of the input file name,
> + up to (and not including) the last period but, unless %w is active,
> + it is affected by the directory selected by -save-temps=*, by
> + -dumpdir, and, in case of multiple compilations, even by -dumpbase
> + and -dumpbase-ext and, in case of linking, by the linker output
> + name. When %w is active, it derives the main output name only from
> + the input file base name; when it is not, it names aux/dump output
> + file.
> + %B same as %b, but include the input file suffix (text after the last
> + period).
> %gSUFFIX
> substitute a file name that has suffix SUFFIX and is chosen
> once per compilation, and mark the argument a la %d. To reduce
> @@ -641,10 +675,10 @@ proper position among the other output files. */
> #define ASM_FINAL_SPEC \
> "%{gsplit-dwarf: \n\
> objcopy --extract-dwo \
> - %{c:%{o*:%*}%{!o*:%b%O}}%{!c:%U%O} \
> - %{c:%{o*:%:replace-extension(%{o*:%*} .dwo)}%{!o*:%b.dwo}}%{!c:%b.dwo} \n\
> + %{c:%{o*:%*}%{!o*:%w%b%O}}%{!c:%U%O} \
> + %b.dwo \n\
> objcopy --strip-dwo \
> - %{c:%{o*:%*}%{!o*:%b%O}}%{!c:%U%O} \
> + %{c:%{o*:%*}%{!o*:%w%b%O}}%{!c:%U%O} \
> }"
> #endif
>
> @@ -1139,22 +1173,20 @@ static const char *cpp_options =
>
> /* This contains cpp options which are not passed when the preprocessor
> output will be used by another program. */
> -static const char *cpp_debug_options = "%{d*}";
> +static const char *cpp_debug_options = "%<dumpdir %<dumpbase %<dumpbase-ext %{d*} %:dumps()";
>
> /* NB: This is shared amongst all front-ends, except for Ada. */
> static const char *cc1_options =
> "%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
> %{!iplugindir*:%{fplugin*:%:find-plugindir()}}\
> - %1 %{!Q:-quiet} %{!dumpbase:-dumpbase %B} %{d*} %{m*} %{aux-info*}\
> - %{fcompare-debug-second:%:compare-debug-auxbase-opt(%b)} \
> - %{!fcompare-debug-second:%{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}}%{!c:%{!S:-auxbase %b}} \
> + %1 %{!Q:-quiet} %(cpp_debug_options) %{m*} %{aux-info*}\
> %{g*} %{O*} %{W*&pedantic*} %{w} %{std*&ansi&trigraphs}\
> %{v:-version} %{pg:-p} %{p} %{f*} %{undef}\
> %{Qn:-fno-ident} %{Qy:} %{-help:--help}\
> %{-target-help:--target-help}\
> %{-version:--version}\
> %{-help=*:--help=%*}\
> - %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\
> + %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %w%b.s}}}\
> %{fsyntax-only:-o %j} %{-param*}\
> %{coverage:-fprofile-arcs -ftest-coverage}\
> %{fprofile-arcs|fprofile-generate*|coverage:\
> @@ -1642,9 +1674,8 @@ static const struct spec_function static_spec_functions[] =
> { "print-asm-header", print_asm_header_spec_function },
> { "compare-debug-dump-opt", compare_debug_dump_opt_spec_function },
> { "compare-debug-self-opt", compare_debug_self_opt_spec_function },
> - { "compare-debug-auxbase-opt", compare_debug_auxbase_opt_spec_function },
> { "pass-through-libs", pass_through_libs_spec_func },
> - { "replace-extension", replace_extension_spec_func },
> + { "dumps", dumps_spec_func },
> { "gt", greater_than_spec_func },
> { "debug-level-gt", debug_level_greater_than_spec_func },
> { "fortran-preinclude-file", find_fortran_preinclude_file},
> @@ -4140,7 +4171,8 @@ driver_handle_option (struct gcc_options *opts,
> return true;
>
> case OPT_save_temps:
> - save_temps_flag = SAVE_TEMPS_CWD;
> + if (!save_temps_flag)
> + save_temps_flag = SAVE_TEMPS_DUMP;
> validated = true;
> break;
>
> @@ -4153,6 +4185,23 @@ driver_handle_option (struct gcc_options *opts,
> else
> fatal_error (input_location, "%qs is an unknown %<-save-temps%> option",
> decoded->orig_option_with_args_text);
> + save_temps_overrides_dumpdir = true;
> + break;
> +
> + case OPT_dumpdir:
> + free (dumpdir);
> + dumpdir = xstrdup (arg);
> + save_temps_overrides_dumpdir = false;
> + break;
> +
> + case OPT_dumpbase:
> + free (dumpbase);
> + dumpbase = xstrdup (arg);
> + break;
> +
> + case OPT_dumpbase_ext:
> + free (dumpbase_ext);
> + dumpbase_ext = xstrdup (arg);
> break;
>
> case OPT_no_canonical_prefixes:
> @@ -4259,8 +4308,6 @@ driver_handle_option (struct gcc_options *opts,
> arg = convert_filename (arg, ! have_c, 0);
> #endif
> output_file = arg;
> - /* Save the output name in case -save-temps=obj was used. */
> - save_temps_prefix = xstrdup (arg);
> /* On some systems, ld cannot handle "-o" without a space. So
> split the option from its argument. */
> save_switch ("-o", 1, &arg, validated, true);
> @@ -4303,6 +4350,19 @@ driver_handle_option (struct gcc_options *opts,
> return true;
> }
>
> +/* Return true if F2 is F1 followed by a single suffix, i.e., by a
> + period and additional characters other than a period. */
> +
> +static inline bool
> +adds_single_suffix_p (const char *f2, const char *f1)
> +{
> + size_t len = strlen (f1);
> +
> + return (strncmp (f1, f2, len) == 0
> + && f2[len] == '.'
> + && strchr (f2 + len + 1, '.') == NULL);
> +}
> +
> /* Put the driver's standard set of option handlers in *HANDLERS. */
>
> static void
> @@ -4319,6 +4379,32 @@ set_option_handlers (struct cl_option_handlers *handlers)
> handlers->handlers[2].mask = CL_TARGET;
> }
>
> +
> +/* Return the index into infiles for the single non-library
> + non-lto-wpa input file, -1 if there isn't any, or -2 if there is
> + more than one. */
> +static inline int
> +single_input_file_index ()
> +{
> + int ret = -1;
> +
> + for (int i = 0; i < n_infiles; i++)
> + {
> + if (infiles[i].language
> + && (infiles[i].language[0] == '*'
> + || (flag_wpa
> + && strcmp (infiles[i].language, "lto") == 0)))
> + continue;
> +
> + if (ret != -1)
> + return -2;
> +
> + ret = i;
> + }
> +
> + return ret;
> +}
> +
> /* Create the vector `switches' and its contents.
> Store its length in `n_switches'. */
>
> @@ -4631,23 +4717,371 @@ process_command (unsigned int decoded_options_count,
> if (output_file != NULL && output_file[0] == '\0')
> fatal_error (input_location, "output filename may not be empty");
>
> + /* -dumpdir and -save-temps=* both specify the location of aux/dump
> + outputs; the one that appears last prevails. When compiling
> + multiple sources, an explicit dumpbase (minus -ext) may be
> + combined with an explicit or implicit dumpdir, whereas when
> + linking, a specified or implied link output name (minus
> + extension) may be combined with a prevailing -save-temps=* or an
> + otherwise implied dumpdir, but not override a prevailing
> + -dumpdir. Primary outputs (e.g., linker output when linking
> + without -o, or .i, .s or .o outputs when processing multiple
> + inputs with -E, -S or -c, respectively) are NOT affected by these
> + -save-temps=/-dump* options, always landing in the current
> + directory and with the same basename as the input when an output
> + name is not given, but when they're intermediate outputs, they
> + are named like other aux outputs, so the options affect their
> + location and name.
> +
> + Here are some examples. There are several more in the
> + documentation of -o and -dump*, and some quite exhaustive tests
> + in gcc.misc-tests/outputs.exp.
> +
> + When compiling any number of sources, no -dump* nor
> + -save-temps=*, all outputs in cwd without prefix:
> +
> + # gcc -c b.c -gsplit-dwarf
> + -> cc1 [-dumpdir ./] -dumpbase b.c -dumpbase-ext .c # b.o b.dwo
> +
> + # gcc -c b.c d.c -gsplit-dwarf
> + -> cc1 [-dumpdir ./] -dumpbase b.c -dumpbase-ext .c # b.o b.dwo
> + && cc1 [-dumpdir ./] -dumpbase d.c -dumpbase-ext .c # d.o d.dwo
> +
> + When compiling and linking, no -dump* nor -save-temps=*, .o
> + outputs are temporary, aux outputs land in the dir of the output,
> + prefixed with the basename of the linker output:
> +
> + # gcc b.c d.c -o ab -gsplit-dwarf
> + -> cc1 -dumpdir ab- -dumpbase b.c -dumpbase-ext .c # ab-b.dwo
> + && cc1 -dumpdir ab- -dumpbase d.c -dumpbase-ext .c # ab-d.dwo
> + && link ... -o ab
> +
> + # gcc b.c d.c [-o a.out] -gsplit-dwarf
> + -> cc1 -dumpdir a- -dumpbase b.c -dumpbase-ext .c # a-b.dwo
> + && cc1 -dumpdir a- -dumpbase d.c -dumpbase-ext .c # a-d.dwo
> + && link ... [-o a.out]
> +
> + When compiling and linking, a prevailing -dumpdir fully overrides
> + the prefix of aux outputs given by the output name:
> +
> + # gcc -dumpdir f b.c d.c -gsplit-dwarf [-o [dir/]whatever]
> + -> cc1 -dumpdir f -dumpbase b.c -dumpbase-ext .c # fb.dwo
> + && cc1 -dumpdir f -dumpbase d.c -dumpbase-ext .c # fd.dwo
> + && link ... [-o whatever]
> +
> + When compiling multiple inputs, an explicit -dumpbase is combined
> + with -dumpdir, affecting aux outputs, but not the .o outputs:
> +
> + # gcc -dumpdir f -dumpbase g- b.c d.c -gsplit-dwarf -c
> + -> cc1 -dumpdir fg- -dumpbase b.c -dumpbase-ext .c # b.o fg-b.dwo
> + && cc1 -dumpdir fg- -dumpbase d.c -dumpbase-ext .c # d.o fg-d.dwo
> +
> + When compiling and linking with -save-temps, the .o outputs that
> + would have been temporary become aux outputs, so they get
> + affected by -dump* flags:
> +
> + # gcc -dumpdir f -dumpbase g- -save-temps b.c d.c
> + -> cc1 -dumpdir fg- -dumpbase b.c -dumpbase-ext .c # fg-b.o
> + && cc1 -dumpdir fg- -dumpbase d.c -dumpbase-ext .c # fg-d.o
> + && link
> +
> + If -save-temps=* prevails over -dumpdir, however, the explicit
> + -dumpdir is discarded, as if it wasn't there. The basename of
> + the implicit linker output, a.out or a.exe, becomes a- as the aux
> + output prefix for all compilations:
> +
> + # gcc [-dumpdir f] -save-temps=cwd b.c d.c
> + -> cc1 -dumpdir a- -dumpbase b.c -dumpbase-ext .c # a-b.o
> + && cc1 -dumpdir a- -dumpbase d.c -dumpbase-ext .c # a-d.o
> + && link
> +
> + A single -dumpbase, applying to multiple inputs, overrides the
> + linker output name, implied or explicit, as the aux output prefix:
> +
> + # gcc [-dumpdir f] -dumpbase g- -save-temps=cwd b.c d.c
> + -> cc1 -dumpdir g- -dumpbase b.c -dumpbase-ext .c # g-b.o
> + && cc1 -dumpdir g- -dumpbase d.c -dumpbase-ext .c # g-d.o
> + && link
> +
> + # gcc [-dumpdir f] -dumpbase g- -save-temps=cwd b.c d.c -o dir/h.out
> + -> cc1 -dumpdir g- -dumpbase b.c -dumpbase-ext .c # g-b.o
> + && cc1 -dumpdir g- -dumpbase d.c -dumpbase-ext .c # g-d.o
> + && link -o dir/h.out
> +
> + Now, if the linker output is NOT overridden as a prefix, but
> + -save-temps=* overrides implicit or explicit -dumpdir, the
> + effective dump dir combines the dir selected by the -save-temps=*
> + option with the basename of the specified or implied link output:
> +
> + # gcc [-dumpdir f] -save-temps=cwd b.c d.c -o dir/h.out
> + -> cc1 -dumpdir h- -dumpbase b.c -dumpbase-ext .c # h-b.o
> + && cc1 -dumpdir h- -dumpbase d.c -dumpbase-ext .c # h-d.o
> + && link -o dir/h.out
> +
> + # gcc [-dumpdir f] -save-temps=obj b.c d.c -o dir/h.out
> + -> cc1 -dumpdir dir/h- -dumpbase b.c -dumpbase-ext .c # dir/h-b.o
> + && cc1 -dumpdir dir/h- -dumpbase d.c -dumpbase-ext .c # dir/h-d.o
> + && link -o dir/h.out
> +
> + But then again, a single -dumpbase applying to multiple inputs
> + gets used instead of the linker output basename in the combined
> + dumpdir:
> +
> + # gcc [-dumpdir f] -dumpbase g- -save-temps=obj b.c d.c -o dir/h.out
> + -> cc1 -dumpdir dir/g- -dumpbase b.c -dumpbase-ext .c # dir/g-b.o
> + && cc1 -dumpdir dir/g- -dumpbase d.c -dumpbase-ext .c # dir/g-d.o
> + && link -o dir/h.out
> +
> + With a single input being compiled, the output basename does NOT
> + affect the dumpdir prefix.
> +
> + # gcc -save-temps=obj b.c -gsplit-dwarf -c -o dir/b.o
> + -> cc1 -dumpdir dir/ -dumpbase b.c -dumpbase-ext .c # dir/b.o dir/b.dwo
> +
> + but when compiling and linking even a single file, it does:
> +
> + # gcc -save-temps=obj b.c -o dir/h.out
> + -> cc1 -dumpdir dir/h- -dumpbase b.c -dumpbase-ext .c # dir/h-b.o
> +
> + unless an explicit -dumpdir prevails:
> +
> + # gcc -save-temps[=obj] -dumpdir g- b.c -o dir/h.out
> + -> cc1 -dumpdir g- -dumpbase b.c -dumpbase-ext .c # g-b.o
> +
> + */
> +
> + bool explicit_dumpdir = dumpdir;
> +
> + if (!save_temps_overrides_dumpdir && explicit_dumpdir)
> + {
> + /* Do nothing. */
> + }
> +
> /* If -save-temps=obj and -o name, create the prefix to use for %b.
> Otherwise just make -save-temps=obj the same as -save-temps=cwd. */
> - if (save_temps_flag == SAVE_TEMPS_OBJ && save_temps_prefix != NULL)
> + else if (save_temps_flag != SAVE_TEMPS_CWD && output_file != NULL)
> + {
> + free (dumpdir);
> + dumpdir = NULL;
> + temp = lbasename (output_file);
> + if (temp != output_file)
> + dumpdir = xstrndup (output_file,
> + strlen (output_file) - strlen (temp));
> + }
> + else if (dumpdir)
> + {
> + free (dumpdir);
> + dumpdir = NULL;
> + }
> +
> + if (save_temps_flag)
> + save_temps_flag = SAVE_TEMPS_DUMP;
> +
> + /* If there is any pathname component in an explicit -dumpbase, it
> + overrides dumpdir entirely, so discard it right away. Although
> + the presence of an explicit -dumpdir matters for the driver, it
> + shouldn't matter for other processes, that get all that's needed
> + from the -dumpdir and -dumpbase always passed to them. */
> + if (dumpdir && dumpbase && lbasename (dumpbase) != dumpbase)
> + {
> + free (dumpdir);
> + dumpdir = NULL;
> + }
> +
> + /* Check that dumpbase_ext matches the end of dumpbase, drop it
> + otherwise. */
> + if (dumpbase_ext && dumpbase && *dumpbase)
> + {
> + int lendb = strlen (dumpbase);
> + int lendbx = strlen (dumpbase_ext);
> +
> + if (lendbx >= lendb
> + || strcmp (dumpbase + lendb - lendbx, dumpbase_ext) != 0)
> + {
> + free (dumpbase_ext);
> + dumpbase_ext = NULL;
> + }
> + }
> +
> + /* -dumpbase with multiple sources goes into dumpdir. With a single
> + source, it does only if linking and if dumpdir was not explicitly
> + specified. */
> + if (dumpbase && *dumpbase
> + && (single_input_file_index () == -2
> + || (!have_c && !explicit_dumpdir)))
> + {
> + char *prefix;
> +
> + if (dumpbase_ext)
> + /* We checked that they match above. */
> + dumpbase[strlen (dumpbase) - strlen (dumpbase_ext)] = '\0';
> +
> + if (dumpdir)
> + prefix = concat (dumpdir, dumpbase, "-", NULL);
> + else
> + prefix = concat (dumpbase, "-", NULL);
> +
> + free (dumpdir);
> + free (dumpbase);
> + free (dumpbase_ext);
> + dumpbase = dumpbase_ext = NULL;
> + dumpdir = prefix;
> + dumpdir_trailing_dash_added = true;
> + }
> +
> + /* If dumpbase was not brought into dumpdir but we're linking, bring
> + output_file into dumpdir unless dumpdir was explicitly specified.
> + The test for !explicit_dumpdir is further below, because we want
> + to use the obase computation for a ghost outbase, passed to
> + GCC_COLLECT_OPTIONS. */
> + else if (!have_c && (!explicit_dumpdir || (dumpbase && !*dumpbase)))
> + {
> + /* If we get here, we know dumpbase was not specified, or it was
> + specified as an empty string. If it was anything else, it
> + would have combined with dumpdir above, because the condition
> + for dumpbase to be used when present is broader than the
> + condition that gets us here. */
> + gcc_assert (!dumpbase || !*dumpbase);
> +
> + const char *obase;
> + char *tofree = NULL;
> + if (!output_file || not_actual_file_p (output_file))
> + obase = "a";
> + else
> + {
> + obase = lbasename (output_file);
> + size_t blen = strlen (obase), xlen;
> + /* Drop the suffix if it's dumpbase_ext, if given,
> + otherwise .exe or the target executable suffix, or if the
> + output was explicitly named a.out, but not otherwise. */
> + if (dumpbase_ext
> + ? (blen > (xlen = strlen (dumpbase_ext))
> + && strcmp ((temp = (obase + blen - xlen)),
> + dumpbase_ext) == 0)
> + : ((temp = strrchr (obase + 1, '.'))
> + && (xlen = strlen (temp))
> + && (strcmp (temp, ".exe") == 0
> +#if HAVE_TARGET_EXECUTABLE_SUFFIX
> + || strcmp (temp, TARGET_EXECUTABLE_SUFFIX) == 0
> +#endif
> + || strcmp (obase, "a.out") == 0)))
> + {
> + tofree = xstrndup (obase, blen - xlen);
> + obase = tofree;
> + }
> + }
> +
> + /* We wish to save this basename to the -dumpdir passed through
> + GCC_COLLECT_OPTIONS within maybe_run_linker, for e.g. LTO,
> + but we do NOT wish to add it to e.g. %b, so we keep
> + outbase_length as zero. */
> + gcc_assert (!outbase);
> + outbase_length = 0;
> +
> + /* If we're building [dir1/]foo[.exe] out of a single input
> + [dir2/]foo.c that shares the same basename, dump to
> + [dir2/]foo.c.* rather than duplicating the basename into
> + [dir2/]foo-foo.c.*. */
> + int idxin;
> + if (dumpbase
> + || ((idxin = single_input_file_index ()) >= 0
> + && adds_single_suffix_p (lbasename (infiles[idxin].name),
> + obase)))
> + {
> + if (obase == tofree)
> + outbase = tofree;
> + else
> + {
> + outbase = xstrdup (obase);
> + free (tofree);
> + }
> + obase = tofree = NULL;
> + }
> + else
> + {
> + if (dumpdir)
> + {
> + char *p = concat (dumpdir, obase, "-", NULL);
> + free (dumpdir);
> + dumpdir = p;
> + }
> + else
> + dumpdir = concat (obase, "-", NULL);
> +
> + dumpdir_trailing_dash_added = true;
> +
> + free (tofree);
> + obase = tofree = NULL;
> + }
> +
> + if (!explicit_dumpdir || dumpbase)
> + {
> + /* Absent -dumpbase and present -dumpbase-ext have been applied
> + to the linker output name, so compute fresh defaults for each
> + compilation. */
> + free (dumpbase_ext);
> + dumpbase_ext = NULL;
> + }
> + }
> +
> + /* Now, if we're compiling, or if we haven't used the dumpbase
> + above, then outbase (%B) is derived from dumpbase, if given, or
> + from the output name, given or implied. We can't precompute
> + implied output names, but that's ok, since they're derived from
> + input names. Just make sure we skip this if dumpbase is the
> + empty string: we want to use input names then, so don't set
> + outbase. */
> + if ((dumpbase || have_c)
> + && !(dumpbase && !*dumpbase))
> {
> - save_temps_length = strlen (save_temps_prefix);
> - temp = strrchr (lbasename (save_temps_prefix), '.');
> - if (temp)
> + gcc_assert (!outbase);
> +
> + if (dumpbase)
> + {
> + gcc_assert (single_input_file_index () != -2);
> + /* We do not want lbasename here; dumpbase with dirnames
> + overrides dumpdir entirely, even if dumpdir is
> + specified. */
> + if (dumpbase_ext)
> + /* We've already checked above that the suffix matches. */
> + outbase = xstrndup (dumpbase,
> + strlen (dumpbase) - strlen (dumpbase_ext));
> + else
> + outbase = xstrdup (dumpbase);
> + }
> + else if (output_file && !not_actual_file_p (output_file))
> {
> - save_temps_length -= strlen (temp);
> - save_temps_prefix[save_temps_length] = '\0';
> + outbase = xstrdup (lbasename (output_file));
> + char *p = strrchr (outbase + 1, '.');
> + if (p)
> + *p = '\0';
> }
>
> + if (outbase)
> + outbase_length = strlen (outbase);
> }
> - else if (save_temps_prefix != NULL)
> +
> + /* If there is any pathname component in an explicit -dumpbase, do
> + not use dumpdir, but retain it to pass it on to the compiler. */
> + if (dumpdir)
> + dumpdir_length = strlen (dumpdir);
> + else
> + dumpdir_length = 0;
> +
> + /* Check that dumpbase_ext, if still present, still matches the end
> + of dumpbase, if present, and drop it otherwise. We only retained
> + it above when dumpbase was absent to maybe use it to drop the
> + extension from output_name before combining it with dumpdir. */
> + if (dumpbase_ext)
> {
> - free (save_temps_prefix);
> - save_temps_prefix = NULL;
> + if (!dumpbase)
> + {
> + free (dumpbase_ext);
> + dumpbase_ext = NULL;
> + }
> + else
> + gcc_assert (strcmp (dumpbase + strlen (dumpbase)
> + - strlen (dumpbase_ext), dumpbase_ext) == 0);
> }
>
> if (save_temps_flag && use_pipes)
> @@ -4843,6 +5277,28 @@ set_collect_gcc_options (void)
> obstack_grow (&collect_obstack, "'", 1);
> }
> }
> +
> + if (dumpdir)
> + {
> + if (!first_time)
> + obstack_grow (&collect_obstack, " ", 1);
> + first_time = FALSE;
> +
> + obstack_grow (&collect_obstack, "'-dumpdir' '", 12);
> + const char *p, *q;
> +
> + q = dumpdir;
> + while ((p = strchr (q, '\'')))
> + {
> + obstack_grow (&collect_obstack, q, p - q);
> + obstack_grow (&collect_obstack, "'\\''", 4);
> + q = ++p;
> + }
> + obstack_grow (&collect_obstack, q, strlen (q));
> +
> + obstack_grow (&collect_obstack, "'", 1);
> + }
> +
> obstack_grow (&collect_obstack, "\0", 1);
> xputenv (XOBFINISH (&collect_obstack, char *));
> }
> @@ -5333,22 +5789,33 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
> fatal_error (input_location, "spec %qs invalid", spec);
>
> case 'b':
> - if (save_temps_length)
> - obstack_grow (&obstack, save_temps_prefix, save_temps_length);
> - else
> + /* Don't use %b in the linker command. */
> + gcc_assert (suffixed_basename_length);
> + if (!this_is_output_file && dumpdir_length)
> + obstack_grow (&obstack, dumpdir, dumpdir_length);
> + if (this_is_output_file || !outbase_length)
> obstack_grow (&obstack, input_basename, basename_length);
> + else
> + obstack_grow (&obstack, outbase, outbase_length);
> if (compare_debug < 0)
> obstack_grow (&obstack, ".gk", 3);
> arg_going = 1;
> break;
>
> case 'B':
> - if (save_temps_length)
> - obstack_grow (&obstack, save_temps_prefix, save_temps_length);
> + /* Don't use %B in the linker command. */
> + gcc_assert (suffixed_basename_length);
> + if (!this_is_output_file && dumpdir_length)
> + obstack_grow (&obstack, dumpdir, dumpdir_length);
> + if (this_is_output_file || !outbase_length)
> + obstack_grow (&obstack, input_basename, basename_length);
> else
> - obstack_grow (&obstack, input_basename, suffixed_basename_length);
> + obstack_grow (&obstack, outbase, outbase_length);
> if (compare_debug < 0)
> obstack_grow (&obstack, ".gk", 3);
> + obstack_grow (&obstack, input_basename + basename_length,
> + suffixed_basename_length - basename_length);
> +
> arg_going = 1;
> break;
>
> @@ -5501,42 +5968,44 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
> suffix_length += 3;
> }
>
> - /* If -save-temps=obj and -o were specified, use that for the
> + /* If -save-temps was specified, use that for the
> temp file. */
> - if (save_temps_length)
> - {
> - char *tmp;
> - temp_filename_length
> - = save_temps_length + suffix_length + 1;
> - tmp = (char *) alloca (temp_filename_length);
> - memcpy (tmp, save_temps_prefix, save_temps_length);
> - memcpy (tmp + save_temps_length, suffix, suffix_length);
> - tmp[save_temps_length + suffix_length] = '\0';
> - temp_filename = save_string (tmp, save_temps_length
> - + suffix_length);
> - obstack_grow (&obstack, temp_filename,
> - temp_filename_length);
> - arg_going = 1;
> - delete_this_arg = 0;
> - break;
> - }
> -
> - /* If the gcc_input_filename has the same suffix specified
> - for the %g, %u, or %U, and -save-temps is specified,
> - we could end up using that file as an intermediate
> - thus clobbering the user's source file (.e.g.,
> - gcc -save-temps foo.s would clobber foo.s with the
> - output of cpp0). So check for this condition and
> - generate a temp file as the intermediate. */
> -
> if (save_temps_flag)
> {
> char *tmp;
> - temp_filename_length = basename_length + suffix_length + 1;
> + bool adjusted_suffix = false;
> + if (suffix_length
> + && !outbase_length && !basename_length
> + && !dumpdir_trailing_dash_added)
> + {
> + adjusted_suffix = true;
> + suffix++;
> + suffix_length--;
> + }
> + temp_filename_length
> + = dumpdir_length + suffix_length + 1;
> + if (!outbase_length)
> + temp_filename_length += basename_length;
> + else
> + temp_filename_length += outbase_length;
> tmp = (char *) alloca (temp_filename_length);
> - memcpy (tmp, input_basename, basename_length);
> - memcpy (tmp + basename_length, suffix, suffix_length);
> - tmp[basename_length + suffix_length] = '\0';
> + if (dumpdir_length)
> + memcpy (tmp, dumpdir, dumpdir_length);
> + if (!outbase_length)
> + memcpy (tmp + dumpdir_length, input_basename,
> + basename_length);
> + else
> + memcpy (tmp + dumpdir_length, outbase,
> + outbase_length);
> + memcpy (tmp + temp_filename_length - suffix_length - 1,
> + suffix, suffix_length);
> + if (adjusted_suffix)
> + {
> + adjusted_suffix = false;
> + suffix--;
> + suffix_length++;
> + }
> + tmp[temp_filename_length - 1] = '\0';
> temp_filename = tmp;
>
> if (filename_cmp (temp_filename, gcc_input_filename) != 0)
> @@ -6047,6 +6516,14 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
> }
> break;
>
> + case '"':
> + /* End a previous argument, if there is one, then issue an
> + empty argument. */
> + end_going_arg ();
> + arg_going = 1;
> + end_going_arg ();
> + break;
> +
> default:
> error ("spec failure: unrecognized spec option %qc", c);
> break;
> @@ -6057,6 +6534,9 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
> /* Backslash: treat next character as ordinary. */
> c = *p++;
>
> + /* When adding more cases that previously matched default, make
> + sure to adjust quote_spec_char_p as well. */
> +
> /* Fall through. */
> default:
> /* Ordinary character: put it into the current argument. */
> @@ -8262,6 +8742,40 @@ driver::maybe_run_linker (const char *argv0) const
> if (explicit_link_files[i] || outfiles[i] != NULL)
> num_linker_inputs++;
>
> + /* Arrange for temporary file names created during linking to take
> + on names related with the linker output rather than with the
> + inputs when appropriate. */
> + if (outbase && *outbase)
> + {
> + if (dumpdir)
> + {
> + char *tofree = dumpdir;
> + gcc_checking_assert (strlen (dumpdir) == dumpdir_length);
> + dumpdir = concat (dumpdir, outbase, ".", NULL);
> + free (tofree);
> + }
> + else
> + dumpdir = concat (outbase, ".", NULL);
> + dumpdir_length += strlen (outbase) + 1;
> + dumpdir_trailing_dash_added = true;
> + }
> + else if (dumpdir_trailing_dash_added)
> + {
> + gcc_assert (dumpdir[dumpdir_length - 1] == '-');
> + dumpdir[dumpdir_length - 1] = '.';
> + }
> +
> + if (dumpdir_trailing_dash_added)
> + {
> + gcc_assert (dumpdir_length > 0);
> + gcc_assert (dumpdir[dumpdir_length - 1] == '.');
> + dumpdir_length--;
> + }
> +
> + free (outbase);
> + input_basename = outbase = NULL;
> + outbase_length = suffixed_basename_length = basename_length = 0;
> +
> /* Run ld to link all the compiler output files. */
>
> if (num_linker_inputs > 0 && !seen_error () && print_subprocess_help < 2)
> @@ -9732,7 +10246,7 @@ compare_debug_dump_opt_spec_function (int arg,
> do_spec_1 (" ", 0, NULL);
>
> if (argbuf.length () > 0
> - && strcmp (argv[argbuf.length () - 1], "."))
> + && strcmp (argv[argbuf.length () - 1], ".") != 0)
> {
> if (!compare_debug)
> return NULL;
> @@ -9742,25 +10256,22 @@ compare_debug_dump_opt_spec_function (int arg,
> }
> else
> {
> - const char *ext = NULL;
> -
> if (argbuf.length () > 0)
> - {
> - do_spec_2 ("%{o*:%*}%{!o:%{!S:%b%O}%{S:%b.s}}", NULL);
> - ext = ".gkd";
> - }
> + do_spec_2 ("%B.gkd", NULL);
> else if (!compare_debug)
> return NULL;
> else
> - do_spec_2 ("%g.gkd", NULL);
> + do_spec_2 ("%{!save-temps*:%g.gkd}%{save-temps*:%B.gkd}", NULL);
>
> do_spec_1 (" ", 0, NULL);
>
> gcc_assert (argbuf.length () > 0);
>
> - name = concat (argbuf.last (), ext, NULL);
> + name = xstrdup (argbuf.last ());
>
> - ret = concat ("-fdump-final-insns=", name, NULL);
> + char *arg = quote_spec (xstrdup (name));
> + ret = concat ("-fdump-final-insns=", arg, NULL);
> + free (arg);
> }
>
> which = compare_debug < 0;
> @@ -9787,8 +10298,6 @@ compare_debug_dump_opt_spec_function (int arg,
> return ret;
> }
>
> -static const char *debug_auxbase_opt;
> -
> /* %:compare-debug-self-opt spec function. Expands to the options
> that are to be passed in the second compilation of
> compare-debug. */
> @@ -9804,16 +10313,6 @@ compare_debug_self_opt_spec_function (int arg,
> if (compare_debug >= 0)
> return NULL;
>
> - do_spec_2 ("%{c|S:%{o*:%*}}", NULL);
> - do_spec_1 (" ", 0, NULL);
> -
> - if (argbuf.length () > 0)
> - debug_auxbase_opt = concat ("-auxbase-strip ",
> - argbuf.last (),
> - NULL);
> - else
> - debug_auxbase_opt = NULL;
> -
> return concat ("\
> %<o %<MD %<MMD %<MF* %<MG %<MP %<MQ* %<MT* \
> %<fdump-final-insns=* -w -S -o %j \
> @@ -9821,50 +10320,6 @@ compare_debug_self_opt_spec_function (int arg,
> ", compare_debug_opt, NULL);
> }
>
> -/* %:compare-debug-auxbase-opt spec function. Expands to the auxbase
> - options that are to be passed in the second compilation of
> - compare-debug. It expects, as an argument, the basename of the
> - current input file name, with the .gk suffix appended to it. */
> -
> -static const char *
> -compare_debug_auxbase_opt_spec_function (int arg,
> - const char **argv)
> -{
> - char *name;
> - int len;
> -
> - if (arg == 0)
> - fatal_error (input_location,
> - "too few arguments to %%:compare-debug-auxbase-opt");
> -
> - if (arg != 1)
> - fatal_error (input_location,
> - "too many arguments to %%:compare-debug-auxbase-opt");
> -
> - if (compare_debug >= 0)
> - return NULL;
> -
> - len = strlen (argv[0]);
> - if (len < 3 || strcmp (argv[0] + len - 3, ".gk") != 0)
> - fatal_error (input_location, "argument to %%:compare-debug-auxbase-opt "
> - "does not end in %<.gk%>");
> -
> - if (debug_auxbase_opt)
> - return debug_auxbase_opt;
> -
> -#define OPT "-auxbase "
> -
> - len -= 3;
> - name = (char*) xmalloc (sizeof (OPT) + len);
> - memcpy (name, OPT, sizeof (OPT) - 1);
> - memcpy (name + sizeof (OPT) - 1, argv[0], len);
> - name[sizeof (OPT) - 1 + len] = '\0';
> -
> -#undef OPT
> -
> - return name;
> -}
> -
> /* %:pass-through-libs spec function. Finds all -l options and input
> file names in the lib spec passed to it, and makes a list of them
> prepended with the plugin option to cause them to be passed through
> @@ -9908,34 +10363,105 @@ pass_through_libs_spec_func (int argc, const char **argv)
> return prepended;
> }
>
> -/* %:replace-extension spec function. Replaces the extension of the
> - first argument with the second argument. */
> +static bool
> +not_actual_file_p (const char *name)
> +{
> + return (strcmp (name, "-") == 0
> + || strcmp (output_file, HOST_BIT_BUCKET) == 0);
> +}
>
> +/* %:dumps spec function. Take an optional argument that overrides
> + the default extension for -dumpbase and -dumpbase-ext.
> + Return -dumpdir, -dumpbase and -dumpbase-ext, if needed. */
> const char *
> -replace_extension_spec_func (int argc, const char **argv)
> +dumps_spec_func (int argc, const char **argv ATTRIBUTE_UNUSED)
> {
> - char *name;
> + const char *ext = dumpbase_ext;
> char *p;
> - char *result;
> - int i;
>
> - if (argc != 2)
> - fatal_error (input_location, "too few arguments to %%:replace-extension");
> + char *args[3] = { NULL, NULL, NULL };
> + int nargs = 0;
>
> - name = xstrdup (argv[0]);
> + /* Do not compute a default for -dumpbase-ext when -dumpbase was
> + given explicitly. */
> + if (dumpbase && *dumpbase && !ext)
> + ext = "";
>
> - for (i = strlen (name) - 1; i >= 0; i--)
> - if (IS_DIR_SEPARATOR (name[i]))
> - break;
> + if (argc == 1)
> + {
> + /* Do not override the explicitly-specified -dumpbase-ext with
> + the specs-provided overrider. */
> + if (!ext)
> + ext = argv[0];
> + }
> + else if (argc != 0)
> + fatal_error (input_location, "too many arguments for %%:dumps");
>
> - p = strrchr (name + i + 1, '.');
> - if (p != NULL)
> - *p = '\0';
> + if (dumpdir)
> + {
> + p = quote_spec_arg (xstrdup (dumpdir));
> + args[nargs++] = concat (" -dumpdir ", p, NULL);
> + free (p);
> + }
>
> - result = concat (name, argv[1], NULL);
> + if (!ext)
> + ext = input_basename + basename_length;
>
> - free (name);
> - return result;
> + /* Use the precomputed outbase, or compute dumpbase from
> + input_basename, just like %b would. */
> + char *base;
> +
> + if (dumpbase && *dumpbase)
> + {
> + base = xstrdup (dumpbase);
> + p = base + outbase_length;
> + gcc_checking_assert (strncmp (base, outbase, outbase_length) == 0);
> + gcc_checking_assert (strcmp (p, ext) == 0);
> + }
> + else if (outbase_length)
> + {
> + base = xstrndup (outbase, outbase_length);
> + p = NULL;
> + }
> + else
> + {
> + base = xstrndup (input_basename, suffixed_basename_length);
> + p = base + basename_length;
> + }
> +
> + if (compare_debug < 0 || !p || strcmp (p, ext) != 0)
> + {
> + if (p)
> + *p = '\0';
> +
> + const char *gk;
> + if (compare_debug < 0)
> + gk = ".gk";
> + else
> + gk = "";
> +
> + p = concat (base, gk, ext, NULL);
> +
> + free (base);
> + base = p;
> + }
> +
> + base = quote_spec_arg (base);
> + args[nargs++] = concat (" -dumpbase ", base, NULL);
> + free (base);
> +
> + if (*ext)
> + {
> + p = quote_spec_arg (xstrdup (ext));
> + args[nargs++] = concat (" -dumpbase-ext ", p, NULL);
> + free (p);
> + }
> +
> + const char *ret = concat (args[0], args[1], args[2], NULL);
> + while (nargs > 0)
> + free (args[--nargs]);
> +
> + return ret;
> }
>
> /* Returns "" if ARGV[ARGC - 2] is greater than ARGV[ARGC-1].
> @@ -10041,6 +10567,44 @@ find_fortran_preinclude_file (int argc, const char **argv)
> return result;
> }
>
> +/* If any character in ORIG fits QUOTE_P (_, P), reallocate the string
> + so as to precede every one of them with a backslash. Return the
> + original string or the reallocated one. */
> +
> +static inline char *
> +quote_string (char *orig, bool (*quote_p)(char, void *), void *p)
> +{
> + int len, number_of_space = 0;
> +
> + for (len = 0; orig[len]; len++)
> + if (quote_p (orig[len], p))
> + number_of_space++;
> +
> + if (number_of_space)
> + {
> + char *new_spec = (char *) xmalloc (len + number_of_space + 1);
> + int j, k;
> + for (j = 0, k = 0; j <= len; j++, k++)
> + {
> + if (quote_p (orig[j], p))
> + new_spec[k++] = '\\';
> + new_spec[k] = orig[j];
> + }
> + free (orig);
> + return new_spec;
> + }
> + else
> + return orig;
> +}
> +
> +/* Return true iff C is any of the characters convert_white_space
> + should quote. */
> +
> +static inline bool
> +whitespace_to_convert_p (char c, void *)
> +{
> + return (c == ' ' || c == '\t');
> +}
>
> /* Insert backslash before spaces in ORIG (usually a file path), to
> avoid being broken by spec parser.
> @@ -10068,26 +10632,50 @@ find_fortran_preinclude_file (int argc, const char **argv)
> static char *
> convert_white_space (char *orig)
> {
> - int len, number_of_space = 0;
> + return quote_string (orig, whitespace_to_convert_p, NULL);
> +}
>
> - for (len = 0; orig[len]; len++)
> - if (orig[len] == ' ' || orig[len] == '\t') number_of_space++;
> +/* Return true iff C matches any of the spec active characters. */
> +static inline bool
> +quote_spec_char_p (char c, void *)
> +{
> + switch (c)
> + {
> + case ' ':
> + case '\t':
> + case '\n':
> + case '|':
> + case '%':
> + case '\\':
> + return true;
>
> - if (number_of_space)
> + default:
> + return false;
> + }
> +}
> +
> +/* Like convert_white_space, but deactivate all active spec chars by
> + quoting them. */
> +
> +static inline char *
> +quote_spec (char *orig)
> +{
> + return quote_string (orig, quote_spec_char_p, NULL);
> +}
> +
> +/* Like quote_spec, but also turn an empty string into the spec for an
> + empty argument. */
> +
> +static inline char *
> +quote_spec_arg (char *orig)
> +{
> + if (!*orig)
> {
> - char *new_spec = (char *) xmalloc (len + number_of_space + 1);
> - int j, k;
> - for (j = 0, k = 0; j <= len; j++, k++)
> - {
> - if (orig[j] == ' ' || orig[j] == '\t')
> - new_spec[k++] = '\\';
> - new_spec[k] = orig[j];
> - }
> free (orig);
> - return new_spec;
> - }
> - else
> - return orig;
> + return xstrdup ("%\"");
> + }
> +
> + return quote_spec (orig);
> }
>
> /* Restore all state within gcc.c to the initial state, so that the driver
> @@ -10124,8 +10712,14 @@ driver::finalize ()
> target_sysroot_suffix = 0;
> target_sysroot_hdrs_suffix = 0;
> save_temps_flag = SAVE_TEMPS_NONE;
> - save_temps_prefix = 0;
> - save_temps_length = 0;
> + save_temps_overrides_dumpdir = false;
> + dumpdir_trailing_dash_added = false;
> + free (dumpdir);
> + free (dumpbase);
> + free (dumpbase_ext);
> + free (outbase);
> + dumpdir = dumpbase = dumpbase_ext = outbase = NULL;
> + dumpdir_length = outbase_length = 0;
> spec_machine = DEFAULT_TARGET_MACHINE;
> greatest_status = 1;
>
> @@ -10264,8 +10858,6 @@ driver::finalize ()
> mdswitches = NULL;
> n_mdswitches = 0;
>
> - debug_auxbase_opt = NULL;
> -
> used_arg.finalize ();
> }
>
> diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c
> index fe8f292..ed076e3 100644
> --- a/gcc/lto-wrapper.c
> +++ b/gcc/lto-wrapper.c
> @@ -125,7 +125,7 @@ maybe_unlink (const char *file)
> }
>
> /* Template of LTRANS dumpbase suffix. */
> -#define DUMPBASE_SUFFIX ".ltrans18446744073709551615"
> +#define DUMPBASE_SUFFIX "ltrans18446744073709551615"
>
> /* Create decoded options from the COLLECT_GCC and COLLECT_GCC_OPTIONS
> environment. */
> @@ -1081,12 +1081,7 @@ debug_objcopy (const char *infile, bool rename)
> }
>
> if (save_temps)
> - {
> - outfile = (char *) xmalloc (strlen (orig_infile)
> - + sizeof (".debug.temp.o") + 1);
> - strcpy (outfile, orig_infile);
> - strcat (outfile, ".debug.temp.o");
> - }
> + outfile = concat (orig_infile, ".debug.temp.o", NULL);
> else
> outfile = make_temp_file (".debug.temp.o");
> errmsg = simple_object_copy_lto_debug_sections (inobj, outfile, &err, rename);
> @@ -1271,6 +1266,8 @@ run_gcc (unsigned argc, char *argv[])
> bool linker_output_rel = false;
> bool skip_debug = false;
> unsigned n_debugobj;
> + const char *dumppfx = NULL, *incoming_dumppfx = NULL;
> + static char current_dir[] = { '.', DIR_SEPARATOR, '\0' };
>
> /* Get the driver and options. */
> collect_gcc = getenv ("COLLECT_GCC");
> @@ -1362,6 +1359,10 @@ run_gcc (unsigned argc, char *argv[])
> linker_output = option->arg;
> break;
>
> + /* We don't have to distinguish between -save-temps=* and
> + -save-temps, -dumpdir already carries that
> + information. */
> + case OPT_save_temps_:
> case OPT_save_temps:
> save_temps = 1;
> break;
> @@ -1407,6 +1408,10 @@ run_gcc (unsigned argc, char *argv[])
> skip_debug = option->arg && !strcmp (option->arg, "0");
> break;
>
> + case OPT_dumpdir:
> + incoming_dumppfx = dumppfx = option->arg;
> + break;
> +
> default:
> break;
> }
> @@ -1439,32 +1444,50 @@ run_gcc (unsigned argc, char *argv[])
> jobserver = 1;
> }
>
> - if (linker_output)
> + if (!dumppfx)
> {
> - char *output_dir, *base, *name;
> - bool bit_bucket = strcmp (linker_output, HOST_BIT_BUCKET) == 0;
> -
> - output_dir = xstrdup (linker_output);
> - base = output_dir;
> - for (name = base; *name; name++)
> - if (IS_DIR_SEPARATOR (*name))
> - base = name + 1;
> - *base = '\0';
> -
> - linker_output = &linker_output[base - output_dir];
> - if (*output_dir == '\0')
> - {
> - static char current_dir[] = { '.', DIR_SEPARATOR, '\0' };
> - output_dir = current_dir;
> - }
> - if (!bit_bucket)
> + if (!linker_output
> + || strcmp (linker_output, HOST_BIT_BUCKET) == 0)
> + dumppfx = "a.";
> + else
> {
> - obstack_ptr_grow (&argv_obstack, "-dumpdir");
> - obstack_ptr_grow (&argv_obstack, output_dir);
> + const char *obase = lbasename (linker_output), *temp;
> +
> + /* Strip the executable extension. */
> + size_t blen = strlen (obase), xlen;
> + if ((temp = strrchr (obase + 1, '.'))
> + && (xlen = strlen (temp))
> + && (strcmp (temp, ".exe") == 0
> +#if HAVE_TARGET_EXECUTABLE_SUFFIX
> + || strcmp (temp, TARGET_EXECUTABLE_SUFFIX) == 0
> +#endif
> + || strcmp (obase, "a.out") == 0))
> + dumppfx = xstrndup (linker_output,
> + obase - linker_output + blen - xlen + 1);
> + else
> + dumppfx = concat (linker_output, ".", NULL);
> }
> + }
>
> - obstack_ptr_grow (&argv_obstack, "-dumpbase");
> + /* If there's no directory component in the dumppfx, add one, so
> + that, when it is used as -dumpbase, it overrides any occurrence
> + of -dumpdir that might have been passed in. */
> + if (!dumppfx || lbasename (dumppfx) == dumppfx)
> + dumppfx = concat (current_dir, dumppfx, NULL);
> +
> + /* Make sure some -dumpdir is passed, so as to get predictable
> + -dumpbase overriding semantics. If we got an incoming -dumpdir
> + argument, we'll pass it on, so don't bother with another one
> + then. */
> + if (!incoming_dumppfx)
> + {
> + obstack_ptr_grow (&argv_obstack, "-dumpdir");
> + /* An empty string would do, if only writeargv would write it
> + out in a way that would not be skipped by expandargv and
> + buildargv. */
> + obstack_ptr_grow (&argv_obstack, current_dir);
> }
> + obstack_ptr_grow (&argv_obstack, "-dumpbase");
>
> /* Remember at which point we can scrub args to re-use the commons. */
> new_head_argc = obstack_object_size (&argv_obstack) / sizeof (void *);
> @@ -1570,15 +1593,11 @@ cont1:
>
> if (lto_mode == LTO_MODE_LTO)
> {
> - if (linker_output)
> - {
> - obstack_ptr_grow (&argv_obstack, linker_output);
> - flto_out = (char *) xmalloc (strlen (linker_output)
> - + sizeof (".lto.o") + 1);
> - strcpy (flto_out, linker_output);
> - strcat (flto_out, ".lto.o");
> - }
> - else
> + /* -dumpbase argument for LTO. */
> + flto_out = concat (dumppfx, "lto.o", NULL);
> + obstack_ptr_grow (&argv_obstack, flto_out);
> +
> + if (!save_temps)
> flto_out = make_temp_file (".lto.o");
> obstack_ptr_grow (&argv_obstack, "-o");
> obstack_ptr_grow (&argv_obstack, flto_out);
> @@ -1586,47 +1605,17 @@ cont1:
> else
> {
> const char *list_option = "-fltrans-output-list=";
> - size_t list_option_len = strlen (list_option);
> - char *tmp;
>
> - if (linker_output)
> - {
> - char *dumpbase = (char *) xmalloc (strlen (linker_output)
> - + sizeof (".wpa") + 1);
> - strcpy (dumpbase, linker_output);
> - strcat (dumpbase, ".wpa");
> - obstack_ptr_grow (&argv_obstack, dumpbase);
> - }
> + /* -dumpbase argument for WPA. */
> + char *dumpbase = concat (dumppfx, "wpa", NULL);
> + obstack_ptr_grow (&argv_obstack, dumpbase);
>
> - if (linker_output && save_temps)
> - {
> - ltrans_output_file = (char *) xmalloc (strlen (linker_output)
> - + sizeof (".ltrans.out") + 1);
> - strcpy (ltrans_output_file, linker_output);
> - strcat (ltrans_output_file, ".ltrans.out");
> - }
> + if (save_temps)
> + ltrans_output_file = concat (dumppfx, "ltrans.out", NULL);
> else
> - {
> - char *prefix = NULL;
> - if (linker_output)
> - {
> - prefix = (char *) xmalloc (strlen (linker_output) + 2);
> - strcpy (prefix, linker_output);
> - strcat (prefix, ".");
> - }
> -
> - ltrans_output_file = make_temp_file_with_prefix (prefix,
> - ".ltrans.out");
> - free (prefix);
> - }
> - list_option_full = (char *) xmalloc (sizeof (char) *
> - (strlen (ltrans_output_file) + list_option_len + 1));
> - tmp = list_option_full;
> -
> - obstack_ptr_grow (&argv_obstack, tmp);
> - strcpy (tmp, list_option);
> - tmp += list_option_len;
> - strcpy (tmp, ltrans_output_file);
> + ltrans_output_file = make_temp_file (".ltrans.out");
> + list_option_full = concat (list_option, ltrans_output_file, NULL);
> + obstack_ptr_grow (&argv_obstack, list_option_full);
>
> if (jobserver)
> {
> @@ -1782,16 +1771,10 @@ cont:
> output_name = XOBFINISH (&env_obstack, char *);
>
> /* Adjust the dumpbase if the linker output file was seen. */
> - if (linker_output)
> - {
> - char *dumpbase
> - = (char *) xmalloc (strlen (linker_output)
> - + sizeof (DUMPBASE_SUFFIX) + 1);
> - snprintf (dumpbase,
> - strlen (linker_output) + sizeof (DUMPBASE_SUFFIX),
> - "%s.ltrans%u", linker_output, i);
> - argv_ptr[0] = dumpbase;
> - }
> + int dumpbase_len = (strlen (dumppfx) + sizeof (DUMPBASE_SUFFIX));
> + char *dumpbase = (char *) xmalloc (dumpbase_len + 1);
> + snprintf (dumpbase, dumpbase_len, "%sltrans%u.ltrans", dumppfx, i);
> + argv_ptr[0] = dumpbase;
>
> argv_ptr[1] = "-fltrans";
> argv_ptr[2] = "-o";
> diff --git a/gcc/opts.c b/gcc/opts.c
> index fa4804c..5b29b98 100644
> --- a/gcc/opts.c
> +++ b/gcc/opts.c
> @@ -845,30 +845,6 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
> /* We have a DUMP_DIR_NAME, prepend that. */
> opts->x_dump_base_name = opts_concat (opts->x_dump_dir_name,
> opts->x_dump_base_name, NULL);
> - else if (opts->x_aux_base_name
> - && strcmp (opts->x_aux_base_name, HOST_BIT_BUCKET) != 0)
> - /* AUX_BASE_NAME is set and is not the bit bucket. If it
> - contains a directory component, prepend those directories.
> - Typically this places things in the same directory as the
> - object file. */
> - {
> - const char *aux_base;
> -
> - base_of_path (opts->x_aux_base_name, &aux_base);
> - if (opts->x_aux_base_name != aux_base)
> - {
> - int dir_len = aux_base - opts->x_aux_base_name;
> - char *new_dump_base_name
> - = XOBNEWVEC (&opts_obstack, char,
> - strlen (opts->x_dump_base_name) + dir_len + 1);
> -
> - /* Copy directory component from OPTS->X_AUX_BASE_NAME. */
> - memcpy (new_dump_base_name, opts->x_aux_base_name, dir_len);
> - /* Append existing OPTS->X_DUMP_BASE_NAME. */
> - strcpy (new_dump_base_name + dir_len, opts->x_dump_base_name);
> - opts->x_dump_base_name = new_dump_base_name;
> - }
> - }
>
> /* It is definitely prefixed now. */
> opts->x_dump_base_name_prefixed = true;
> @@ -2314,17 +2290,6 @@ common_handle_option (struct gcc_options *opts,
> opts->x_flag_gen_aux_info = 1;
> break;
>
> - case OPT_auxbase_strip:
> - {
> - char *tmp = xstrdup (arg);
> - strip_off_ending (tmp, strlen (tmp));
> - if (tmp[0])
> - opts->x_aux_base_name = tmp;
> - else
> - free (tmp);
> - }
> - break;
> -
> case OPT_d:
> decode_d_option (arg, opts, loc, dc);
> break;
> diff --git a/gcc/testsuite/gcc.misc-tests/outputs-0.c b/gcc/testsuite/gcc.misc-tests/outputs-0.c
> new file mode 100644
> index 00000000..ca2ac4a
> --- /dev/null
> +++ b/gcc/testsuite/gcc.misc-tests/outputs-0.c
> @@ -0,0 +1 @@
> +int main () {}
> diff --git a/gcc/testsuite/gcc.misc-tests/outputs-1.c b/gcc/testsuite/gcc.misc-tests/outputs-1.c
> new file mode 100644
> index 00000000..35f19cf
> --- /dev/null
> +++ b/gcc/testsuite/gcc.misc-tests/outputs-1.c
> @@ -0,0 +1,4 @@
> +extern void f();
> +int main() {
> + f();
> +}
> diff --git a/gcc/testsuite/gcc.misc-tests/outputs-2.c b/gcc/testsuite/gcc.misc-tests/outputs-2.c
> new file mode 100644
> index 00000000..109733d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.misc-tests/outputs-2.c
> @@ -0,0 +1,2 @@
> +void f() {
> +}
> diff --git a/gcc/testsuite/gcc.misc-tests/outputs.exp b/gcc/testsuite/gcc.misc-tests/outputs.exp
> new file mode 100644
> index 00000000..a37e978
> --- /dev/null
> +++ b/gcc/testsuite/gcc.misc-tests/outputs.exp
> @@ -0,0 +1,655 @@
> +# Copyright (C) 2005-2020 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 of the License, 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 GCC; see the file COPYING3. If not see
> +# <http://www.gnu.org/licenses/>.
> +
> +# This file contains a set of test that check that options intended to
> +# control the location and name of GCC outputs behave as expected.
> +
> +load_lib gcc-defs.exp
> +
> +set b "outputs"
> +
> +# These tests don't run runtest_file_p consistently if it
> +# doesn't return the same values, so disable parallelization
> +# of this *.exp file. The first parallel runtest to reach
> +# this will run all the tests serially.
> +if ![gcc_parallel_test_run_p $b] {
> + return
> +}
> +gcc_parallel_test_enable 0
> +
> +# For the test named TEST, run the compiler with SOURCES and OPTS, and
> +# look in DIRS for OUTPUTS. SOURCES is a list of suffixes for source
> +# files starting with $b in $srcdir/$subdir, OPTS is a string with
> +# options to be passed to the compiler, DIRS and OUTPUTS are lists.
> +# DIRS is a list of output directories, children before parent, and
> +# for each element of DIRS, there should be a corresponding sublist in
> +# OUTPUTS. If OUTPUTS has an additional trailing sublist, that's the
> +# output list for the current directory. Each element of the sublists
> +# in OUTPUT is a file name or glob pattern to be checked for; a name
> +# starting with a dash or a period is taken as a suffix for $b; with a
> +# double dash, or a dash followed by a period, the first dash is
> +# replaced with $b-$b; names starting with "a--" or "a-." have "$b"
> +# inserted after the first dash. The glob pattern may expand to more
> +# than one file, but then the test will pass when there any number of
> +# matches. So, it's safe to use for a.{out,exe}, but .{i,s,o} and
> +# .[iso] will pass even if only the .o is present.
> +proc outest { test sources opts dirs outputs } {
> + global b
> + global srcdir
> + global subdir
> + set src {}
> + foreach s $sources {
> + lappend src $srcdir/$subdir/$b$s
> + }
> + foreach f [glob -nocomplain -path $b -- *] {
> + file delete $f
> + }
> + foreach d $dirs {
> + file mkdir $d
> + foreach f [glob -nocomplain -path $d -- *] {
> + file delete $d$f
> + }
> + }
> + set options ""
> + foreach opt [split $opts " "] {
> + set options "$options additional_flags=$opt"
> + }
> + set gcc_output [gcc_target_compile $src "" none "$options"]
> + set outs {}
> + foreach d $dirs olist $outputs {
> + foreach og $olist {
> + if { [string index $og 0] == "-" } then {
> + if { [string index $og 1] == "-" || \
> + [string index $og 1] == "." } then {
> + set o "$b-$b[string range $og 1 end]"
> + } else {
> + set o "$b$og"
> + }
> + } elseif { [string index $og 0] == "." } then {
> + set o "$b$og"
> + } elseif { [string range $og 0 2] == "a--" } then {
> + set o "a-$b-[string range $og 3 end]"
> + } elseif { [string range $og 0 2] == "a-." } then {
> + set o "a-$b.[string range $og 3 end]"
> + } else {
> + set o "$og"
> + }
> + if { [file exists $d$o] } then {
> + pass "$test: $d$o"
> + file delete $d$o
> + } else {
> + set ogl [glob -nocomplain -path $d -- $o]
> + if { $ogl != {} } {
> + pass "$test: $d$o"
> + file delete $ogl
> + } else {
> + fail "$test: $d$o"
> + }
> + }
> + }
> + foreach ol [glob -nocomplain -path $d$b -- *] {
> + lappend outs $ol
> + }
> + foreach ol [glob -nocomplain -path $d -- a{-,.}*] {
> + lappend outs $ol
> + }
> + }
> +
> + foreach f $outs {
> + file delete $f
> + }
> + foreach d $dirs {
> + file delete -force $d
> + }
> +
> + if { [llength $outs] == 0 } then {
> + pass "$test: extra"
> + } else {
> + fail "$test: extra $outs"
> + }
> +
> + if { [string equal "$gcc_output" ""] } then {
> + pass "$test: std out"
> + } else {
> + fail "$test: std out $gcc_output"
> + }
> +
> +}
> +
> +set sing {-0.c}
> +set mult {-1.c -2.c}
> +
> +# Driver-chosen outputs.
> +outest "$b asm default 1" $sing "-S" {} {{-0.s}}
> +outest "$b asm default 2" $mult "-S" {} {{-1.s -2.s}}
> +
> +outest "$b obj default 1" $sing "-c" {} {{-0.o}}
> +outest "$b obj default 2" $mult "-c" {} {{-1.o -2.o}}
> +
> +outest "$b exe default 1" $sing "" {} {{a.{out,exe}}}
> +outest "$b exe default 2" $mult "" {} {{a.{out,exe}}}
> +
> +# Driver-chosen aux outputs.
> +outest "$b asm savetmp 1" $sing "-S -save-temps" {} {{-0.i -0.s}}
> +outest "$b asm savetmp 2" $mult "-S -save-temps" {} {{-1.i -1.s -2.i -2.s}}
> +outest "$b obj savetmp unnamed1" $sing "-c -save-temps" {} {{-0.i -0.s -0.o}}
> +outest "$b obj savetmp unnamed2" $mult "-c -save-temps" {} {{-1.i -1.s -1.o -2.i -2.s -2.o}}
> +
> +# Aux outputs computed within the driver, based on output name (and
> +# input).
> +outest "$b cpp savetmp named0" $sing "-E -o $b-0.i -save-temps" {} {{-0.i}}
> +outest "$b asm savetmp named0" $sing "-S -o $b-0.s -save-temps" {} {{-0.i -0.s}}
> +outest "$b obj savetmp named0" $sing "-c -o $b-0.o -save-temps" {} {{-0.i -0.s -0.o}}
> +outest "$b cpp savetmp namedb" $sing "-E -o $b.i -save-temps" {} {{.i}}
> +outest "$b asm savetmp namedb" $sing "-S -o $b.s -save-temps" {} {{.i .s}}
> +outest "$b obj savetmp namedb" $sing "-c -o $b.o -save-temps" {} {{.i .s .o}}
> +
> +# When linking, the executable name gets prepended to aux output
> +# basenames, except when executable and single input share the same
> +# basename.
> +outest "$b exe savetmp unnamed1" $sing "-save-temps" {} {{a--0.i a--0.s a--0.o a.{out,exe}}}
> +outest "$b exe savetmp unnamed2" $mult "-save-temps" {} {{a--1.i a--1.s a--1.o a--2.i a--2.s a--2.o a.{out,exe}}}
> +outest "$b exe savetmp named0" $sing "-o $b-0.exe -save-temps" {} {{-0.i -0.s -0.o -0.exe}}
> +outest "$b exe savetmp namedb" $sing "-o $b.exe -save-temps" {} {{--0.i --0.s --0.o .exe}}
> +outest "$b exe savetmp named2" $mult "-o $b.exe -save-temps" {} {{--1.i --1.s --1.o --2.i --2.s --2.o .exe}}
> +
> +# Setting the main output to a dir selects it as the default aux&dump
> +# location.
> +outest "$b cpp savetmp namedir0" $sing "-E -o o/$b-0.i -save-temps" {o/} {{-0.i} {}}
> +outest "$b asm savetmp namedir0" $sing "-S -o o/$b-0.s -save-temps" {o/} {{-0.i -0.s} {}}
> +outest "$b obj savetmp namedir0" $sing "-c -o o/$b-0.o -save-temps" {o/} {{-0.i -0.s -0.o} {}}
> +outest "$b cpp savetmp namedir" $sing "-E -o o/$b.i -save-temps" {o/} {{.i} {}}
> +outest "$b asm savetmp namedir" $sing "-S -o o/$b.s -save-temps" {o/} {{.i .s} {}}
> +outest "$b obj savetmp namedir" $sing "-c -o o/$b.o -save-temps" {o/} {{.i .s .o} {}}
> +outest "$b exe savetmp namedir0" $sing "-o o/$b-0.exe -save-temps" {o/} {{-0.i -0.s -0.o -0.exe} {}}
> +outest "$b exe savetmp namedirb" $sing "-o o/$b.exe -save-temps" {o/} {{--0.i --0.s --0.o .exe} {}}
> +outest "$b exe savetmp namedir2" $mult "-o o/$b.exe -save-temps" {o/} {{--1.i --1.s --1.o --2.i --2.s --2.o .exe} {}}
> +
> +# -save-temps=cwd overrides the aux output location to the current dir.
> +outest "$b obj savecwd unnamed1" $sing "-c -save-temps=cwd" {} {{-0.i -0.s -0.o}}
> +outest "$b obj savecwd unnamed2" $mult "-c -save-temps=cwd" {} {{-1.i -1.s -1.o -2.i -2.s -2.o}}
> +outest "$b cpp savecwd named0" $sing "-E -o $b-0.i -save-temps=cwd" {} {{-0.i}}
> +outest "$b asm savecwd named0" $sing "-S -o $b-0.s -save-temps=cwd" {} {{-0.i -0.s}}
> +outest "$b obj savecwd named0" $sing "-c -o $b-0.o -save-temps=cwd" {} {{-0.i -0.s -0.o}}
> +outest "$b cpp savecwd namedb" $sing "-E -o $b.i -save-temps=cwd" {} {{.i}}
> +outest "$b asm savecwd namedb" $sing "-S -o $b.s -save-temps=cwd" {} {{.i .s}}
> +outest "$b obj savecwd namedb" $sing "-c -o $b.o -save-temps=cwd" {} {{.i .s .o}}
> +outest "$b exe savecwd unnamed1" $sing "-save-temps=cwd" {} {{a--0.i a--0.s a--0.o a.{out,exe}}}
> +outest "$b exe savecwd unnamed2" $mult "-save-temps=cwd" {} {{a--1.i a--1.s a--1.o a--2.i a--2.s a--2.o a.{out,exe}}}
> +outest "$b exe savecwd named0" $sing "-o $b-0.exe -save-temps=cwd" {} {{-0.i -0.s -0.o -0.exe}}
> +outest "$b exe savecwd namedb" $sing "-o $b.exe -save-temps=cwd" {} {{--0.i --0.s --0.o .exe}}
> +outest "$b exe savecwd named2" $mult "-o $b.exe -save-temps=cwd" {} {{--1.i --1.s --1.o --2.i --2.s --2.o .exe}}
> +
> +outest "$b cpp savecwd namedir0" $sing "-E -o o/$b-0.i -save-temps=cwd" {o/} {{-0.i} {}}
> +outest "$b asm savecwd namedir0" $sing "-S -o o/$b-0.s -save-temps=cwd" {o/} {{-0.s} {-0.i}}
> +outest "$b obj savecwd namedir0" $sing "-c -o o/$b-0.o -save-temps=cwd" {o/} {{-0.o} {-0.i -0.s}}
> +outest "$b cpp savecwd namedir" $sing "-E -o o/$b.i -save-temps=cwd" {o/} {{.i} {}}
> +outest "$b asm savecwd namedir" $sing "-S -o o/$b.s -save-temps=cwd" {o/} {{.s} {.i}}
> +outest "$b obj savecwd namedir" $sing "-c -o o/$b.o -save-temps=cwd" {o/} {{.o} {.i .s}}
> +outest "$b exe savecwd namedir0" $sing "-o o/$b-0.exe -save-temps=cwd" {o/} {{-0.exe} {-0.i -0.s -0.o}}
> +outest "$b exe savecwd namedirb" $sing "-o o/$b.exe -save-temps=cwd" {o/} {{.exe} {--0.i --0.s --0.o}}
> +outest "$b exe savecwd namedir2" $mult "-o o/$b.exe -save-temps=cwd" {o/} {{.exe} {--1.i --1.s --1.o --2.i --2.s --2.o}}
> +
> +# -save-temps=obj overrides the aux output location to that of the
> +# main output
> +outest "$b obj saveobj unnamed1" $sing "-c -save-temps=obj" {} {{-0.i -0.s -0.o}}
> +outest "$b obj saveobj unnamed2" $mult "-c -save-temps=obj" {} {{-1.i -1.s -1.o -2.i -2.s -2.o}}
> +outest "$b cpp saveobj named0" $sing "-E -o $b-0.i -save-temps=obj" {} {{-0.i}}
> +outest "$b asm saveobj named0" $sing "-S -o $b-0.s -save-temps=obj" {} {{-0.i -0.s}}
> +outest "$b obj saveobj named0" $sing "-c -o $b-0.o -save-temps=obj" {} {{-0.i -0.s -0.o}}
> +outest "$b cpp saveobj namedb" $sing "-E -o $b.i -save-temps=obj" {} {{.i}}
> +outest "$b asm saveobj namedb" $sing "-S -o $b.s -save-temps=obj" {} {{.i .s}}
> +outest "$b obj saveobj namedb" $sing "-c -o $b.o -save-temps=obj" {} {{.i .s .o}}
> +outest "$b exe saveobj unnamed1" $sing "-save-temps=obj" {} {{a--0.i a--0.s a--0.o a.{out,exe}}}
> +outest "$b exe saveobj unnamed2" $mult "-save-temps=obj" {} {{a--1.i a--1.s a--1.o a--2.i a--2.s a--2.o a.{out,exe}}}
> +outest "$b exe saveobj named0" $sing "-o $b-0.exe -save-temps=obj" {} {{-0.i -0.s -0.o -0.exe}}
> +outest "$b exe saveobj namedb" $sing "-o $b.exe -save-temps=obj" {} {{--0.i --0.s --0.o .exe}}
> +outest "$b exe saveobj named2" $mult "-o $b.exe -save-temps=obj" {} {{--1.i --1.s --1.o --2.i --2.s --2.o .exe}}
> +
> +outest "$b cpp saveobj namedir0" $sing "-E -o o/$b-0.i -save-temps=obj" {o/} {{-0.i} {}}
> +outest "$b asm saveobj namedir0" $sing "-S -o o/$b-0.s -save-temps=obj" {o/} {{-0.i -0.s} {}}
> +outest "$b obj saveobj namedir0" $sing "-c -o o/$b-0.o -save-temps=obj" {o/} {{-0.i -0.s -0.o} {}}
> +outest "$b cpp saveobj namedir" $sing "-E -o o/$b.i -save-temps=obj" {o/} {{.i} {}}
> +outest "$b asm saveobj namedir" $sing "-S -o o/$b.s -save-temps=obj" {o/} {{.i .s} {}}
> +outest "$b obj saveobj namedir" $sing "-c -o o/$b.o -save-temps=obj" {o/} {{.i .s .o} {}}
> +outest "$b exe saveobj namedir0" $sing "-o o/$b-0.exe -save-temps=obj" {o/} {{-0.i -0.s -0.o -0.exe} {}}
> +outest "$b exe saveobj namedirb" $sing "-o o/$b.exe -save-temps=obj" {o/} {{--0.i --0.s --0.o .exe} {}}
> +outest "$b exe saveobj namedir2" $mult "-o o/$b.exe -save-temps=obj" {o/} {{--1.i --1.s --1.o --2.i --2.s --2.o .exe} {}}
> +
> +# Check -dumpdir overriding by -save-temps=*, and -save-temps
> +# non-overriding, with one catch: the presence of a given dumpdir,
> +# even if ultimately overridden, still disables the prepending of the
> +# executable basename to the aux&dump output basenames (or rather the
> +# appending of the executable basename to the dumpdir).
> +outest "$b exe sobjovr namedir0" $sing "-o o/$b-0.exe -dumpdir no/ -save-temps=obj -save-temps" {o/} {{-0.i -0.s -0.o -0.exe} {}}
> +outest "$b exe sobjovr namedirb" $sing "-o o/$b.exe -dumpdir no/ -save-temps=obj -save-temps" {o/} {{-0.i -0.s -0.o .exe} {}}
> +outest "$b exe sobjovr namedir2" $mult "-o o/$b.exe -dumpdir no/ -save-temps=obj -save-temps" {o/} {{-1.i -1.s -1.o -2.i -2.s -2.o .exe} {}}
> +outest "$b exe scwdovr namedir0" $sing "-o o/$b-0.exe -dumpdir o/ -save-temps=cwd -save-temps" {o/} {{-0.exe} {-0.i -0.s -0.o}}
> +outest "$b exe scwdovr namedirb" $sing "-o o/$b.exe -dumpdir o/ -save-temps=cwd -save-temps" {o/} {{.exe} {-0.i -0.s -0.o}}
> +outest "$b exe scwdovr namedir2" $mult "-o o/$b.exe -dumpdir o/ -save-temps=cwd -save-temps" {o/} {{.exe} {-1.i -1.s -1.o -2.i -2.s -2.o}}
> +outest "$b exe ddstovr namedir0" $sing "-o $b-0.exe -dumpdir o/ -save-temps" {o/} {{-0.i -0.s -0.o} {-0.exe}}
> +outest "$b exe ddstovr namedirb" $sing "-o $b.exe -dumpdir o/ -save-temps" {o/} {{-0.i -0.s -0.o} {.exe}}
> +outest "$b exe ddstovr namedir2" $mult "-o $b.exe -dumpdir o/ -save-temps" {o/} {{-1.i -1.s -1.o -2.i -2.s -2.o} {.exe}}
> +
> +# Check -dumpdir prevailing over -save-temps*. Even though -dumpdir
> +# overrides the -save-temps=* directory selection, -save-temps remains
> +# enabled.
> +outest "$b exe soddovr namedir0" $sing "-o o/$b-0.exe -save-temps=obj -dumpdir ./" {o/} {{-0.exe} {-0.i -0.s -0.o}}
> +outest "$b exe soddovr namedirb" $sing "-o o/$b.exe -save-temps=obj -dumpdir ./" {o/} {{.exe} {-0.i -0.s -0.o}}
> +outest "$b exe soddovr namedir2" $mult "-o o/$b.exe -save-temps=obj -dumpdir ./" {o/} {{.exe} {-1.i -1.s -1.o -2.i -2.s -2.o}}
> +outest "$b exe scddovr namedir0" $sing "-o o/$b-0.exe -save-temps=cwd -dumpdir o/" {o/} {{-0.i -0.s -0.o -0.exe} {}}
> +outest "$b exe scddovr namedirb" $sing "-o o/$b.exe -save-temps=cwd -dumpdir o/" {o/} {{-0.i -0.s -0.o .exe} {}}
> +outest "$b exe scddovr namedir2" $mult "-o o/$b.exe -save-temps=cwd -dumpdir o/" {o/} {{-1.i -1.s -1.o -2.i -2.s -2.o .exe} {}}
> +outest "$b exe ddstovr namedir0" $sing "-o $b-0.exe -save-temps -dumpdir o/" {o/} {{-0.i -0.s -0.o} {-0.exe}}
> +outest "$b exe ddstovr namedirb" $sing "-o $b.exe -save-temps -dumpdir o/" {o/} {{-0.i -0.s -0.o} {.exe}}
> +outest "$b exe ddstovr namedir2" $mult "-o $b.exe -save-temps -dumpdir o/" {o/} {{-1.i -1.s -1.o -2.i -2.s -2.o} {.exe}}
> +
> +
> +# Compiler- and driver-generated aux and dump outputs.
> +# -fdump-rtl-final creates a .c.???r.final dump in the compiler.
> +# -fstack-usage creates a .su aux output in the compiler.
> +# -gsplit-dwarf extracts a .dwo aux output from the .o in the driver.
> +outest "$b asm auxdump 1" $sing "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {} {{-0.c.???r.final -0.su -0.s}}
> +outest "$b asm auxdump 2" $mult "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {} {{-1.c.???r.final -1.su -1.s -2.c.???r.final -2.su -2.s}}
> +outest "$b obj auxdump unnamed1" $sing "-c -g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {} {{-0.c.???r.final -0.su -0.dwo -0.o}}
> +outest "$b obj auxdump unnamed2" $mult "-c -g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {} {{-1.c.???r.final -1.su -1.dwo -1.o -2.c.???r.final -2.su -2.dwo -2.o}}
> +
> +outest "$b cpp auxdump named0" $sing "-E -o $b-0.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {} {{-0.i}}
> +outest "$b asm auxdump named0" $sing "-S -o $b-0.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {} {{-0.c.???r.final -0.su -0.s}}
> +outest "$b obj auxdump named0" $sing "-c -o $b-0.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {} {{-0.c.???r.final -0.su -0.dwo -0.o}}
> +outest "$b cpp auxdump namedb" $sing "-E -o $b.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {} {{.i}}
> +outest "$b asm auxdump namedb" $sing "-S -o $b.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {} {{.c.???r.final .su .s}}
> +outest "$b obj auxdump namedb" $sing "-c -o $b.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {} {{.c.???r.final .su .dwo .o}}
> +
> +outest "$b exe auxdump unnamed1" $sing "-g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {} {{a--0.c.???r.final a--0.su a--0.dwo a.{out,exe}}}
> +outest "$b exe auxdump unnamed2" $mult "-g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {} {{a--1.c.???r.final a--1.su a--1.dwo a--2.c.???r.final a--2.su a--2.dwo a.{out,exe}}}
> +outest "$b exe auxdump named0" $sing "-o $b-0.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {} {{-0.c.???r.final -0.su -0.dwo -0.exe}}
> +outest "$b exe auxdump namedb" $sing "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {} {{--0.c.???r.final --0.su --0.dwo .exe}}
> +outest "$b exe auxdump named2" $mult "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {} {{--1.c.???r.final --1.su --1.dwo --2.c.???r.final --2.su --2.dwo .exe}}
> +
> +outest "$b cpp auxdump namedir0" $sing "-E -o o/$b-0.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {o/} {{-0.i} {}}
> +outest "$b asm auxdump namedir0" $sing "-S -o o/$b-0.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {o/} {{-0.c.???r.final -0.su -0.s} {}}
> +outest "$b obj auxdump namedir0" $sing "-c -o o/$b-0.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {o/} {{-0.c.???r.final -0.su -0.dwo -0.o} {}}
> +outest "$b cpp auxdump namedir" $sing "-E -o o/$b.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {o/} {{.i} {}}
> +outest "$b asm auxdump namedir" $sing "-S -o o/$b.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {o/} {{.c.???r.final .su .s} {}}
> +outest "$b obj auxdump namedir" $sing "-c -o o/$b.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {o/} {{.c.???r.final .su .dwo .o} {}}
> +outest "$b exe auxdump namedir0" $sing "-o o/$b-0.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {o/} {{-0.c.???r.final -0.su -0.dwo -0.exe} {}}
> +outest "$b exe auxdump namedirb" $sing "-o o/$b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {o/} {{--0.c.???r.final --0.su --0.dwo .exe} {}}
> +outest "$b exe auxdump namedir2" $mult "-o o/$b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf" {o/} {{--1.c.???r.final --1.su --1.dwo --2.c.???r.final --2.su --2.dwo .exe} {}}
> +
> +# Check that -save-temps doesn't break compiler aux or dumps as it
> +# changes temp file names.
> +outest "$b asm auxdmps 1" $sing "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {} {{-0.i -0.c.???r.final -0.su -0.s}}
> +outest "$b asm auxdmps 2" $mult "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {} {{-1.i -1.c.???r.final -1.su -1.s -2.i -2.c.???r.final -2.su -2.s}}
> +outest "$b obj auxdmps unnamed1" $sing "-c -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {} {{-0.i -0.c.???r.final -0.su -0.s -0.dwo -0.o}}
> +outest "$b obj auxdmps unnamed2" $mult "-c -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {} {{-1.i -1.c.???r.final -1.su -1.s -1.dwo -1.o -2.i -2.c.???r.final -2.su -2.s -2.dwo -2.o}}
> +
> +outest "$b cpp auxdmps named0" $sing "-E -o $b-0.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {} {{-0.i}}
> +outest "$b asm auxdmps named0" $sing "-S -o $b-0.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {} {{-0.i -0.c.???r.final -0.su -0.s}}
> +outest "$b obj auxdmps named0" $sing "-c -o $b-0.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {} {{-0.i -0.c.???r.final -0.su -0.s -0.dwo -0.o}}
> +outest "$b cpp auxdmps namedb" $sing "-E -o $b.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {} {{.i}}
> +outest "$b asm auxdmps namedb" $sing "-S -o $b.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {} {{.i .c.???r.final .su .s}}
> +outest "$b obj auxdmps namedb" $sing "-c -o $b.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {} {{.i .c.???r.final .su .s .dwo .o}}
> +
> +outest "$b exe auxdmps unnamed1" $sing "-g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {} {{a--0.i a--0.c.???r.final a--0.su a--0.s a--0.dwo a--0.o a.{out,exe}}}
> +outest "$b exe auxdmps unnamed2" $mult "-g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {} {{a--1.i a--1.c.???r.final a--1.su a--1.s a--1.dwo a--1.o a--2.i a--2.c.???r.final a--2.su a--2.s a--2.dwo a--2.o a.{out,exe}}}
> +outest "$b exe auxdmps named0" $sing "-o $b-0.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {} {{-0.i -0.c.???r.final -0.su -0.s -0.dwo -0.o -0.exe}}
> +outest "$b exe auxdmps namedb" $sing "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {} {{--0.i --0.c.???r.final --0.su --0.s --0.dwo --0.o .exe}}
> +outest "$b exe auxdmps named2" $mult "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {} {{--1.i --1.c.???r.final --1.su --1.s --1.dwo --1.o --2.i --2.c.???r.final --2.su --2.s --2.dwo --2.o .exe}}
> +
> +outest "$b cpp auxdmps namedir0" $sing "-E -o o/$b-0.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {o/} {{-0.i} {}}
> +outest "$b asm auxdmps namedir0" $sing "-S -o o/$b-0.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {o/} {{-0.i -0.c.???r.final -0.su -0.s} {}}
> +outest "$b obj auxdmps namedir0" $sing "-c -o o/$b-0.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {o/} {{-0.i -0.c.???r.final -0.su -0.s -0.dwo -0.o} {}}
> +outest "$b cpp auxdmps namedir" $sing "-E -o o/$b.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {o/} {{.i} {}}
> +outest "$b asm auxdmps namedir" $sing "-S -o o/$b.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {o/} {{.i .c.???r.final .su .s} {}}
> +outest "$b obj auxdmps namedir" $sing "-c -o o/$b.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {o/} {{.i .c.???r.final .su .s .dwo .o} {}}
> +outest "$b exe auxdmps namedir0" $sing "-o o/$b-0.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {o/} {{-0.i -0.c.???r.final -0.su -0.s -0.dwo -0.o -0.exe} {}}
> +outest "$b exe auxdmps namedirb" $sing "-o o/$b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {o/} {{--0.i --0.c.???r.final --0.su --0.s --0.dwo --0.o .exe} {}}
> +outest "$b exe auxdmps namedir2" $mult "-o o/$b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -save-temps" {o/} {{--1.i --1.c.???r.final --1.su --1.s --1.dwo --1.o --2.i --2.c.???r.final --2.su --2.s --2.dwo --2.o .exe} {}}
> +
> +
> +# Check that dumpdir changes the location of non-primary outputs
> +outest "$b asm dumpdir 1" $sing "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/" {od/} {{-0.c.???r.final -0.su} {-0.s}}
> +outest "$b asm dumpdir 2" $mult "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/" {od/} {{-1.c.???r.final -1.su -2.c.???r.final -2.su} {-1.s -2.s}}
> +outest "$b obj dumpdir unnamed1" $sing "-c -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/" {od/} {{-0.c.???r.final -0.su -0.dwo} {-0.o}}
> +outest "$b obj dumpdir unnamed2" $mult "-c -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/" {od/} {{-1.c.???r.final -1.su -1.dwo -2.c.???r.final -2.su -2.dwo} {-1.o -2.o}}
> +
> +outest "$b cpp dumpdir named0" $sing "-E -o $b-0.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/" {od/} {{} {-0.i}}
> +outest "$b asm dumpdir named0" $sing "-S -o $b-0.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/" {od/} {{-0.c.???r.final -0.su} {-0.s}}
> +outest "$b obj dumpdir named0" $sing "-c -o $b-0.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/" {od/} {{-0.c.???r.final -0.su -0.dwo} {-0.o}}
> +outest "$b cpp dumpdir namedb" $sing "-E -o $b.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/" {od/} {{} {.i}}
> +outest "$b asm dumpdir namedb" $sing "-S -o $b.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/" {od/} {{.c.???r.final .su} {.s}}
> +outest "$b obj dumpdir namedb" $sing "-c -o $b.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/" {od/} {{.c.???r.final .su .dwo} {.o}}
> +
> +outest "$b exe dumpdir unnamed1" $sing "-g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/a-" {od/} {{a--0.c.???r.final a--0.su a--0.dwo} {a.{out,exe}}}
> +outest "$b exe dumpdir unnamed2" $mult "-g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/a-" {od/} {{a--1.c.???r.final a--1.su a--1.dwo a--2.c.???r.final a--2.su a--2.dwo} {a.{out,exe}}}
> +outest "$b exe dumpdir named0" $sing "-o $b-0.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/" {od/} {{-0.c.???r.final -0.su -0.dwo} {-0.exe}}
> +outest "$b exe dumpdir namedb" $sing "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/" {od/} {{-0.c.???r.final -0.su -0.dwo} {.exe}}
> +outest "$b exe dumpdir named2" $mult "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/" {od/} {{-1.c.???r.final -1.su -1.dwo -2.c.???r.final -2.su -2.dwo} {.exe}}
> +outest "$b exe dumpdira namedb" $sing "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/a-" {od/} {{a--0.c.???r.final a--0.su a--0.dwo} {.exe}}
> +outest "$b exe dumpdira named2" $mult "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/a-" {od/} {{a--1.c.???r.final a--1.su a--1.dwo a--2.c.???r.final a--2.su a--2.dwo} {.exe}}
> +outest "$b exe dumpdirb namedb" $sing "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/$b-" {od/} {{--0.c.???r.final --0.su --0.dwo} {.exe}}
> +outest "$b exe dumpdirb named2" $mult "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/$b-" {od/} {{--1.c.???r.final --1.su --1.dwo --2.c.???r.final --2.su --2.dwo} {.exe}}
> +
> +outest "$b cpp dumpdir namedir0" $sing "-E -o o/$b-0.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/" {od/ o/} {{} {-0.i} {}}
> +outest "$b asm dumpdir namedir0" $sing "-S -o o/$b-0.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/" {od/ o/} {{-0.c.???r.final -0.su} {-0.s} {}}
> +outest "$b obj dumpdir namedir0" $sing "-c -o o/$b-0.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/" {od/ o/} {{-0.c.???r.final -0.su -0.dwo} {-0.o} {}}
> +outest "$b cpp dumpdir namedir" $sing "-E -o o/$b.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/" {od/ o/} {{} {.i} {}}
> +outest "$b asm dumpdir namedir" $sing "-S -o o/$b.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/" {od/ o/} {{.c.???r.final .su} {.s} {}}
> +outest "$b obj dumpdir namedir" $sing "-c -o o/$b.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/" {od/ o/} {{.c.???r.final .su .dwo} {.o} {}}
> +outest "$b exe dumpdir namedir0" $sing "-o o/$b-0.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/" {od/ o/} {{-0.c.???r.final -0.su -0.dwo} {-0.exe} {}}
> +outest "$b exe dumpdir namedirb" $sing "-o o/$b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/" {od/ o/} {{-0.c.???r.final -0.su -0.dwo} {.exe} {}}
> +outest "$b exe dumpdir namedir2" $mult "-o o/$b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/" {od/ o/} {{-1.c.???r.final -1.su -1.dwo -2.c.???r.final -2.su -2.dwo} {.exe} {}}
> +outest "$b exe dumpdira namedirb" $sing "-o o/$b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/a-" {od/ o/} {{a--0.c.???r.final a--0.su a--0.dwo} {.exe} {}}
> +outest "$b exe dumpdira namedir2" $mult "-o o/$b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/a-" {od/ o/} {{a--1.c.???r.final a--1.su a--1.dwo a--2.c.???r.final a--2.su a--2.dwo} {.exe} {}}
> +outest "$b exe dumpdirb namedirb" $sing "-o o/$b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/$b-" {od/ o/} {{--0.c.???r.final --0.su --0.dwo} {.exe} {}}
> +outest "$b exe dumpdirb namedir2" $mult "-o o/$b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/$b-" {od/ o/} {{--1.c.???r.final --1.su --1.dwo --2.c.???r.final --2.su --2.dwo} {.exe} {}}
> +
> +# Check that a -dumpbase with a dir component disregards the -dumpdir
> +# prefix. Also, start testing -dumpbase-ext to distinguish between
> +# aux and dump files: only the latter retain the named extension.
> +# -dumpbase-ext, if absent or used in combination with -dumpbase for
> +# an executable name, defaults to the extension of the source file.
> +# The specified dumpbase is combined with the dumpdir prefix when
> +# processing more than one input (we couldn't use the same dumpbase
> +# for them all), or when linking (the specified dumpbase is then used
> +# as prefix instead of the linker output, and a new dumpbase is
> +# computed per source).
> +outest "$b asm dbsovrdd 1" $sing "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b" {od/} {{.???r.final .su} {-0.s}}
> +outest "$b asm dbsovrddx 1" $sing "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b.c -dumpbase-ext .c" {od/} {{.c.???r.final .su} {-0.s}}
> +outest "$b asm dbsovrdd-x 1" $sing "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b.c" {od/} {{.c.???r.final .c.su} {-0.s}}
> +outest "$b asm dbsovrdd.x 1" $sing "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b.x" {od/} {{.x.???r.final .x.su} {-0.s}}
> +outest "$b asm dbsovrdd 2" $mult "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b" {od/} {{--1.c.???r.final --1.su --2.c.???r.final --2.su} {-1.s -2.s}}
> +outest "$b asm dbsovrddx 2" $mult "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b.x -dumpbase-ext .x" {od/} {{--1.c.???r.final --1.su --2.c.???r.final --2.su} {-1.s -2.s}}
> +outest "$b obj dbsovrdd unnamed1" $sing "-c -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b" {od/} {{.???r.final .su .dwo} {-0.o}}
> +outest "$b obj dbsovrddx unnamed1" $sing "-c -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b.c -dumpbase-ext .c" {od/} {{.c.???r.final .su .dwo} {-0.o}}
> +outest "$b obj dbsovrdd unnamed2" $mult "-c -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b" {od/} {{--1.c.???r.final --1.su --1.dwo --2.c.???r.final --2.su --2.dwo} {-1.o -2.o}}
> +
> +outest "$b cpp dbsovrdd named0" $sing "-E -o $b-0.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b" {od/} {{} {-0.i}}
> +outest "$b asm dbsovrdd named0" $sing "-S -o $b-0.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b" {od/} {{.???r.final .su} {-0.s}}
> +outest "$b obj dbsovrdd named0" $sing "-c -o $b-0.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b" {od/} {{.???r.final .su .dwo} {-0.o}}
> +outest "$b cpp dbsovrdd namedb" $sing "-E -o $b.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b" {od/} {{} {.i}}
> +outest "$b asm dbsovrdd namedb" $sing "-S -o $b.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b" {od/} {{.???r.final .su} {.s}}
> +outest "$b obj dbsovrdd namedb" $sing "-c -o $b.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b" {od/} {{.???r.final .su .dwo} {.o}}
> +
> +# Nit: -dumpdir affects whether the specified dumpbase is combined
> +# into dumpdir or taken as the output basename, even if dumpbase will
> +# ultimately override it.
> +outest "$b exe dbsovrdd unnamed1" $sing "-g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b" {od/} {{.???r.final .su .dwo} {a.{out,exe}}}
> +outest "$b exe dbsovrdd unnamed2" $mult "-g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/a" {od/} {{a--1.c.???r.final a--1.su a--1.dwo a--2.c.???r.final a--2.su a--2.dwo} {a.{out,exe}}}
> +outest "$b exe dbsovrdd named0" $sing "-o $b-0.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b" {od/} {{.???r.final .su .dwo} {-0.exe}}
> +outest "$b exe dbsovrdd namedb" $sing "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b.exe -dumpbase-ext .exe" {od/} {{.exe.???r.final .su .dwo} {.exe}}
> +outest "$b exe dbsovrdd named2" $mult "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b" {od/} {{--1.c.???r.final --1.su --1.dwo --2.c.???r.final --2.su --2.dwo} {.exe}}
> +outest "$b exe dbsovrdda namedb" $sing "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/a" {od/} {{a.???r.final a.su a.dwo} {.exe}}
> +outest "$b exe dbsovrddac namedb" $sing "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/a.c -dumpbase-ext .c" {od/} {{a.c.???r.final a.su a.dwo} {.exe}}
> +outest "$b exe dbsovrdda named2" $mult "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/a" {od/} {{a--1.c.???r.final a--1.su a--1.dwo a--2.c.???r.final a--2.su a--2.dwo} {.exe}}
> +
> +outest "$b cpp dbsovrdd namedir0" $sing "-E -o o/$b-0.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b" {od/ o/} {{} {-0.i} {}}
> +outest "$b asm dbsovrdd namedir0" $sing "-S -o o/$b-0.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b" {od/ o/} {{.???r.final .su} {-0.s} {}}
> +outest "$b obj dbsovrdd namedir0" $sing "-c -o o/$b-0.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b" {od/ o/} {{.???r.final .su .dwo} {-0.o} {}}
> +outest "$b cpp dbsovrdd namedir" $sing "-E -o o/$b.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b" {od/ o/} {{} {.i} {}}
> +outest "$b asm dbsovrdd namedir" $sing "-S -o o/$b.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b" {od/ o/} {{.???r.final .su} {.s} {}}
> +outest "$b obj dbsovrdd namedir" $sing "-c -o o/$b.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b" {od/ o/} {{.???r.final .su .dwo} {.o} {}}
> +outest "$b exe dbsovrdd namedir0" $sing "-o o/$b-0.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b" {od/ o/} {{.???r.final .su .dwo} {-0.exe} {}}
> +outest "$b exe dbsovrdd namedirb" $sing "-o o/$b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b.exe -dumpbase-ext .exe" {od/ o/} {{.exe.???r.final .su .dwo} {.exe} {}}
> +outest "$b exe dbsovrdd namedir2" $mult "-o o/$b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/$b" {od/ o/} {{--1.c.???r.final --1.su --1.dwo --2.c.???r.final --2.su --2.dwo} {.exe} {}}
> +outest "$b exe dbsovrdda namedirb" $sing "-o o/$b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/a" {od/ o/} {{a.???r.final a.su a.dwo} {.exe} {}}
> +outest "$b exe dbsovrdda namedir2" $mult "-o o/$b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir ./ -dumpbase od/a" {od/ o/} {{a--1.c.???r.final a--1.su a--1.dwo a--2.c.???r.final a--2.su a--2.dwo} {.exe} {}}
> +
> +
> +# Check that a -dumpbase without a dir component adds to the -dumpdir
> +# prefix.
> +outest "$b asm dbswthdd 1" $sing "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b" {od/} {{.???r.final .su} {-0.s}}
> +outest "$b asm dbswthddx 1" $sing "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b.c -dumpbase-ext .c" {od/} {{.c.???r.final .su} {-0.s}}
> +outest "$b asm dbswthdd-x 1" $sing "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b.c" {od/} {{.c.???r.final .c.su} {-0.s}}
> +outest "$b asm dbswthdd.x 1" $sing "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b.x" {od/} {{.x.???r.final .x.su} {-0.s}}
> +outest "$b asm dbswthdd 2" $mult "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b" {od/} {{--1.c.???r.final --1.su --2.c.???r.final --2.su} {-1.s -2.s}}
> +outest "$b asm dbswthddx 2" $mult "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b.x -dumpbase-ext .x" {od/} {{--1.c.???r.final --1.su --2.c.???r.final --2.su} {-1.s -2.s}}
> +outest "$b obj dbswthdd unnamed1" $sing "-c -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b" {od/} {{.???r.final .su .dwo} {-0.o}}
> +outest "$b obj dbswthddx unnamed1" $sing "-c -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b.c -dumpbase-ext .c" {od/} {{.c.???r.final .su .dwo} {-0.o}}
> +outest "$b obj dbswthdd unnamed2" $mult "-c -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b" {od/} {{--1.c.???r.final --1.su --1.dwo --2.c.???r.final --2.su --2.dwo} {-1.o -2.o}}
> +
> +outest "$b cpp dbswthdd named0" $sing "-E -o $b-0.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b" {od/} {{} {-0.i}}
> +outest "$b asm dbswthdd named0" $sing "-S -o $b-0.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b" {od/} {{.???r.final .su} {-0.s}}
> +outest "$b obj dbswthdd named0" $sing "-c -o $b-0.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b" {od/} {{.???r.final .su .dwo} {-0.o}}
> +outest "$b cpp dbswthdd namedb" $sing "-E -o $b.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b" {od/} {{} {.i}}
> +outest "$b asm dbswthdd namedb" $sing "-S -o $b.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b" {od/} {{.???r.final .su} {.s}}
> +outest "$b obj dbswthdd namedb" $sing "-c -o $b.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b" {od/} {{.???r.final .su .dwo} {.o}}
> +
> +# Nitty details: -dumpdir affects whether the specified dumpbase is
> +# combined into dumpdir or taken as the output basename, even if
> +# dumpbase will ultimately override it.
> +outest "$b exe dbswthdd unnamed1" $sing "-g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b" {od/} {{.???r.final .su .dwo} {a.{out,exe}}}
> +outest "$b exe dbswthdd unnamed2" $mult "-g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase a" {od/} {{a--1.c.???r.final a--1.su a--1.dwo a--2.c.???r.final a--2.su a--2.dwo} {a.{out,exe}}}
> +outest "$b exe dbswthdd named0" $sing "-o $b-0.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b" {od/} {{.???r.final .su .dwo} {-0.exe}}
> +outest "$b exe dbswthdd namedb" $sing "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b.exe -dumpbase-ext .exe" {od/} {{.exe.???r.final .su .dwo} {.exe}}
> +outest "$b exe dbswthdd named2" $mult "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b" {od/} {{--1.c.???r.final --1.su --1.dwo --2.c.???r.final --2.su --2.dwo} {.exe}}
> +outest "$b exe dbswthdda namedb" $sing "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase a" {od/} {{a.???r.final a.su a.dwo} {.exe}}
> +outest "$b exe dbswthddac namedb" $sing "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase a.c -dumpbase-ext .c" {od/} {{a.c.???r.final a.su a.dwo} {.exe}}
> +outest "$b exe dbswthdda named2" $mult "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase a" {od/} {{a--1.c.???r.final a--1.su a--1.dwo a--2.c.???r.final a--2.su a--2.dwo} {.exe}}
> +
> +outest "$b cpp dbswthdd namedir0" $sing "-E -o o/$b-0.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b" {od/ o/} {{} {-0.i} {}}
> +outest "$b asm dbswthdd namedir0" $sing "-S -o o/$b-0.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b" {od/ o/} {{.???r.final .su} {-0.s} {}}
> +outest "$b obj dbswthdd namedir0" $sing "-c -o o/$b-0.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b" {od/ o/} {{.???r.final .su .dwo} {-0.o} {}}
> +outest "$b cpp dbswthdd namedir" $sing "-E -o o/$b.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b" {od/ o/} {{} {.i} {}}
> +outest "$b asm dbswthdd namedir" $sing "-S -o o/$b.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b" {od/ o/} {{.???r.final .su} {.s} {}}
> +outest "$b obj dbswthdd namedir" $sing "-c -o o/$b.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b" {od/ o/} {{.???r.final .su .dwo} {.o} {}}
> +outest "$b exe dbswthdd namedir0" $sing "-o o/$b-0.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b" {od/ o/} {{.???r.final .su .dwo} {-0.exe} {}}
> +outest "$b exe dbswthdd namedirb" $sing "-o o/$b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b.exe -dumpbase-ext .exe" {od/ o/} {{.exe.???r.final .su .dwo} {.exe} {}}
> +outest "$b exe dbswthdd namedir2" $mult "-o o/$b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase $b" {od/ o/} {{--1.c.???r.final --1.su --1.dwo --2.c.???r.final --2.su --2.dwo} {.exe} {}}
> +outest "$b exe dbswthdda namedirb" $sing "-o o/$b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase a" {od/ o/} {{a.???r.final a.su a.dwo} {.exe} {}}
> +outest "$b exe dbswthdda namedir2" $mult "-o o/$b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpdir od/ -dumpbase a" {od/ o/} {{a--1.c.???r.final a--1.su a--1.dwo a--2.c.???r.final a--2.su a--2.dwo} {.exe} {}}
> +
> +
> +# Check for the minor differences when -dumpbase is used without
> +# -dumpdir. The main difference between dbwoutdd and dbswthdd tests
> +# is in the single-input link tests: with the dump dir/ prefix moved
> +# to dumpbase, and without -dumpdir we end up using -dumpbase as the
> +# executable prefix rather than as the dumpbase for the single input.
> +outest "$b asm dbwoutdd 1" $sing "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b" {od/} {{.???r.final .su} {-0.s}}
> +outest "$b asm dbwoutddx 1" $sing "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b.c -dumpbase-ext .c" {od/} {{.c.???r.final .su} {-0.s}}
> +outest "$b asm dbwoutdd-x 1" $sing "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b.c" {od/} {{.c.???r.final .c.su} {-0.s}}
> +outest "$b asm dbwoutdd.x 1" $sing "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b.x" {od/} {{.x.???r.final .x.su} {-0.s}}
> +outest "$b asm dbwoutdd 2" $mult "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b" {od/} {{--1.c.???r.final --1.su --2.c.???r.final --2.su} {-1.s -2.s}}
> +outest "$b asm dbwoutddx 2" $mult "-S -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b.x -dumpbase-ext .x" {od/} {{--1.c.???r.final --1.su --2.c.???r.final --2.su} {-1.s -2.s}}
> +outest "$b obj dbwoutdd unnamed1" $sing "-c -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b" {od/} {{.???r.final .su .dwo} {-0.o}}
> +outest "$b obj dbwoutddx unnamed1" $sing "-c -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b.c -dumpbase-ext .c" {od/} {{.c.???r.final .su .dwo} {-0.o}}
> +outest "$b obj dbwoutdd unnamed2" $mult "-c -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b" {od/} {{--1.c.???r.final --1.su --1.dwo --2.c.???r.final --2.su --2.dwo} {-1.o -2.o}}
> +
> +outest "$b cpp dbwoutdd named0" $sing "-E -o $b-0.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b" {od/} {{} {-0.i}}
> +outest "$b asm dbwoutdd named0" $sing "-S -o $b-0.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b" {od/} {{.???r.final .su} {-0.s}}
> +outest "$b obj dbwoutdd named0" $sing "-c -o $b-0.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b" {od/} {{.???r.final .su .dwo} {-0.o}}
> +outest "$b cpp dbwoutdd namedb" $sing "-E -o $b.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b" {od/} {{} {.i}}
> +outest "$b asm dbwoutdd namedb" $sing "-S -o $b.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b" {od/} {{.???r.final .su} {.s}}
> +outest "$b obj dbwoutdd namedb" $sing "-c -o $b.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b" {od/} {{.???r.final .su .dwo} {.o}}
> +
> +outest "$b exe dbwoutdd unnamed1" $sing "-g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b" {od/} {{--0.c.???r.final --0.su --0.dwo} {a.{out,exe}}}
> +outest "$b exe dbwoutdd unnamed2" $mult "-g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/a" {od/} {{a--1.c.???r.final a--1.su a--1.dwo a--2.c.???r.final a--2.su a--2.dwo} {a.{out,exe}}}
> +outest "$b exe dbwoutdd named0" $sing "-o $b-0.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b" {od/} {{--0.c.???r.final --0.su --0.dwo} {-0.exe}}
> +outest "$b exe dbwoutdd named0d" $sing "-o od/$b-0.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase $b" {od/} {{--0.c.???r.final --0.su --0.dwo -0.exe} {}}
> +outest "$b exe dbwoutdd namedb" $sing "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b.exe -dumpbase-ext .exe" {od/} {{--0.c.???r.final --0.su --0.dwo} {.exe}}
> +outest "$b exe dbwoutdd named2" $mult "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b" {od/} {{--1.c.???r.final --1.su --1.dwo --2.c.???r.final --2.su --2.dwo} {.exe}}
> +outest "$b exe dbwoutdda namedb" $sing "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/a" {od/} {{a--0.c.???r.final a--0.su a--0.dwo} {.exe}}
> +outest "$b exe dbwoutddac namedb" $sing "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/a.c -dumpbase-ext .c" {od/} {{a--0.c.???r.final a--0.su a--0.dwo} {.exe}}
> +outest "$b exe dbwoutdda named2" $mult "-o $b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/a" {od/} {{a--1.c.???r.final a--1.su a--1.dwo a--2.c.???r.final a--2.su a--2.dwo} {.exe}}
> +
> +outest "$b cpp dbwoutdd namedir0" $sing "-E -o o/$b-0.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b" {od/ o/} {{} {-0.i} {}}
> +outest "$b asm dbwoutdd namedir0" $sing "-S -o o/$b-0.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b" {od/ o/} {{.???r.final .su} {-0.s} {}}
> +outest "$b obj dbwoutdd namedir0" $sing "-c -o o/$b-0.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b" {od/ o/} {{.???r.final .su .dwo} {-0.o} {}}
> +outest "$b cpp dbwoutdd namedir" $sing "-E -o o/$b.i -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b" {od/ o/} {{} {.i} {}}
> +outest "$b asm dbwoutdd namedir" $sing "-S -o o/$b.s -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b" {od/ o/} {{.???r.final .su} {.s} {}}
> +outest "$b obj dbwoutdd namedir" $sing "-c -o o/$b.o -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b" {od/ o/} {{.???r.final .su .dwo} {.o} {}}
> +outest "$b exe dbwoutdd namedir0" $sing "-o o/$b-0.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b" {od/ o/} {{--0.c.???r.final --0.su --0.dwo} {-0.exe} {}}
> +outest "$b exe dbwoutdd namedirb" $sing "-o o/$b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b.exe -dumpbase-ext .exe" {od/ o/} {{--0.c.???r.final --0.su --0.dwo} {.exe} {}}
> +outest "$b exe dbwoutdd namedir2" $mult "-o o/$b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/$b" {od/ o/} {{--1.c.???r.final --1.su --1.dwo --2.c.???r.final --2.su --2.dwo} {.exe} {}}
> +outest "$b exe dbwoutdda namedirb" $sing "-o o/$b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/a" {od/ o/} {{a--0.c.???r.final a--0.su a--0.dwo} {.exe} {}}
> +outest "$b exe dbwoutdda namedir2" $mult "-o o/$b.exe -g -fdump-rtl-final -fstack-usage -gsplit-dwarf -dumpbase od/a" {od/ o/} {{a--1.c.???r.final a--1.su a--1.dwo a--2.c.???r.final a--2.su a--2.dwo} {.exe} {}}
> +
> +# -fcompare-debug
> +outest "$b obj compare-debug" $sing "-c -fcompare-debug -fdump-rtl-final -fstack-usage -gsplit-dwarf -fdump-final-insns" {} {{-0.c.???r.final -0.su -0.c.gkd -0.gk.c.???r.final -0.dwo -0.o}}
> +outest "$b obj compare-debug save-temps" $sing "-c -fcompare-debug -save-temps -fdump-rtl-final -fstack-usage -gsplit-dwarf -fdump-final-insns" {} {{-0.c.???r.final -0.su -0.i -0.c.gkd -0.s -0.gk.i -0.gk.c.???r.final -0.gk.c.gkd -0.dwo -0.o}}
> +
> +# -flto
> +outest "$b lto sing unnamed" $sing "-O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {} {{a--0.c.???i.icf a.wpa.???i.icf a.ltrans0.ltrans.???r.final a.ltrans0.ltrans.su a.{out,exe}}}
> +outest "$b lto mult unnamed" $mult "-O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {} {{a--1.c.???i.icf a--2.c.???i.icf a.wpa.???i.icf a.ltrans0.ltrans.???r.final a.ltrans0.ltrans.su a.{out,exe}}}
> +outest "$b lto sing named" $sing "-o $b.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {} {{--0.c.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su .exe}}
> +outest "$b lto mult named" $mult "-o $b.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {} {{--1.c.???i.icf --2.c.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su .exe}}
> +outest "$b lto sing nameddir" $sing "-o dir/$b.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--0.c.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su .exe} {}}
> +outest "$b lto mult nameddir" $mult "-o dir/$b.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--1.c.???i.icf --2.c.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su .exe} {}}
> +
> +# -dumpbase without -dumpdir. The trailing dumppfx dash after it is
> +# combined with dumpbase turns into a period when passed to lto as
> +# -dumpdir, because the dash is introduced by the compiler driver.
> +outest "$b lto sing dumpbase unnamed" $sing "-dumpbase dir/$b -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--0.c.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su} {a.{out,exe}}}
> +outest "$b lto mult dumpbase unnamed" $mult "-dumpbase dir/$b -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--1.c.???i.icf --2.c.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su} {a.{out,exe}}}
> +outest "$b lto sing dumpbase named" $sing "-dumpbase dir/$b -o $b-0.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--0.c.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su} {-0.exe}}
> +outest "$b lto mult dumpbase named" $mult "-dumpbase dir/$b -o $b-1.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--1.c.???i.icf --2.c.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su} {-1.exe}}
> +outest "$b lto sing dumpbase namedb" $sing "-dumpbase dir/$b -o $b.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--0.c.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su} {.exe}}
> +outest "$b lto mult dumpbase namedb" $mult "-dumpbase dir/$b -o $b.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--1.c.???i.icf --2.c.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su} {.exe}}
> +
> +# -dumpdir without -dumpbase. The trailing dash in -dumpdir is given
> +# by the user, thus not replaced with a dot.
> +outest "$b lto sing dumpdir unnamed" $sing "-dumpdir dir/$b- -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--0.c.???i.icf -wpa.???i.icf -ltrans0.ltrans.???r.final -ltrans0.ltrans.su} {a.{out,exe}}}
> +outest "$b lto mult dumpdir unnamed" $mult "-dumpdir dir/$b- -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--1.c.???i.icf --2.c.???i.icf -wpa.???i.icf -ltrans0.ltrans.???r.final -ltrans0.ltrans.su} {a.{out,exe}}}
> +outest "$b lto sing dumpdir named" $sing "-dumpdir dir/$b- -o $b-0.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--0.c.???i.icf -wpa.???i.icf -ltrans0.ltrans.???r.final -ltrans0.ltrans.su} {-0.exe}}
> +outest "$b lto mult dumpdir named" $mult "-dumpdir dir/$b- -o $b-1.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--1.c.???i.icf --2.c.???i.icf -wpa.???i.icf -ltrans0.ltrans.???r.final -ltrans0.ltrans.su} {-1.exe}}
> +outest "$b lto sing dumpdir namedb" $sing "-dumpdir dir/$b- -o $b.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--0.c.???i.icf -wpa.???i.icf -ltrans0.ltrans.???r.final -ltrans0.ltrans.su} {.exe}}
> +outest "$b lto mult dumpdir namedb" $mult "-dumpdir dir/$b- -o $b.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--1.c.???i.icf --2.c.???i.icf -wpa.???i.icf -ltrans0.ltrans.???r.final -ltrans0.ltrans.su} {.exe}}
> +
> +# -dumpdir and non-overriding -dumpbase.
> +outest "$b lto dbswthdd sing unnamed" $sing "-dumpdir dir/ -dumpbase $b -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su} {a.{out,exe}}}
> +outest "$b lto dbswthdd mult unnamed" $mult "-dumpdir dir/ -dumpbase $b -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--1.c.???i.icf --2.c.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su} {a.{out,exe}}}
> +outest "$b lto dbswthdd sing named" $sing "-dumpdir dir/ -dumpbase $b -o $b-0.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su} {-0.exe}}
> +outest "$b lto dbswthdd mult named" $mult "-dumpdir dir/ -dumpbase $b -o $b-1.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--1.c.???i.icf --2.c.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su} {-1.exe}}
> +outest "$b lto dbswthdd sing namedb" $sing "-dumpdir dir/ -dumpbase $b -o $b.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su} {.exe}}
> +outest "$b lto dbswthdd mult namedb" $mult "-dumpdir dir/ -dumpbase $b -o $b.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--1.c.???i.icf --2.c.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su} {.exe}}
> +
> +# -dumpdir and an overriding -dumpbase.
> +outest "$b lto dbsovrdd sing unnamed" $sing "-dumpdir ignore/ -dumpbase dir/$b -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su} {a.{out,exe}}}
> +outest "$b lto dbsovrdd mult unnamed" $mult "-dumpdir ignore/ -dumpbase dir/$b -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--1.c.???i.icf --2.c.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su} {a.{out,exe}}}
> +outest "$b lto dbsovrdd sing named" $sing "-dumpdir ignore/ -dumpbase dir/$b -o $b-0.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su} {-0.exe}}
> +outest "$b lto dbsovrdd mult named" $mult "-dumpdir ignore/ -dumpbase dir/$b -o $b-1.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--1.c.???i.icf --2.c.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su} {-1.exe}}
> +outest "$b lto dbsovrdd sing namedb" $sing "-dumpdir ignore/ -dumpbase dir/$b -o $b.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su} {.exe}}
> +outest "$b lto dbsovrdd mult namedb" $mult "-dumpdir ignore/ -dumpbase dir/$b -o $b.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--1.c.???i.icf --2.c.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su} {.exe}}
> +
> +# Check that -dumpbase '' gets source names as dumpbases for
> +# compilation, and output name as dumpbase for linking, regardless of
> +# how many source files.
> +outest "$b lto sing empty dumpbase unnamed" $sing "-dumpbase \"\" -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {} {{-0.c.???i.icf a.wpa.???i.icf a.ltrans0.ltrans.???r.final a.ltrans0.ltrans.su a.{out,exe}}}
> +outest "$b lto mult empty dumpbase unnamed" $mult "-dumpbase \"\" -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {} {{-1.c.???i.icf -2.c.???i.icf a.wpa.???i.icf a.ltrans0.ltrans.???r.final a.ltrans0.ltrans.su a.{out,exe}}}
> +outest "$b lto sing empty dumpbase named" $sing "-dumpbase \"\" -o dir/$b-0.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{-0.c.???i.icf -0.wpa.???i.icf -0.ltrans0.ltrans.???r.final -0.ltrans0.ltrans.su -0.exe} {}}
> +outest "$b lto mult empty dumpbase named" $mult "-dumpbase \"\" -o dir/$b-1.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{-1.c.???i.icf -2.c.???i.icf -1.wpa.???i.icf -1.ltrans0.ltrans.???r.final -1.ltrans0.ltrans.su -1.exe} {}}
> +outest "$b lto sing empty dumpbase namedb" $sing "-dumpbase \"\" -o $b.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {} {{-0.c.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su .exe}}
> +outest "$b lto mult empty dumpbase namedb" $mult "-dumpbase \"\" -o $b.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {} {{-1.c.???i.icf -2.c.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su .exe}}
> +
> +# Now with -dumpdir too.
> +outest "$b lto sing empty dumpbase dumpdir unnamed" $sing "-dumpdir dir/$b- -dumpbase \"\" -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--0.c.???i.icf -a.wpa.???i.icf -a.ltrans0.ltrans.???r.final -a.ltrans0.ltrans.su} {a.{out,exe}}}
> +outest "$b lto mult empty dumpbase dumpdir unnamed" $mult "-dumpdir dir/$b- -dumpbase \"\" -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--1.c.???i.icf --2.c.???i.icf -a.wpa.???i.icf -a.ltrans0.ltrans.???r.final -a.ltrans0.ltrans.su} {a.{out,exe}}}
> +outest "$b lto sing empty dumpbase dumpdir named" $sing "-dumpdir dir/$b- -dumpbase \"\" -o $b-0.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--0.c.???i.icf --0.wpa.???i.icf --0.ltrans0.ltrans.???r.final --0.ltrans0.ltrans.su} {-0.exe}}
> +outest "$b lto mult empty dumpbase dumpdir named" $mult "-dumpdir dir/$b- -dumpbase \"\" -o $b-1.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--1.c.???i.icf --2.c.???i.icf --1.wpa.???i.icf --1.ltrans0.ltrans.???r.final --1.ltrans0.ltrans.su} {-1.exe}}
> +outest "$b lto sing empty dumpbase dumpdir namedb" $sing "-dumpdir dir/$b- -dumpbase \"\" -o $b.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--0.c.???i.icf -.wpa.???i.icf -.ltrans0.ltrans.???r.final -.ltrans0.ltrans.su} {.exe}}
> +outest "$b lto mult empty dumpbase dumpdir namedb" $mult "-dumpdir dir/$b- -dumpbase \"\" -o $b.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--1.c.???i.icf --2.c.???i.icf -.wpa.???i.icf -.ltrans0.ltrans.???r.final -.ltrans0.ltrans.su} {.exe}}
> +
> +# And also with an empty -dumpdir. That's equivalent to -dumpdir ./,
> +# overriding any dumpdir implied by the output.
> +outest "$b lto sing empty dumpdir empty dumpbase unnamed" $sing "-dumpdir \"\" -dumpbase \"\" -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {} {{-0.c.???i.icf a.wpa.???i.icf a.ltrans0.ltrans.???r.final a.ltrans0.ltrans.su a.{out,exe}}}
> +outest "$b lto mult empty dumpdir empty dumpbase unnamed" $mult "-dumpdir \"\" -dumpbase \"\" -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {} {{-1.c.???i.icf -2.c.???i.icf a.wpa.???i.icf a.ltrans0.ltrans.???r.final a.ltrans0.ltrans.su a.{out,exe}}}
> +outest "$b lto sing empty dumpdir empty dumpbase named" $sing "-dumpdir \"\" -dumpbase \"\" -o dir/$b-0.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{-0.exe} {-0.c.???i.icf -0.wpa.???i.icf -0.ltrans0.ltrans.???r.final -0.ltrans0.ltrans.su}}
> +outest "$b lto mult empty dumpdir empty dumpbase named" $mult "-dumpdir \"\" -dumpbase \"\" -o dir/$b-1.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{-1.exe} {-1.c.???i.icf -2.c.???i.icf -1.wpa.???i.icf -1.ltrans0.ltrans.???r.final -1.ltrans0.ltrans.su}}
> +outest "$b lto sing empty dumpdir empty dumpbase namedb" $sing "-dumpdir \"\" -dumpbase \"\" -o dir/$b.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{.exe} {-0.c.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su}}
> +outest "$b lto mult empty dumpdir empty dumpbase namedb" $mult "-dumpdir \"\" -dumpbase \"\" -o dir/$b.exe -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{.exe} {-1.c.???i.icf -2.c.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su}}
> +
> +# Now -flto with -save-temps, not exhaustive.
> +outest "$b lto st sing empty dumpbase unnamed" $sing "-dumpbase \"\" -save-temps -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {} {{-0.i -0.s -0.o -0.c.???i.icf a.lto_wrapper_args a.wpa.???i.icf a.ltrans.out a.res a.ltrans0.o a.ltrans0.ltrans.???r.final a.ltrans0.ltrans.su a.ltrans0.ltrans.s a.ltrans0.ltrans.o a.{out,exe}}}
> +outest "$b lto st mult empty dumpbase unnamed" $mult "-dumpbase \"\" -save-temps -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {} {{-1.i -1.s -1.o -1.c.???i.icf -2.i -2.s -2.o -2.c.???i.icf a.lto_wrapper_args a.wpa.???i.icf a.ltrans.out a.res a.ltrans0.o a.ltrans0.ltrans.???r.final a.ltrans0.ltrans.su a.ltrans0.ltrans.s a.ltrans0.ltrans.o a.{out,exe}}}
> +outest "$b lto st sing dumpdir empty dumpbase named" $sing "-dumpdir dir/ -dumpbase \"\" -o $b-0.exe -save-temps -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{-0.i -0.s -0.o -0.c.???i.icf -0.lto_wrapper_args -0.wpa.???i.icf -0.ltrans.out -0.res -0.ltrans0.o -0.ltrans0.ltrans.???r.final -0.ltrans0.ltrans.su -0.ltrans0.ltrans.s -0.ltrans0.ltrans.o} {-0.exe}}
> +outest "$b lto st mult dumpdir empty dumpbase named" $mult "-dumpdir dir/ -dumpbase \"\" -o $b-1.exe -save-temps -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{-1.i -1.s -1.o -1.c.???i.icf -2.i -2.s -2.o -2.c.???i.icf -1.lto_wrapper_args -1.wpa.???i.icf -1.ltrans.out -1.res -1.ltrans0.o -1.ltrans0.ltrans.???r.final -1.ltrans0.ltrans.su -1.ltrans0.ltrans.s -1.ltrans0.ltrans.o} {-1.exe}}
> +outest "$b lto st sing empty dumpbase namedb" $sing "-dumpbase \"\" -o dir/$b.exe -save-temps -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{-0.i -0.s -0.o -0.c.???i.icf .lto_wrapper_args .wpa.???i.icf .ltrans.out .res .ltrans0.o .ltrans0.ltrans.???r.final .ltrans0.ltrans.su .ltrans0.ltrans.s .ltrans0.ltrans.o .exe} {}}
> +outest "$b lto st mult empty dumpbase namedb" $mult "-dumpbase \"\" -o dir/$b.exe -save-temps -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{-1.i -1.s -1.o -1.c.???i.icf -2.i -2.s -2.o -2.c.???i.icf .lto_wrapper_args .wpa.???i.icf .ltrans.out .res .ltrans0.o .ltrans0.ltrans.???r.final .ltrans0.ltrans.su .ltrans0.ltrans.s .ltrans0.ltrans.o .exe} {}}
> +
> +# lto save-temps without -dumpbase.
> +outest "$b lto st sing unnamed" $sing "-save-temps -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {} {{a--0.i a--0.s a--0.o a--0.c.???i.icf a.lto_wrapper_args a.wpa.???i.icf a.ltrans.out a.res a.ltrans0.o a.ltrans0.ltrans.???r.final a.ltrans0.ltrans.su a.ltrans0.ltrans.s a.ltrans0.ltrans.o a.{out,exe}}}
> +outest "$b lto st mult unnamed" $mult "-save-temps -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {} {{a--1.i a--1.s a--1.o a--1.c.???i.icf a--2.i a--2.s a--2.o a--2.c.???i.icf a.lto_wrapper_args a.wpa.???i.icf a.ltrans.out a.res a.ltrans0.o a.ltrans0.ltrans.???r.final a.ltrans0.ltrans.su a.ltrans0.ltrans.s a.ltrans0.ltrans.o a.{out,exe}}}
> +outest "$b lto st sing dumpdir named" $sing "-dumpdir dir/$b- -o $b-0.exe -save-temps -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--0.i --0.s --0.o --0.c.???i.icf -lto_wrapper_args -wpa.???i.icf -ltrans.out -res -ltrans0.o -ltrans0.ltrans.???r.final -ltrans0.ltrans.su -ltrans0.ltrans.s -ltrans0.ltrans.o} {-0.exe}}
> +outest "$b lto st mult dumpdir named" $mult "-dumpdir dir/$b- -o $b-1.exe -save-temps -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--1.i --1.s --1.o --1.c.???i.icf --2.i --2.s --2.o --2.c.???i.icf -lto_wrapper_args -wpa.???i.icf -ltrans.out -res -ltrans0.o -ltrans0.ltrans.???r.final -ltrans0.ltrans.su -ltrans0.ltrans.s -ltrans0.ltrans.o} {-1.exe}}
> +outest "$b lto st sing namedb" $sing "-o dir/$b.exe -save-temps -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--0.i --0.s --0.o --0.c.???i.icf .lto_wrapper_args .wpa.???i.icf .ltrans.out .res .ltrans0.o .ltrans0.ltrans.???r.final .ltrans0.ltrans.su .ltrans0.ltrans.s .ltrans0.ltrans.o .exe} {}}
> +outest "$b lto st mult namedb" $mult "-o dir/$b.exe -save-temps -O2 -flto -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--1.i --1.s --1.o --1.c.???i.icf --2.i --2.s --2.o --2.c.???i.icf .lto_wrapper_args .wpa.???i.icf .ltrans.out .res .ltrans0.o .ltrans0.ltrans.???r.final .ltrans0.ltrans.su .ltrans0.ltrans.s .ltrans0.ltrans.o .exe} {}}
> +
> +# Below are examples taken from the documentation.
> +# They are likely redundant with earlier test,
> +# but we want to make sure behavior matches the docs.
> +
> +# gcc -c foo.c ...
> +outest "$b doc single -c !-o" $sing "-c -fdump-rtl-final -fstack-usage -gsplit-dwarf" {} {{-0.c.???r.final -0.su -0.dwo -0.o}}
> +
> +# gcc -c foo.c -o dir/foobar.o ...
> +outest "$b doc single -c +-o" $sing "-c -o dir/$b.o -fdump-rtl-final -fstack-usage -gsplit-dwarf" {dir/} {{.c.???r.final .su .dwo .o} {}}
> +
> +# gcc foo.c bar.c -o dir/foobar ...
> +outest "$b doc double !-c -o" $mult "-o dir/$b.exe -fdump-rtl-final -fstack-usage -gsplit-dwarf" {dir/} {{--1.c.???r.final --1.su --1.dwo --2.c.???r.final --2.su --2.dwo .exe} {}}
> +
> +# gcc foo.c -o dir/foo ...
> +outest "$b doc single !-c -o" $sing "-o dir/$b-0 -fdump-rtl-final -fstack-usage -gsplit-dwarf" {dir/} {{-0.c.???r.final -0.su -0.dwo -0} {}}
> +
> +# gcc -save-temps -S foo.c
> +outest "$b doc single -S -st" $sing "-save-temps -S" {} {{-0.i -0.s}}
> +
> +# gcc -save-temps -dumpbase save-foo -c foo.c
> +outest "$b doc single -c -st -db" $sing "-save-temps -dumpbase $b -c" {} {{.i .s -0.o}}
> +
> +# gcc foo.c -c -o dir/foo.o -dumpbase alt/foo \
> +# -dumpdir pfx- -save-temps=cwd ...
> +outest "$b doc single -c -o -db" $sing "-c -o dir/$b.o -dumpbase alt/$b -dumpdir pfx- -save-temps=cwd -fdump-rtl-final -fstack-usage -gsplit-dwarf" {alt/ dir/} {{.i .s .???r.final .su .dwo} {.o} {}}
> +
> +# gcc foo.c bar.c -c -dumpbase main ...
> +outest "$b doc double -c !-o -db" $mult "-c -dumpbase $b -fdump-rtl-final -fstack-usage -gsplit-dwarf" {} {{--1.c.???r.final --1.su --1.dwo -1.o --2.c.???r.final --2.su --2.dwo -2.o}}
> +
> +# gcc -c foo.c -o dir/foobar.o -dumpbase '' ...
> +outest "$b doc single -c -o -db''" $sing "-c -o dir/$b.o -dumpbase \"\" -fdump-rtl-final -fstack-usage -gsplit-dwarf" {dir/} {{-0.c.???r.final -0.su -0.dwo .o} {}}
> +
> +# gcc foo.c bar.c -o dir/foobar -dumpbase '' -flto ...
> +outest "$b doc double !-c -o -db'' -flto" $mult "-o dir/$b.exe -dumpbase \"\" -flto -O2 -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{-1.c.???i.icf -2.c.???i.icf .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su .exe} {}}
> +
> +
> +# gcc foo.c -c -o dir/foo.o -dumpbase x-foo.c -dumpbase-ext .c ...
> +outest "$b doc single -c -o -dbx" $sing "-c -o dir/$b-0.o -dumpbase $b.c -dumpbase-ext .c -fdump-rtl-final -fstack-usage -gsplit-dwarf" {dir/} {{.c.???r.final .su .dwo -0.o} {}}
> +
> +# gcc foo.c bar.c -o main.out -dumpbase-ext .out ...
> +outest "$b doc double !-c -o -dbx" $mult "-o $b.out -dumpbase-ext .out -fdump-rtl-final -fstack-usage -gsplit-dwarf" {} {{--1.c.???r.final --1.su --1.dwo --2.c.???r.final --2.su --2.dwo .out}}
> +
> +# gcc -dumpdir pfx- -c foo.c ...
> +outest "$b doc single -c !-o -dd" $sing "-dumpdir $b- -c -fdump-rtl-final -fstack-usage -gsplit-dwarf" {} {{--0.c.???r.final --0.su --0.dwo -0.o}}
> +
> +# gcc -dumpdir dir/ -c foo.c -o obj/bar.o ...
> +outest "$b doc single -c -o -dd" $sing "-dumpdir dir/ -c -o obj/$b.o -fdump-rtl-final -fstack-usage -gsplit-dwarf" {dir/ obj/} {{.c.???r.final .su .dwo} {.o} {}}
> +
> +# gcc -dumpdir pfx- -c foo.c -save-temps=obj ...
> +outest "$b doc single -c -o -dd -st=" $sing "-dumpdir $b- -c -save-temps=obj -fdump-rtl-final -fstack-usage -gsplit-dwarf" {} {{-0.c.???r.final -0.su -0.dwo -0.i -0.s -0.o}}
> +
> +# gcc foo.c bar.c -c -dumpdir dir/pfx- -dumpbase main ...
> +outest "$b doc double -c !-o -dd -db" $mult "-c -dumpdir dir/ -dumpbase $b -fdump-rtl-final -fstack-usage -gsplit-dwarf" {dir/} {{--1.c.???r.final --1.su --1.dwo --2.c.???r.final --2.su --2.dwo} {-1.o -2.o}}
> +
> +# gcc foo.c -c -dumpdir dir/pfx- -dumpbase main ...
> +outest "$b doc single -c !-o -dd -db" $sing "-c -dumpdir dir/ -dumpbase $b -fdump-rtl-final -fstack-usage -gsplit-dwarf" {dir/} {{.???r.final .su .dwo} {-0.o}}
> +
> +# gcc foo.c bar.c -dumpdir dir/pfx- -o main ...
> +outest "$b doc double !-c -o -dd" $mult "-dumpdir dir/ -o $b.exe -fdump-rtl-final -fstack-usage -gsplit-dwarf" {dir/} {{-1.c.???r.final -1.su -1.dwo -2.c.???r.final -2.su -2.dwo} {.exe}}
> +
> +# gcc foo.c -dumpdir alt/pfx- -o dir/main.exe -save-temps=cwd ...
> +outest "$b doc single !-c -o -dd -st=" $sing "-c -dumpdir dir/ -dumpbase $b -fdump-rtl-final -fstack-usage -gsplit-dwarf" {dir/} {{.???r.final .su .dwo} {-0.o}}
> +
> +
> +gcc_parallel_test_enable 1
> diff --git a/gcc/testsuite/lib/gcc-defs.exp b/gcc/testsuite/lib/gcc-defs.exp
> index da0d1bc..e656e27 100644
> --- a/gcc/testsuite/lib/gcc-defs.exp
> +++ b/gcc/testsuite/lib/gcc-defs.exp
> @@ -305,6 +305,10 @@ proc dg-additional-files-options { options source } {
> set to_download [concat $to_download $additional_sources]
> set additional_sources_used "$additional_sources"
> set additional_sources ""
> + # This option restores naming of aux and dump output files
> + # after input files when multiple input files are named,
> + # instead of getting them combined with the output name.
> + lappend options "additional_flags=-dumpbase \"\""
> }
> if { $additional_files != "" } then {
> regsub -all "^| " $additional_files " [file dirname $source]/" additional_files
> diff --git a/gcc/testsuite/lib/profopt.exp b/gcc/testsuite/lib/profopt.exp
> index 0b853a1..af1fd62f 100644
> --- a/gcc/testsuite/lib/profopt.exp
> +++ b/gcc/testsuite/lib/profopt.exp
> @@ -353,6 +353,10 @@ proc profopt-execute { src } {
>
> set count 0
> foreach option $prof_option_list {
> + # We pass -dumpbase-ext ${execext}[123] to the compile&link
> + # commands so as to avoid the combination of the executable
> + # with the source name in the aux outputs.
> + set execext ".x${count}"
> set execname1 "${executable}${count}1"
> set execname2 "${executable}${count}2"
> set execname3 "${executable}${count}3"
> @@ -402,7 +406,7 @@ proc profopt-execute { src } {
> # Compile for profiling.
>
> set options "$extra_options"
> - lappend options "additional_flags=$option $extra_flags $profile_option"
> + lappend options "additional_flags=$option $extra_flags $profile_option -dumpbase-ext ${execext}1"
> set optstr "$option $profile_option"
> set comp_output [${tool}_target_compile "$src" "$execname1" executable $options]
> if ![${tool}_check_compile "$testcase compilation" $optstr $execname1 $comp_output] {
> @@ -491,7 +495,7 @@ proc profopt-execute { src } {
> # Compile with feedback-directed optimizations.
>
> set options "$extra_options"
> - lappend options "additional_flags=$option $extra_flags $feedback_option"
> + lappend options "additional_flags=$option $extra_flags $feedback_option -dumpbase-ext ${execext}2"
> set optstr "$option $feedback_option"
> if { [string first "-fauto-profile" $options] >= 0} {
> set options [regsub -- "-fauto-profile" $options "-fauto-profile=$tmpdir/$bprefix$base.$ext"]
> @@ -548,7 +552,7 @@ proc profopt-execute { src } {
> # Compile with normal optimizations.
>
> set options "$extra_options"
> - lappend options "additional_flags=$option"
> + lappend options "additional_flags=$option -dumpbase-ext ${execext}3"
> set optstr "$option"
> set comp_output [${tool}_target_compile "$src" "$execname3" "executable" $options]
> if ![${tool}_check_compile "$testcase compilation" $optstr $execname3 $comp_output] {
> diff --git a/gcc/testsuite/lib/scandump.exp b/gcc/testsuite/lib/scandump.exp
> index 4c7d904..b29a95a 100644
> --- a/gcc/testsuite/lib/scandump.exp
> +++ b/gcc/testsuite/lib/scandump.exp
> @@ -32,6 +32,9 @@ proc dump-suffix { arg } {
> proc dump-base { args } {
> set src [lindex $args 0]
> set dumpbase_suf [lindex $args 1]
> + # The dump basename may vary depending on the output name, on
> + # whether there are multiple sources. We use -dumpbase "" in
> + # gcc-defs to base compilation dumps only on the source basename.
> set dumpbase $src
> if { [string length $dumpbase_suf] != 0 } {
> regsub {[.][^.]*$} $src $dumpbase_suf dumpbase
> diff --git a/gcc/testsuite/lib/scanltranstree.exp b/gcc/testsuite/lib/scanltranstree.exp
> index cff956b..6d35bef 100644
> --- a/gcc/testsuite/lib/scanltranstree.exp
> +++ b/gcc/testsuite/lib/scanltranstree.exp
> @@ -37,11 +37,11 @@ proc scan-ltrans-tree-dump { args } {
> }
> if { [llength $args] >= 3 } {
> scan-dump "ltrans-tree" [lindex $args 0] \
> - "\[0-9\]\[0-9\]\[0-9\]t.[lindex $args 1]" ".exe.ltrans0" \
> + "\[0-9\]\[0-9\]\[0-9\]t.[lindex $args 1]" ".ltrans0.ltrans" \
> [lindex $args 2]
> } else {
> scan-dump "ltrans-tree" [lindex $args 0] \
> - "\[0-9\]\[0-9\]\[0-9\]t.[lindex $args 1]" ".exe.ltrans0"
> + "\[0-9\]\[0-9\]\[0-9\]t.[lindex $args 1]" ".ltrans0.ltrans"
> }
> }
>
> @@ -63,10 +63,10 @@ proc scan-ltrans-tree-dump-times { args } {
> if { [llength $args] >= 4 } {
> scan-dump-times "ltrans-tree" [lindex $args 0] [lindex $args 1] \
> "\[0-9\]\[0-9\]\[0-9\]t.[lindex $args 2]" \
> - ".exe.ltrans0" [lindex $args 3]
> + ".ltrans0.ltrans" [lindex $args 3]
> } else {
> scan-dump-times "ltrans-tree" [lindex $args 0] [lindex $args 1] \
> - "\[0-9\]\[0-9\]\[0-9\]t.[lindex $args 2]" ".exe.ltrans0"
> + "\[0-9\]\[0-9\]\[0-9\]t.[lindex $args 2]" ".ltrans0.ltrans"
> }
> }
>
> @@ -87,11 +87,11 @@ proc scan-ltrans-tree-dump-not { args } {
> }
> if { [llength $args] >= 3 } {
> scan-dump-not "ltrans-tree" [lindex $args 0] \
> - "\[0-9\]\[0-9\]\[0-9\]t.[lindex $args 1]" ".exe.ltrans0" \
> + "\[0-9\]\[0-9\]\[0-9\]t.[lindex $args 1]" ".ltrans0.ltrans" \
> [lindex $args 2]
> } else {
> scan-dump-not "ltrans-tree" [lindex $args 0] \
> - "\[0-9\]\[0-9\]\[0-9\]t.[lindex $args 1]" ".exe.ltrans0"
> + "\[0-9\]\[0-9\]\[0-9\]t.[lindex $args 1]" ".ltrans0.ltrans"
> }
> }
>
> @@ -113,11 +113,11 @@ proc scan-ltrans-tree-dump-dem { args } {
> }
> if { [llength $args] >= 3 } {
> scan-dump-dem "ltrans-tree" [lindex $args 0] \
> - "\[0-9\]\[0-9\]\[0-9\]t.[lindex $args 1]" ".exe.ltrans0" \
> + "\[0-9\]\[0-9\]\[0-9\]t.[lindex $args 1]" ".ltrans0.ltrans" \
> [lindex $args 2]
> } else {
> scan-dump-dem "ltrans-tree" [lindex $args 0] \
> - "\[0-9\]\[0-9\]\[0-9\]t.[lindex $args 1]" ".exe.ltrans0"
> + "\[0-9\]\[0-9\]\[0-9\]t.[lindex $args 1]" ".ltrans0.ltrans"
> }
> }
>
> @@ -139,10 +139,10 @@ proc scan-ltrans-tree-dump-dem-not { args } {
> if { [llength $args] >= 3 } {
> scan-dump-dem-not "ltrans-tree" [lindex $args 0] \
> "\[0-9\]\[0-9\]\[0-9\]t.[lindex $args 1]" \
> - ".exe.ltrans0" [lindex $args 2]
> + ".ltrans0.ltrans" [lindex $args 2]
> } else {
> scan-dump-dem-not "ltrans-tree" [lindex $args 0] \
> "\[0-9\]\[0-9\]\[0-9\]t.[lindex $args 1]" \
> - ".exe.ltrans0"
> + ".ltrans0.ltrans"
> }
> }
> diff --git a/gcc/testsuite/lib/scanwpaipa.exp b/gcc/testsuite/lib/scanwpaipa.exp
> index d00b400..39e95b8 100644
> --- a/gcc/testsuite/lib/scanwpaipa.exp
> +++ b/gcc/testsuite/lib/scanwpaipa.exp
> @@ -37,11 +37,11 @@ proc scan-wpa-ipa-dump { args } {
> }
> if { [llength $args] >= 3 } {
> scan-dump "wpa-ipa" [lindex $args 0] \
> - "\[0-9\]\[0-9\]\[0-9\]i.[lindex $args 1]" ".exe.wpa" \
> + "\[0-9\]\[0-9\]\[0-9\]i.[lindex $args 1]" ".wpa" \
> [lindex $args 2]
> } else {
> scan-dump "wpa-ipa" [lindex $args 0] \
> - "\[0-9\]\[0-9\]\[0-9\]i.[lindex $args 1]" ".exe.wpa"
> + "\[0-9\]\[0-9\]\[0-9\]i.[lindex $args 1]" ".wpa"
> }
> }
>
> @@ -62,11 +62,11 @@ proc scan-wpa-ipa-dump-times { args } {
> }
> if { [llength $args] >= 4 } {
> scan-dump-times "wpa-ipa" [lindex $args 0] [lindex $args 1] \
> - "\[0-9\]\[0-9\]\[0-9\]i.[lindex $args 2]" ".exe.wpa" \
> + "\[0-9\]\[0-9\]\[0-9\]i.[lindex $args 2]" ".wpa" \
> [lindex $args 3]
> } else {
> scan-dump-times "wpa-ipa" [lindex $args 0] [lindex $args 1] \
> - "\[0-9\]\[0-9\]\[0-9\]i.[lindex $args 2]" ".exe.wpa"
> + "\[0-9\]\[0-9\]\[0-9\]i.[lindex $args 2]" ".wpa"
> }
> }
>
> @@ -87,11 +87,11 @@ proc scan-wpa-ipa-dump-not { args } {
> }
> if { [llength $args] >= 3 } {
> scan-dump-not "wpa-ipa" [lindex $args 0] \
> - "\[0-9\]\[0-9\]\[0-9\]i.[lindex $args 1]" ".exe.wpa" \
> + "\[0-9\]\[0-9\]\[0-9\]i.[lindex $args 1]" ".wpa" \
> [lindex $args 2]
> } else {
> scan-dump-not "wpa-ipa" [lindex $args 0] \
> - "\[0-9\]\[0-9\]\[0-9\]i.[lindex $args 1]" ".exe.wpa"
> + "\[0-9\]\[0-9\]\[0-9\]i.[lindex $args 1]" ".wpa"
> }
> }
>
> @@ -113,11 +113,11 @@ proc scan-wpa-ipa-dump-dem { args } {
> }
> if { [llength $args] >= 3 } {
> scan-dump-dem "wpa-ipa" [lindex $args 0] \
> - "\[0-9\]\[0-9\]\[0-9\]i.[lindex $args 1]" ".exe.wpa" \
> + "\[0-9\]\[0-9\]\[0-9\]i.[lindex $args 1]" ".wpa" \
> [lindex $args 2]
> } else {
> scan-dump-dem "wpa-ipa" [lindex $args 0] \
> - "\[0-9\]\[0-9\]\[0-9\]i.[lindex $args 1]" ".exe.wpa"
> + "\[0-9\]\[0-9\]\[0-9\]i.[lindex $args 1]" ".wpa"
> }
> }
>
> @@ -138,10 +138,10 @@ proc scan-wpa-ipa-dump-dem-not { args } {
> }
> if { [llength $args] >= 3 } {
> scan-dump-dem-not "wpa-ipa" [lindex $args 0] \
> - "\[0-9\]\[0-9\]\[0-9\]i.[lindex $args 1]" ".exe.wpa" \
> + "\[0-9\]\[0-9\]\[0-9\]i.[lindex $args 1]" ".wpa" \
> [lindex $args 2]
> } else {
> scan-dump-dem-not "wpa-ipa" [lindex $args 0] \
> - "\[0-9\]\[0-9\]\[0-9\]i.[lindex $args 1]" ".exe.wpa"
> + "\[0-9\]\[0-9\]\[0-9\]i.[lindex $args 1]" ".wpa"
> }
> }
> diff --git a/gcc/toplev.c b/gcc/toplev.c
> index 4c8be50..04f8938 100644
> --- a/gcc/toplev.c
> +++ b/gcc/toplev.c
> @@ -796,8 +796,8 @@ print_switch_values (print_switch_fn_type print_fn)
> case OPT_o:
> case OPT_d:
> case OPT_dumpbase:
> + case OPT_dumpbase_ext:
> case OPT_dumpdir:
> - case OPT_auxbase:
> case OPT_quiet:
> case OPT_version:
> /* Ignore these. */
> @@ -1410,11 +1410,19 @@ process_options (void)
> /* Set aux_base_name if not already set. */
> if (aux_base_name)
> ;
> - else if (main_input_filename)
> + else if (dump_base_name)
> {
> - char *name = xstrdup (lbasename (main_input_filename));
> + const char *name = dump_base_name;
> + int nlen, len;
> +
> + if (dump_base_ext && (len = strlen (dump_base_ext))
> + && (nlen = strlen (name)) && nlen > len
> + && strcmp (name + nlen - len, dump_base_ext) == 0)
> + {
> + char *p = xstrndup (name, nlen - len);
> + name = p;
> + }
>
> - strip_off_ending (name, strlen (name));
> aux_base_name = name;
> }
> else
> @@ -1961,8 +1969,21 @@ static int
> lang_dependent_init (const char *name)
> {
> location_t save_loc = input_location;
> - if (dump_base_name == 0)
> - dump_base_name = name && name[0] ? name : "gccdump";
> + if (!dump_base_name)
> + {
> + dump_base_name = name && name[0] ? name : "gccdump";
> +
> + /* We do not want to derive a non-empty dumpbase-ext from an
> + explicit -dumpbase argument, only from a defaulted
> + dumpbase. */
> + if (!dump_base_ext)
> + {
> + const char *base = lbasename (dump_base_name);
> + const char *ext = strrchr (base, '.');
> + if (ext)
> + dump_base_ext = ext;
> + }
> + }
>
> /* Other front-end initialization. */
> input_location = BUILTINS_LOCATION;
> @@ -1974,20 +1995,25 @@ lang_dependent_init (const char *name)
> {
> init_asm_output (name);
>
> - /* If stack usage information is desired, open the output file. */
> - if (flag_stack_usage && !flag_generate_lto)
> - stack_usage_file = open_auxiliary_file ("su");
> -
> - /* If call graph information is desired, open the output file. */
> - if (flag_callgraph_info && !flag_generate_lto)
> + if (!flag_generate_lto && !flag_compare_debug)
> {
> - callgraph_info_file = open_auxiliary_file ("ci");
> - /* Write the file header. */
> - fprintf (callgraph_info_file,
> - "graph: { title: \"%s\"\n", main_input_filename);
> - bitmap_obstack_initialize (NULL);
> - callgraph_info_external_printed = BITMAP_ALLOC (NULL);
> + /* If stack usage information is desired, open the output file. */
> + if (flag_stack_usage)
> + stack_usage_file = open_auxiliary_file ("su");
> +
> + /* If call graph information is desired, open the output file. */
> + if (flag_callgraph_info)
> + {
> + callgraph_info_file = open_auxiliary_file ("ci");
> + /* Write the file header. */
> + fprintf (callgraph_info_file,
> + "graph: { title: \"%s\"\n", main_input_filename);
> + bitmap_obstack_initialize (NULL);
> + callgraph_info_external_printed = BITMAP_ALLOC (NULL);
> + }
> }
> + else
> + flag_stack_usage = flag_callgraph_info = false;
> }
>
> /* This creates various _DECL nodes, so needs to be called after the
> diff --git a/lto-plugin/lto-plugin.c b/lto-plugin/lto-plugin.c
> index c307fc8..30f9cca 100644
> --- a/lto-plugin/lto-plugin.c
> +++ b/lto-plugin/lto-plugin.c
> @@ -195,6 +195,10 @@ static int linker_output_set;
> static int linker_output_known;
> static const char *link_output_name = NULL;
>
> +/* This indicates link_output_name already contains the dot of the
> + suffix, so we can skip it in extensions. */
> +static int skip_in_suffix = 0;
> +
> /* The version of gold being used, or -1 if not gold. The number is
> MAJOR * 100 + MINOR. */
> static int gold_version = -1;
> @@ -567,14 +571,11 @@ exec_lto_wrapper (char *argv[])
> /* Write argv to a file to avoid a command line that is too long
> Save the file locally on save-temps. */
> if (save_temps && link_output_name)
> - {
> - arguments_file_name = (char *) xmalloc (strlen (link_output_name)
> - + sizeof (".lto_wrapper_args") + 1);
> - strcpy (arguments_file_name, link_output_name);
> - strcat (arguments_file_name, ".lto_wrapper_args");
> - }
> + arguments_file_name = concat (link_output_name,
> + ".lto_wrapper_args"
> + + skip_in_suffix, NULL);
> else
> - arguments_file_name = make_temp_file (".lto_wrapper_args");
> + arguments_file_name = make_temp_file (".lto_wrapper_args");
> check (arguments_file_name, LDPL_FATAL,
> "Failed to generate a temorary file name");
>
> @@ -1312,12 +1313,82 @@ onload (struct ld_plugin_tv *tv)
> if (strstr (collect_gcc_options, "'-fno-use-linker-plugin'"))
> return LDPS_ERR;
>
> - if ( strstr (collect_gcc_options, "'-save-temps'"))
> + if (strstr (collect_gcc_options, "'-save-temps'"))
> save_temps = true;
>
> if (strstr (collect_gcc_options, "'-v'")
> || strstr (collect_gcc_options, "'--verbose'"))
> verbose = true;
> +
> + const char *p;
> + if ((p = strstr (collect_gcc_options, "'-dumpdir'")))
> + {
> + p += sizeof ("'-dumpdir'");
> + while (*p == ' ')
> + p++;
> + const char *start = p;
> + int ticks = 0, escapes = 0;
> + /* Count ticks (') and escaped (\.) characters. Stop at the
> + end of the options or at a blank after an even number of
> + ticks (not counting escaped ones. */
> + for (p = start; *p; p++)
> + {
> + if (*p == '\'')
> + {
> + ticks++;
> + continue;
> + }
> + else if ((ticks % 2) != 0)
> + {
> + if (*p == ' ')
> + break;
> + if (*p == '\\')
> + {
> + if (*++p)
> + escapes++;
> + else
> + p--;
> + }
> + }
> + }
> +
> + /* Now allocate a new link_output_name and decode dumpdir
> + into it. The loop uses the same logic, except it counts
> + ticks and escapes backwards (so ticks is adjusted if we
> + find an odd number of them), and it copies characters
> + that are escaped or not otherwise skipped. */
> + int len = p - start - ticks - escapes + 1;
> + char *q = xmalloc (len);
> + link_output_name = q;
> + int oddticks = (ticks % 2);
> + ticks += oddticks;
> + for (p = start; *p; p++)
> + {
> + if (*p == '\'')
> + {
> + ticks--;
> + continue;
> + }
> + else if ((ticks % 2) != 0)
> + {
> + if (*p == ' ')
> + break;
> + if (*p == '\\')
> + {
> + if (*++p)
> + escapes--;
> + else
> + p--;
> + }
> + }
> + *q++ = *p;
> + }
> + *q = '\0';
> + assert (escapes == 0);
> + assert (ticks == oddticks);
> + assert (q - link_output_name == len - 1);
> + skip_in_suffix = 1;
> + }
> }
>
> return LDPS_OK;
>
>
--
Richard Biener <rguenther@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)
More information about the Gcc-patches
mailing list