public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Alexandre Oliva <oliva@adacore.com>
To: Richard Biener <rguenther@suse.de>
Cc: gcc-patches@gcc.gnu.org, ebotcazou@adacore.com, joseph@codesourcery.com
Subject: Re: drop -aux{dir,base}, revamp -dump{dir,base}
Date: Tue, 26 May 2020 04:08:44 -0300	[thread overview]
Message-ID: <or7dwzb2bn.fsf@livre.home> (raw)
In-Reply-To: <nycvar.YFH.7.76.2005220803360.4397@zhemvz.fhfr.qr> (Richard Biener's message of "Fri, 22 May 2020 08:05:19 +0200 (CEST)")

On May 22, 2020, Richard Biener <rguenther@suse.de> wrote:

>> https://gcc.gnu.org/pipermail/gcc-patches/2020-May/546015.html
>> 
>> Did you by any chance miss it, or choose not to review it?

> I looked at it shortly but decided somebody else may have more knowledge
> there - I'd simply trust you'd done things correctly...

> So unless anybody comes up to review and ack it consider it approved
> by me after the weekend ;)

Thanks, here's the combined patch I'm checking in.

revamp dump and aux output names

From: Alexandre Oliva <oliva@adacore.com>

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 "".  When compiling and
linking tests in the testsuite with additional inputs, we now use this
flag.  Files named in dejagnu board ldflags, libs, and ldscripts are
now quoted in the gcc testsuite with -Wl, so that they are not counted
as additional inputs by the compiler driver.

- 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.


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 (HAVE_TARGET_EXECUTABLE_SUFFIX): Define if...
	(TARGET_EXECUTABLE_SUFFIX): ... is defined; define this to the
	empty string otherwise.
	(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.

gcc/fortran/ChangeLog:

	* options.c (gfc_get_option_string): Drop auxbase, add
	dumpbase_ext.

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.

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.

contrib/ChangeLog:

	* compare-debug: Adjust for .gkd files named as dump files,
	with the source suffix rather than the object suffix.

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 (gcc_adjusted_linker_flags): New.
	(gcc_adjust_linker_flags): New.
	(dg-additional-files-options): Call it.  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                        |  157 ++---
 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 |  695 ++++++++++++++++++++++
 gcc/testsuite/lib/gcc-defs.exp           |   46 +
 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, 2126 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 10f8473..12b7cf5e 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 4464049..1b770bc 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)
@@ -852,12 +861,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
 
@@ -869,11 +872,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 8b9935d..78c2f50 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -185,7 +185,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
@@ -1602,9 +1604,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
@@ -1613,6 +1615,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
@@ -16279,54 +16589,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
@@ -16363,7 +16647,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
@@ -30630,17 +30914,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 fad5eb4..9deca03 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -24351,9 +24351,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 b0d0308..8c851d7 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 *);
+
 \f
 /* 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
 
@@ -1144,22 +1178,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:\
@@ -1647,9 +1679,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},
@@ -4145,7 +4176,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;
 
@@ -4158,6 +4190,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:
@@ -4264,8 +4313,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);
@@ -4308,6 +4355,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
@@ -4324,6 +4384,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'.  */
 
@@ -4636,23 +4722,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)
     {
-      save_temps_length = strlen (save_temps_prefix);
-      temp = strrchr (lbasename (save_temps_prefix), '.');
-      if (temp)
+      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)
 	{
-	  save_temps_length -= strlen (temp);
-	  save_temps_prefix[save_temps_length] = '\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 defined(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))
+    {
+      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))
+	{
+	  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)
@@ -4848,6 +5282,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 *));
 }
@@ -5366,22 +5822,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;
 
@@ -5534,42 +6001,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)
@@ -6080,6 +6549,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;
@@ -6090,6 +6567,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.  */
@@ -8296,6 +8776,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)
@@ -9766,7 +10280,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;
@@ -9776,25 +10290,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;
@@ -9821,8 +10332,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.  */
@@ -9838,16 +10347,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 \
@@ -9855,50 +10354,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
@@ -9942,34 +10397,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].
@@ -10075,6 +10601,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.
@@ -10102,26 +10666,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
@@ -10158,8 +10746,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;
 
@@ -10298,8 +10892,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 e34b697..d565b08 100644
--- a/gcc/lto-wrapper.c
+++ b/gcc/lto-wrapper.c
@@ -53,6 +53,13 @@ along with GCC; see the file COPYING3.  If not see
    driver to lto-wrapper.  */
 #define OFFLOAD_TARGET_NAMES_ENV	"OFFLOAD_TARGET_NAMES"
 
+/* By default there is no special suffix for target executables.  */
+#ifdef TARGET_EXECUTABLE_SUFFIX
+#define HAVE_TARGET_EXECUTABLE_SUFFIX
+#else
+#define TARGET_EXECUTABLE_SUFFIX ""
+#endif
+
 enum lto_mode_d {
   LTO_MODE_NONE,			/* Not doing LTO.  */
   LTO_MODE_LTO,				/* Normal LTO.  */
@@ -126,7 +133,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.  */
@@ -1100,12 +1107,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);
@@ -1296,6 +1298,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");
@@ -1407,6 +1411,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;
@@ -1452,6 +1460,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;
 	}
@@ -1490,32 +1502,47 @@ run_gcc (unsigned argc, char *argv[])
 	}
     }
 
-  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 defined(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");
+      obstack_ptr_grow (&argv_obstack, "");
     }
+  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 *);
@@ -1621,15 +1648,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);
@@ -1637,47 +1660,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)
 	{
@@ -1833,16 +1826,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 ec3ca07..340d9943 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;
@@ -2346,17 +2322,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..9823710
--- /dev/null
+++ b/gcc/testsuite/gcc.misc-tests/outputs.exp
@@ -0,0 +1,695 @@
+# 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] || [is_remote host]} {
+    return
+}
+gcc_parallel_test_enable 0
+
+set gsplit_dwarf "-gsplit-dwarf"
+if ![check_no_compiler_messages gsplitdwarf object {
+    void foo (void) { }
+} "$gsplit_dwarf"] {
+    set gsplit_dwarf ""
+}
+
+# Prepare additional options to be used for linking.
+# We do not compile to an executable, because that requires naming an output.
+set link_options ""
+set dest [target_info name]
+foreach i { ldflags libs ldscripts } {
+    if {[board_info $dest exists $i]} {
+	set skip ""
+	foreach opt [split [board_info $dest $i]] {
+	    if { $skip != "" } then {
+		set skip ""
+	    } elseif { $opt == "-Xlinker" } then {
+		set skip $opt
+	    } elseif { ![string match "-*" $opt] && [file isfile $opt] } {
+	    	set opt "-Wl,$opt"
+	    }
+	    append link_options " additional_flags=$opt"
+	}
+    }
+}
+if {[board_info $dest exists output_format]} {
+    append link_options " additional_flags=-Wl,-oformat,[board_info $dest output_format]"
+}
+
+# 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
+    global gsplit_dwarf
+    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 " "] {
+	append options " additional_flags=$opt"
+    }
+    # Add linker flags if we're linking
+    if {![string match "* -\[ESc\] *" " $opts "]} {
+	global link_options
+	append options "$link_options"
+    }
+    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 { "$gsplit_dwarf" == "" \
+		 && [string match "*.dwo" "$og"] } then {
+		continue
+	    }
+	    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\n$outs"
+    }
+
+    if { [string equal "$gcc_output" ""] } then {
+	pass "$test: std out"
+    } else {
+	fail "$test: std out\n$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 180a9ab..fc7e8e2 100644
--- a/gcc/testsuite/lib/gcc-defs.exp
+++ b/gcc/testsuite/lib/gcc-defs.exp
@@ -285,11 +285,53 @@ proc dg-additional-files { args } {
     set additional_files [lindex $args 1]
 }
 
+set gcc_adjusted_linker_flags 0
+
+# Add -Wl, before any file names in ldflags, libs, and ldscripts, so
+# that default object files or libraries do not change the names of
+# gcc auxiliary outputs.
+
+proc gcc_adjust_linker_flags {} {
+    global gcc_adjusted_linker_flags
+    if {$gcc_adjusted_linker_flags} {
+	return
+    }
+    set gcc_adjusted_linker_flags 1
+
+    if {![is_remote host]} {
+	set dest [target_info name]
+	foreach i { ldflags libs ldscripts } {
+	    if {[board_info $dest exists $i]} {
+		set opts [board_info $dest $i]
+		set nopts {}
+		set skip ""
+		foreach opt [split $opts] {
+		    if { $skip != "" } then {
+			set skip ""
+		    } elseif { $opt == "-Xlinker" } then {
+			set skip $opt
+		    } elseif { ![string match "-*" $opt] \
+				&& [file isfile $opt] } {
+			set opt "-Wl,$opt"
+		    }
+		    lappend nopts $opt
+		}
+		if { $nopts != $opts } {
+		    unset_currtarget_info $i
+		    set_currtarget_info $i "$nopts"
+		}
+	    }
+	}
+    }
+}
+
 # Return an updated version of OPTIONS that mentions any additional
 # source files registered with dg-additional-sources.  SOURCE is the
 # name of the test case.
 
 proc dg-additional-files-options { options source } {
+    gcc_adjust_linker_flags
+
     global additional_sources
     global additional_sources_used
     global additional_files
@@ -305,6 +347,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 d6ba350..2479c89 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 2f58823..cc50cc4 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"
     }
 }
 
@@ -85,11 +85,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"
     }
 }
 
@@ -110,11 +110,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"
     }
 }
 
@@ -136,11 +136,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"
     }
 }
 
@@ -161,10 +161,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 96316fb..1a75485 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
@@ -1964,8 +1972,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;
@@ -1977,20 +1998,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 37f4bda..a65c280 100644
--- a/lto-plugin/lto-plugin.c
+++ b/lto-plugin/lto-plugin.c
@@ -203,6 +203,10 @@ static bool linker_output_known;
 static bool linker_output_auto_nolto_rel;
 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;
@@ -621,14 +625,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");
 
@@ -1439,12 +1440,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;


-- 
Alexandre Oliva, freedom fighter    he/him    https://FSFLA.org/blogs/lxo/
Free Software Evangelist              Stallman was right, but he's left :(
GNU Toolchain Engineer           Live long and free, and prosper ethically

  reply	other threads:[~2020-05-26  7:08 UTC|newest]

Thread overview: 117+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-26  5:30 introduce -fcallgraph-info option Alexandre Oliva
2019-10-26  8:12 ` Richard Biener
2019-10-26 11:21   ` Alexandre Oliva
2019-10-27  9:08     ` Alexandre Oliva
2019-10-28  8:38       ` Richard Biener
2019-10-30 10:12         ` Alexandre Oliva
2019-10-30 11:28           ` Richard Biener
2019-11-02 19:31             ` Alexandre Oliva
2019-11-04  8:28               ` Richard Biener
2019-11-06 10:53                 ` Alexandre Oliva
2019-11-20  4:35                   ` Alexandre Oliva
2019-11-20  9:16                     ` Richard Biener
2019-11-06 15:38                 ` Alexandre Oliva
2019-11-07  7:49                   ` Richard Biener
2019-11-07 10:50                     ` Alexandre Oliva
2019-11-07 11:48                       ` Richard Biener
2019-11-07 12:30                         ` Alexandre Oliva
2019-11-07 14:02                           ` Richard Biener
2019-11-07 22:39                             ` Alexandre Oliva
2019-11-08  8:28                               ` Richard Biener
2019-11-08 23:12                                 ` Eric Gallager
2019-11-15  1:34                                   ` Alexandre Oliva
2019-11-15  1:01                                 ` Alexandre Oliva
2019-11-15  7:30                                   ` Alexandre Oliva
2019-11-15  8:08                                     ` Richard Biener
2019-11-15 22:50                                       ` Alexandre Oliva
2019-12-03 22:44                                   ` Alexandre Oliva
2019-12-09  9:41                                     ` Richard Biener
2019-12-12  1:14                                       ` Alexandre Oliva
2019-12-25 10:05                               ` Alexandre Oliva
2019-12-26 19:00                                 ` drop -aux{dir,base}, revamp -dump{dir,base} (was: Re: introduce -fcallgraph-info option) Alexandre Oliva
2020-01-09 13:33                                   ` Richard Biener
2020-01-09 19:09                                     ` drop -aux{dir,base}, revamp -dump{dir,base} Alexandre Oliva
2020-01-16 11:06                                       ` Alexandre Oliva
2020-01-16 11:15                                         ` Alexandre Oliva
2020-01-17  2:14                                           ` Joseph Myers
2020-01-20 10:38                                         ` Richard Biener
2020-01-22  1:25                                           ` Alexandre Oliva
2020-01-22  8:15                                             ` Richard Biener
2020-01-23 20:06                                               ` Alexandre Oliva
2020-01-24  1:50                                               ` Alexandre Oliva
2020-05-19  8:51                                                 ` Alexandre Oliva
2020-05-19  8:59                                                   ` Alexandre Oliva
2020-05-19  9:29                                                     ` Richard Biener
2020-05-19  8:59                                                   ` Alexandre Oliva
2020-05-19  9:30                                                     ` Richard Biener
2020-05-19  9:00                                                   ` Alexandre Oliva
2020-05-19  9:04                                                   ` Richard Biener
2020-05-22  0:32                                                     ` Alexandre Oliva
2020-05-22  6:05                                                       ` Richard Biener
2020-05-26  7:08                                                         ` Alexandre Oliva [this message]
2020-05-26  8:52                                                           ` Richard Biener
2020-05-26  9:02                                                             ` Martin Liška
2020-05-26 10:00                                                             ` Alexandre Oliva
2020-05-26 12:14                                                             ` Alexandre Oliva
2020-05-26 13:52                                                             ` Alexandre Oliva
2020-05-26 13:56                                                               ` Richard Biener
2020-05-27 22:05                                                                 ` Alexandre Oliva
2020-05-27 23:01                                                                   ` Jeff Law
2020-06-02 11:52                                                                   ` Alexandre Oliva
2020-06-02 12:02                                                                     ` Richard Biener
2020-05-27  1:04                                                               ` Broken build (was: Re: drop -aux{dir,base}, revamp -dump{dir,base}) Hans-Peter Nilsson
2020-05-27 14:30                                                                 ` Broken build Alexandre Oliva
2020-05-27 15:04                                                                   ` Hans-Peter Nilsson
2020-05-28  0:53                                                                     ` Alexandre Oliva
2020-05-28  0:39                                                                 ` Anthony Green
2020-06-02 11:29                                                                   ` Alexandre Oliva
2020-06-02 14:07                                                                     ` Hans-Peter Nilsson
2020-05-27  9:45                                                           ` drop -aux{dir,base}, revamp -dump{dir,base} Andreas Schwab
2020-05-27 10:28                                                             ` Andreas Schwab
2020-05-27 14:41                                                               ` Alexandre Oliva
2020-05-27 14:59                                                                 ` Andreas Schwab
2020-06-09 12:29                                                           ` Thomas Schwinge
2020-06-09 12:42                                                             ` BRIG FE testsuite: Fix all dump-scans (Was: Re: drop -aux{dir, base}, revamp -dump{dir, base}) Martin Jambor
2020-06-09 18:31                                                               ` BRIG FE testsuite: Fix all dump-scans (Was: Re: drop -aux{dir,base}, revamp -dump{dir,base}) Mike Stump
2020-06-11 14:28                                                                 ` BRIG FE testsuite: Fix all dump-scans (Was: Re: drop -aux{dir, base}, revamp -dump{dir, base}) Martin Jambor
2020-06-12 20:52                                                                   ` BRIG FE testsuite: Fix all dump-scans (Was: Re: drop -aux{dir,base}, revamp -dump{dir,base}) Mike Stump
2020-06-10 21:50                                                               ` BRIG FE testsuite: Fix all dump-scans Alexandre Oliva
2020-06-23  9:44                                                             ` drop -aux{dir,base}, revamp -dump{dir,base} Alexandre Oliva
2020-06-23 11:30                                                               ` Martin Jambor
2020-06-09 13:08                                                           ` Thomas Schwinge
2020-06-10 22:24                                                             ` Alexandre Oliva
2020-06-17 10:50                                                               ` Tobias Burnus
2020-06-18  2:58                                                                 ` Alexandre Oliva
2020-06-18  6:10                                                             ` Alexandre Oliva
2020-06-18  9:41                                                               ` Tobias Burnus
2020-06-18 10:39                                                                 ` Alexandre Oliva
2020-06-18 12:06                                                                   ` Tobias Burnus
2020-06-30 16:13                                                                     ` Thomas Schwinge
2020-07-14  5:46                                                                       ` Alexandre Oliva
2020-07-24  6:08                                                                         ` Thomas Schwinge
2020-07-24 17:54                                                                           ` Alexandre Oliva
2020-07-14  5:49                                                                       ` Alexandre Oliva
2020-06-19  9:53                                                                 ` Alexandre Oliva
2020-06-19 16:09                                                                   ` Tobias Burnus
2020-06-22  6:08                                                                     ` Alexandre Oliva
2020-06-22  7:07                                                                       ` Tobias Burnus
2020-06-22 14:32                                                                         ` Alexandre Oliva
2020-06-23  8:17                                                                           ` Richard Biener
2020-06-30 16:35                                                                           ` Thomas Schwinge
2020-07-24 12:06                                                                             ` Thomas Schwinge
2020-06-30 18:52                                                                           ` Thomas Schwinge
2020-07-14  4:48                                                                             ` Alexandre Oliva
2020-07-24  6:01                                                                               ` Thomas Schwinge
2020-07-24 18:00                                                                                 ` Alexandre Oliva
2023-11-24 12:46                                                                           ` testsuite: Add 'only_for_offload_target' wrapper for 'scan-offload-tree-dump' etc. (was: drop -aux{dir,base}, revamp -dump{dir,base}) Thomas Schwinge
2020-06-23  9:50                                                             ` drop -aux{dir,base}, revamp -dump{dir,base} Alexandre Oliva
2020-06-30 16:07                                                               ` Thomas Schwinge
2020-07-23 21:12                                                               ` [PR95720] protect gluefile and wrap_flags with -Wl too (was: Re: drop -aux{dir,base}, revamp -dump{dir,base}) Alexandre Oliva
2020-07-24  6:48                                                                 ` Richard Biener
2020-05-26  8:09                                                       ` [wwwdocs] Re: drop -aux{dir,base}, revamp -dump{dir,base} Alexandre Oliva
2019-10-28 23:56 ` introduce -fcallgraph-info option Joseph Myers
2019-10-30  9:22   ` Alexandre Oliva
2019-10-30  9:43   ` Alexandre Oliva
2019-10-30 18:17     ` Joseph Myers
2019-11-06 21:27 ` Thomas Schwinge
2019-11-07 11:23   ` Alexandre Oliva

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=or7dwzb2bn.fsf@livre.home \
    --to=oliva@adacore.com \
    --cc=ebotcazou@adacore.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=joseph@codesourcery.com \
    --cc=rguenther@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).