public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-4644] d: Merge upstream dmd, druntime f9efc98fd7, phobos a3f22129d.
@ 2023-10-15 11:12 Iain Buclaw
  0 siblings, 0 replies; only message in thread
From: Iain Buclaw @ 2023-10-15 11:12 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:ac908237bd551fb55f2f82736cb37038e9b91459

commit r14-4644-gac908237bd551fb55f2f82736cb37038e9b91459
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sun Oct 15 12:05:10 2023 +0200

    d: Merge upstream dmd, druntime f9efc98fd7, phobos a3f22129d.
    
    D front-end changes:
    
            - Import dmd v2.105.2.
            - A function with enum storage class is now deprecated.
            - Global variables can now be initialized with Associative
              Arrays.
            - Improvements for the C++ header generation of static variables
              used in a default argument context.
    
    D runtime changes:
    
            - Import druntime v2.105.2.
            - The `core.memory.GC' functions `GC.enable', `GC.disable',
              `GC.collect', and `GC.minimize' `have been marked `@safe'.
    
    Phobos changes:
    
            - Import phobos v2.105.2.
    
    gcc/d/ChangeLog:
    
            * dmd/MERGE: Merge upstream dmd f9efc98fd7.
            * dmd/VERSION: Bump version to v2.105.2.
            * d-builtins.cc (build_frontend_type): Update for new front-end
            interface.
            * d-diagnostic.cc (verrorReport): Don't emit tips when error gagging
            is turned on.
            * d-lang.cc (d_handle_option): Remove obsolete parameter.
            (d_post_options): Likewise.
            (d_read_ddoc_files): New function.
            (d_generate_ddoc_file): New function.
            (d_parse_file): Update for new front-end interface.
            * expr.cc (ExprVisitor::visit (AssocArrayLiteralExp *)): Check for new
            front-end lowering of static associative arrays.
    
    libphobos/ChangeLog:
    
            * libdruntime/MERGE: Merge upstream druntime f9efc98fd7.
            * libdruntime/Makefile.am (DRUNTIME_DSOURCES): Add
            core/internal/newaa.d.
            * libdruntime/Makefile.in: Regenerate.
            * src/MERGE: Merge upstream phobos a3f22129d.
            * testsuite/libphobos.hash/test_hash.d: Update test.
            * testsuite/libphobos.phobos/phobos.exp: Add compiler flags
            -Wno-deprecated.
            * testsuite/libphobos.phobos_shared/phobos_shared.exp: Likewise.
    
    gcc/testsuite/ChangeLog:
    
            * lib/gdc-utils.exp (gdc-convert-args): Handle new compiler options.

Diff:
---
 gcc/d/d-builtins.cc                                |   3 +-
 gcc/d/d-diagnostic.cc                              |   5 +-
 gcc/d/d-lang.cc                                    |  78 ++++-
 gcc/d/dmd/MERGE                                    |   2 +-
 gcc/d/dmd/VERSION                                  |   2 +-
 gcc/d/dmd/attrib.d                                 |   2 +-
 gcc/d/dmd/blockexit.d                              | 107 +++---
 gcc/d/dmd/canthrow.d                               |   2 +-
 gcc/d/dmd/chkformat.d                              |  32 +-
 gcc/d/dmd/clone.d                                  |  20 +-
 gcc/d/dmd/cond.d                                   |   2 +-
 gcc/d/dmd/cparse.d                                 |  11 +-
 gcc/d/dmd/cppmangle.d                              |   2 -
 gcc/d/dmd/ctfeexpr.d                               |   6 +-
 gcc/d/dmd/dcast.d                                  |  13 +-
 gcc/d/dmd/dclass.d                                 |   6 +-
 gcc/d/dmd/declaration.d                            |   7 +-
 gcc/d/dmd/delegatize.d                             |   1 -
 gcc/d/dmd/denum.d                                  |   2 -
 gcc/d/dmd/dinterpret.d                             |  14 +-
 gcc/d/dmd/dmacro.d                                 |  56 ++-
 gcc/d/dmd/dmodule.d                                |   4 +-
 gcc/d/dmd/doc.d                                    | 353 +++++++++----------
 gcc/d/dmd/doc.h                                    |   3 +-
 gcc/d/dmd/dscope.d                                 |   1 +
 gcc/d/dmd/dstruct.d                                |   1 +
 gcc/d/dmd/dsymbol.d                                |   1 +
 gcc/d/dmd/dsymbolsem.d                             |  58 +++-
 gcc/d/dmd/dtemplate.d                              |  24 +-
 gcc/d/dmd/dtoh.d                                   |  10 +-
 gcc/d/dmd/errors.h                                 |   3 +-
 gcc/d/dmd/errorsink.d                              |   1 +
 gcc/d/dmd/escape.d                                 |  40 ++-
 gcc/d/dmd/expression.d                             |  47 +--
 gcc/d/dmd/expression.h                             |   3 +-
 gcc/d/dmd/expressionsem.d                          | 109 +++---
 gcc/d/dmd/func.d                                   |  21 +-
 gcc/d/dmd/globals.d                                |  33 +-
 gcc/d/dmd/globals.h                                |  35 +-
 gcc/d/dmd/hdrgen.d                                 | 375 +++++++++++----------
 gcc/d/dmd/hdrgen.h                                 |   4 +-
 gcc/d/dmd/iasmgcc.d                                |   2 +-
 gcc/d/dmd/id.d                                     |   2 +
 gcc/d/dmd/init.d                                   |   2 +-
 gcc/d/dmd/initsem.d                                |  31 +-
 gcc/d/dmd/json.d                                   |  23 +-
 gcc/d/dmd/json.h                                   |   2 +-
 gcc/d/dmd/lexer.d                                  |  88 ++++-
 gcc/d/dmd/location.d                               |  20 +-
 gcc/d/dmd/module.h                                 |   2 +-
 gcc/d/dmd/mtype.d                                  |  55 ++-
 gcc/d/dmd/mtype.h                                  |   5 +-
 gcc/d/dmd/opover.d                                 |   8 +-
 gcc/d/dmd/optimize.d                               |  28 +-
 gcc/d/dmd/parse.d                                  | 110 ++++--
 gcc/d/dmd/printast.d                               |   2 +-
 gcc/d/dmd/safe.d                                   |  23 +-
 gcc/d/dmd/semantic2.d                              |  53 +++
 gcc/d/dmd/semantic3.d                              |  14 +-
 gcc/d/dmd/statement.d                              | 117 +------
 gcc/d/dmd/statement.h                              |   3 +-
 gcc/d/dmd/statementsem.d                           | 293 ++++++++--------
 gcc/d/dmd/tokens.d                                 |  22 +-
 gcc/d/dmd/tokens.h                                 |   1 +
 gcc/d/dmd/traits.d                                 |   2 +-
 gcc/d/dmd/typesem.d                                |  19 +-
 gcc/d/dmd/utils.d                                  |  24 +-
 gcc/d/expr.cc                                      |   9 +
 .../gdc.test/compilable/dtoh_StructDeclaration.d   |  15 +
 gcc/testsuite/gdc.test/compilable/dtoh_functions.d |   4 +-
 gcc/testsuite/gdc.test/compilable/issue22682.d     |   8 +
 gcc/testsuite/gdc.test/compilable/obsolete_body.d  |   5 +
 .../gdc.test/compilable/shortened_methods.d        |   5 +
 gcc/testsuite/gdc.test/compilable/test23145.d      |  13 +-
 gcc/testsuite/gdc.test/compilable/test24066.d      |  11 +
 gcc/testsuite/gdc.test/compilable/test24107.d      |  17 +
 gcc/testsuite/gdc.test/compilable/test24109.d      |  17 +
 gcc/testsuite/gdc.test/compilable/test24118.d      |  15 +
 gcc/testsuite/gdc.test/fail_compilation/aa_init.d  |  16 +
 gcc/testsuite/gdc.test/fail_compilation/body.d     |  11 -
 .../gdc.test/fail_compilation/chkformat.d          |   2 +
 .../gdc.test/fail_compilation/dephexstrings.d      |   9 -
 .../gdc.test/fail_compilation/diag10169.d          |   3 +-
 .../gdc.test/fail_compilation/diag10783.d          |   5 +-
 .../gdc.test/fail_compilation/diag12063.d          |  42 ++-
 .../gdc.test/fail_compilation/diag12829.d          |  13 +-
 .../gdc.test/fail_compilation/diag13609a.d         |   7 +-
 .../gdc.test/fail_compilation/diag14145.d          |   9 +-
 .../gdc.test/fail_compilation/diag15713.d          |   9 +-
 gcc/testsuite/gdc.test/fail_compilation/diag3913.d |   6 +-
 gcc/testsuite/gdc.test/fail_compilation/diag5385.d |  24 +-
 gcc/testsuite/gdc.test/fail_compilation/diag7477.d |   4 +-
 gcc/testsuite/gdc.test/fail_compilation/diag8697.d |   3 +-
 gcc/testsuite/gdc.test/fail_compilation/diag8894.d |  12 +-
 .../fail_compilation/dip1000_deprecation.d         |  19 +-
 gcc/testsuite/gdc.test/fail_compilation/dip22a.d   |  12 +-
 .../gdc.test/fail_compilation/enum_function.d      |   9 +-
 .../gdc.test/fail_compilation/fail10528.d          |  20 +-
 .../gdc.test/fail_compilation/fail10534.d          |  32 +-
 gcc/testsuite/gdc.test/fail_compilation/fail109.d  |   2 +-
 gcc/testsuite/gdc.test/fail_compilation/fail121.d  |   5 +-
 gcc/testsuite/gdc.test/fail_compilation/fail136.d  |   2 +-
 .../gdc.test/fail_compilation/fail17570.d          |   7 +-
 .../gdc.test/fail_compilation/fail17969.d          |   3 +-
 .../gdc.test/fail_compilation/fail18219.d          |   9 +-
 .../gdc.test/fail_compilation/fail18892.d          |   6 +-
 .../gdc.test/fail_compilation/fail18970.d          |  10 +-
 .../gdc.test/fail_compilation/fail18979.d          |   3 +-
 gcc/testsuite/gdc.test/fail_compilation/fail1900.d |   6 +-
 .../gdc.test/fail_compilation/fail19076.d          |   5 +-
 .../gdc.test/fail_compilation/fail19103.d          |   8 +-
 gcc/testsuite/gdc.test/fail_compilation/fail196.d  |  49 +--
 .../gdc.test/fail_compilation/fail20637.d          |   3 +-
 .../gdc.test/fail_compilation/fail22054.d          |  10 +-
 .../gdc.test/fail_compilation/fail22529.d          |   2 +-
 .../gdc.test/fail_compilation/fail23109.d          |   2 +
 gcc/testsuite/gdc.test/fail_compilation/fail61.d   |  11 +-
 gcc/testsuite/gdc.test/fail_compilation/fail7861.d |   3 +-
 gcc/testsuite/gdc.test/fail_compilation/fail9.d    |   3 +-
 .../gdc.test/fail_compilation/fail_scope.d         |  30 +-
 .../gdc.test/fail_compilation/faildottypeinfo.d    |   5 +-
 .../gdc.test/fail_compilation/fnconstraint.d       |  11 +-
 .../gdc.test/fail_compilation/goto_skip.d          |  57 ++++
 gcc/testsuite/gdc.test/fail_compilation/ice10713.d |   3 +-
 gcc/testsuite/gdc.test/fail_compilation/ice10938.d |   5 +-
 gcc/testsuite/gdc.test/fail_compilation/ice11518.d |   6 +-
 gcc/testsuite/gdc.test/fail_compilation/ice11982.d |  20 +-
 gcc/testsuite/gdc.test/fail_compilation/ice8100.d  |   7 +-
 .../gdc.test/fail_compilation/issue12652.d         |  24 --
 .../gdc.test/fail_compilation/issue22682.d         |  18 +
 gcc/testsuite/gdc.test/fail_compilation/lexer1.d   |   4 +-
 gcc/testsuite/gdc.test/fail_compilation/lexer2.d   |   8 +-
 gcc/testsuite/gdc.test/fail_compilation/main.d     |   9 +
 .../gdc.test/fail_compilation/match_func_ptr.d     |  17 +
 .../fail_compilation/misc_parser_err_cov1.d        |   3 +-
 gcc/testsuite/gdc.test/fail_compilation/nogc3.d    |  18 +-
 .../gdc.test/fail_compilation/noreturn_expr.d      |  16 +
 .../gdc.test/fail_compilation/noreturn_expr2.d     |  14 +
 .../gdc.test/fail_compilation/operator_undefined.d |  20 ++
 gcc/testsuite/gdc.test/fail_compilation/parseStc.d |   6 +-
 gcc/testsuite/gdc.test/fail_compilation/retscope.d |   2 +-
 gcc/testsuite/gdc.test/fail_compilation/skip.d     |   6 +-
 .../gdc.test/fail_compilation/switch_skip.d        |  48 +++
 gcc/testsuite/gdc.test/fail_compilation/switches.d |  68 +---
 .../gdc.test/fail_compilation/test13536.d          |   7 +-
 .../gdc.test/fail_compilation/test15785.d          |   5 +-
 .../gdc.test/fail_compilation/test15897.d          |   3 +-
 .../gdc.test/fail_compilation/test16188.d          |   1 +
 .../gdc.test/fail_compilation/test16193.d          |   5 +-
 .../gdc.test/fail_compilation/test16365.d          |   9 +-
 .../gdc.test/fail_compilation/test17380spec.d      |   7 +-
 .../gdc.test/fail_compilation/test20655.d          |  32 ++
 .../gdc.test/fail_compilation/test21353.d          |  13 +-
 .../gdc.test/fail_compilation/test21912.d          |  20 +-
 .../gdc.test/fail_compilation/test22329.d          |   3 +-
 .../gdc.test/fail_compilation/test23112.d          |   3 +-
 .../gdc.test/fail_compilation/test24015.d          |  20 ++
 .../gdc.test/fail_compilation/test24036.d          |  21 ++
 .../gdc.test/fail_compilation/test24065.d          |  18 +
 .../gdc.test/fail_compilation/test24084.d          |  28 ++
 .../gdc.test/fail_compilation/test24110.d          |  12 +
 .../gdc.test/fail_compilation/testOpApply.d        |  16 +-
 gcc/testsuite/gdc.test/fail_compilation/testsemi.d |   3 +-
 gcc/testsuite/gdc.test/runnable/staticaa.d         | 126 +++++++
 gcc/testsuite/gdc.test/runnable/test24078.d        |   6 +
 gcc/testsuite/gdc.test/runnable/test24139.d        |  25 ++
 gcc/testsuite/lib/gdc-utils.exp                    |   3 +
 libphobos/libdruntime/MERGE                        |   2 +-
 libphobos/libdruntime/Makefile.am                  |   6 +-
 libphobos/libdruntime/Makefile.in                  |  37 +-
 libphobos/libdruntime/core/internal/newaa.d        | 144 ++++++++
 libphobos/libdruntime/core/stdc/math.d             |  13 +-
 libphobos/libdruntime/core/stdcpp/string.d         |   6 +-
 libphobos/libdruntime/core/sys/posix/fcntl.d       |  21 ++
 libphobos/libdruntime/core/sys/posix/signal.d      |  22 +-
 .../libdruntime/core/sys/posix/sys/resource.d      |  35 +-
 libphobos/libdruntime/core/sys/windows/sql.d       |   4 +
 libphobos/libdruntime/core/sys/windows/sqlext.d    |   4 +
 libphobos/libdruntime/core/sys/windows/sqltypes.d  |   4 +
 libphobos/libdruntime/core/sys/windows/sqlucode.d  |   4 +
 libphobos/libdruntime/core/sys/windows/winnt.d     |   2 +-
 libphobos/libdruntime/object.d                     |   8 +
 libphobos/libdruntime/rt/aaA.d                     |  19 ++
 libphobos/libdruntime/rt/minfo.d                   |  14 +-
 libphobos/src/MERGE                                |   2 +-
 libphobos/src/std/int128.d                         |  46 ++-
 libphobos/src/std/string.d                         |   1 +
 libphobos/testsuite/libphobos.hash/test_hash.d     |   4 +-
 libphobos/testsuite/libphobos.phobos/phobos.exp    |   2 +-
 .../libphobos.phobos_shared/phobos_shared.exp      |   2 +-
 190 files changed, 2771 insertions(+), 1427 deletions(-)

diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc
index 60f76fc694c..cf998d22721 100644
--- a/gcc/d/d-builtins.cc
+++ b/gcc/d/d-builtins.cc
@@ -322,7 +322,8 @@ build_frontend_type (tree type)
 		  return NULL;
 		}
 
-	      args->push (Parameter::create (sc, targ, NULL, NULL, NULL));
+	      args->push (Parameter::create (Loc (), sc, targ,
+					     NULL, NULL, NULL));
 	    }
 
 	  /* GCC generic and placeholder built-ins are marked as variadic, yet
diff --git a/gcc/d/d-diagnostic.cc b/gcc/d/d-diagnostic.cc
index be779d93297..b698d4e49b8 100644
--- a/gcc/d/d-diagnostic.cc
+++ b/gcc/d/d-diagnostic.cc
@@ -220,7 +220,7 @@ d_diagnostic_report_diagnostic (const Loc &loc, int opt, const char *format,
 
 void D_ATTRIBUTE_FORMAT(2,0) ATTRIBUTE_GCC_DIAG(2,0)
 verrorReport (const Loc& loc, const char *format, va_list ap, ErrorKind kind,
-	      const char *prefix1 = NULL, const char *prefix2 = NULL)
+	      const char *prefix1, const char *prefix2)
 {
   diagnostic_t diag_kind = DK_UNSPECIFIED;
   int opt = 0;
@@ -277,6 +277,9 @@ verrorReport (const Loc& loc, const char *format, va_list ap, ErrorKind kind,
     }
   else if (kind == ErrorKind::tip)
     {
+      if (global.gag)
+	return;
+
       diag_kind = DK_DEBUG;
       verbatim = true;
     }
diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc
index f290acf494b..6509d766708 100644
--- a/gcc/d/d-lang.cc
+++ b/gcc/d/d-lang.cc
@@ -779,7 +779,6 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
     case OPT_Wall:
       if (value)
 	global.params.warnings = DIAGNOSTICinform;
-      global.params.obsolete = value;
       break;
 
     case OPT_Wdeprecated:
@@ -941,7 +940,6 @@ d_post_options (const char ** fn)
   global.compileEnv.previewIn = global.params.previewIn;
   global.compileEnv.ddocOutput = global.params.ddoc.doOutput;
   global.compileEnv.shortenedMethods = global.params.shortenedMethods;
-  global.compileEnv.obsolete = global.params.obsolete;
 
   /* Add in versions given on the command line.  */
   if (global.params.versionids)
@@ -1002,6 +1000,66 @@ d_write_file (const char *filename, const char *data)
     error ("writing output file %s: %m", filename);
 }
 
+/* Read ddoc macro files named by the DDOCFILES, then write the concatenated
+   the contents into DDOCBUF.  */
+
+static void
+d_read_ddoc_files (Strings &ddocfiles, OutBuffer &ddocbuf)
+{
+  if (ddocbuf.length ())
+    return;
+
+  for (size_t i = 0; i < ddocfiles.length; i++)
+    {
+      int fd = open (ddocfiles[i], O_RDONLY);
+      bool ok = false;
+      struct stat buf;
+
+      if (fd == -1 || fstat (fd, &buf))
+	{
+	  error ("unable to open %s for reading: %m", ddocfiles[i]);
+	  continue;
+	}
+
+      /* Check we've not been given a directory, or a file bigger than 4GB.  */
+      if (S_ISDIR (buf.st_mode))
+	errno = ENOENT;
+      else if (buf.st_size != unsigned (buf.st_size))
+	errno = EMFILE;
+      else
+	{
+	  unsigned size = unsigned (buf.st_size);
+	  char *buffer = (char *) xmalloc (size);
+
+	  if (read (fd, buffer, size) == ssize_t (size))
+	    {
+	      ddocbuf.write (buffer, size);
+	      ok = true;
+	    }
+
+	  free (buffer);
+	}
+
+      close (fd);
+      if (!ok)
+	fatal_error (input_location, "reading ddoc file %s: %m", ddocfiles[i]);
+    }
+}
+
+static void
+d_generate_ddoc_file (Module *m, OutBuffer &ddocbuf)
+{
+  input_location = make_location_t (m->loc);
+
+  d_read_ddoc_files (global.params.ddoc.files, ddocbuf);
+
+  OutBuffer ddocbuf_out;
+  gendocfile (m, ddocbuf.peekChars (), ddocbuf.length (), global.datetime,
+	      global.errorSink, ddocbuf_out);
+
+  d_write_file (m->docfile.toChars (), ddocbuf_out.peekChars ());
+}
+
 /* Implements the lang_hooks.parse_file routine for language D.  */
 
 static void
@@ -1038,6 +1096,9 @@ d_parse_file (void)
   Modules modules;
   modules.reserve (num_in_fnames);
 
+  /* Buffer for contents of .ddoc files.  */
+  OutBuffer ddocbuf;
+
   /* In this mode, the first file name is supposed to be a duplicate
      of one of the input files.  */
   if (d_option.fonly && strcmp (d_option.fonly, main_input_filename) != 0)
@@ -1125,7 +1186,8 @@ d_parse_file (void)
 
       if (m->filetype == FileType::ddoc)
 	{
-	  gendocfile (m, global.errorSink);
+	  d_generate_ddoc_file (m, ddocbuf);
+
 	  /* Remove M from list of modules.  */
 	  modules.remove (i);
 	  i--;
@@ -1168,7 +1230,9 @@ d_parse_file (void)
 	  if (global.params.verbose)
 	    message ("import    %s", m->toChars ());
 
-	  genhdrfile (m);
+	  OutBuffer buf;
+	  genhdrfile (m, buf);
+	  d_write_file (m->hdrfile.toChars (), buf.peekChars ());
 	}
 
       dump_headers = true;
@@ -1308,7 +1372,7 @@ d_parse_file (void)
   if (global.params.json.doOutput)
     {
       OutBuffer buf;
-      json_generate (&buf, &modules);
+      json_generate (modules, buf);
       d_write_file (global.params.json.name.ptr, buf.peekChars ());
     }
 
@@ -1318,7 +1382,7 @@ d_parse_file (void)
       for (size_t i = 0; i < modules.length; i++)
 	{
 	  Module *m = modules[i];
-	  gendocfile (m, global.errorSink);
+	  d_generate_ddoc_file (m, ddocbuf);
 	}
     }
 
@@ -1331,7 +1395,7 @@ d_parse_file (void)
 	  OutBuffer buf;
 	  buf.doindent = 1;
 
-	  moduleToBuffer (&buf, m);
+	  moduleToBuffer (buf, m);
 	  message ("%s", buf.peekChars ());
 	}
     }
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index dc267787cab..d5dfe0d0edd 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-4574d1728d1f7e52ff40e6733b8c39889d128349
+f9efc98fd7954741333f72c6a50af273f3863a1a
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/VERSION b/gcc/d/dmd/VERSION
index 8012337e422..fd05dcf2136 100644
--- a/gcc/d/dmd/VERSION
+++ b/gcc/d/dmd/VERSION
@@ -1 +1 @@
-v2.105.0
+v2.105.2
diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d
index baabe930c68..5a91bc74229 100644
--- a/gcc/d/dmd/attrib.d
+++ b/gcc/d/dmd/attrib.d
@@ -679,7 +679,7 @@ extern (C++) final class VisibilityDeclaration : AttribDeclaration
     {
         assert(visibility.kind > Visibility.Kind.undefined);
         OutBuffer buf;
-        visibilityToBuffer(&buf, visibility);
+        visibilityToBuffer(buf, visibility);
         return buf.extractChars();
     }
 
diff --git a/gcc/d/dmd/blockexit.d b/gcc/d/dmd/blockexit.d
index bdc81f246cd..a0da77a2898 100644
--- a/gcc/d/dmd/blockexit.d
+++ b/gcc/d/dmd/blockexit.d
@@ -18,6 +18,7 @@ import dmd.astenums;
 import dmd.canthrow;
 import dmd.dclass;
 import dmd.declaration;
+import dmd.errorsink;
 import dmd.expression;
 import dmd.func;
 import dmd.globals;
@@ -56,11 +57,11 @@ enum BE : int
  * Params:
  *   s = statement to check for block exit status
  *   func = function that statement s is in
- *   mustNotThrow = generate an error if it throws
+ *   eSink = generate an error if it throws
  * Returns:
  *   BE.xxxx
  */
-int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
+int blockExit(Statement s, FuncDeclaration func, ErrorSink eSink)
 {
         int result = BE.none;
 
@@ -97,7 +98,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
                 if (s.exp.type && s.exp.type.toBasetype().isTypeNoreturn())
                     result = BE.halt;
 
-                result |= canThrow(s.exp, func, mustNotThrow);
+                result |= canThrow(s.exp, func, eSink !is null);
             }
         }
 
@@ -143,23 +144,23 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
                                 // Deprecated in 2.100
                                 // Make an error in 2.110
                                 if (sl && sl.isCaseStatement())
-                                    s.deprecation("switch case fallthrough - use 'goto %s;' if intended", gototype);
+                                    global.errorSink.deprecation(s.loc, "switch case fallthrough - use 'goto %s;' if intended", gototype);
                                 else
-                                    s.error("switch case fallthrough - use 'goto %s;' if intended", gototype);
+                                    global.errorSink.error(s.loc, "switch case fallthrough - use 'goto %s;' if intended", gototype);
                             }
                         }
                     }
 
                     if (!(result & BE.fallthru) && !s.comeFrom())
                     {
-                        if (blockExit(s, func, mustNotThrow) != BE.halt && s.hasCode() &&
+                        if (blockExit(s, func, eSink) != BE.halt && s.hasCode() &&
                             s.loc != Loc.initial) // don't emit warning for generated code
-                            s.warning("statement is not reachable");
+                            global.errorSink.warning(s.loc, "statement is not reachable");
                     }
                     else
                     {
                         result &= ~BE.fallthru;
-                        result |= blockExit(s, func, mustNotThrow);
+                        result |= blockExit(s, func, eSink);
                     }
                     slast = s;
                 }
@@ -173,7 +174,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
             {
                 if (s)
                 {
-                    int r = blockExit(s, func, mustNotThrow);
+                    int r = blockExit(s, func, eSink);
                     result |= r & ~(BE.break_ | BE.continue_ | BE.fallthru);
                     if ((r & (BE.fallthru | BE.continue_ | BE.break_)) == 0)
                         result &= ~BE.fallthru;
@@ -184,7 +185,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
         void visitScope(ScopeStatement s)
         {
             //printf("ScopeStatement::blockExit(%p)\n", s.statement);
-            result = blockExit(s.statement, func, mustNotThrow);
+            result = blockExit(s.statement, func, eSink);
         }
 
         void visitWhile(WhileStatement s)
@@ -197,7 +198,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
         {
             if (s._body)
             {
-                result = blockExit(s._body, func, mustNotThrow);
+                result = blockExit(s._body, func, eSink);
                 if (result == BE.break_)
                 {
                     result = BE.fallthru;
@@ -210,7 +211,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
                 result = BE.fallthru;
             if (result & BE.fallthru)
             {
-                result |= canThrow(s.condition, func, mustNotThrow);
+                result |= canThrow(s.condition, func, eSink !is null);
 
                 if (!(result & BE.break_) && s.condition.toBool().hasValue(true))
                     result &= ~BE.fallthru;
@@ -223,13 +224,13 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
             result = BE.fallthru;
             if (s._init)
             {
-                result = blockExit(s._init, func, mustNotThrow);
+                result = blockExit(s._init, func, eSink);
                 if (!(result & BE.fallthru))
                     return;
             }
             if (s.condition)
             {
-                result |= canThrow(s.condition, func, mustNotThrow);
+                result |= canThrow(s.condition, func, eSink !is null);
 
                 const opt = s.condition.toBool();
                 if (opt.hasValue(true))
@@ -241,22 +242,22 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
                 result &= ~BE.fallthru; // the body must do the exiting
             if (s._body)
             {
-                int r = blockExit(s._body, func, mustNotThrow);
+                int r = blockExit(s._body, func, eSink);
                 if (r & (BE.break_ | BE.goto_))
                     result |= BE.fallthru;
                 result |= r & ~(BE.fallthru | BE.break_ | BE.continue_);
             }
             if (s.increment)
-                result |= canThrow(s.increment, func, mustNotThrow);
+                result |= canThrow(s.increment, func, eSink !is null);
         }
 
         void visitForeach(ForeachStatement s)
         {
             result = BE.fallthru;
-            result |= canThrow(s.aggr, func, mustNotThrow);
+            result |= canThrow(s.aggr, func, eSink !is null);
 
             if (s._body)
-                result |= blockExit(s._body, func, mustNotThrow) & ~(BE.break_ | BE.continue_);
+                result |= blockExit(s._body, func, eSink) & ~(BE.break_ | BE.continue_);
         }
 
         void visitForeachRange(ForeachRangeStatement s)
@@ -269,30 +270,30 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
         {
             //printf("IfStatement::blockExit(%p)\n", s);
             result = BE.none;
-            result |= canThrow(s.condition, func, mustNotThrow);
+            result |= canThrow(s.condition, func, eSink !is null);
 
             const opt = s.condition.toBool();
             if (opt.hasValue(true))
             {
-                result |= blockExit(s.ifbody, func, mustNotThrow);
+                result |= blockExit(s.ifbody, func, eSink);
             }
             else if (opt.hasValue(false))
             {
-                result |= blockExit(s.elsebody, func, mustNotThrow);
+                result |= blockExit(s.elsebody, func, eSink);
             }
             else
             {
-                result |= blockExit(s.ifbody, func, mustNotThrow);
-                result |= blockExit(s.elsebody, func, mustNotThrow);
+                result |= blockExit(s.ifbody, func, eSink);
+                result |= blockExit(s.elsebody, func, eSink);
             }
             //printf("IfStatement::blockExit(%p) = x%x\n", s, result);
         }
 
         void visitConditional(ConditionalStatement s)
         {
-            result = blockExit(s.ifbody, func, mustNotThrow);
+            result = blockExit(s.ifbody, func, eSink);
             if (s.elsebody)
-                result |= blockExit(s.elsebody, func, mustNotThrow);
+                result |= blockExit(s.elsebody, func, eSink);
         }
 
         void visitPragma(PragmaStatement s)
@@ -308,11 +309,11 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
         void visitSwitch(SwitchStatement s)
         {
             result = BE.none;
-            result |= canThrow(s.condition, func, mustNotThrow);
+            result |= canThrow(s.condition, func, eSink !is null);
 
             if (s._body)
             {
-                result |= blockExit(s._body, func, mustNotThrow);
+                result |= blockExit(s._body, func, eSink);
                 if (result & BE.break_)
                 {
                     result |= BE.fallthru;
@@ -325,12 +326,12 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
 
         void visitCase(CaseStatement s)
         {
-            result = blockExit(s.statement, func, mustNotThrow);
+            result = blockExit(s.statement, func, eSink);
         }
 
         void visitDefault(DefaultStatement s)
         {
-            result = blockExit(s.statement, func, mustNotThrow);
+            result = blockExit(s.statement, func, eSink);
         }
 
         void visitGotoDefault(GotoDefaultStatement s)
@@ -353,7 +354,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
         {
             result = BE.return_;
             if (s.exp)
-                result |= canThrow(s.exp, func, mustNotThrow);
+                result |= canThrow(s.exp, func, eSink !is null);
         }
 
         void visitBreak(BreakStatement s)
@@ -369,20 +370,20 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
 
         void visitSynchronized(SynchronizedStatement s)
         {
-            result = blockExit(s._body, func, mustNotThrow);
+            result = blockExit(s._body, func, eSink);
         }
 
         void visitWith(WithStatement s)
         {
             result = BE.none;
-            result |= canThrow(s.exp, func, mustNotThrow);
-            result |= blockExit(s._body, func, mustNotThrow);
+            result |= canThrow(s.exp, func, eSink !is null);
+            result |= blockExit(s._body, func, eSink);
         }
 
         void visitTryCatch(TryCatchStatement s)
         {
             assert(s._body);
-            result = blockExit(s._body, func, false);
+            result = blockExit(s._body, func, null);
 
             int catchresult = 0;
             foreach (c; *s.catches)
@@ -390,7 +391,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
                 if (c.type == Type.terror)
                     continue;
 
-                int cresult = blockExit(c.handler, func, mustNotThrow);
+                int cresult = blockExit(c.handler, func, eSink);
 
                 /* If we're catching Object, then there is no throwing
                  */
@@ -411,10 +412,10 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
                 }
                 catchresult |= cresult;
             }
-            if (mustNotThrow && (result & BE.throw_))
+            if (eSink && (result & BE.throw_))
             {
                 // now explain why this is nothrow
-                blockExit(s._body, func, mustNotThrow);
+                blockExit(s._body, func, eSink);
             }
             result |= catchresult;
         }
@@ -423,12 +424,12 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
         {
             result = BE.fallthru;
             if (s._body)
-                result = blockExit(s._body, func, false);
+                result = blockExit(s._body, func, null);
 
             // check finally body as well, it may throw (bug #4082)
             int finalresult = BE.fallthru;
             if (s.finalbody)
-                finalresult = blockExit(s.finalbody, func, false);
+                finalresult = blockExit(s.finalbody, func, null);
 
             // If either body or finalbody halts
             if (result == BE.halt)
@@ -436,13 +437,13 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
             if (finalresult == BE.halt)
                 result = BE.none;
 
-            if (mustNotThrow)
+            if (eSink)
             {
                 // now explain why this is nothrow
                 if (s._body && (result & BE.throw_))
-                    blockExit(s._body, func, mustNotThrow);
+                    blockExit(s._body, func, eSink);
                 if (s.finalbody && (finalresult & BE.throw_))
-                    blockExit(s.finalbody, func, mustNotThrow);
+                    blockExit(s.finalbody, func, eSink);
             }
 
             version (none)
@@ -452,7 +453,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
                 // destructor call, exit of synchronized statement, etc.
                 if (result == BE.halt && finalresult != BE.halt && s.finalbody && s.finalbody.hasCode())
                 {
-                    s.finalbody.warning("statement is not reachable");
+                    eSink.warning(s.finalbody.loc, "statement is not reachable");
                 }
             }
 
@@ -472,12 +473,12 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
             if (s.internalThrow)
             {
                 // https://issues.dlang.org/show_bug.cgi?id=8675
-                // Allow throwing 'Throwable' object even if mustNotThrow.
+                // Allow throwing 'Throwable' object even if eSink.
                 result = BE.fallthru;
                 return;
             }
 
-            result = checkThrow(s.loc, s.exp, mustNotThrow, func);
+            result = checkThrow(s.loc, s.exp, func, eSink);
         }
 
         void visitGoto(GotoStatement s)
@@ -489,7 +490,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
         void visitLabel(LabelStatement s)
         {
             //printf("LabelStatement::blockExit(%p)\n", s);
-            result = blockExit(s.statement, func, mustNotThrow);
+            result = blockExit(s.statement, func, eSink);
             if (s.breaks)
                 result |= BE.fallthru;
         }
@@ -502,8 +503,8 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
             {
                 if(func)
                     func.setThrow(s.loc, "`asm` statement is assumed to throw - mark it with `nothrow` if it does not");
-                if (mustNotThrow)
-                    s.error("`asm` statement is assumed to throw - mark it with `nothrow` if it does not"); // TODO
+                if (eSink)
+                    eSink.error(s.loc, "`asm` statement is assumed to throw - mark it with `nothrow` if it does not"); // TODO
                 else
                     result |= BE.throw_;
             }
@@ -528,15 +529,13 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
  + Params:
  +   loc          = location of the `throw`
  +   exp          = expression yielding the throwable
- +   mustNotThrow = inside of a `nothrow` scope?
+ +   eSink        = if !null then inside of a `nothrow` scope
  +   func         = function containing the `throw`
  +
  + Returns: `BE.[err]throw` depending on the type of `exp`
  +/
-BE checkThrow(ref const Loc loc, Expression exp, const bool mustNotThrow, FuncDeclaration func)
+BE checkThrow(ref const Loc loc, Expression exp, FuncDeclaration func, ErrorSink eSink)
 {
-    import dmd.errors : error;
-
     Type t = exp.type.toBasetype();
     ClassDeclaration cd = t.isClassHandle();
     assert(cd);
@@ -545,8 +544,8 @@ BE checkThrow(ref const Loc loc, Expression exp, const bool mustNotThrow, FuncDe
     {
         return BE.errthrow;
     }
-    if (mustNotThrow)
-        loc.error("`%s` is thrown but not caught", exp.type.toChars());
+    if (eSink)
+        eSink.error(loc, "`%s` is thrown but not caught", exp.type.toChars());
     else if (func)
         func.setThrow(loc, "`%s` is thrown but not caught", exp.type);
 
diff --git a/gcc/d/dmd/canthrow.d b/gcc/d/dmd/canthrow.d
index ba13eb084bd..4cead300f40 100644
--- a/gcc/d/dmd/canthrow.d
+++ b/gcc/d/dmd/canthrow.d
@@ -202,7 +202,7 @@ extern (C++) /* CT */ BE canThrow(Expression e, FuncDeclaration func, bool mustN
 
         override void visit(ThrowExp te)
         {
-            const res = checkThrow(te.loc, te.e1, mustNotThrow, func);
+            const res = checkThrow(te.loc, te.e1, func, mustNotThrow ? global.errorSink : null);
             assert((res & ~(CT.exception | CT.error)) == 0);
             result |= res;
         }
diff --git a/gcc/d/dmd/chkformat.d b/gcc/d/dmd/chkformat.d
index feaa3c7ee6b..8cfad5916c7 100644
--- a/gcc/d/dmd/chkformat.d
+++ b/gcc/d/dmd/chkformat.d
@@ -15,7 +15,7 @@ import core.stdc.ctype : isdigit;
 
 import dmd.astenums;
 import dmd.cond;
-import dmd.errors;
+import dmd.errorsink;
 import dmd.expression;
 import dmd.globals;
 import dmd.identifier;
@@ -53,6 +53,7 @@ import dmd.target;
  *      format = format string
  *      args = arguments to match with format string
  *      isVa_list = if a "v" function (format check only)
+ *      eSink = where the error messages go
  *
  * Returns:
  *      `true` if errors occurred
@@ -60,7 +61,8 @@ import dmd.target;
  * C99 7.19.6.1
  * https://www.cplusplus.com/reference/cstdio/printf/
  */
-bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expression[] args, bool isVa_list)
+public
+bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expression[] args, bool isVa_list, ErrorSink eSink)
 {
     //printf("checkPrintFormat('%.*s')\n", cast(int)format.length, format.ptr);
     size_t n;    // index in args
@@ -87,7 +89,7 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
         {
             // format check only
             if (fmt == Format.error)
-                deprecation(loc, "format specifier `\"%.*s\"` is invalid", cast(int)slice.length, slice.ptr);
+                eSink.deprecation(loc, "format specifier `\"%.*s\"` is invalid", cast(int)slice.length, slice.ptr);
             continue;
         }
 
@@ -96,7 +98,7 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
             if (n == args.length)
             {
                 if (args.length < (n + 1))
-                    deprecation(loc, "more format specifiers than %d arguments", cast(int)n);
+                    eSink.deprecation(loc, "more format specifiers than %d arguments", cast(int)n);
                 else
                     skip = true;
                 return null;
@@ -106,7 +108,7 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
 
         void errorMsg(const char* prefix, Expression arg, const char* texpect, Type tactual)
         {
-            deprecation(arg.loc, "%sargument `%s` for format specification `\"%.*s\"` must be `%s`, not `%s`",
+            eSink.deprecation(arg.loc, "%sargument `%s` for format specification `\"%.*s\"` must be `%s`, not `%s`",
                   prefix ? prefix : "", arg.toChars(), cast(int)slice.length, slice.ptr, texpect, tactual.toChars());
         }
 
@@ -178,7 +180,7 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
                     else
                         errorMsg(null, e, (c_longsize == 4 ? "int" : "long"), t);
                     if (t.isintegral() && t.size() != c_longsize)
-                        errorSupplemental(e.loc, "C `long` is %d bytes on your system", c_longsize);
+                        eSink.errorSupplemental(e.loc, "C `long` is %d bytes on your system", c_longsize);
                 }
                 break;
 
@@ -226,7 +228,7 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
                 break;
 
             case Format.n:      // pointer to int
-                if (!(t.ty == Tpointer && tnext.ty == Tint32))
+                if (!(t.ty == Tpointer && tnext.ty == Tint32 && tnext.isMutable()))
                     errorMsg(null, e, "int*", t);
                 break;
 
@@ -286,7 +288,7 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
                 break;
 
             case Format.error:
-                deprecation(loc, "format specifier `\"%.*s\"` is invalid", cast(int)slice.length, slice.ptr);
+                eSink.deprecation(loc, "format specifier `\"%.*s\"` is invalid", cast(int)slice.length, slice.ptr);
                 break;
 
             case Format.GNU_m:
@@ -327,6 +329,7 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
  *      format = format string
  *      args = arguments to match with format string
  *      isVa_list = if a "v" function (format check only)
+ *      eSink = where the error messages go
  *
  * Returns:
  *      `true` if errors occurred
@@ -334,7 +337,8 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
  * C99 7.19.6.2
  * https://www.cplusplus.com/reference/cstdio/scanf/
  */
-bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expression[] args, bool isVa_list)
+public
+bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expression[] args, bool isVa_list, ErrorSink eSink)
 {
     size_t n = 0;
     for (size_t i = 0; i < format.length;)
@@ -357,7 +361,7 @@ bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expres
         {
             // format check only
             if (fmt == Format.error)
-                deprecation(loc, "format specifier `\"%.*s\"` is invalid", cast(int)slice.length, slice.ptr);
+                eSink.deprecation(loc, "format specifier `\"%.*s\"` is invalid", cast(int)slice.length, slice.ptr);
             continue;
         }
 
@@ -366,7 +370,7 @@ bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expres
             if (n == args.length)
             {
                 if (!asterisk)
-                    deprecation(loc, "more format specifiers than %d arguments", cast(int)n);
+                    eSink.deprecation(loc, "more format specifiers than %d arguments", cast(int)n);
                 return null;
             }
             return args[n++];
@@ -374,7 +378,7 @@ bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expres
 
         void errorMsg(const char* prefix, Expression arg, const char* texpect, Type tactual)
         {
-            deprecation(arg.loc, "%sargument `%s` for format specification `\"%.*s\"` must be `%s`, not `%s`",
+            eSink.deprecation(arg.loc, "%sargument `%s` for format specification `\"%.*s\"` must be `%s`, not `%s`",
                   prefix ? prefix : "", arg.toChars(), cast(int)slice.length, slice.ptr, texpect, tactual.toChars());
         }
 
@@ -512,7 +516,7 @@ bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expres
                 break;
 
             case Format.error:
-                deprecation(loc, "format specifier `\"%.*s\"` is invalid", cast(int)slice.length, slice.ptr);
+                eSink.deprecation(loc, "format specifier `\"%.*s\"` is invalid", cast(int)slice.length, slice.ptr);
                 break;
 
             case Format.GNU_m:
@@ -523,6 +527,8 @@ bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expres
     return false;
 }
 
+/*****************************************************************************************************/
+
 private:
 
 /**************************************
diff --git a/gcc/d/dmd/clone.d b/gcc/d/dmd/clone.d
index 4cff1ecf49c..181268ec26c 100644
--- a/gcc/d/dmd/clone.d
+++ b/gcc/d/dmd/clone.d
@@ -297,7 +297,7 @@ FuncDeclaration buildOpAssign(StructDeclaration sd, Scope* sc)
     }
 
     auto fparams = new Parameters();
-    fparams.push(new Parameter(STC.nodtor, sd.type, Id.p, null, null));
+    fparams.push(new Parameter(loc, STC.nodtor, sd.type, Id.p, null, null));
     auto tf = new TypeFunction(ParameterList(fparams), sd.handleType(), LINK.d, stc | STC.ref_);
     auto fop = new FuncDeclaration(declLoc, Loc.initial, Id.assign, stc, tf);
     fop.storage_class |= STC.inference;
@@ -546,10 +546,11 @@ FuncDeclaration buildXopEquals(StructDeclaration sd, Scope* sc)
             TypeFunction tfeqptr;
             {
                 Scope scx;
+                scx.eSink = sc.eSink;
                 /* const bool opEquals(ref const S s);
                  */
                 auto parameters = new Parameters();
-                parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, null, null, null));
+                parameters.push(new Parameter(Loc.initial, STC.ref_ | STC.const_, sd.type, null, null, null));
                 tfeqptr = new TypeFunction(ParameterList(parameters), Type.tbool, LINK.d);
                 tfeqptr.mod = MODFlags.const_;
                 tfeqptr = cast(TypeFunction)tfeqptr.typeSemantic(Loc.initial, &scx);
@@ -577,7 +578,7 @@ FuncDeclaration buildXopEquals(StructDeclaration sd, Scope* sc)
     Loc declLoc; // loc is unnecessary so __xopEquals is never called directly
     Loc loc; // loc is unnecessary so errors are gagged
     auto parameters = new Parameters();
-    parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, Id.p, null, null));
+    parameters.push(new Parameter(loc, STC.ref_ | STC.const_, sd.type, Id.p, null, null));
     auto tf = new TypeFunction(ParameterList(parameters), Type.tbool, LINK.d, STC.const_);
     tf = tf.addSTC(STC.const_).toTypeFunction();
     Identifier id = Id.xopEquals;
@@ -620,10 +621,11 @@ FuncDeclaration buildXopCmp(StructDeclaration sd, Scope* sc)
             TypeFunction tfcmpptr;
             {
                 Scope scx;
+                scx.eSink = sc.eSink;
                 /* const int opCmp(ref const S s);
                  */
                 auto parameters = new Parameters();
-                parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, null, null, null));
+                parameters.push(new Parameter(Loc.initial, STC.ref_ | STC.const_, sd.type, null, null, null));
                 tfcmpptr = new TypeFunction(ParameterList(parameters), Type.tint32, LINK.d);
                 tfcmpptr.mod = MODFlags.const_;
                 tfcmpptr = cast(TypeFunction)tfcmpptr.typeSemantic(Loc.initial, &scx);
@@ -701,7 +703,7 @@ FuncDeclaration buildXopCmp(StructDeclaration sd, Scope* sc)
     Loc declLoc; // loc is unnecessary so __xopCmp is never called directly
     Loc loc; // loc is unnecessary so errors are gagged
     auto parameters = new Parameters();
-    parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, Id.p, null, null));
+    parameters.push(new Parameter(loc, STC.ref_ | STC.const_, sd.type, Id.p, null, null));
     auto tf = new TypeFunction(ParameterList(parameters), Type.tint32, LINK.d, STC.const_);
     tf = tf.addSTC(STC.const_).toTypeFunction();
     Identifier id = Id.xopCmp;
@@ -820,7 +822,7 @@ FuncDeclaration buildXtoHash(StructDeclaration sd, Scope* sc)
     Loc declLoc; // loc is unnecessary so __xtoHash is never called directly
     Loc loc; // internal code should have no loc to prevent coverage
     auto parameters = new Parameters();
-    parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, Id.p, null, null));
+    parameters.push(new Parameter(loc, STC.ref_ | STC.const_, sd.type, Id.p, null, null));
     auto tf = new TypeFunction(ParameterList(parameters), Type.thash_t, LINK.d, STC.nothrow_ | STC.trusted);
     Identifier id = Id.xtoHash;
     auto fop = new FuncDeclaration(declLoc, Loc.initial, id, STC.static_, tf);
@@ -1074,7 +1076,7 @@ private DtorDeclaration buildWindowsCppDtor(AggregateDeclaration ad, DtorDeclara
     //   // TODO: if (del) delete (char*)this;
     //   return (void*) this;
     // }
-    Parameter delparam = new Parameter(STC.undefined_, Type.tuns32, Identifier.idPool("del"), new IntegerExp(dtor.loc, 0, Type.tuns32), null);
+    Parameter delparam = new Parameter(Loc.initial, STC.undefined_, Type.tuns32, Identifier.idPool("del"), new IntegerExp(dtor.loc, 0, Type.tuns32), null);
     Parameters* params = new Parameters;
     params.push(delparam);
     const stc = dtor.storage_class & ~STC.scope_; // because we add the `return this;` later
@@ -1126,7 +1128,7 @@ private DtorDeclaration buildExternDDtor(AggregateDeclaration ad, Scope* sc)
         return null;
 
     // Generate shim only when ABI incompatible on target platform
-    if (ad.classKind != ClassKind.cpp || !target.cpp.wrapDtorInExternD)
+    if (dtor._linkage != LINK.cpp || !target.cpp.wrapDtorInExternD)
         return dtor;
 
     // generate member function that adjusts calling convention
@@ -1514,7 +1516,7 @@ private CtorDeclaration generateCopyCtorDeclaration(StructDeclaration sd, const
 {
     auto fparams = new Parameters();
     auto structType = sd.type;
-    fparams.push(new Parameter(paramStc | STC.ref_ | STC.return_ | STC.scope_, structType, Id.p, null, null));
+    fparams.push(new Parameter(Loc.initial, paramStc | STC.ref_ | STC.return_ | STC.scope_, structType, Id.p, null, null));
     ParameterList pList = ParameterList(fparams);
     auto tf = new TypeFunction(pList, structType, LINK.d, STC.ref_);
     auto ccd = new CtorDeclaration(sd.loc, Loc.initial, STC.ref_, tf, true);
diff --git a/gcc/d/dmd/cond.d b/gcc/d/dmd/cond.d
index 360acf590bb..76cef77d8ed 100644
--- a/gcc/d/dmd/cond.d
+++ b/gcc/d/dmd/cond.d
@@ -322,7 +322,7 @@ extern (C++) final class StaticForeach : RootObject
             foreach (params; pparams)
             {
                 auto p = aggrfe ? (*aggrfe.parameters)[i] : rangefe.prm;
-                params.push(new Parameter(p.storageClass, p.type, p.ident, null, null));
+                params.push(new Parameter(aloc, p.storageClass, p.type, p.ident, null, null));
             }
         }
         Expression[2] res;
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index 03383d13fd5..b05d81d3b14 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -626,7 +626,7 @@ final class CParser(AST) : Parser!AST
 
                 default:
                     // ImportC extensions: parse as a D asm block.
-                    s = parseAsm();
+                    s = parseAsm(compileEnv.masm);
                     break;
             }
             break;
@@ -3114,12 +3114,13 @@ final class CParser(AST) : Parser!AST
             }
 
             Identifier id;
+            const paramLoc = token.loc;
             auto t = cparseDeclarator(DTR.xparameter, tspec, id, specifier);
             if (token.value == TOK.__attribute__)
                 cparseGnuAttributes(specifier);
             if (specifier.mod & MOD.xconst)
                 t = toConst(t);
-            auto param = new AST.Parameter(specifiersToSTC(LVL.parameter, specifier),
+            auto param = new AST.Parameter(paramLoc, specifiersToSTC(LVL.parameter, specifier),
                                            t, id, null, null);
             parameters.push(param);
             if (token.value == TOK.rightParenthesis || token.value == TOK.endOfFile)
@@ -3297,8 +3298,10 @@ final class CParser(AST) : Parser!AST
                 nextToken();
             else
             {
-                error("extended-decl-modifier expected");
-                break;
+                error("extended-decl-modifier expected after `__declspec(`, saw `%s` instead", token.toChars());
+                nextToken();
+                if (token.value != TOK.rightParenthesis)
+                    break;
             }
         }
     }
diff --git a/gcc/d/dmd/cppmangle.d b/gcc/d/dmd/cppmangle.d
index 5d74ec4c91a..0c32fad7803 100644
--- a/gcc/d/dmd/cppmangle.d
+++ b/gcc/d/dmd/cppmangle.d
@@ -23,7 +23,6 @@
 
 module dmd.cppmangle;
 
-import core.stdc.string;
 import core.stdc.stdio;
 
 import dmd.arraytypes;
@@ -46,7 +45,6 @@ import dmd.common.outbuffer;
 import dmd.root.rootobject;
 import dmd.root.string;
 import dmd.target;
-import dmd.tokens;
 import dmd.typesem;
 import dmd.visitor;
 
diff --git a/gcc/d/dmd/ctfeexpr.d b/gcc/d/dmd/ctfeexpr.d
index d355538e97c..c0a2ca6a2a5 100644
--- a/gcc/d/dmd/ctfeexpr.d
+++ b/gcc/d/dmd/ctfeexpr.d
@@ -12,7 +12,6 @@
 module dmd.ctfeexpr;
 
 import core.stdc.stdio;
-import core.stdc.stdlib;
 import core.stdc.string;
 import dmd.arraytypes;
 import dmd.astenums;
@@ -306,9 +305,10 @@ UnionExp copyLiteral(Expression e)
     }
     if (auto aae = e.isAssocArrayLiteralExp())
     {
-        emplaceExp!(AssocArrayLiteralExp)(&ue, e.loc, copyLiteralArray(aae.keys), copyLiteralArray(aae.values));
+        emplaceExp!(AssocArrayLiteralExp)(&ue, aae.loc, copyLiteralArray(aae.keys), copyLiteralArray(aae.values));
         AssocArrayLiteralExp r = ue.exp().isAssocArrayLiteralExp();
-        r.type = e.type;
+        r.type = aae.type;
+        r.lowering = aae.lowering;
         r.ownedByCtfe = OwnedBy.ctfe;
         return ue;
     }
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index b2aa6433baf..d7cb2b1f970 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -23,7 +23,6 @@ import dmd.declaration;
 import dmd.dscope;
 import dmd.dstruct;
 import dmd.dsymbol;
-import dmd.errors;
 import dmd.escape;
 import dmd.expression;
 import dmd.expressionsem;
@@ -32,7 +31,6 @@ import dmd.globals;
 import dmd.hdrgen;
 import dmd.location;
 import dmd.impcnvtab;
-import dmd.id;
 import dmd.importc;
 import dmd.init;
 import dmd.intrange;
@@ -44,7 +42,6 @@ import dmd.root.rmem;
 import dmd.root.utf;
 import dmd.tokens;
 import dmd.typesem;
-import dmd.visitor;
 
 enum LOG = false;
 
@@ -73,7 +70,7 @@ Expression implicitCastTo(Expression e, Scope* sc, Type t)
         {
             // no need for an extra cast when matching is exact
 
-            if (match == MATCH.convert && e.type.isTypeNoreturn())
+            if (match == MATCH.convert && e.type.isTypeNoreturn() && e.op != EXP.type)
             {
                 return specialNoreturnCast(e, t);
             }
@@ -174,7 +171,7 @@ Expression implicitCastTo(Expression e, Scope* sc, Type t)
     {
         //printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", e.type, e.type ? e.type.toChars() : NULL, t.toChars());
         FuncExp fe;
-        if (e.matchType(t, sc, &fe) > MATCH.nomatch)
+        if (e.matchType(t, sc, &fe, global.errorSink) > MATCH.nomatch)
         {
             return fe;
         }
@@ -1075,7 +1072,7 @@ MATCH implicitConvTo(Expression e, Type t)
     MATCH visitFunc(FuncExp e)
     {
         //printf("FuncExp::implicitConvTo type = %p %s, t = %s\n", e.type, e.type ? e.type.toChars() : NULL, t.toChars());
-        MATCH m = e.matchType(t, null, null, 1);
+        MATCH m = e.matchType(t, null, null, global.errorSinkNull);
         if (m > MATCH.nomatch)
         {
             return m;
@@ -1537,7 +1534,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
         {
             return e;
         }
-        if (e.type.isTypeNoreturn())
+        if (e.type.isTypeNoreturn() && e.op != EXP.type)
         {
             return specialNoreturnCast(e, t);
         }
@@ -2489,7 +2486,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
     {
         //printf("FuncExp::castTo type = %s, t = %s\n", e.type.toChars(), t.toChars());
         FuncExp fe;
-        if (e.matchType(t, sc, &fe, 1) > MATCH.nomatch)
+        if (e.matchType(t, sc, &fe, global.errorSinkNull) > MATCH.nomatch)
         {
             return fe;
         }
diff --git a/gcc/d/dmd/dclass.d b/gcc/d/dmd/dclass.d
index 20cb82e1a36..b446e77b879 100644
--- a/gcc/d/dmd/dclass.d
+++ b/gcc/d/dmd/dclass.d
@@ -19,14 +19,12 @@ import core.stdc.string;
 import dmd.aggregate;
 import dmd.arraytypes;
 import dmd.astenums;
-import dmd.attrib;
 import dmd.gluelayer;
 import dmd.declaration;
 import dmd.dscope;
 import dmd.dsymbol;
 import dmd.dsymbolsem;
 import dmd.func;
-import dmd.globals;
 import dmd.id;
 import dmd.identifier;
 import dmd.location;
@@ -879,6 +877,10 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
             return 0;
         }
 
+        // opaque class is not abstract if it is not declared abstract
+        if (!members)
+            return no();
+
         for (size_t i = 0; i < members.length; i++)
         {
             auto s = (*members)[i];
diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d
index 8a91a802dae..b21678ce508 100644
--- a/gcc/d/dmd/declaration.d
+++ b/gcc/d/dmd/declaration.d
@@ -16,7 +16,6 @@ import core.stdc.stdio;
 import dmd.aggregate;
 import dmd.arraytypes;
 import dmd.astenums;
-import dmd.attrib;
 import dmd.ctorflow;
 import dmd.dclass;
 import dmd.delegatize;
@@ -647,11 +646,11 @@ extern (C++) final class TupleDeclaration : Declaration
                 {
                     buf.printf("_%s_%d", ident.toChars(), i);
                     auto id = Identifier.idPool(buf.extractSlice());
-                    auto arg = new Parameter(STC.in_, t, id, null);
+                    auto arg = new Parameter(Loc.initial, STC.in_, t, id, null);
                 }
                 else
                 {
-                    auto arg = new Parameter(0, t, null, null, null);
+                    auto arg = new Parameter(Loc.initial, 0, t, null, null, null);
                 }
                 (*args)[i] = arg;
                 if (!t.deco)
@@ -1602,6 +1601,8 @@ extern (C++) class VarDeclaration : Declaration
         {
             inuse++;
             _init = _init.initializerSemantic(_scope, type, INITinterpret);
+            import dmd.semantic2 : lowerStaticAAs;
+            lowerStaticAAs(this, _scope);
             _scope = null;
             inuse--;
         }
diff --git a/gcc/d/dmd/delegatize.d b/gcc/d/dmd/delegatize.d
index 559f103908d..490ef56646f 100644
--- a/gcc/d/dmd/delegatize.d
+++ b/gcc/d/dmd/delegatize.d
@@ -21,7 +21,6 @@ import dmd.dsymbol;
 import dmd.expression;
 import dmd.expressionsem;
 import dmd.func;
-import dmd.globals;
 import dmd.init;
 import dmd.initsem;
 import dmd.location;
diff --git a/gcc/d/dmd/denum.d b/gcc/d/dmd/denum.d
index 87b40b854b9..955a17dc6e8 100644
--- a/gcc/d/dmd/denum.d
+++ b/gcc/d/dmd/denum.d
@@ -24,13 +24,11 @@ import dmd.dscope;
 import dmd.dsymbol;
 import dmd.dsymbolsem;
 import dmd.expression;
-import dmd.globals;
 import dmd.id;
 import dmd.identifier;
 import dmd.init;
 import dmd.location;
 import dmd.mtype;
-import dmd.tokens;
 import dmd.typesem;
 import dmd.visitor;
 
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index 59483511f6d..7cdafda050c 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -40,7 +40,6 @@ import dmd.init;
 import dmd.initsem;
 import dmd.location;
 import dmd.mtype;
-import dmd.printast;
 import dmd.root.rmem;
 import dmd.root.array;
 import dmd.root.ctfloat;
@@ -635,8 +634,6 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
     {
         if (ctfeGlobals.callDepth > CTFE_RECURSION_LIMIT)
         {
-            // This is a compiler error. It must not be suppressed.
-            global.gag = 0;
             fd.error("CTFE recursion limit exceeded");
             e = CTFEExp.cantexp;
             break;
@@ -790,7 +787,7 @@ Expression interpretStatement(UnionExp* pue, Statement s, InterState* istate)
             istate.start = null;
         }
 
-        s.error("statement `%s` cannot be interpreted at compile time", s.toChars());
+        error(s.loc, "statement `%s` cannot be interpreted at compile time", s.toChars());
         result = CTFEExp.cantexp;
     }
 
@@ -976,7 +973,7 @@ Expression interpretStatement(UnionExp* pue, Statement s, InterState* istate)
         {
             // To support this, we need to copy all the closure vars
             // into the delegate literal.
-            s.error("closures are not yet supported in CTFE");
+            error(s.loc, "closures are not yet supported in CTFE");
             result = CTFEExp.cantexp;
             return;
         }
@@ -1259,7 +1256,7 @@ Expression interpretStatement(UnionExp* pue, Statement s, InterState* istate)
         if (!scase)
         {
             if (s.hasNoDefault)
-                s.error("no `default` or `case` for `%s` in `switch` statement", econdition.toChars());
+                error(s.loc, "no `default` or `case` for `%s` in `switch` statement", econdition.toChars());
             scase = s.sdefault;
         }
 
@@ -1599,7 +1596,7 @@ Expression interpretStatement(UnionExp* pue, Statement s, InterState* istate)
                 return;
             istate.start = null;
         }
-        s.error("`asm` statements cannot be interpreted at compile time");
+        error(s.loc, "`asm` statements cannot be interpreted at compile time");
         result = CTFEExp.cantexp;
     }
 
@@ -6105,7 +6102,8 @@ public:
                 result = interpret(&ue, e.msg, istate);
                 if (exceptionOrCant(result))
                     return;
-                if (StringExp se = result.isStringExp())
+                result = scrubReturnValue(e.loc, result);
+                if (StringExp se = result.toStringExp())
                     e.error("%s", se.toStringz().ptr);
                 else
                     e.error("%s", result.toChars());
diff --git a/gcc/d/dmd/dmacro.d b/gcc/d/dmd/dmacro.d
index 6fc23e99e86..6e6c4b17e99 100644
--- a/gcc/d/dmd/dmacro.d
+++ b/gcc/d/dmd/dmacro.d
@@ -13,11 +13,12 @@ module dmd.dmacro;
 
 import core.stdc.ctype;
 import core.stdc.string;
-import dmd.doc;
 import dmd.common.outbuffer;
 import dmd.root.rmem;
 
-extern (C++) struct MacroTable
+@trusted:
+
+struct MacroTable
 {
     /**********************************
      * Define name=text macro.
@@ -26,7 +27,7 @@ extern (C++) struct MacroTable
      *  name = name of macro
      *  text = text of macro
      */
-    extern (D) void define(const(char)[] name, const(char)[] text) nothrow pure @safe
+    void define(const(char)[] name, const(char)[] text) nothrow pure @safe
     {
         //printf("MacroTable::define('%.*s' = '%.*s')\n", cast(int)name.length, name.ptr, text.length, text.ptr);
         if (auto table = name in mactab)
@@ -37,13 +38,16 @@ extern (C++) struct MacroTable
         mactab[name] = new Macro(name, text);
     }
 
+    alias fp_t = bool function(const(char)* p) @nogc nothrow pure;
+
     /*****************************************************
      * Look for macros in buf and expand them in place.
      * Only look at the text in buf from start to pend.
      *
      * Returns: `true` on success, `false` when the recursion limit was reached
      */
-    extern (D) bool expand(ref OutBuffer buf, size_t start, ref size_t pend, const(char)[] arg, int recursionLimit) nothrow pure
+    bool expand(ref OutBuffer buf, size_t start, ref size_t pend, const(char)[] arg, int recursionLimit,
+        fp_t isIdStart, fp_t isIdTail) nothrow pure
     {
         version (none)
         {
@@ -101,7 +105,7 @@ extern (C++) struct MacroTable
                     end += marg.length - 2;
                     // Scan replaced text for further expansion
                     size_t mend = u + marg.length;
-                    const success = expand(buf, u, mend, null, recursionLimit);
+                    const success = expand(buf, u, mend, null, recursionLimit, isIdStart, isIdTail);
                     if (!success)
                         return false;
                     end += mend - (u + marg.length);
@@ -119,7 +123,7 @@ extern (C++) struct MacroTable
                     end += -2 + 2 + marg.length + 2;
                     // Scan replaced text for further expansion
                     size_t mend = u + 2 + marg.length;
-                    const success = expand(buf, u + 2, mend, null, recursionLimit);
+                    const success = expand(buf, u + 2, mend, null, recursionLimit, isIdStart, isIdTail);
                     if (!success)
                         return false;
                     end += mend - (u + 2 + marg.length);
@@ -149,7 +153,7 @@ extern (C++) struct MacroTable
                 /* Scan forward to find end of macro name and
                  * beginning of macro argument (marg).
                  */
-                for (v = u + 2; v < end; v += utfStride(p + v))
+                for (v = u + 2; v < end; v += utfStride(p[v]))
                 {
                     if (!isIdTail(p + v))
                     {
@@ -228,7 +232,7 @@ extern (C++) struct MacroTable
                             // Scan replaced text for further expansion
                             m.inuse++;
                             size_t mend = v + 1 + 2 + m.text.length + 2;
-                            const success = expand(buf, v + 1, mend, marg, recursionLimit);
+                            const success = expand(buf, v + 1, mend, marg, recursionLimit, isIdStart, isIdTail);
                             if (!success)
                                 return false;
                             end += mend - (v + 1 + 2 + m.text.length + 2);
@@ -260,7 +264,7 @@ extern (C++) struct MacroTable
 
   private:
 
-    extern (D) Macro* search(const(char)[] name) @nogc nothrow pure @safe
+    Macro* search(const(char)[] name) @nogc nothrow pure @safe
     {
         //printf("Macro::search(%.*s)\n", cast(int)name.length, name.ptr);
         if (auto table = name in mactab)
@@ -299,7 +303,7 @@ struct Macro
  *      copy allocated with mem.xmalloc()
  */
 
-char[] memdup(const(char)[] p) nothrow pure @trusted
+char[] memdup(const(char)[] p) nothrow pure
 {
     size_t len = p.length;
     return (cast(char*)memcpy(mem.xmalloc(len), p.ptr, len))[0 .. len];
@@ -424,3 +428,35 @@ Largstart:
     //printf("extractArg%d('%.*s') = '%.*s'\n", n, cast(int)end, p, cast(int)marg.length, marg.ptr);
     return v;
 }
+
+/*****************************************
+ * Get number of UTF-8 code units in code point that starts with `c`
+ * Params:
+ *      c = starting code unit
+ * Returns: number of UTF-8 code units (i.e. bytes), else 1 on invalid UTF start
+ */
+@safe
+int utfStride(char c) @nogc nothrow pure
+{
+    return
+        c < 0x80 ? 1 :
+        c < 0xC0 ? 1 : // invalid UTF start
+        c < 0xE0 ? 2 :
+        c < 0xF0 ? 3 :
+        c < 0xF8 ? 4 :
+        c < 0xFC ? 5 :
+        c < 0xFE ? 6 :
+                   1; // invalid UTF start
+}
+
+unittest
+{
+    assert(utfStride(0) == 1);
+    assert(utfStride(0x80) == 1);
+    assert(utfStride(0xC0) == 2);
+    assert(utfStride(0xE0) == 3);
+    assert(utfStride(0xF0) == 4);
+    assert(utfStride(0xF8) == 5);
+    assert(utfStride(0xFC) == 6);
+    assert(utfStride(0xFE) == 1);
+}
diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index 4a2e15c981b..eb68b31edeb 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/dmd/dmodule.d
@@ -780,7 +780,9 @@ extern (C++) final class Module : Package
         {
             filetype = FileType.c;
 
+            global.compileEnv.masm = target.os == Target.OS.Windows && !target.omfobj; // Microsoft inline assembler format
             scope p = new CParser!AST(this, buf, cast(bool) docfile, global.errorSink, target.c, &defines, &global.compileEnv);
+            global.compileEnv.masm = false;
             p.nextToken();
             checkCompiledImport();
             members = p.parseModule();
@@ -1253,7 +1255,7 @@ extern (C++) final class Module : Package
     // Back end
     int doppelganger; // sub-module
     Symbol* cov; // private uint[] __coverage;
-    uint* covb; // bit array of valid code line numbers
+    uint[] covb; // bit array of valid code line numbers
     Symbol* sictor; // module order independent constructor
     Symbol* sctor; // module constructor
     Symbol* sdtor; // module destructor
diff --git a/gcc/d/dmd/doc.d b/gcc/d/dmd/doc.d
index 887fd6c696c..5488d5a0008 100644
--- a/gcc/d/dmd/doc.d
+++ b/gcc/d/dmd/doc.d
@@ -52,9 +52,11 @@ import dmd.root.rmem;
 import dmd.root.string;
 import dmd.root.utf;
 import dmd.tokens;
-import dmd.utils;
 import dmd.visitor;
 
+private:
+
+public
 struct Escape
 {
     const(char)[][char.max] strings;
@@ -94,7 +96,7 @@ struct Escape
 
 /***********************************************************
  */
-private class Section
+class Section
 {
     const(char)[] name;
     const(char)[] body_;
@@ -105,7 +107,7 @@ private class Section
         assert(0);
     }
 
-    void write(Loc loc, DocComment* dc, Scope* sc, Dsymbols* a, OutBuffer* buf)
+    void write(Loc loc, DocComment* dc, Scope* sc, Dsymbols* a, ref OutBuffer buf)
     {
         assert(a.length);
         if (name.length)
@@ -151,16 +153,16 @@ private class Section
         size_t o = buf.length;
         buf.write(body_);
         escapeStrayParenthesis(loc, buf, o, true, sc.eSink);
-        highlightText(sc, a, loc, *buf, o);
+        highlightText(sc, a, loc, buf, o);
         buf.writestring(")");
     }
 }
 
 /***********************************************************
  */
-private final class ParamSection : Section
+final class ParamSection : Section
 {
-    override void write(Loc loc, DocComment* dc, Scope* sc, Dsymbols* a, OutBuffer* buf)
+    override void write(Loc loc, DocComment* dc, Scope* sc, Dsymbols* a, ref OutBuffer buf)
     {
         assert(a.length);
         Dsymbol s = (*a)[0]; // test
@@ -241,7 +243,7 @@ private final class ParamSection : Section
                         }
                         else if (fparam && fparam.type && fparam.ident)
                         {
-                            .toCBuffer(fparam.type, buf, fparam.ident, &hgs);
+                            toCBuffer(fparam.type, buf, fparam.ident, hgs);
                         }
                         else
                         {
@@ -257,7 +259,7 @@ private final class ParamSection : Section
                             buf.write(namestart[0 .. namelen]);
                         }
                         escapeStrayParenthesis(loc, buf, o, true, sc.eSink);
-                        highlightCode(sc, a, *buf, o);
+                        highlightCode(sc, a, buf, o);
                     }
                     buf.writestring(")");
                     buf.writestring("$(DDOC_PARAM_DESC ");
@@ -265,7 +267,7 @@ private final class ParamSection : Section
                         size_t o = buf.length;
                         buf.write(textstart[0 .. textlen]);
                         escapeStrayParenthesis(loc, buf, o, true, sc.eSink);
-                        highlightText(sc, a, loc, *buf, o);
+                        highlightText(sc, a, loc, buf, o);
                     }
                     buf.writestring(")");
                 }
@@ -317,19 +319,19 @@ private final class ParamSection : Section
 
 /***********************************************************
  */
-private final class MacroSection : Section
+final class MacroSection : Section
 {
-    override void write(Loc loc, DocComment* dc, Scope* sc, Dsymbols* a, OutBuffer* buf)
+    override void write(Loc loc, DocComment* dc, Scope* sc, Dsymbols* a, ref OutBuffer buf)
     {
         //printf("MacroSection::write()\n");
         DocComment.parseMacros(dc.escapetable, *dc.pmacrotable, body_);
     }
 }
 
-private alias Sections = Array!(Section);
+alias Sections = Array!(Section);
 
 // Workaround for missing Parameter instance for variadic params. (it's unnecessary to instantiate one).
-private bool isCVariadicParameter(Dsymbols* a, const(char)[] p) @safe
+bool isCVariadicParameter(Dsymbols* a, const(char)[] p) @safe
 {
     foreach (member; *a)
     {
@@ -340,7 +342,7 @@ private bool isCVariadicParameter(Dsymbols* a, const(char)[] p) @safe
     return false;
 }
 
-private Dsymbol getEponymousMember(TemplateDeclaration td) @safe
+Dsymbol getEponymousMember(TemplateDeclaration td) @safe
 {
     if (!td.onemember)
         return null;
@@ -355,7 +357,7 @@ private Dsymbol getEponymousMember(TemplateDeclaration td) @safe
     return null;
 }
 
-private TemplateDeclaration getEponymousParent(Dsymbol s) @safe
+TemplateDeclaration getEponymousParent(Dsymbol s) @safe
 {
     if (!s.parent)
         return null;
@@ -363,40 +365,46 @@ private TemplateDeclaration getEponymousParent(Dsymbol s) @safe
     return (td && getEponymousMember(td)) ? td : null;
 }
 
-private immutable ddoc_default = import("default_ddoc_theme." ~ ddoc_ext);
-private immutable ddoc_decl_s = "$(DDOC_DECL ";
-private immutable ddoc_decl_e = ")\n";
-private immutable ddoc_decl_dd_s = "$(DDOC_DECL_DD ";
-private immutable ddoc_decl_dd_e = ")\n";
+immutable ddoc_default = import("default_ddoc_theme." ~ ddoc_ext);
+immutable ddoc_decl_s = "$(DDOC_DECL ";
+immutable ddoc_decl_e = ")\n";
+immutable ddoc_decl_dd_s = "$(DDOC_DECL_DD ";
+immutable ddoc_decl_dd_e = ")\n";
 
 /****************************************************
+ * Generate Ddoc file for Module m.
+ * Params:
+ *      m = Module
+ *      ddoctext_ptr = combined text of .ddoc files for macro definitions
+ *      ddoctext_length = extant of ddoctext_ptr
+ *      datetime = charz returned by ctime()
+ *      eSink = send error messages to eSink
+ *      outbuf = append the Ddoc text to this
  */
-extern(C++) void gendocfile(Module m, ErrorSink eSink)
+public
+extern(C++) void gendocfile(Module m, const char* ddoctext_ptr, size_t ddoctext_length, const char* datetime, ErrorSink eSink, ref OutBuffer outbuf)
 {
-    __gshared OutBuffer mbuf;
-    __gshared int mbuf_done;
-    OutBuffer buf;
-    //printf("Module::gendocfile()\n");
-    if (!mbuf_done) // if not already read the ddoc files
-    {
-        mbuf_done = 1;
-        // Use our internal default
-        mbuf.writestring(ddoc_default);
-        // Override with DDOCFILE specified in the sc.ini file
-        char* p = getenv("DDOCFILE");
-        if (p)
-            global.params.ddoc.files.shift(p);
-        // Override with the ddoc macro files from the command line
-        for (size_t i = 0; i < global.params.ddoc.files.length; i++)
-        {
-            auto buffer = readFile(m.loc, global.params.ddoc.files[i]);
-            // BUG: convert file contents to UTF-8 before use
-            const data = buffer.data;
-            //printf("file: '%.*s'\n", cast(int)data.length, data.ptr);
-            mbuf.write(data);
-        }
-    }
-    DocComment.parseMacros(m.escapetable, m.macrotable, mbuf[]);
+    gendocfile(m, ddoctext_ptr[0 .. ddoctext_length], datetime, eSink, outbuf);
+}
+
+/****************************************************
+ * Generate Ddoc text for Module `m` and append it to `outbuf`.
+ * Params:
+ *      m = Module
+ *      ddoctext = combined text of .ddoc files for macro definitions
+ *      datetime = charz returned by ctime()
+ *      eSink = send error messages to eSink
+ *      outbuf = append the Ddoc text to this
+ */
+public
+void gendocfile(Module m, const char[] ddoctext, const char* datetime, ErrorSink eSink, ref OutBuffer outbuf)
+{
+    // Load internal default macros first
+    DocComment.parseMacros(m.escapetable, m.macrotable, ddoc_default[]);
+
+    // Ddoc files override default macros
+    DocComment.parseMacros(m.escapetable, m.macrotable, ddoctext);
+
     Scope* sc = Scope.createGlobal(m, eSink); // create root scope
     DocComment* dc = DocComment.parse(m, m.comment);
     dc.pmacrotable = &m.macrotable;
@@ -409,14 +417,9 @@ extern(C++) void gendocfile(Module m, ErrorSink eSink)
         m.macrotable.define("TITLE", p);
     }
     // Set time macros
-    {
-        time_t t;
-        time(&t);
-        char* p = ctime(&t);
-        p = mem.xstrdup(p);
-        m.macrotable.define("DATETIME", p.toDString());
-        m.macrotable.define("YEAR", p[20 .. 20 + 4]);
-    }
+    m.macrotable.define("DATETIME", datetime[0 .. 26]);
+    m.macrotable.define("YEAR", datetime[20 .. 20 + 4]);
+
     const srcfilename = m.srcfile.toString();
     m.macrotable.define("SRCFILENAME", srcfilename);
     const docfilename = m.docfile.toString();
@@ -426,6 +429,8 @@ extern(C++) void gendocfile(Module m, ErrorSink eSink)
         dc.copyright.nooutput = 1;
         m.macrotable.define("COPYRIGHT", dc.copyright.body_);
     }
+
+    OutBuffer buf;
     if (m.filetype == FileType.ddoc)
     {
         const ploc = m.md ? &m.md.loc : &m.loc;
@@ -433,14 +438,14 @@ extern(C++) void gendocfile(Module m, ErrorSink eSink)
         if (!loc.filename)
             loc.filename = srcfilename.ptr;
 
-        size_t commentlen = strlen(cast(char*)m.comment);
+        size_t commentlen = m.comment ? strlen(cast(char*)m.comment) : 0;
         Dsymbols a;
         // https://issues.dlang.org/show_bug.cgi?id=9764
         // Don't push m in a, to prevent emphasize ddoc file name.
         if (dc.macros)
         {
             commentlen = dc.macros.name.ptr - m.comment;
-            dc.macros.write(loc, dc, sc, &a, &buf);
+            dc.macros.write(loc, dc, sc, &a, buf);
         }
         buf.write(m.comment[0 .. commentlen]);
         highlightText(sc, &a, loc, buf, 0);
@@ -449,73 +454,47 @@ extern(C++) void gendocfile(Module m, ErrorSink eSink)
     {
         Dsymbols a;
         a.push(m);
-        dc.writeSections(sc, &a, &buf);
+        dc.writeSections(sc, &a, buf);
         emitMemberComments(m, buf, sc);
     }
     //printf("BODY= '%.*s'\n", cast(int)buf.length, buf.data);
     m.macrotable.define("BODY", buf[]);
+
     OutBuffer buf2;
     buf2.writestring("$(DDOC)");
     size_t end = buf2.length;
 
-    const success = m.macrotable.expand(buf2, 0, end, null, global.recursionLimit);
+    // Expand buf in place with macro expansions
+    const success = m.macrotable.expand(buf2, 0, end, null, global.recursionLimit, &isIdStart, &isIdTail);
     if (!success)
         eSink.error(Loc.initial, "DDoc macro expansion limit exceeded; more than %d expansions.", global.recursionLimit);
 
-    version (all)
+    /* Remove all the escape sequences from buf,
+     * and make CR-LF the newline.
+     */
+    const slice = buf2[];
+    outbuf.reserve(slice.length);
+    auto p = slice.ptr;
+    for (size_t j = 0; j < slice.length; j++)
     {
-        /* Remove all the escape sequences from buf2,
-         * and make CR-LF the newline.
-         */
+        char c = p[j];
+        if (c == 0xFF && j + 1 < slice.length)
         {
-            const slice = buf2[];
-            buf.setsize(0);
-            buf.reserve(slice.length);
-            auto p = slice.ptr;
-            for (size_t j = 0; j < slice.length; j++)
-            {
-                char c = p[j];
-                if (c == 0xFF && j + 1 < slice.length)
-                {
-                    j++;
-                    continue;
-                }
-                if (c == '\n')
-                    buf.writeByte('\r');
-                else if (c == '\r')
-                {
-                    buf.writestring("\r\n");
-                    if (j + 1 < slice.length && p[j + 1] == '\n')
-                    {
-                        j++;
-                    }
-                    continue;
-                }
-                buf.writeByte(c);
-            }
+            j++;
+            continue;
         }
-        writeFile(m.loc, m.docfile.toString(), buf[]);
-    }
-    else
-    {
-        /* Remove all the escape sequences from buf2
-         */
+        if (c == '\n')
+            outbuf.writeByte('\r');
+        else if (c == '\r')
         {
-            size_t i = 0;
-            char* p = buf2.data;
-            for (size_t j = 0; j < buf2.length; j++)
+            outbuf.writestring("\r\n");
+            if (j + 1 < slice.length && p[j + 1] == '\n')
             {
-                if (p[j] == 0xFF && j + 1 < buf2.length)
-                {
-                    j++;
-                    continue;
-                }
-                p[i] = p[j];
-                i++;
+                j++;
             }
-            buf2.setsize(i);
+            continue;
         }
-        writeFile(m.loc, m.docfile.toString(), buf2[]);
+        outbuf.writeByte(c);
     }
 }
 
@@ -526,11 +505,12 @@ extern(C++) void gendocfile(Module m, ErrorSink eSink)
  * to preserve text literally. This also means macros in the
  * text won't be expanded.
  */
-void escapeDdocString(OutBuffer* buf, size_t start)
+public
+void escapeDdocString(ref OutBuffer buf, size_t start)
 {
     for (size_t u = start; u < buf.length; u++)
     {
-        char c = (*buf)[u];
+        char c = buf[u];
         switch (c)
         {
         case '$':
@@ -568,14 +548,14 @@ void escapeDdocString(OutBuffer* buf, size_t start)
  *    directly preceeded by a backslash with $(LPAREN) or $(RPAREN) instead of
  *    counting them as stray parentheses
  */
-private void escapeStrayParenthesis(Loc loc, OutBuffer* buf, size_t start, bool respectBackslashEscapes, ErrorSink eSink)
+private void escapeStrayParenthesis(Loc loc, ref OutBuffer buf, size_t start, bool respectBackslashEscapes, ErrorSink eSink)
 {
     uint par_open = 0;
     char inCode = 0;
     bool atLineStart = true;
     for (size_t u = start; u < buf.length; u++)
     {
-        char c = (*buf)[u];
+        char c = buf[u];
         switch (c)
         {
         case '(':
@@ -619,7 +599,7 @@ private void escapeStrayParenthesis(Loc loc, OutBuffer* buf, size_t start, bool
             // Issue 15465: don't try to escape unbalanced parens inside code
             // blocks.
             int numdash = 1;
-            for (++u; u < buf.length && (*buf)[u] == c; ++u)
+            for (++u; u < buf.length && buf[u] == c; ++u)
                 ++numdash;
             --u;
             if (c == '`' || (atLineStart && numdash >= 3))
@@ -635,14 +615,14 @@ private void escapeStrayParenthesis(Loc loc, OutBuffer* buf, size_t start, bool
             // replace backslash-escaped parens with their macros
             if (!inCode && respectBackslashEscapes && u+1 < buf.length)
             {
-                if ((*buf)[u+1] == '(' || (*buf)[u+1] == ')')
+                if (buf[u+1] == '(' || buf[u+1] == ')')
                 {
-                    const paren = (*buf)[u+1] == '(' ? "$(LPAREN)" : "$(RPAREN)";
+                    const paren = buf[u+1] == '(' ? "$(LPAREN)" : "$(RPAREN)";
                     buf.remove(u, 2); //remove the \)
                     buf.insert(u, paren); //insert this instead
                     u += 8; //skip over newly inserted macro
                 }
-                else if ((*buf)[u+1] == '\\')
+                else if (buf[u+1] == '\\')
                     ++u;
             }
             break;
@@ -657,7 +637,7 @@ private void escapeStrayParenthesis(Loc loc, OutBuffer* buf, size_t start, bool
         for (size_t u = buf.length; u > start;)
         {
             u--;
-            char c = (*buf)[u];
+            char c = buf[u];
             switch (c)
             {
             case ')':
@@ -683,14 +663,14 @@ private void escapeStrayParenthesis(Loc loc, OutBuffer* buf, size_t start, bool
 
 // Basically, this is to skip over things like private{} blocks in a struct or
 // class definition that don't add any components to the qualified name.
-private Scope* skipNonQualScopes(Scope* sc) @safe
+Scope* skipNonQualScopes(Scope* sc) @safe
 {
     while (sc && !sc.scopesym)
         sc = sc.enclosing;
     return sc;
 }
 
-private bool emitAnchorName(ref OutBuffer buf, Dsymbol s, Scope* sc, bool includeParent)
+bool emitAnchorName(ref OutBuffer buf, Dsymbol s, Scope* sc, bool includeParent)
 {
     if (!s || s.isPackage() || s.isModule())
         return false;
@@ -721,7 +701,7 @@ private bool emitAnchorName(ref OutBuffer buf, Dsymbol s, Scope* sc, bool includ
     return true;
 }
 
-private void emitAnchor(ref OutBuffer buf, Dsymbol s, Scope* sc, bool forHeader = false)
+void emitAnchor(ref OutBuffer buf, Dsymbol s, Scope* sc, bool forHeader = false)
 {
     Identifier ident;
     {
@@ -846,7 +826,7 @@ private void emitAnchor(ref OutBuffer buf, Dsymbol s, Scope* sc, bool forHeader
 /******************************* emitComment **********************************/
 
 /** Get leading indentation from 'src' which represents lines of code. */
-private size_t getCodeIndent(const(char)* src)
+size_t getCodeIndent(const(char)* src)
 {
     while (src && (*src == '\r' || *src == '\n'))
         ++src; // skip until we find the first non-empty line
@@ -860,7 +840,7 @@ private size_t getCodeIndent(const(char)* src)
 }
 
 /** Recursively expand template mixin member docs into the scope. */
-private void expandTemplateMixinComments(TemplateMixin tm, ref OutBuffer buf, Scope* sc)
+void expandTemplateMixinComments(TemplateMixin tm, ref OutBuffer buf, Scope* sc)
 {
     if (!tm.semanticRun)
         tm.dsymbolSemantic(sc);
@@ -879,7 +859,7 @@ private void expandTemplateMixinComments(TemplateMixin tm, ref OutBuffer buf, Sc
     }
 }
 
-private void emitMemberComments(ScopeDsymbol sds, ref OutBuffer buf, Scope* sc)
+void emitMemberComments(ScopeDsymbol sds, ref OutBuffer buf, Scope* sc)
 {
     if (!sds.members)
         return;
@@ -920,14 +900,14 @@ private void emitMemberComments(ScopeDsymbol sds, ref OutBuffer buf, Scope* sc)
         buf.writestring(")");
 }
 
-private void emitVisibility(ref OutBuffer buf, Import i)
+void emitVisibility(ref OutBuffer buf, Import i)
 {
     // imports are private by default, which is different from other declarations
     // so they should explicitly show their visibility
     emitVisibility(buf, i.visibility);
 }
 
-private void emitVisibility(ref OutBuffer buf, Declaration d)
+void emitVisibility(ref OutBuffer buf, Declaration d)
 {
     auto vis = d.visibility;
     if (vis.kind != Visibility.Kind.undefined && vis.kind != Visibility.Kind.public_)
@@ -936,13 +916,13 @@ private void emitVisibility(ref OutBuffer buf, Declaration d)
     }
 }
 
-private void emitVisibility(ref OutBuffer buf, Visibility vis)
+void emitVisibility(ref OutBuffer buf, Visibility vis)
 {
-    visibilityToBuffer(&buf, vis);
+    visibilityToBuffer(buf, vis);
     buf.writeByte(' ');
 }
 
-private void emitComment(Dsymbol s, ref OutBuffer buf, Scope* sc)
+void emitComment(Dsymbol s, ref OutBuffer buf, Scope* sc)
 {
     extern (C++) final class EmitComment : Visitor
     {
@@ -1037,7 +1017,7 @@ private void emitComment(Dsymbol s, ref OutBuffer buf, Scope* sc)
                 // Put the ddoc comment as the document 'description'
                 buf.writestring(ddoc_decl_dd_s);
                 {
-                    dc.writeSections(sc, &dc.a, buf);
+                    dc.writeSections(sc, &dc.a, *buf);
                     if (ScopeDsymbol sds = dc.a[0].isScopeDsymbol())
                         emitMemberComments(sds, *buf, sc);
                 }
@@ -1226,7 +1206,7 @@ private void emitComment(Dsymbol s, ref OutBuffer buf, Scope* sc)
         s.accept(v);
 }
 
-private void toDocBuffer(Dsymbol s, ref OutBuffer buf, Scope* sc)
+void toDocBuffer(Dsymbol s, ref OutBuffer buf, Scope* sc)
 {
     extern (C++) final class ToDocBuffer : Visitor
     {
@@ -1246,7 +1226,7 @@ private void toDocBuffer(Dsymbol s, ref OutBuffer buf, Scope* sc)
             //printf("Dsymbol::toDocbuffer() %s\n", s.toChars());
             HdrGenState hgs;
             hgs.ddoc = true;
-            .toCBuffer(s, buf, &hgs);
+            toCBuffer(s, *buf, hgs);
         }
 
         void prefix(Dsymbol s)
@@ -1296,7 +1276,7 @@ private void toDocBuffer(Dsymbol s, ref OutBuffer buf, Scope* sc)
             HdrGenState hgs;
             hgs.ddoc = true;
             emitVisibility(*buf, i);
-            .toCBuffer(i, buf, &hgs);
+            toCBuffer(i, *buf, hgs);
         }
 
         override void visit(Declaration d)
@@ -1315,10 +1295,10 @@ private void toDocBuffer(Dsymbol s, ref OutBuffer buf, Scope* sc)
                 Type origType = d.originalType ? d.originalType : d.type;
                 if (origType.ty == Tfunction)
                 {
-                    functionToBufferFull(cast(TypeFunction)origType, buf, d.ident, &hgs, td);
+                    functionToBufferFull(cast(TypeFunction)origType, *buf, d.ident, &hgs, td);
                 }
                 else
-                    .toCBuffer(origType, buf, d.ident, &hgs);
+                    toCBuffer(origType, *buf, d.ident, hgs);
             }
             else
                 buf.writestring(d.ident.toString());
@@ -1331,7 +1311,7 @@ private void toDocBuffer(Dsymbol s, ref OutBuffer buf, Scope* sc)
                     {
                         if (i)
                             buf.writestring(", ");
-                        toCBuffer((*td.origParameters)[i], buf, &hgs);
+                        toCBuffer((*td.origParameters)[i], *buf, hgs);
                     }
                 }
                 buf.writeByte(')');
@@ -1345,7 +1325,7 @@ private void toDocBuffer(Dsymbol s, ref OutBuffer buf, Scope* sc)
                     buf.writestring("$(DDOC_CONSTRAINT ");
                 }
 
-                .toCBuffer(td.constraint, buf, &hgs);
+                toCBuffer(td.constraint, *buf, hgs);
 
                 if (noFuncDecl)
                 {
@@ -1505,7 +1485,7 @@ private void toDocBuffer(Dsymbol s, ref OutBuffer buf, Scope* sc)
                 else
                 {
                     HdrGenState hgs;
-                    .toCBuffer(bc.type, buf, null, &hgs);
+                    toCBuffer(bc.type, *buf, null, hgs);
                 }
             }
             buf.writestring(";\n");
@@ -1520,7 +1500,7 @@ private void toDocBuffer(Dsymbol s, ref OutBuffer buf, Scope* sc)
             {
                 buf.writestring(": $(DDOC_ENUM_BASETYPE ");
                 HdrGenState hgs;
-                .toCBuffer(ed.memtype, buf, null, &hgs);
+                toCBuffer(ed.memtype, *buf, null, hgs);
                 buf.writestring(")");
             }
             buf.writestring(";\n");
@@ -1540,6 +1520,7 @@ private void toDocBuffer(Dsymbol s, ref OutBuffer buf, Scope* sc)
 
 /***********************************************************
  */
+public
 struct DocComment
 {
     Sections sections;      // Section*[]
@@ -1872,7 +1853,7 @@ struct DocComment
         }
     }
 
-    void writeSections(Scope* sc, Dsymbols* a, OutBuffer* buf)
+    void writeSections(Scope* sc, Dsymbols* a, ref OutBuffer buf)
     {
         assert(a.length);
         //printf("DocComment::writeSections()\n");
@@ -1897,7 +1878,7 @@ struct DocComment
                 size_t o = buf.length;
                 buf.write(sec.body_);
                 escapeStrayParenthesis(loc, buf, o, true, sc.eSink);
-                highlightText(sc, a, loc, *buf, o);
+                highlightText(sc, a, loc, buf, o);
                 buf.writestring(")");
             }
             else
@@ -1928,7 +1909,7 @@ struct DocComment
                     buf.writestring("----\n");
                     buf.writestring(codedoc);
                     buf.writestring("----\n");
-                    highlightText(sc, a, loc, *buf, o);
+                    highlightText(sc, a, loc, buf, o);
                 }
                 buf.writestring(")");
             }
@@ -1948,7 +1929,7 @@ struct DocComment
 /*****************************************
  * Return true if comment consists entirely of "ditto".
  */
-private bool isDitto(const(char)* comment)
+bool isDitto(const(char)* comment)
 {
     if (comment)
     {
@@ -1962,13 +1943,13 @@ private bool isDitto(const(char)* comment)
 /**********************************************
  * Skip white space.
  */
-private const(char)* skipwhitespace(const(char)* p)
+const(char)* skipwhitespace(const(char)* p)
 {
     return skipwhitespace(p.toDString).ptr;
 }
 
 /// Ditto
-private const(char)[] skipwhitespace(const(char)[] p) @safe
+const(char)[] skipwhitespace(const(char)[] p) @safe
 {
     foreach (idx, char c; p)
     {
@@ -1993,7 +1974,7 @@ private const(char)[] skipwhitespace(const(char)[] p) @safe
  *  chars         = the characters to skip; order is unimportant
  * Returns: the index after skipping characters.
  */
-private size_t skipChars(ref OutBuffer buf, size_t i, string chars) @safe
+size_t skipChars(ref OutBuffer buf, size_t i, string chars) @safe
 {
     Outer:
     foreach (j, c; buf[][i..$])
@@ -2028,7 +2009,7 @@ unittest {
  *  r = the string to replace `c` with
  * Returns: `s` with `c` replaced with `r`
  */
-private inout(char)[] replaceChar(inout(char)[] s, char c, string r) pure @safe
+inout(char)[] replaceChar(inout(char)[] s, char c, string r) pure @safe
 {
     int count = 0;
     foreach (char sc; s)
@@ -2070,7 +2051,7 @@ unittest
  *  s = the string to lowercase
  * Returns: the lowercase version of the string or the original if already lowercase
  */
-private string toLowercase(string s) pure @safe
+string toLowercase(string s) pure @safe
 {
     string lower;
     foreach (size_t i; 0..s.length)
@@ -2112,7 +2093,7 @@ unittest
  *  to    = the index within `buf` to stop counting at, exclusive
  * Returns: the indent
  */
-private int getMarkdownIndent(ref OutBuffer buf, size_t from, size_t to) @safe
+int getMarkdownIndent(ref OutBuffer buf, size_t from, size_t to) @safe
 {
     const slice = buf[];
     if (to > slice.length)
@@ -2158,7 +2139,7 @@ size_t skiptoident(ref OutBuffer buf, size_t i) @safe
 /************************************************
  * Scan forward past end of identifier.
  */
-private size_t skippastident(ref OutBuffer buf, size_t i) @safe
+size_t skippastident(ref OutBuffer buf, size_t i) @safe
 {
     const slice = buf[];
     while (i < slice.length)
@@ -2188,7 +2169,7 @@ private size_t skippastident(ref OutBuffer buf, size_t i) @safe
  * Scan forward past end of an identifier that might
  * contain dots (e.g. `abc.def`)
  */
-private size_t skipPastIdentWithDots(ref OutBuffer buf, size_t i) @safe
+size_t skipPastIdentWithDots(ref OutBuffer buf, size_t i) @safe
 {
     const slice = buf[];
     bool lastCharWasDot;
@@ -2250,7 +2231,7 @@ private size_t skipPastIdentWithDots(ref OutBuffer buf, size_t i) @safe
  *      i if not a URL
  *      index just past it if it is a URL
  */
-private size_t skippastURL(ref OutBuffer buf, size_t i)
+size_t skippastURL(ref OutBuffer buf, size_t i)
 {
     const slice = buf[][i .. $];
     size_t j;
@@ -2295,7 +2276,7 @@ Lno:
  *  i             = an index within `buf`. If `i` is after `iAt` then it gets
  *                  reduced by the length of the removed macro.
  */
-private void removeBlankLineMacro(ref OutBuffer buf, ref size_t iAt, ref size_t i)
+void removeBlankLineMacro(ref OutBuffer buf, ref size_t iAt, ref size_t i)
 {
     if (!iAt)
         return;
@@ -2320,7 +2301,7 @@ private void removeBlankLineMacro(ref OutBuffer buf, ref size_t iAt, ref size_t
  *  loc         = the current location within the file
  * Returns: whether a thematic break was replaced
  */
-private bool replaceMarkdownThematicBreak(ref OutBuffer buf, ref size_t i, size_t iLineStart, const ref Loc loc)
+bool replaceMarkdownThematicBreak(ref OutBuffer buf, ref size_t i, size_t iLineStart, const ref Loc loc)
 {
 
     const slice = buf[];
@@ -2356,7 +2337,7 @@ private bool replaceMarkdownThematicBreak(ref OutBuffer buf, ref size_t i, size_
  *          the detected heading level from 1 to 6, or
  *          0 if not at an ATX heading
  */
-private int detectAtxHeadingLevel(ref OutBuffer buf, const size_t i) @safe
+int detectAtxHeadingLevel(ref OutBuffer buf, const size_t i) @safe
 {
     const iHeadingStart = i;
     const iAfterHashes = skipChars(buf, i, "#");
@@ -2380,7 +2361,7 @@ private int detectAtxHeadingLevel(ref OutBuffer buf, const size_t i) @safe
  *  buf   = an OutBuffer containing the DDoc
  *  i     = the index within `buf` to start looking for a suffix at
  */
-private void removeAnyAtxHeadingSuffix(ref OutBuffer buf, size_t i)
+void removeAnyAtxHeadingSuffix(ref OutBuffer buf, size_t i)
 {
     size_t j = i;
     size_t iSuffixStart = 0;
@@ -2425,7 +2406,7 @@ private void removeAnyAtxHeadingSuffix(ref OutBuffer buf, size_t i)
  *  headingLevel  = the level (1-6) of heading to end. Is set to `0` when this
  *                  function ends.
  */
-private void endMarkdownHeading(ref OutBuffer buf, size_t iStart, ref size_t iEnd, const ref Loc loc, ref int headingLevel)
+void endMarkdownHeading(ref OutBuffer buf, size_t iStart, ref size_t iEnd, const ref Loc loc, ref int headingLevel)
 {
     char[5] heading = "$(H0 ";
     heading[3] = cast(char) ('0' + headingLevel);
@@ -2446,7 +2427,7 @@ private void endMarkdownHeading(ref OutBuffer buf, size_t iStart, ref size_t iEn
  *  quoteLevel  = the current quote level. Is set to `0` when this function ends.
  * Returns: the amount that `i` was moved
  */
-private size_t endAllMarkdownQuotes(ref OutBuffer buf, size_t i, ref int quoteLevel)
+size_t endAllMarkdownQuotes(ref OutBuffer buf, size_t i, ref int quoteLevel)
 {
     const length = quoteLevel;
     for (; quoteLevel > 0; --quoteLevel)
@@ -2468,7 +2449,7 @@ private size_t endAllMarkdownQuotes(ref OutBuffer buf, size_t i, ref int quoteLe
  *                      `0` when this function ends.
  * Returns: the amount that `i` was moved
  */
-private size_t endAllListsAndQuotes(ref OutBuffer buf, ref size_t i, ref MarkdownList[] nestedLists, ref int quoteLevel, out int quoteMacroLevel)
+size_t endAllListsAndQuotes(ref OutBuffer buf, ref size_t i, ref MarkdownList[] nestedLists, ref int quoteLevel, out int quoteMacroLevel)
 {
     quoteMacroLevel = 0;
     const i0 = i;
@@ -2487,7 +2468,7 @@ private size_t endAllListsAndQuotes(ref OutBuffer buf, ref size_t i, ref Markdow
  *  downToLevel       = the length within `inlineDelimiters`` to reduce emphasis to
  * Returns: the number of characters added to the buffer by the replacements
  */
-private size_t replaceMarkdownEmphasis(ref OutBuffer buf, const ref Loc loc, ref MarkdownDelimiter[] inlineDelimiters, int downToLevel = 0)
+size_t replaceMarkdownEmphasis(ref OutBuffer buf, const ref Loc loc, ref MarkdownDelimiter[] inlineDelimiters, int downToLevel = 0)
 {
     size_t replaceEmphasisPair(ref MarkdownDelimiter start, ref MarkdownDelimiter end)
     {
@@ -2566,7 +2547,7 @@ private size_t replaceMarkdownEmphasis(ref OutBuffer buf, const ref Loc loc, ref
 
 /****************************************************
  */
-private bool isIdentifier(Dsymbols* a, const(char)[] s) @safe
+bool isIdentifier(Dsymbols* a, const(char)[] s) @safe
 {
     foreach (member; *a)
     {
@@ -2608,7 +2589,7 @@ private bool isIdentifier(Dsymbols* a, const(char)[] s) @safe
 
 /****************************************************
  */
-private bool isKeyword(const(char)[] str) @safe
+bool isKeyword(const(char)[] str) @safe
 {
     immutable string[3] table = ["true", "false", "null"];
     foreach (s; table)
@@ -2621,7 +2602,7 @@ private bool isKeyword(const(char)[] str) @safe
 
 /****************************************************
  */
-private TypeFunction isTypeFunction(Dsymbol s) @safe
+TypeFunction isTypeFunction(Dsymbol s) @safe
 {
     FuncDeclaration f = s.isFuncDeclaration();
     /* f.type may be NULL for template members.
@@ -2637,7 +2618,7 @@ private TypeFunction isTypeFunction(Dsymbol s) @safe
 
 /****************************************************
  */
-private Parameter isFunctionParameter(Dsymbol s, const(char)[] str) @safe
+Parameter isFunctionParameter(Dsymbol s, const(char)[] str) @safe
 {
     TypeFunction tf = isTypeFunction(s);
     if (tf && tf.parameterList.parameters)
@@ -2655,7 +2636,7 @@ private Parameter isFunctionParameter(Dsymbol s, const(char)[] str) @safe
 
 /****************************************************
  */
-private Parameter isFunctionParameter(Dsymbols* a, const(char)[] p) @safe
+Parameter isFunctionParameter(Dsymbols* a, const(char)[] p) @safe
 {
     foreach (Dsymbol sym; *a)
     {
@@ -2670,7 +2651,7 @@ private Parameter isFunctionParameter(Dsymbols* a, const(char)[] p) @safe
 
 /****************************************************
  */
-private Parameter isEponymousFunctionParameter(Dsymbols *a, const(char)[] p) @safe
+Parameter isEponymousFunctionParameter(Dsymbols *a, const(char)[] p) @safe
 {
     foreach (Dsymbol dsym; *a)
     {
@@ -2718,7 +2699,7 @@ private Parameter isEponymousFunctionParameter(Dsymbols *a, const(char)[] p) @sa
 
 /****************************************************
  */
-private TemplateParameter isTemplateParameter(Dsymbols* a, const(char)* p, size_t len)
+TemplateParameter isTemplateParameter(Dsymbols* a, const(char)* p, size_t len)
 {
     for (size_t i = 0; i < a.length; i++)
     {
@@ -2744,7 +2725,7 @@ private TemplateParameter isTemplateParameter(Dsymbols* a, const(char)* p, size_
  * Return true if str is a reserved symbol name
  * that starts with a double underscore.
  */
-private bool isReservedName(const(char)[] str) @safe
+bool isReservedName(const(char)[] str) @safe
 {
     immutable string[] table =
     [
@@ -2791,7 +2772,7 @@ private bool isReservedName(const(char)[] str) @safe
 /****************************************************
  * A delimiter for Markdown inline content like emphasis and links.
  */
-private struct MarkdownDelimiter
+struct MarkdownDelimiter
 {
     size_t iStart;  /// the index where this delimiter starts
     int count;      /// the length of this delimeter's start sequence
@@ -2811,7 +2792,7 @@ private struct MarkdownDelimiter
 /****************************************************
  * Info about a Markdown list.
  */
-private struct MarkdownList
+struct MarkdownList
 {
     string orderedStart;    /// an optional start number--if present then the list starts at this number
     size_t iStart;          /// the index where the list item starts
@@ -3028,7 +3009,7 @@ private struct MarkdownList
 /****************************************************
  * A Markdown link.
  */
-private struct MarkdownLink
+struct MarkdownLink
 {
     string href;    /// the link destination
     string title;   /// an optional title for the link
@@ -3607,7 +3588,7 @@ private struct MarkdownLink
 /**************************************************
  * A set of Markdown link references.
  */
-private struct MarkdownLinkReferences
+struct MarkdownLinkReferences
 {
     MarkdownLink[string] references;    // link references keyed by normalized label
     MarkdownLink[string] symbols;       // link symbols keyed by name
@@ -3872,7 +3853,7 @@ private struct MarkdownLinkReferences
     }
 }
 
-private enum TableColumnAlignment
+enum TableColumnAlignment
 {
     none,
     left,
@@ -3893,7 +3874,7 @@ private enum TableColumnAlignment
  *  columnAlignments = alignments to populate for each column
  * Returns: the index of the end of the parsed delimiter, or `0` if not found
  */
-private size_t parseTableDelimiterRow(ref OutBuffer buf, const size_t iStart, bool inQuote, ref TableColumnAlignment[] columnAlignments) @safe
+size_t parseTableDelimiterRow(ref OutBuffer buf, const size_t iStart, bool inQuote, ref TableColumnAlignment[] columnAlignments) @safe
 {
     size_t i = skipChars(buf, iStart, inQuote ? ">| \t" : "| \t");
     while (i < buf.length && buf[i] != '\r' && buf[i] != '\n')
@@ -3945,7 +3926,7 @@ private size_t parseTableDelimiterRow(ref OutBuffer buf, const size_t iStart, bo
  *  columnAlignments = the parsed alignments for each column
  * Returns: the number of characters added by starting the table, or `0` if unchanged
  */
-private size_t startTable(ref OutBuffer buf, size_t iStart, size_t iEnd, const ref Loc loc, bool inQuote, ref MarkdownDelimiter[] inlineDelimiters, out TableColumnAlignment[] columnAlignments)
+size_t startTable(ref OutBuffer buf, size_t iStart, size_t iEnd, const ref Loc loc, bool inQuote, ref MarkdownDelimiter[] inlineDelimiters, out TableColumnAlignment[] columnAlignments)
 {
     const iDelimiterRowEnd = parseTableDelimiterRow(buf, iEnd + 1, inQuote, columnAlignments);
     if (iDelimiterRowEnd)
@@ -3981,7 +3962,7 @@ private size_t startTable(ref OutBuffer buf, size_t iStart, size_t iEnd, const r
  *  delta     = the number of characters added by replacing the row, or `0` if unchanged
  * Returns: `true` if a table row was found and replaced
  */
-private bool replaceTableRow(ref OutBuffer buf, size_t iStart, size_t iEnd, const ref Loc loc, ref MarkdownDelimiter[] inlineDelimiters, TableColumnAlignment[] columnAlignments, bool headerRow, out size_t delta)
+bool replaceTableRow(ref OutBuffer buf, size_t iStart, size_t iEnd, const ref Loc loc, ref MarkdownDelimiter[] inlineDelimiters, TableColumnAlignment[] columnAlignments, bool headerRow, out size_t delta)
 {
     delta = 0;
 
@@ -4108,7 +4089,7 @@ private bool replaceTableRow(ref OutBuffer buf, size_t iStart, size_t iEnd, cons
  *  columnAlignments = alignments for each column; upon return is set to length `0`
  * Returns: the number of characters added by ending the table, or `0` if unchanged
  */
-private size_t endTable(ref OutBuffer buf, size_t i, ref TableColumnAlignment[] columnAlignments)
+size_t endTable(ref OutBuffer buf, size_t i, ref TableColumnAlignment[] columnAlignments)
 {
     if (!columnAlignments.length)
         return 0;
@@ -4130,7 +4111,7 @@ private size_t endTable(ref OutBuffer buf, size_t i, ref TableColumnAlignment[]
  *  columnAlignments = alignments for each column; upon return is set to length `0`
  * Returns: the number of characters added by replacing the row, or `0` if unchanged
  */
-private size_t endRowAndTable(ref OutBuffer buf, size_t iStart, size_t iEnd, const ref Loc loc, ref MarkdownDelimiter[] inlineDelimiters, ref TableColumnAlignment[] columnAlignments)
+size_t endRowAndTable(ref OutBuffer buf, size_t iStart, size_t iEnd, const ref Loc loc, ref MarkdownDelimiter[] inlineDelimiters, ref TableColumnAlignment[] columnAlignments)
 {
     size_t delta;
     replaceTableRow(buf, iStart, iEnd, loc, inlineDelimiters, columnAlignments, false, delta);
@@ -4148,7 +4129,7 @@ private size_t endRowAndTable(ref OutBuffer buf, size_t iStart, size_t iEnd, con
  *  buf   = an OutBuffer containing the DDoc
  *  offset = the index within buf to start highlighting
  */
-private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, size_t offset)
+void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, size_t offset)
 {
     const incrementLoc = loc.linnum == 0 ? 1 : 0;
     loc.linnum = loc.linnum + incrementLoc;
@@ -4417,7 +4398,7 @@ private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, s
                     codebuf.write(buf[iCodeStart + count .. i]);
                     // escape the contents, but do not perform highlighting except for DDOC_PSYMBOL
                     highlightCode(sc, a, codebuf, 0);
-                    escapeStrayParenthesis(loc, &codebuf, 0, false, sc.eSink);
+                    escapeStrayParenthesis(loc, codebuf, 0, false, sc.eSink);
                     buf.remove(iCodeStart, i - iCodeStart + count); // also trimming off the current `
                     immutable pre = "$(DDOC_BACKQUOTED ";
                     i = buf.insert(iCodeStart, pre);
@@ -4626,7 +4607,7 @@ private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, s
                         highlightCode2(sc, a, codebuf, 0);
                     else
                         codebuf.remove(codebuf.length-1, 1);    // remove the trailing 0 byte
-                    escapeStrayParenthesis(loc, &codebuf, 0, false, sc.eSink);
+                    escapeStrayParenthesis(loc, codebuf, 0, false, sc.eSink);
                     buf.remove(iCodeStart, i - iCodeStart);
                     i = buf.insert(iCodeStart, codebuf[]);
                     i = buf.insert(i, ")\n");
@@ -5002,7 +4983,7 @@ private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, s
 /**************************************************
  * Highlight code for DDOC section.
  */
-private void highlightCode(Scope* sc, Dsymbol s, ref OutBuffer buf, size_t offset)
+void highlightCode(Scope* sc, Dsymbol s, ref OutBuffer buf, size_t offset)
 {
     auto imp = s.isImport();
     if (imp && imp.aliases.length > 0)
@@ -5037,7 +5018,7 @@ private void highlightCode(Scope* sc, Dsymbol s, ref OutBuffer buf, size_t offse
 
 /****************************************************
  */
-private void highlightCode(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t offset)
+void highlightCode(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t offset)
 {
     //printf("highlightCode(a = '%s')\n", a.toChars());
     bool resolvedTemplateParameters = false;
@@ -5119,7 +5100,7 @@ private void highlightCode(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t off
 
                     size_t lastOffset = parametersBuf.length;
 
-                    .toCBuffer(tp, &parametersBuf, &hgs);
+                    toCBuffer(tp, parametersBuf, hgs);
 
                     paramLens[parami] = parametersBuf.length - lastOffset;
                 }
@@ -5163,7 +5144,7 @@ private void highlightCode(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t off
 
 /****************************************
  */
-private void highlightCode3(Scope* sc, ref OutBuffer buf, const(char)* p, const(char)* pend)
+void highlightCode3(Scope* sc, ref OutBuffer buf, const(char)* p, const(char)* pend)
 {
     for (; p < pend; p++)
     {
@@ -5178,7 +5159,7 @@ private void highlightCode3(Scope* sc, ref OutBuffer buf, const(char)* p, const(
 /**************************************************
  * Highlight code for CODE section.
  */
-private void highlightCode2(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t offset)
+void highlightCode2(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t offset)
 {
     scope eSinkNull = new ErrorSinkNull();
 
@@ -5236,7 +5217,7 @@ private void highlightCode2(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t of
                  * https://issues.dlang.org/show_bug.cgi?id=7715
                  * https://issues.dlang.org/show_bug.cgi?id=10519
                  */
-                escapeDdocString(&res, o);
+                escapeDdocString(res, o);
             res.writeByte(')');
         }
         else
@@ -5252,7 +5233,7 @@ private void highlightCode2(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t of
 /****************************************
  * Determine if p points to the start of a "..." parameter identifier.
  */
-private bool isCVariadicArg(const(char)[] p) @nogc nothrow pure @safe
+bool isCVariadicArg(const(char)[] p) @nogc nothrow pure @safe
 {
     return p.length >= 3 && p[0 .. 3] == "...";
 }
@@ -5260,6 +5241,7 @@ private bool isCVariadicArg(const(char)[] p) @nogc nothrow pure @safe
 /****************************************
  * Determine if p points to the start of an identifier.
  */
+@trusted
 bool isIdStart(const(char)* p) @nogc nothrow pure
 {
     dchar c = *p;
@@ -5279,6 +5261,7 @@ bool isIdStart(const(char)* p) @nogc nothrow pure
 /****************************************
  * Determine if p points to the rest of an identifier.
  */
+@trusted
 bool isIdTail(const(char)* p) @nogc nothrow pure
 {
     dchar c = *p;
@@ -5298,7 +5281,7 @@ bool isIdTail(const(char)* p) @nogc nothrow pure
 /****************************************
  * Determine if p points to the indentation space.
  */
-private bool isIndentWS(const(char)* p) @nogc nothrow pure @safe
+bool isIndentWS(const(char)* p) @nogc nothrow pure @safe
 {
     return (*p == ' ') || (*p == '\t');
 }
@@ -5316,7 +5299,7 @@ int utfStride(const(char)* p) @nogc nothrow pure
     return cast(int)i;
 }
 
-private inout(char)* stripLeadingNewlines(inout(char)* s) @nogc nothrow pure
+inout(char)* stripLeadingNewlines(inout(char)* s) @nogc nothrow pure
 {
     while (s && *s == '\n' || *s == '\r')
         s++;
diff --git a/gcc/d/dmd/doc.h b/gcc/d/dmd/doc.h
index 669e308dcf6..562427f1a4d 100644
--- a/gcc/d/dmd/doc.h
+++ b/gcc/d/dmd/doc.h
@@ -13,4 +13,5 @@
 class Module;
 class ErrorSink;
 
-void gendocfile(Module *m, ErrorSink *eSink);
+void gendocfile(Module *m, const char *ddoctext_ptr, size_t ddoctext_length,
+                const char *datetime, ErrorSink *eSink, OutBuffer &outbuf);
diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d
index c2c0628f5ed..981e093934c 100644
--- a/gcc/d/dmd/dscope.d
+++ b/gcc/d/dmd/dscope.d
@@ -169,6 +169,7 @@ extern (C++) struct Scope
         sc.scopesym = new ScopeDsymbol();
         sc.scopesym.symtab = new DsymbolTable();
         sc.eSink = eSink;
+        assert(eSink);
         // Add top level package as member of this global scope
         Dsymbol m = _module;
         while (m.parent)
diff --git a/gcc/d/dmd/dstruct.d b/gcc/d/dmd/dstruct.d
index 49b98411ad3..a131a8a721c 100644
--- a/gcc/d/dmd/dstruct.d
+++ b/gcc/d/dmd/dstruct.d
@@ -105,6 +105,7 @@ extern (C++) void semanticTypeInfo(Scope* sc, Type t)
         if (!sc) // inline may request TypeInfo.
         {
             Scope scx;
+            scx.eSink = global.errorSink;
             scx._module = sd.getModule();
             getTypeInfoType(sd.loc, t, &scx);
             sd.requestTypeInfo = true;
diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d
index 0fa4dbcfa5c..c9a2c92194b 100644
--- a/gcc/d/dmd/dsymbol.d
+++ b/gcc/d/dmd/dsymbol.d
@@ -1801,6 +1801,7 @@ public:
             if (!tfgetmembers)
             {
                 Scope sc;
+                sc.eSink = global.errorSink;
                 auto parameters = new Parameters();
                 Parameters* p = new Parameter(STC.in_, Type.tchar.constOf().arrayOf(), null, null);
                 parameters.push(p);
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index 378d3e6dd64..ebdd3a8566d 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -83,7 +83,7 @@ else version = MARS;
 
 enum LOG = false;
 
-private uint setMangleOverride(Dsymbol s, const(char)[] sym)
+package uint setMangleOverride(Dsymbol s, const(char)[] sym)
 {
     if (s.isFuncDeclaration() || s.isVarDeclaration())
     {
@@ -766,7 +766,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             else
             {
                 OutBuffer buf;
-                stcToBuffer(&buf, stc);
+                stcToBuffer(buf, stc);
                 dsym.error("cannot be `%s`", buf.peekChars());
             }
             dsym.storage_class &= ~stc; // strip off
@@ -783,7 +783,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             if (stc)
             {
                 OutBuffer buf;
-                stcToBuffer(&buf, stc);
+                stcToBuffer(buf, stc);
                 dsym.error("cannot be `scope` and `%s`", buf.peekChars());
             }
             else if (dsym.isMember())
@@ -1121,11 +1121,9 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                                 if (ne.member && !(ne.member.storage_class & STC.scope_))
                                 {
                                     import dmd.escape : setUnsafeDIP1000;
-                                    const inSafeFunc = sc.func && sc.func.isSafeBypassingInference();
+                                    const inSafeFunc = sc.func && sc.func.isSafeBypassingInference();   // isSafeBypassingInference may call setUnsafe().
                                     if (sc.setUnsafeDIP1000(false, dsym.loc, "`scope` allocation of `%s` requires that constructor be annotated with `scope`", dsym))
                                         errorSupplemental(ne.member.loc, "is the location of the constructor");
-                                    else if (global.params.obsolete && inSafeFunc)
-                                        warningSupplemental(ne.member.loc, "is the location of the constructor");
                                 }
                                 ne.onstack = 1;
                                 dsym.onstack = true;
@@ -1512,11 +1510,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         ob.writestring(") : ");
         // use visibility instead of sc.visibility because it couldn't be
         // resolved yet, see the comment above
-        visibilityToBuffer(ob, imp.visibility);
+        visibilityToBuffer(*ob, imp.visibility);
         ob.writeByte(' ');
         if (imp.isstatic)
         {
-            stcToBuffer(ob, STC.static_);
+            stcToBuffer(*ob, STC.static_);
             ob.writeByte(' ');
         }
         ob.writestring(": ");
@@ -2528,9 +2526,14 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 if (!em.ed.isAnonymous())
                     em.ed.memtype = t;
             }
+            const errors = global.startGagging();
             Expression e = new IntegerExp(em.loc, 0, t);
             e = e.ctfeInterpret();
-
+            if (global.endGagging(errors))
+            {
+                error(em.loc, "cannot generate 0 value of type `%s` for `%s`",
+                    t.toChars(), em.toChars());
+            }
             // save origValue for better json output
             em.origValue = e;
 
@@ -2564,7 +2567,9 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             if (emprev.errors)
                 return errorReturn();
 
+            auto errors = global.startGagging();
             Expression eprev = emprev.value;
+            assert(eprev);
             // .toHeadMutable() due to https://issues.dlang.org/show_bug.cgi?id=18645
             Type tprev = eprev.type.toHeadMutable().equals(em.ed.type.toHeadMutable())
                 ? em.ed.memtype
@@ -2578,12 +2583,23 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             emax = emax.expressionSemantic(sc);
             emax = emax.ctfeInterpret();
 
-            // Set value to (eprev + 1).
-            // But first check that (eprev != emax)
-            assert(eprev);
+            // check that (eprev != emax)
             Expression e = new EqualExp(EXP.equal, em.loc, eprev, emax);
             e = e.expressionSemantic(sc);
             e = e.ctfeInterpret();
+            if (global.endGagging(errors))
+            {
+                // display an introductory error before showing what actually failed
+                error(em.loc, "cannot check `%s` value for overflow", em.toPrettyChars());
+                // rerun to show errors
+                Expression e2 = DotIdExp.create(em.ed.loc, new TypeExp(em.ed.loc, tprev), Id.max);
+                e2 = e2.expressionSemantic(sc);
+                e2 = e2.ctfeInterpret();
+                e2 = new EqualExp(EXP.equal, em.loc, eprev, e2);
+                e2 = e2.expressionSemantic(sc);
+                e2 = e2.ctfeInterpret();
+            }
+            // now any errors are for generating a value
             if (e.toInteger())
             {
                 auto mt = em.ed.memtype;
@@ -2593,13 +2609,21 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                     emprev.ed.toChars(), emprev.toChars(), mt.toChars());
                 return errorReturn();
             }
-
+            errors = global.startGagging();
             // Now set e to (eprev + 1)
             e = new AddExp(em.loc, eprev, IntegerExp.literal!1);
             e = e.expressionSemantic(sc);
             e = e.castTo(sc, eprev.type);
             e = e.ctfeInterpret();
-
+            if (global.endGagging(errors))
+            {
+                error(em.loc, "cannot generate value for `%s`", em.toPrettyChars());
+                // rerun to show errors
+                Expression e2 = new AddExp(em.loc, eprev, IntegerExp.literal!1);
+                e2 = e2.expressionSemantic(sc);
+                e2 = e2.castTo(sc, eprev.type);
+                e2 = e2.ctfeInterpret();
+            }
             // save origValue (without cast) for better json output
             if (e.op != EXP.error) // avoid duplicate diagnostics
             {
@@ -3351,7 +3375,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             if (!tf.isNaked() && !(funcdecl.isThis() || funcdecl.isNested()))
             {
                 OutBuffer buf;
-                MODtoBuffer(&buf, tf.mod);
+                MODtoBuffer(buf, tf.mod);
                 funcdecl.error("without `this` cannot be `%s`", buf.peekChars());
                 tf.mod = 0; // remove qualifiers
             }
@@ -3889,7 +3913,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                     OutBuffer buf;
 
                     auto fd = s.isFuncDeclaration();
-                    functionToBufferFull(cast(TypeFunction)(funcdecl.type), &buf,
+                    functionToBufferFull(cast(TypeFunction)(funcdecl.type), buf,
                         new Identifier(funcdecl.toPrettyChars()), &hgs, null);
                     const(char)* funcdeclToChars = buf.peekChars();
 
@@ -3912,7 +3936,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                         }
                         else
                         {
-                            functionToBufferFull(cast(TypeFunction)(fd.type), &buf1,
+                            functionToBufferFull(cast(TypeFunction)(fd.type), buf1,
                                 new Identifier(fd.toPrettyChars()), &hgs, null);
 
                             error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?",
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index e492c7e7aef..67ca2ef66a4 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -750,7 +750,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
         {
             if (i)
                 buf.writestring(", ");
-            .toCBuffer(tp, &buf, &hgs);
+            toCBuffer(tp, buf, hgs);
         }
         buf.writeByte(')');
 
@@ -768,7 +768,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
             constraint)
         {
             buf.writestring(" if (");
-            .toCBuffer(constraint, &buf, &hgs);
+            toCBuffer(constraint, buf, hgs);
             buf.writeByte(')');
         }
 
@@ -865,7 +865,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
                 if (!fparam.ident)
                     continue;
                 // don't add it, if it has no name
-                auto v = new VarDeclaration(loc, fparam.type, fparam.ident, null);
+                auto v = new VarDeclaration(fparam.loc, fparam.type, fparam.ident, null);
                 fparam.storageClass |= STC.parameter;
                 v.storage_class = fparam.storageClass;
                 v.dsymbolSemantic(scx);
@@ -6024,14 +6024,14 @@ extern (C++) class TemplateInstance : ScopeDsymbol
     override const(char)* toChars() const
     {
         OutBuffer buf;
-        toCBufferInstance(this, &buf);
+        toCBufferInstance(this, buf);
         return buf.extractChars();
     }
 
     override final const(char)* toPrettyCharsHelper()
     {
         OutBuffer buf;
-        toCBufferInstance(this, &buf, true);
+        toCBufferInstance(this, buf, true);
         return buf.extractChars();
     }
 
@@ -6058,11 +6058,9 @@ extern (C++) class TemplateInstance : ScopeDsymbol
             {
                 case Classification.error:
                     return &errorSupplemental;
-                case Classification.warning:
-                    return &warningSupplemental;
                 case Classification.deprecation:
                     return &deprecationSupplemental;
-                case Classification.gagged, Classification.tip:
+                case Classification.gagged, Classification.tip, Classification.warning:
                     assert(0);
             }
         }();
@@ -7056,10 +7054,10 @@ extern (C++) class TemplateInstance : ScopeDsymbol
 
             if (td_ambig)
             {
-                .error(loc, "%s `%s.%s` matches more than one template declaration:\n%s:     `%s`\nand\n%s:     `%s`",
-                    td_best.kind(), td_best.parent.toPrettyChars(), td_best.ident.toChars(),
-                    td_best.loc.toChars(), td_best.toChars(),
-                    td_ambig.loc.toChars(), td_ambig.toChars());
+                .error(loc, "%s `%s.%s` matches more than one template declaration:",
+                    td_best.kind(), td_best.parent.toPrettyChars(), td_best.ident.toChars());
+                .errorSupplemental(td_best.loc, "`%s`\nand:", td_best.toChars());
+                .errorSupplemental(td_ambig.loc, "`%s`", td_ambig.toChars());
                 return false;
             }
             if (td_best)
@@ -7825,7 +7823,7 @@ extern (C++) final class TemplateMixin : TemplateInstance
     override const(char)* toChars() const
     {
         OutBuffer buf;
-        toCBufferInstance(this, &buf);
+        toCBufferInstance(this, buf);
         return buf.extractChars();
     }
 
diff --git a/gcc/d/dmd/dtoh.d b/gcc/d/dmd/dtoh.d
index 6a7442ad702..d5f658a8a42 100644
--- a/gcc/d/dmd/dtoh.d
+++ b/gcc/d/dmd/dtoh.d
@@ -199,7 +199,8 @@ struct _d_dynamicArray final
     else
     {
         const(char)[] name = FileName.combine(global.params.cxxhdr.dir, global.params.cxxhdr.name);
-        writeFile(Loc.initial, name, buf[]);
+        if (!writeFile(Loc.initial, name, buf[]))
+            return fatal();
     }
 }
 
@@ -2327,7 +2328,12 @@ public:
         {
             //printf("%s %d\n", p.defaultArg.toChars, p.defaultArg.op);
             buf.writestring(" = ");
+            // Always emit the FDN of a symbol for the default argument,
+            // to avoid generating an ambiguous assignment.
+            auto save = adparent;
+            adparent = null;
             printExpressionFor(p.type, p.defaultArg);
+            adparent = save;
         }
     }
 
@@ -2636,7 +2642,7 @@ public:
             import dmd.hdrgen;
             // Hex floating point literals were introduced in C++ 17
             const allowHex = global.params.cplusplus >= CppStdRevision.cpp17;
-            floatToBuffer(e.type, e.value, buf, allowHex);
+            floatToBuffer(e.type, e.value, *buf, allowHex);
         }
     }
 
diff --git a/gcc/d/dmd/errors.h b/gcc/d/dmd/errors.h
index c6b5975113a..759ad277fda 100644
--- a/gcc/d/dmd/errors.h
+++ b/gcc/d/dmd/errors.h
@@ -14,6 +14,7 @@
 
 struct Loc;
 
+// Constants used to discriminate kinds of error messages.
 enum class ErrorKind
 {
     warning = 0,
@@ -43,7 +44,7 @@ D_ATTRIBUTE_FORMAT(1, 2) void message(const char *format, ...);
 D_ATTRIBUTE_FORMAT(2, 3) void message(const Loc& loc, const char *format, ...);
 D_ATTRIBUTE_FORMAT(1, 2) void tip(const char *format, ...);
 
-D_ATTRIBUTE_FORMAT(2, 0) void verrorReport(const Loc& loc, const char *format, va_list ap, const char *p1 = NULL, const char *p2 = NULL);
+D_ATTRIBUTE_FORMAT(2, 0) void verrorReport(const Loc& loc, const char *format, va_list ap, ErrorKind kind, const char *p1 = NULL, const char *p2 = NULL);
 D_ATTRIBUTE_FORMAT(2, 0) void verrorReportSupplemental(const Loc& loc, const char* format, va_list ap, ErrorKind kind);
 
 #if defined(__GNUC__) || defined(__clang__)
diff --git a/gcc/d/dmd/errorsink.d b/gcc/d/dmd/errorsink.d
index e14829ecfdb..ce2351738d6 100644
--- a/gcc/d/dmd/errorsink.d
+++ b/gcc/d/dmd/errorsink.d
@@ -62,6 +62,7 @@ class ErrorSinkNull : ErrorSink
 
 /*****************************************
  * Simplest implementation, just sends messages to stderr.
+ * See also: ErrorSinkCompiler.
  */
 class ErrorSinkStderr : ErrorSink
 {
diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d
index f817a4ee42f..8562e2eabd6 100644
--- a/gcc/d/dmd/escape.d
+++ b/gcc/d/dmd/escape.d
@@ -37,6 +37,8 @@ import dmd.tokens;
 import dmd.visitor;
 import dmd.arraytypes;
 
+private:
+
 /// Groups global state for escape checking together
 package(dmd) struct EscapeState
 {
@@ -69,6 +71,7 @@ package(dmd) struct EscapeState
  * Returns:
  *      `true` if error
  */
+public
 bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf,
     Expression ethis, Expressions* arguments, bool gag)
 {
@@ -179,7 +182,7 @@ bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf,
             const(char)* msg = eb.isMutable && eb2.isMutable
                                 ? "more than one mutable reference %s `%s` in arguments to `%s()`"
                                 : "mutable and const references %s `%s` in arguments to `%s()`";
-            error((*arguments)[i].loc, msg,
+            sc.eSink.error((*arguments)[i].loc, msg,
                   referenceVerb,
                   v.toChars(),
                   fd ? fd.toPrettyChars() : "indirectly");
@@ -226,6 +229,7 @@ bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf,
  * Returns:
  *      `true` if any elements escaped
  */
+public
 bool checkArrayLiteralEscape(Scope *sc, ArrayLiteralExp ae, bool gag)
 {
     bool errors;
@@ -249,6 +253,7 @@ bool checkArrayLiteralEscape(Scope *sc, ArrayLiteralExp ae, bool gag)
  * Returns:
  *      `true` if any elements escaped
  */
+public
 bool checkAssocArrayLiteralEscape(Scope *sc, AssocArrayLiteralExp ae, bool gag)
 {
     bool errors;
@@ -274,6 +279,7 @@ bool checkAssocArrayLiteralEscape(Scope *sc, AssocArrayLiteralExp ae, bool gag)
  *    v = parameter that was not inferred
  *    recursionLimit = recursion limit for printing the reason
  */
+private
 void printScopeFailure(E)(E printFunc, VarDeclaration v, int recursionLimit)
 {
     recursionLimit--;
@@ -316,12 +322,13 @@ void printScopeFailure(E)(E printFunc, VarDeclaration v, int recursionLimit)
  * Returns:
  *      `true` if pointers to the stack can escape via assignment
  */
+public
 bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier parId, VarDeclaration vPar, STC parStc, Expression arg, bool assertmsg, bool gag)
 {
     enum log = false;
-    if (log) printf("checkParamArgumentEscape(arg: %s par: %s)\n",
+    if (log) printf("checkParamArgumentEscape(arg: %s par: %s parSTC: %llx)\n",
         arg ? arg.toChars() : "null",
-        parId ? parId.toChars() : "null");
+        parId ? parId.toChars() : "null", parStc);
     //printf("type = %s, %d\n", arg.type.toChars(), arg.type.hasPointers());
 
     if (!arg.type.hasPointers())
@@ -334,7 +341,7 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier parId,
     if (parStc & STC.scope_)
     {
         // These errors only apply to non-scope parameters
-        // When the paraneter is `scope`, only `checkScopeVarAddr` on `er.byref` is needed
+        // When the parameter is `scope`, only `checkScopeVarAddr` on `er.byref` is needed
         er.byfunc.setDim(0);
         er.byvalue.setDim(0);
         er.byexp.setDim(0);
@@ -467,6 +474,7 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier parId,
  * Returns:
  *      `true` if assignment to `firstArg` would cause an error
  */
+public
 bool checkParamArgumentReturn(Scope* sc, Expression firstArg, Expression arg, Parameter param, bool gag)
 {
     enum log = false;
@@ -502,6 +510,7 @@ bool checkParamArgumentReturn(Scope* sc, Expression firstArg, Expression arg, Pa
  * Returns:
  *      `true` if construction would cause an escaping reference error
  */
+public
 bool checkConstructorEscape(Scope* sc, CallExp ce, bool gag)
 {
     enum log = false;
@@ -543,6 +552,7 @@ bool checkConstructorEscape(Scope* sc, CallExp ce, bool gag)
 }
 
 /// How a `return` parameter escapes its pointer value
+public
 enum ReturnParamDest
 {
     returnVal, /// through return statement: `return x`
@@ -564,6 +574,7 @@ enum ReturnParamDest
  *   tthis = type of `this` parameter, or `null` if none
  * Returns: What a `return` parameter should transfer the lifetime of the argument to
  */
+public
 ReturnParamDest returnParamDest(TypeFunction tf, Type tthis)
 {
     assert(tf);
@@ -596,6 +607,7 @@ ReturnParamDest returnParamDest(TypeFunction tf, Type tthis)
  * Returns:
  *      `true` if pointers to the stack can escape via assignment
  */
+public
 bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
 {
     enum log = false;
@@ -912,7 +924,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
             !(va && va.storage_class & STC.temp))
         {
             if (!gag)
-                deprecation(ee.loc, "slice of static array temporary returned by `%s` assigned to longer lived variable `%s`",
+                sc.eSink.deprecation(ee.loc, "slice of static array temporary returned by `%s` assigned to longer lived variable `%s`",
                     ee.toChars(), e1.toChars());
             //result = true;
             continue;
@@ -959,6 +971,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
  * Returns:
  *      `true` if pointers to the stack can escape
  */
+public
 bool checkThrowEscape(Scope* sc, Expression e, bool gag)
 {
     //printf("[%s] checkThrowEscape, e = %s\n", e.loc.toChars(), e.toChars());
@@ -1002,6 +1015,7 @@ bool checkThrowEscape(Scope* sc, Expression e, bool gag)
  * Returns:
  *      `true` if pointers to the stack can escape
  */
+public
 bool checkNewEscape(Scope* sc, Expression e, bool gag)
 {
     import dmd.globals: FeatureState;
@@ -1124,7 +1138,7 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
     {
         if (log) printf("byexp %s\n", ee.toChars());
         if (!gag)
-            error(ee.loc, "storing reference to stack allocated value returned by `%s` into allocated memory causes it to escape",
+            sc.eSink.error(ee.loc, "storing reference to stack allocated value returned by `%s` into allocated memory causes it to escape",
                   ee.toChars());
         result = true;
     }
@@ -1144,6 +1158,7 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
  * Returns:
  *      `true` if pointers to the stack can escape
  */
+public
 bool checkReturnEscape(Scope* sc, Expression e, bool gag)
 {
     //printf("[%s] checkReturnEscape, e: %s\n", e.loc.toChars(), e.toChars());
@@ -1161,6 +1176,7 @@ bool checkReturnEscape(Scope* sc, Expression e, bool gag)
  * Returns:
  *      `true` if references to the stack can escape
  */
+public
 bool checkReturnEscapeRef(Scope* sc, Expression e, bool gag)
 {
     version (none)
@@ -1266,7 +1282,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
         else if (v.isTypesafeVariadicArray && p == sc.func)
         {
             if (!gag)
-                error(e.loc, "returning `%s` escapes a reference to variadic parameter `%s`", e.toChars(), v.toChars());
+                sc.eSink.error(e.loc, "returning `%s` escapes a reference to variadic parameter `%s`", e.toChars(), v.toChars());
             result = false;
         }
         else
@@ -1420,7 +1436,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
         else
         {
             if (!gag)
-                error(ee.loc, "escaping reference to stack allocated value returned by `%s`", ee.toChars());
+                sc.eSink.error(ee.loc, "escaping reference to stack allocated value returned by `%s`", ee.toChars());
             result = true;
         }
     }
@@ -1434,6 +1450,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
  *      va = variable to infer scope for
  * Returns: `true` if succesful or already `scope`
  */
+private
 bool inferScope(VarDeclaration va)
 {
     if (!va)
@@ -1526,6 +1543,7 @@ private bool inferReturn(FuncDeclaration fd, VarDeclaration v, bool returnScope)
  *      live = if @live semantics apply, i.e. expressions `p`, `*p`, `**p`, etc., all return `p`.
   *     retRefTransition = if `e` is returned through a `return ref scope` function call
  */
+public
 void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool retRefTransition = false)
 {
     //printf("[%s] escapeByValue, e: %s\n", e.loc.toChars(), e.toChars());
@@ -1924,6 +1942,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
  *      live = if @live semantics apply, i.e. expressions `p`, `*p`, `**p`, etc., all return `p`.
  *      retRefTransition = if `e` is returned through a `return ref scope` function call
  */
+private
 void escapeByRef(Expression e, EscapeByResults* er, bool live = false, bool retRefTransition = false)
 {
     //printf("[%s] escapeByRef, e: %s, retRefTransition: %d\n", e.loc.toChars(), e.toChars(), retRefTransition);
@@ -2158,6 +2177,7 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false, bool retR
 /************************************
  * Aggregate the data collected by the escapeBy??() functions.
  */
+public
 struct EscapeByResults
 {
     VarDeclarations byref;      // array into which variables being returned by ref are inserted
@@ -2295,6 +2315,7 @@ private void doNotInferScope(VarDeclaration v, RootObject o)
  *   f = final function type. `funcdecl.type` started as the 'premature type' before attribute
  *       inference, then its inferred attributes are copied over to final type `f`
  */
+public
 void finishScopeParamInference(FuncDeclaration funcdecl, ref TypeFunction f)
 {
 
@@ -2427,6 +2448,7 @@ private void eliminateMaybeScopes(VarDeclaration[] array)
  * Returns:
  *      true if it's a pointer (or reference) to mutable data
  */
+private
 bool isReferenceToMutable(Type t)
 {
     t = t.baseElemOf();
@@ -2486,6 +2508,7 @@ bool isReferenceToMutable(Type t)
  * Returns:
  *      true if it's a pointer (or reference) to mutable data
  */
+private
 bool isReferenceToMutable(Parameter p, Type t)
 {
     if (p.isReference())
@@ -2561,6 +2584,7 @@ private void addMaybe(VarDeclaration va, VarDeclaration v)
 }
 
 // `setUnsafePreview` partially evaluated for dip1000
+public
 bool setUnsafeDIP1000(Scope* sc, bool gag, Loc loc, const(char)* msg,
     RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null)
 {
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index 07cc8d4b7e8..99f65879046 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -40,6 +40,7 @@ import dmd.dsymbol;
 import dmd.dsymbolsem;
 import dmd.dtemplate;
 import dmd.errors;
+import dmd.errorsink;
 import dmd.escape;
 import dmd.expressionsem;
 import dmd.func;
@@ -813,7 +814,7 @@ extern (C++) abstract class Expression : ASTNode
     {
         OutBuffer buf;
         HdrGenState hgs;
-        toCBuffer(this, &buf, &hgs);
+        toCBuffer(this, buf, hgs);
         return buf.extractChars();
     }
 
@@ -1186,7 +1187,7 @@ extern (C++) abstract class Expression : ASTNode
         return checkValue();
     }
 
-    extern (D) final bool checkArithmetic()
+    extern (D) final bool checkArithmetic(EXP op)
     {
         if (op == EXP.error)
             return true;
@@ -1194,7 +1195,11 @@ extern (C++) abstract class Expression : ASTNode
             return true;
         if (!type.isintegral() && !type.isfloating())
         {
-            error("`%s` is not of arithmetic type, it is a `%s`", toChars(), type.toChars());
+            // unary aggregate ops error here
+            const char* msg = type.isAggregate() ?
+                "operator `%s` is not defined for `%s` of type `%s`" :
+                "illegal operator `%s` for `%s` of type `%s`";
+            error(msg, EXPtoString(op).ptr, toChars(), type.toChars());
             return true;
         }
         return checkValue();
@@ -3250,6 +3255,8 @@ extern (C++) final class AssocArrayLiteralExp : Expression
 
     Expressions* keys;
     Expressions* values;
+    /// Lower to core.internal.newaa for static initializaton
+    Expression lowering;
 
     extern (D) this(const ref Loc loc, Expressions* keys, Expressions* values) @safe
     {
@@ -4036,13 +4043,11 @@ extern (C++) final class FuncExp : Expression
             return new FuncExp(loc, fd);
     }
 
-    extern (D) MATCH matchType(Type to, Scope* sc, FuncExp* presult, int flag = 0)
+    extern (D) MATCH matchType(Type to, Scope* sc, FuncExp* presult, ErrorSink eSink)
     {
-
-        static MATCH cannotInfer(Expression e, Type to, int flag)
+        MATCH cannotInfer()
         {
-            if (!flag)
-                e.error("cannot infer parameter types from `%s`", to.toChars());
+            eSink.error(loc, "cannot infer parameter types from `%s`", to.toChars());
             return MATCH.nomatch;
         }
 
@@ -4055,8 +4060,7 @@ extern (C++) final class FuncExp : Expression
         {
             if (tok == TOK.function_)
             {
-                if (!flag)
-                    error("cannot match function literal to delegate type `%s`", to.toChars());
+                eSink.error(loc, "cannot match function literal to delegate type `%s`", to.toChars());
                 return MATCH.nomatch;
             }
             tof = cast(TypeFunction)to.nextOf();
@@ -4065,8 +4069,7 @@ extern (C++) final class FuncExp : Expression
         {
             if (tok == TOK.delegate_)
             {
-                if (!flag)
-                    error("cannot match delegate literal to function pointer type `%s`", to.toChars());
+                eSink.error(loc, "cannot match delegate literal to function pointer type `%s`", to.toChars());
                 return MATCH.nomatch;
             }
         }
@@ -4075,7 +4078,7 @@ extern (C++) final class FuncExp : Expression
         {
             if (!tof)
             {
-                return cannotInfer(this, to, flag);
+                return cannotInfer();
             }
 
             // Parameter types inference from 'tof'
@@ -4086,7 +4089,7 @@ extern (C++) final class FuncExp : Expression
             const dim = tf.parameterList.length;
 
             if (tof.parameterList.length != dim || tof.parameterList.varargs != tf.parameterList.varargs)
-                return cannotInfer(this, to, flag);
+                return cannotInfer();
 
             auto tiargs = new Objects();
             tiargs.reserve(td.parameters.length);
@@ -4106,7 +4109,7 @@ extern (C++) final class FuncExp : Expression
                 Parameter pto = tof.parameterList[u];
                 Type t = pto.type;
                 if (t.ty == Terror)
-                    return cannotInfer(this, to, flag);
+                    return cannotInfer();
                 tf.parameterList[u].storageClass = tof.parameterList[u].storageClass;
                 tiargs.push(t);
             }
@@ -4124,9 +4127,9 @@ extern (C++) final class FuncExp : Expression
             if (ex.op == EXP.error)
                 return MATCH.nomatch;
             if (auto ef = ex.isFuncExp())
-                return ef.matchType(to, sc, presult, flag);
+                return ef.matchType(to, sc, presult, eSink);
             else
-                return cannotInfer(this, to, flag);
+                return cannotInfer();
         }
 
         if (!tof || !tof.next)
@@ -4198,10 +4201,10 @@ extern (C++) final class FuncExp : Expression
                 (*presult).fd.modifyReturns(sc, tof.next);
             }
         }
-        else if (!flag)
+        else if (!cast(ErrorSinkNull)eSink)
         {
             auto ts = toAutoQualChars(tx, to);
-            error("cannot implicitly convert expression `%s` of type `%s` to `%s`",
+            eSink.error(loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`",
                 toChars(), ts[0], ts[1]);
         }
         return m;
@@ -4674,8 +4677,8 @@ extern (C++) abstract class BinExp : Expression
 
     extern (D) final bool checkArithmeticBin()
     {
-        bool r1 = e1.checkArithmetic();
-        bool r2 = e2.checkArithmetic();
+        bool r1 = e1.checkArithmetic(this.op);
+        bool r2 = e2.checkArithmetic(this.op);
         return (r1 || r2);
     }
 
@@ -7217,7 +7220,7 @@ extern (C++) final class PrettyFuncInitExp : DefaultInitExp
         {
             const funcStr = fd.Dsymbol.toPrettyChars();
             OutBuffer buf;
-            functionToBufferWithIdent(fd.type.isTypeFunction(), &buf, funcStr, fd.isStatic);
+            functionToBufferWithIdent(fd.type.isTypeFunction(), buf, funcStr, fd.isStatic);
             s = buf.extractChars();
         }
         else
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index 1f04c6cb1db..2189757e61f 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -94,7 +94,7 @@ public:
 
     const char *toChars() const override;
     void error(const char *format, ...) const;
-    void warning(const char *format, ...) const;
+    void warning(unsigned flag, const char *format, ...) const;
     void deprecation(const char *format, ...) const;
 
     virtual dinteger_t toInteger();
@@ -446,6 +446,7 @@ public:
     OwnedBy ownedByCtfe;
     Expressions *keys;
     Expressions *values;
+    Expression* lowering;
 
     bool equals(const RootObject * const o) const override;
     AssocArrayLiteralExp *syntaxCopy() override;
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index 69999cbf32a..30382bbc6bb 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -1197,6 +1197,11 @@ private bool haveSameThis(FuncDeclaration outerFunc, FuncDeclaration calledFunc)
     if (thisAd == requiredAd)
         return true;
 
+    // if outerfunc is the member of a nested aggregate, then let
+    // getRightThis take care of this.
+    if (thisAd.isNested())
+        return true;
+
     // outerfunc is the member of a base class that contains calledFunc,
     // then we consider that they have the same this.
     auto cd = requiredAd.isClassDeclaration();
@@ -1206,11 +1211,6 @@ private bool haveSameThis(FuncDeclaration outerFunc, FuncDeclaration calledFunc)
     if (cd.isBaseOf2(thisAd.isClassDeclaration()))
         return true;
 
-    // if outerfunc is the member of a nested aggregate, then let
-    // getRightThis take care of this.
-    if (thisAd.isNested())
-        return true;
-
     return false;
 }
 
@@ -2319,6 +2319,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
             }
             err |= arg.checkValue();
             err |= arg.checkSharedAccess(sc);
+            err |= checkParamArgumentEscape(sc, fd, Id.dotdotdot, null, cast(STC) tf.parameterList.stc, arg, false, false);
             arg = arg.optimize(WANTvalue);
         }
         (*arguments)[i] = arg;
@@ -2331,14 +2332,14 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
     {
         if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp())
         {
-            checkPrintfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list);
+            checkPrintfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list, sc.eSink);
         }
     }
     else if (fd && fd.scanf)
     {
         if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp())
         {
-            checkScanfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list);
+            checkScanfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list, sc.eSink);
         }
     }
     else
@@ -2528,7 +2529,8 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
         auto args = new Parameters(arguments.length - nparams);
         for (size_t i = 0; i < arguments.length - nparams; i++)
         {
-            auto arg = new Parameter(STC.in_, (*arguments)[nparams + i].type, null, null, null);
+            Expression earg = (*arguments)[nparams + i];
+            auto arg = new Parameter(earg.loc, STC.in_, earg.type, null, null, null);
             (*args)[i] = arg;
         }
         auto tup = new TypeTuple(args);
@@ -3889,10 +3891,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     foreach (v; c.fields)
                     {
                         if (v.inuse || v._scope is null || v._init is null ||
-                            v._init.isVoidInitializer())
+                            v._init.isVoidInitializer() || v.semanticRun >= PASS.semantic2done)
                             continue;
                         v.inuse++;
                         v._init = v._init.initializerSemantic(v._scope, v.type, INITinterpret);
+                        import dmd.semantic2 : lowerStaticAAs;
+                        lowerStaticAAs(v, sc);
                         v.inuse--;
                     }
                 }
@@ -4312,7 +4316,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             if (exp.fd.treq) // defer type determination
             {
                 FuncExp fe;
-                if (exp.matchType(exp.fd.treq, sc, &fe) > MATCH.nomatch)
+                if (exp.matchType(exp.fd.treq, sc, &fe, sc.eSink) > MATCH.nomatch)
                     e = fe;
                 else
                     e = ErrorExp.get();
@@ -5275,10 +5279,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             {
                 OutBuffer buf;
                 buf.writeByte('(');
-                argExpTypesToCBuffer(&buf, exp.arguments);
+                argExpTypesToCBuffer(buf, exp.arguments);
                 buf.writeByte(')');
                 if (tthis)
-                    tthis.modToBuffer(&buf);
+                    tthis.modToBuffer(buf);
 
                 //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco);
                 .error(exp.loc, "%s `%s%s` is not callable using argument types `%s`",
@@ -5348,7 +5352,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 {
                     OutBuffer buf;
                     buf.writeByte('(');
-                    argExpTypesToCBuffer(&buf, exp.arguments);
+                    argExpTypesToCBuffer(buf, exp.arguments);
                     buf.writeByte(')');
 
                     //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco);
@@ -5947,7 +5951,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     for (size_t i = 0; i < cd.baseclasses.length; i++)
                     {
                         BaseClass* b = (*cd.baseclasses)[i];
-                        args.push(new Parameter(STC.in_, b.type, null, null, null));
+                        args.push(new Parameter(Loc.initial, STC.in_, b.type, null, null, null));
                     }
                     tded = new TypeTuple(args);
                 }
@@ -5993,7 +5997,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                          */
                         if (e.tok2 == TOK.parameters && arg.defaultArg && arg.defaultArg.op == EXP.error)
                             return setError();
-                        args.push(new Parameter(arg.storageClass, arg.type, (e.tok2 == TOK.parameters) ? arg.ident : null, (e.tok2 == TOK.parameters) ? arg.defaultArg : null, arg.userAttribDecl));
+                        args.push(new Parameter(arg.loc, arg.storageClass, arg.type, (e.tok2 == TOK.parameters) ? arg.ident : null, (e.tok2 == TOK.parameters) ? arg.defaultArg : null, arg.userAttribDecl));
                     }
                     tded = new TypeTuple(args);
                     break;
@@ -7278,7 +7282,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         else if (!exp.e1.type.deco)
         {
             // try to resolve the type
-            exp.e1.type = exp.e1.type.typeSemantic(exp.e1.loc, null);
+            exp.e1.type = exp.e1.type.typeSemantic(exp.e1.loc, sc);
             if (!exp.e1.type.deco)  // still couldn't resolve it
             {
                 if (auto ve = exp.e1.isVarExp())
@@ -7527,7 +7531,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         }
         if (exp.e1.checkNoBool())
             return setError();
-        if (exp.e1.checkArithmetic() ||
+        if (exp.e1.checkArithmetic(exp.op) ||
             exp.e1.checkSharedAccess(sc))
             return setError();
 
@@ -7557,7 +7561,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         }
         if (exp.e1.checkNoBool())
             return setError();
-        if (exp.e1.checkArithmetic())
+        if (exp.e1.checkArithmetic(exp.op))
             return setError();
         if (exp.e1.checkSharedAccess(sc))
             return setError();
@@ -10024,19 +10028,22 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     return setError();
             }
 
-            if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == EXP.assign &&
-                e2x.op != EXP.slice && e2x.op != EXP.assign &&
-                e2x.op != EXP.arrayLiteral && e2x.op != EXP.string_ &&
-                !(e2x.op == EXP.add || e2x.op == EXP.min ||
-                  e2x.op == EXP.mul || e2x.op == EXP.div ||
-                  e2x.op == EXP.mod || e2x.op == EXP.xor ||
-                  e2x.op == EXP.and || e2x.op == EXP.or ||
-                  e2x.op == EXP.pow ||
-                  e2x.op == EXP.tilde || e2x.op == EXP.negate))
+            version (none)
             {
-                const(char)* e1str = exp.e1.toChars();
-                const(char)* e2str = e2x.toChars();
-                exp.warning("explicit element-wise assignment `%s = (%s)[]` is better than `%s = %s`", e1str, e2str, e1str, e2str);
+                if (global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == EXP.assign &&
+                    e2x.op != EXP.slice && e2x.op != EXP.assign &&
+                    e2x.op != EXP.arrayLiteral && e2x.op != EXP.string_ &&
+                    !(e2x.op == EXP.add || e2x.op == EXP.min ||
+                      e2x.op == EXP.mul || e2x.op == EXP.div ||
+                      e2x.op == EXP.mod || e2x.op == EXP.xor ||
+                      e2x.op == EXP.and || e2x.op == EXP.or ||
+                      e2x.op == EXP.pow ||
+                      e2x.op == EXP.tilde || e2x.op == EXP.negate))
+                {
+                    const(char)* e1str = exp.e1.toChars();
+                    const(char)* e2str = e2x.toChars();
+                    exp.warning("explicit element-wise assignment `%s = (%s)[]` is better than `%s = %s`", e1str, e2str, e1str, e2str);
+                }
             }
 
             Type t2n = t2.nextOf();
@@ -10085,17 +10092,20 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         }
         else
         {
-            if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == EXP.assign &&
-                t1.ty == Tarray && t2.ty == Tsarray &&
-                e2x.op != EXP.slice &&
-                t2.implicitConvTo(t1))
+            version (none)
             {
-                // Disallow ar[] = sa (Converted to ar[] = sa[])
-                // Disallow da   = sa (Converted to da   = sa[])
-                const(char)* e1str = exp.e1.toChars();
-                const(char)* e2str = e2x.toChars();
-                const(char)* atypestr = exp.e1.op == EXP.slice ? "element-wise" : "slice";
-                exp.warning("explicit %s assignment `%s = (%s)[]` is better than `%s = %s`", atypestr, e1str, e2str, e1str, e2str);
+                if (global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == EXP.assign &&
+                    t1.ty == Tarray && t2.ty == Tsarray &&
+                    e2x.op != EXP.slice &&
+                    t2.implicitConvTo(t1))
+                {
+                    // Disallow ar[] = sa (Converted to ar[] = sa[])
+                    // Disallow da   = sa (Converted to da   = sa[])
+                    const(char)* e1str = exp.e1.toChars();
+                    const(char)* e2str = e2x.toChars();
+                    const(char)* atypestr = exp.e1.op == EXP.slice ? "element-wise" : "slice";
+                    exp.warning("explicit %s assignment `%s = (%s)[]` is better than `%s = %s`", atypestr, e1str, e2str, e1str, e2str);
+                }
             }
             if (exp.op == EXP.blit)
                 e2x = e2x.castTo(sc, exp.e1.type);
@@ -10785,11 +10795,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         bool err = false;
         if (tb1.ty == Tdelegate || tb1.isPtrToFunction())
         {
-            err |= exp.e1.checkArithmetic() || exp.e1.checkSharedAccess(sc);
+            err |= exp.e1.checkArithmetic(exp.op) || exp.e1.checkSharedAccess(sc);
         }
         if (tb2.ty == Tdelegate || tb2.isPtrToFunction())
         {
-            err |= exp.e2.checkArithmetic() || exp.e2.checkSharedAccess(sc);
+            err |= exp.e2.checkArithmetic(exp.op) || exp.e2.checkSharedAccess(sc);
         }
         if (err)
             return setError();
@@ -10891,11 +10901,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         bool err = false;
         if (t1.ty == Tdelegate || t1.isPtrToFunction())
         {
-            err |= exp.e1.checkArithmetic() || exp.e1.checkSharedAccess(sc);
+            err |= exp.e1.checkArithmetic(exp.op) || exp.e1.checkSharedAccess(sc);
         }
         if (t2.ty == Tdelegate || t2.isPtrToFunction())
         {
-            err |= exp.e2.checkArithmetic() || exp.e2.checkSharedAccess(sc);
+            err |= exp.e2.checkArithmetic(exp.op) || exp.e2.checkSharedAccess(sc);
         }
         if (err)
             return setError();
@@ -11032,7 +11042,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             (exp.e2.isStringExp() && (exp.e1.isIntegerExp() || exp.e1.isStringExp())))
             return exp;
 
-        Identifier hook = global.params.tracegc ? Id._d_arraycatnTXTrace : Id._d_arraycatnTX;
+        bool useTraceGCHook = global.params.tracegc && sc.needsCodegen();
+
+        Identifier hook = useTraceGCHook ? Id._d_arraycatnTXTrace : Id._d_arraycatnTX;
         if (!verifyHookExist(exp.loc, *sc, hook, "concatenating arrays"))
         {
             setError();
@@ -11061,7 +11073,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         }
 
         auto arguments = new Expressions();
-        if (global.params.tracegc)
+        if (useTraceGCHook)
         {
             auto funcname = (sc.callsc && sc.callsc.func) ?
                 sc.callsc.func.toPrettyChars() : sc.func.toPrettyChars();
@@ -11088,7 +11100,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         /* `_d_arraycatnTX` canot be used with `-betterC`, but `CatExp`s may be
          * used with `-betterC`, but only during CTFE.
          */
-        if (!global.params.useGC || !sc.needsCodegen())
+        if (!global.params.useGC)
             return;
 
         if (auto ce = exp.isCatExp())
@@ -12087,8 +12099,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 return setError();
             }
 
-            if (sc.needsCodegen() &&
-                (t1.ty == Tarray || t1.ty == Tsarray) &&
+            if ((t1.ty == Tarray || t1.ty == Tsarray) &&
                 (t2.ty == Tarray || t2.ty == Tsarray))
             {
                 if (!verifyHookExist(exp.loc, *sc, Id.__cmp, "comparing arrays"))
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index 73f1ba786cb..bf7ad7ee8d5 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -173,7 +173,7 @@ public:
             Identifier id = Identifier.generateId("__o");
 
             Statement handler = new PeelStatement(sexception);
-            if (sexception.blockExit(fd, false) & BE.fallthru)
+            if (sexception.blockExit(fd, null) & BE.fallthru)
             {
                 auto ts = new ThrowStatement(Loc.initial, new IdentifierExp(Loc.initial, id));
                 ts.internalThrow = true;
@@ -1311,7 +1311,7 @@ extern (C++) class FuncDeclaration : Declaration
     final const(char)* toFullSignature()
     {
         OutBuffer buf;
-        functionToBufferWithIdent(type.toTypeFunction(), &buf, toChars(), isStatic);
+        functionToBufferWithIdent(type.toTypeFunction(), buf, toChars(), isStatic);
         return buf.extractChars();
     }
 
@@ -2279,8 +2279,11 @@ extern (C++) class FuncDeclaration : Declaration
                                 break LcheckAncestorsOfANestedRef;
                         }
                         a.push(f);
-                        .errorSupplemental(f.loc, "`%s` closes over variable `%s` at %s",
-                            f.toPrettyChars(), v.toChars(), v.loc.toChars());
+                        .errorSupplemental(f.loc, "%s `%s` closes over variable `%s`",
+                            f.kind, f.toPrettyChars(), v.toChars());
+                        if (v.ident != Id.This)
+                            .errorSupplemental(v.loc, "`%s` declared here", v.toChars());
+
                         break LcheckAncestorsOfANestedRef;
                     }
                 }
@@ -2657,7 +2660,7 @@ extern (C++) class FuncDeclaration : Declaration
             auto fparams = new Parameters();
             if (canBuildResultVar())
             {
-                Parameter p = new Parameter(STC.ref_ | STC.const_, f.nextOf(), Id.result, null, null);
+                Parameter p = new Parameter(loc, STC.ref_ | STC.const_, f.nextOf(), Id.result, null, null);
                 fparams.push(p);
             }
             auto fo = cast(TypeFunction)(originalType ? originalType : f);
@@ -3340,14 +3343,14 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
         s = fd = td.funcroot;
 
     OutBuffer tiargsBuf;
-    arrayObjectsToBuffer(&tiargsBuf, tiargs);
+    arrayObjectsToBuffer(tiargsBuf, tiargs);
 
     OutBuffer fargsBuf;
     fargsBuf.writeByte('(');
-    argExpTypesToCBuffer(&fargsBuf, fargs);
+    argExpTypesToCBuffer(fargsBuf, fargs);
     fargsBuf.writeByte(')');
     if (tthis)
-        tthis.modToBuffer(&fargsBuf);
+        tthis.modToBuffer(fargsBuf);
 
     // The call is ambiguous
     if (m.lastf && m.nextf)
@@ -4623,7 +4626,7 @@ bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char)
         {
             if (!gag)
             {
-                if (!sc.isDeprecated() && global.params.obsolete)
+                version (none) // disable obsolete warning
                     warning(loc, msg, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : "");
             }
         }
diff --git a/gcc/d/dmd/globals.d b/gcc/d/dmd/globals.d
index af711a0fd0a..840074e5d8f 100644
--- a/gcc/d/dmd/globals.d
+++ b/gcc/d/dmd/globals.d
@@ -101,6 +101,23 @@ extern(C++) struct Output
     OutBuffer* buffer;  // if this output is buffered, this is the buffer
     int bufferLines;    // number of lines written to the buffer
 }
+
+/// Command line state related to printing usage about other switches
+extern(C++) struct Help
+{
+    bool manual;       // open browser on compiler manual
+    bool usage;        // print usage and exit
+    // print help of switch:
+    bool mcpu;         // -mcpu
+    bool transition;   // -transition
+    bool check;        // -check
+    bool checkAction;  // -checkaction
+    bool revert;       // -revert
+    bool preview;      // -preview
+    bool externStd;    // -extern-std
+    bool hc;           // -HC
+}
+
 /// Put command line switches in here
 extern (C++) struct Param
 {
@@ -124,7 +141,6 @@ extern (C++) struct Param
     bool release;           // build release version
     bool preservePaths;     // true means don't strip path from source file
     DiagnosticReporting warnings = DiagnosticReporting.off;  // how compiler warnings are handled
-    bool obsolete;          // enable warnings about use of obsolete messages
     bool color;             // use ANSI colors in console output
     bool cov;               // generate code coverage data
     ubyte covPercent;       // 0..100 code coverage percentage required
@@ -143,16 +159,7 @@ extern (C++) struct Param
 
     bool showGaggedErrors;  // print gagged errors anyway
     bool printErrorContext;  // print errors with the error context (the error line in the source file)
-    bool manual;            // open browser on compiler manual
-    bool usage;             // print usage and exit
-    bool mcpuUsage;         // print help on -mcpu switch
-    bool transitionUsage;   // print help on -transition switch
-    bool checkUsage;        // print help on -check switch
-    bool checkActionUsage;  // print help on -checkaction switch
-    bool revertUsage;       // print help on -revert switch
-    bool previewUsage;      // print help on -preview switch
-    bool externStdUsage;    // print help on -extern-std switch
-    bool hcUsage;           // print help on -HC switch
+    Help help;
     bool logo;              // print compiler logo
 
     // Options for `-preview=/-revert=`
@@ -258,6 +265,7 @@ extern (C++) struct Global
     Array!(const(char)*)* filePath;     /// Array of char*'s which form the file import lookup path
 
     private enum string _version = import("VERSION");
+    char[26] datetime;      /// string returned by ctime()
     CompileEnv compileEnv;
 
     Param params;           /// command line parameters
@@ -281,6 +289,7 @@ extern (C++) struct Global
     enum recursionLimit = 500; /// number of recursive template expansions before abort
 
     ErrorSink errorSink;       /// where the error messages go
+    ErrorSink errorSinkNull;   /// where the error messages are ignored
 
     extern (C++) FileName function(FileName, ref const Loc, out bool, OutBuffer*) preprocess;
 
@@ -337,6 +346,7 @@ extern (C++) struct Global
     extern (C++) void _init()
     {
         errorSink = new ErrorSinkCompiler;
+        errorSinkNull = new ErrorSinkNull;
 
         this.fileManager = new FileManager();
         version (MARS)
@@ -369,6 +379,7 @@ extern (C++) struct Global
             core.stdc.time.time(&ct);
         const p = ctime(&ct);
         assert(p);
+        datetime[] = p[0 .. 26];
 
         __gshared char[11 + 1] date = 0;        // put in BSS segment
         __gshared char[8  + 1] time = 0;
diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h
index 0ef9eed405c..e24042a4f21 100644
--- a/gcc/d/dmd/globals.h
+++ b/gcc/d/dmd/globals.h
@@ -96,6 +96,22 @@ struct Output
     int bufferLines;    // number of lines written to the buffer
 };
 
+/// Command line state related to printing uasage about other switches
+struct Help
+{
+    d_bool manual;       // open browser on compiler manual
+    d_bool usage;        // print usage and exit
+    // print help of switch:
+    d_bool mcpu;         // -mcpu
+    d_bool transition;   // -transition
+    d_bool check;        // -check
+    d_bool checkAction;  // -checkaction
+    d_bool revert;       // -revert
+    d_bool preview;      // -preview
+    d_bool externStd;    // -extern-std
+    d_bool hc;           // -HC
+};
+
 // Put command line switches in here
 struct Param
 {
@@ -119,7 +135,6 @@ struct Param
     d_bool release;       // build release version
     d_bool preservePaths; // true means don't strip path from source file
     Diagnostic warnings;
-    d_bool obsolete;      // warn about use of obsolete features
     d_bool color;         // use ANSI colors in console output
     d_bool cov;           // generate code coverage data
     unsigned char covPercent;   // 0..100 code coverage percentage required
@@ -136,16 +151,7 @@ struct Param
     CppStdRevision cplusplus;  // version of C++ name mangling to support
     d_bool showGaggedErrors;  // print gagged errors anyway
     d_bool printErrorContext;  // print errors with the error context (the error line in the source file)
-    d_bool manual;            // open browser on compiler manual
-    d_bool usage;             // print usage and exit
-    d_bool mcpuUsage;         // print help on -mcpu switch
-    d_bool transitionUsage;   // print help on -transition switch
-    d_bool checkUsage;        // print help on -check switch
-    d_bool checkActionUsage;  // print help on -checkaction switch
-    d_bool revertUsage;       // print help on -revert switch
-    d_bool previewUsage;      // print help on -preview switch
-    d_bool externStdUsage;    // print help on -extern-std switch
-    d_bool hcUsage;           // print help on -HC switch
+    Help help;
     d_bool logo;              // print logo;
 
     // Options for `-preview=/-revert=`
@@ -265,7 +271,6 @@ struct CompileEnv
     bool previewIn;
     bool ddocOutput;
     bool shortenedMethods;
-    bool obsolete;
 };
 
 struct Global
@@ -277,6 +282,7 @@ struct Global
     Array<const char *> *path;        // Array of char*'s which form the import lookup path
     Array<const char *> *filePath;    // Array of char*'s which form the file import lookup path
 
+    char datetime[26];       /// string returned by ctime()
     CompileEnv compileEnv;
 
     Param params;
@@ -296,6 +302,7 @@ struct Global
 
     FileManager* fileManager;
     ErrorSink* errorSink;       // where the error messages go
+    ErrorSink* errorSinkNull;   // where the error messages disappear
 
     FileName (*preprocess)(FileName, const Loc&, bool&, OutBuffer&);
 
@@ -358,8 +365,8 @@ struct Loc
 {
 private:
     unsigned _linnum;
-    unsigned short _charnum;
-    unsigned short fileIndex;
+    unsigned _charnum;
+    unsigned fileIndex;
 public:
     static void set(bool showColumns, MessageStyle messageStyle);
 
diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d
index 33cbc19c690..b4c8e8b899b 100644
--- a/gcc/d/dmd/hdrgen.d
+++ b/gcc/d/dmd/hdrgen.d
@@ -51,7 +51,6 @@ import dmd.statement;
 import dmd.staticassert;
 import dmd.target;
 import dmd.tokens;
-import dmd.utils;
 import dmd.visitor;
 
 struct HdrGenState
@@ -73,16 +72,20 @@ struct HdrGenState
 
 enum TEST_EMIT_ALL = 0;
 
-extern (C++) void genhdrfile(Module m)
+/****************************************
+ * Generate a header (.di) file for Module m.
+ * Params:
+ *      m = Module to generate header for
+ *      buf = buffer to write the data to
+ */
+extern (C++) void genhdrfile(Module m, ref OutBuffer buf)
 {
-    OutBuffer buf;
     buf.doindent = 1;
     buf.printf("// D import file generated from '%s'", m.srcfile.toChars());
     buf.writenl();
     HdrGenState hgs;
     hgs.hdrgen = true;
-    toCBuffer(m, &buf, &hgs);
-    writeFile(m.loc, m.hdrfile.toString(), buf[]);
+    toCBuffer(m, buf, hgs);
 }
 
 /**
@@ -91,14 +94,14 @@ extern (C++) void genhdrfile(Module m)
  *   buf = buffer to write to.
  *   m = module to visit all members of.
  */
-extern (C++) void moduleToBuffer(OutBuffer* buf, Module m)
+extern (C++) void moduleToBuffer(ref OutBuffer buf, Module m)
 {
     HdrGenState hgs;
     hgs.fullDump = true;
-    toCBuffer(m, buf, &hgs);
+    toCBuffer(m, buf, hgs);
 }
 
-void moduleToBuffer2(Module m, OutBuffer* buf, HdrGenState* hgs)
+void moduleToBuffer2(Module m, ref OutBuffer buf, HdrGenState* hgs)
 {
     if (m.md)
     {
@@ -132,7 +135,7 @@ void moduleToBuffer2(Module m, OutBuffer* buf, HdrGenState* hgs)
     }
 }
 
-private void statementToBuffer(Statement s, OutBuffer* buf, HdrGenState* hgs)
+private void statementToBuffer(Statement s, ref OutBuffer buf, HdrGenState* hgs)
 {
     void visitDefaultCase(Statement s)
     {
@@ -201,8 +204,7 @@ private void statementToBuffer(Statement s, OutBuffer* buf, HdrGenState* hgs)
                 auto d = ds.exp.isDeclarationExp().declaration;
                 if (auto v = d.isVarDeclaration())
                 {
-                    scope ppv = new DsymbolPrettyPrintVisitor(buf, hgs);
-                    ppv.visitVarDecl(v, anywritten);
+                    visitVarDecl(v, anywritten, buf, *hgs);
                 }
                 else
                     d.dsymbolToBuffer(buf, hgs);
@@ -792,9 +794,9 @@ private void statementToBuffer(Statement s, OutBuffer* buf, HdrGenState* hgs)
     visit.VisitStatement(s);
 }
 
-private void dsymbolToBuffer(Dsymbol s, OutBuffer* buf, HdrGenState* hgs)
+private void dsymbolToBuffer(Dsymbol s, ref OutBuffer buf, HdrGenState* hgs)
 {
-    scope v = new DsymbolPrettyPrintVisitor(buf, hgs);
+    scope v = new DsymbolPrettyPrintVisitor(&buf, hgs);
     s.accept(v);
 }
 
@@ -822,13 +824,13 @@ public:
     {
         buf.writestring(s.kind());
         buf.writeByte('(');
-        s.exp.expressionToBuffer(buf, hgs);
+        s.exp.expressionToBuffer(*buf, hgs);
         if (s.msgs)
         {
             foreach (m; (*s.msgs)[])
             {
                 buf.writestring(", ");
-                m.expressionToBuffer(buf, hgs);
+                m.expressionToBuffer(*buf, hgs);
             }
         }
         buf.writestring(");");
@@ -860,13 +862,13 @@ public:
     override void visit(EnumMember em)
     {
         if (em.type)
-            typeToBuffer(em.type, em.ident, buf, hgs);
+            typeToBuffer(em.type, em.ident, *buf, hgs);
         else
             buf.writestring(em.ident.toString());
         if (em.value)
         {
             buf.writestring(" = ");
-            em.value.expressionToBuffer(buf, hgs);
+            em.value.expressionToBuffer(*buf, hgs);
         }
     }
 
@@ -916,7 +918,7 @@ public:
         bool hasSTC;
         if (auto stcd = d.isStorageClassDeclaration)
         {
-            hasSTC = stcToBuffer(buf, stcd.stc);
+            hasSTC = stcToBuffer(*buf, stcd.stc);
         }
 
         if (!d.decl)
@@ -959,7 +961,7 @@ public:
     override void visit(DeprecatedDeclaration d)
     {
         buf.writestring("deprecated(");
-        d.msg.expressionToBuffer(buf, hgs);
+        d.msg.expressionToBuffer(*buf, hgs);
         buf.writestring(") ");
         visit(cast(AttribDeclaration)d);
     }
@@ -994,7 +996,7 @@ public:
 
     override void visit(VisibilityDeclaration d)
     {
-        visibilityToBuffer(buf, d.visibility);
+        visibilityToBuffer(*buf, d.visibility);
         AttribDeclaration ad = cast(AttribDeclaration)d;
         if (ad.decl.length <= 1)
             buf.writeByte(' ');
@@ -1047,7 +1049,7 @@ public:
         if (d.args && d.args.length)
         {
             buf.writestring(", ");
-            argsToBuffer(d.args, buf, hgs);
+            argsToBuffer(d.args, *buf, hgs);
         }
 
         buf.writeByte(')');
@@ -1065,7 +1067,7 @@ public:
 
     override void visit(ConditionalDeclaration d)
     {
-        d.condition.conditionToBuffer(buf, hgs);
+        d.condition.conditionToBuffer(*buf, hgs);
         if (d.decl || d.elsedecl)
         {
             buf.writenl();
@@ -1108,15 +1110,15 @@ public:
             {
                 if (i)
                     buf.writestring(", ");
-                if (stcToBuffer(buf, p.storageClass))
+                if (stcToBuffer(*buf, p.storageClass))
                     buf.writeByte(' ');
                 if (p.type)
-                    typeToBuffer(p.type, p.ident, buf, hgs);
+                    typeToBuffer(p.type, p.ident, *buf, hgs);
                 else
                     buf.writestring(p.ident.toString());
             }
             buf.writestring("; ");
-            s.aggr.expressionToBuffer(buf, hgs);
+            s.aggr.expressionToBuffer(*buf, hgs);
             buf.writeByte(')');
             buf.writenl();
         }
@@ -1128,13 +1130,13 @@ public:
             buf.writestring(Token.toString(s.op));
             buf.writestring(" (");
             if (s.prm.type)
-                typeToBuffer(s.prm.type, s.prm.ident, buf, hgs);
+                typeToBuffer(s.prm.type, s.prm.ident, *buf, hgs);
             else
                 buf.writestring(s.prm.ident.toString());
             buf.writestring("; ");
-            s.lwr.expressionToBuffer(buf, hgs);
+            s.lwr.expressionToBuffer(*buf, hgs);
             buf.writestring(" .. ");
-            s.upr.expressionToBuffer(buf, hgs);
+            s.upr.expressionToBuffer(*buf, hgs);
             buf.writeByte(')');
             buf.writenl();
         }
@@ -1162,7 +1164,7 @@ public:
     override void visit(MixinDeclaration d)
     {
         buf.writestring("mixin(");
-        argsToBuffer(d.exps, buf, hgs, null);
+        argsToBuffer(d.exps, *buf, hgs, null);
         buf.writestring(");");
         buf.writenl();
     }
@@ -1170,7 +1172,7 @@ public:
     override void visit(UserAttributeDeclaration d)
     {
         buf.writestring("@(");
-        argsToBuffer(d.atts, buf, hgs);
+        argsToBuffer(d.atts, *buf, hgs);
         buf.writeByte(')');
         visit(cast(AttribDeclaration)d);
     }
@@ -1221,9 +1223,9 @@ public:
         if (FuncDeclaration fd = onemember.isFuncDeclaration())
         {
             assert(fd.type);
-            if (stcToBuffer(buf, fd.storage_class))
+            if (stcToBuffer(*buf, fd.storage_class))
                 buf.writeByte(' ');
-            functionToBufferFull(cast(TypeFunction)fd.type, buf, d.ident, hgs, d);
+            functionToBufferFull(cast(TypeFunction)fd.type, *buf, d.ident, hgs, d);
             visitTemplateConstraint(d.constraint);
             hgs.tpltMember++;
             bodyToBuffer(fd);
@@ -1262,10 +1264,10 @@ public:
         {
             if (d.constraint)
                 return false;
-            if (stcToBuffer(buf, vd.storage_class))
+            if (stcToBuffer(*buf, vd.storage_class))
                 buf.writeByte(' ');
             if (vd.type)
-                typeToBuffer(vd.type, vd.ident, buf, hgs);
+                typeToBuffer(vd.type, vd.ident, *buf, hgs);
             else
                 buf.writestring(vd.ident.toString());
             buf.writeByte('(');
@@ -1276,9 +1278,9 @@ public:
                 buf.writestring(" = ");
                 ExpInitializer ie = vd._init.isExpInitializer();
                 if (ie && (ie.exp.op == EXP.construct || ie.exp.op == EXP.blit))
-                    (cast(AssignExp)ie.exp).e2.expressionToBuffer(buf, hgs);
+                    (cast(AssignExp)ie.exp).e2.expressionToBuffer(*buf, hgs);
                 else
-                    vd._init.initializerToBuffer(buf, hgs);
+                    vd._init.initializerToBuffer(*buf, hgs);
             }
             buf.writeByte(';');
             buf.writenl();
@@ -1295,7 +1297,7 @@ public:
         {
             if (i)
                 buf.writestring(", ");
-            p.templateParameterToBuffer(buf, hgs);
+            p.templateParameterToBuffer(*buf, hgs);
         }
     }
 
@@ -1304,27 +1306,27 @@ public:
         if (!constraint)
             return;
         buf.writestring(" if (");
-        constraint.expressionToBuffer(buf, hgs);
+        constraint.expressionToBuffer(*buf, hgs);
         buf.writeByte(')');
     }
 
     override void visit(TemplateInstance ti)
     {
         buf.writestring(ti.name.toChars());
-        tiargsToBuffer(ti, buf, hgs);
+        tiargsToBuffer(ti, *buf, hgs);
 
         if (hgs.fullDump)
         {
             buf.writenl();
-            dumpTemplateInstance(ti, buf, hgs);
+            dumpTemplateInstance(ti, *buf, hgs);
         }
     }
 
     override void visit(TemplateMixin tm)
     {
         buf.writestring("mixin ");
-        typeToBuffer(tm.tqual, null, buf, hgs);
-        tiargsToBuffer(tm, buf, hgs);
+        typeToBuffer(tm.tqual, null, *buf, hgs);
+        tiargsToBuffer(tm, *buf, hgs);
         if (tm.ident && memcmp(tm.ident.toChars(), cast(const(char)*)"__mixin", 7) != 0)
         {
             buf.writeByte(' ');
@@ -1333,7 +1335,7 @@ public:
         buf.writeByte(';');
         buf.writenl();
         if (hgs.fullDump)
-            dumpTemplateInstance(tm, buf, hgs);
+            dumpTemplateInstance(tm, *buf, hgs);
     }
 
     override void visit(EnumDeclaration d)
@@ -1349,7 +1351,7 @@ public:
         if (d.memtype)
         {
             buf.writestring(" : ");
-            typeToBuffer(d.memtype, null, buf, hgs);
+            typeToBuffer(d.memtype, null, *buf, hgs);
         }
         if (!d.members)
         {
@@ -1452,7 +1454,7 @@ public:
         {
             if (i)
                 buf.writestring(", ");
-            typeToBuffer(b.type, null, buf, hgs);
+            typeToBuffer(b.type, null, *buf, hgs);
         }
     }
 
@@ -1465,7 +1467,7 @@ public:
         {
             buf.writestring(d.ident.toString());
             buf.writestring(" = ");
-            if (stcToBuffer(buf, d.storage_class))
+            if (stcToBuffer(*buf, d.storage_class))
                 buf.writeByte(' ');
             /*
                 https://issues.dlang.org/show_bug.cgi?id=23223
@@ -1484,18 +1486,18 @@ public:
         }
         else if (d.type.ty == Tfunction)
         {
-            if (stcToBuffer(buf, d.storage_class))
+            if (stcToBuffer(*buf, d.storage_class))
                 buf.writeByte(' ');
-            typeToBuffer(d.type, d.ident, buf, hgs);
+            typeToBuffer(d.type, d.ident, *buf, hgs);
         }
         else if (d.ident)
         {
             hgs.declstring = (d.ident == Id.string || d.ident == Id.wstring || d.ident == Id.dstring);
             buf.writestring(d.ident.toString());
             buf.writestring(" = ");
-            if (stcToBuffer(buf, d.storage_class))
+            if (stcToBuffer(*buf, d.storage_class))
                 buf.writeByte(' ');
-            typeToBuffer(d.type, null, buf, hgs);
+            typeToBuffer(d.type, null, *buf, hgs);
             hgs.declstring = false;
         }
         buf.writeByte(';');
@@ -1509,7 +1511,7 @@ public:
         if (d.aliassym)
             d.aliassym.accept(this);
         else // d.type
-            typeToBuffer(d.type, null, buf, hgs);
+            typeToBuffer(d.type, null, *buf, hgs);
         buf.writeByte(';');
         buf.writenl();
     }
@@ -1518,69 +1520,18 @@ public:
     {
         if (d.storage_class & STC.local)
             return;
-        visitVarDecl(d, false);
+        visitVarDecl(d, false, *buf, *hgs);
         buf.writeByte(';');
         buf.writenl();
     }
 
-    void visitVarDecl(VarDeclaration v, bool anywritten)
-    {
-        const bool isextern = hgs.hdrgen &&
-            !hgs.insideFuncBody &&
-            !hgs.tpltMember &&
-            !hgs.insideAggregate &&
-            !(v.storage_class & STC.manifest);
-
-        void vinit(VarDeclaration v)
-        {
-            auto ie = v._init.isExpInitializer();
-            if (ie && (ie.exp.op == EXP.construct || ie.exp.op == EXP.blit))
-                (cast(AssignExp)ie.exp).e2.expressionToBuffer(buf, hgs);
-            else
-                v._init.initializerToBuffer(buf, hgs);
-        }
-
-        if (anywritten)
-        {
-            buf.writestring(", ");
-            buf.writestring(v.ident.toString());
-        }
-        else
-        {
-            const bool useTypeof = isextern && v._init && !v.type;
-            auto stc = v.storage_class;
-            if (isextern)
-                stc |= STC.extern_;
-            if (useTypeof)
-                stc &= ~STC.auto_;
-            if (stcToBuffer(buf, stc))
-                buf.writeByte(' ');
-            if (v.type)
-                typeToBuffer(v.type, v.ident, buf, hgs);
-            else if (useTypeof)
-            {
-                buf.writestring("typeof(");
-                vinit(v);
-                buf.writestring(") ");
-                buf.writestring(v.ident.toString());
-            }
-            else
-                buf.writestring(v.ident.toString());
-        }
-        if (v._init && !isextern)
-        {
-            buf.writestring(" = ");
-            vinit(v);
-        }
-    }
-
     override void visit(FuncDeclaration f)
     {
         //printf("FuncDeclaration::toCBuffer() '%s'\n", f.toChars());
-        if (stcToBuffer(buf, f.storage_class))
+        if (stcToBuffer(*buf, f.storage_class))
             buf.writeByte(' ');
         auto tf = cast(TypeFunction)f.type;
-        typeToBuffer(tf, f.ident, buf, hgs);
+        typeToBuffer(tf, f.ident, *buf, hgs);
 
         if (hgs.hdrgen)
         {
@@ -1627,7 +1578,7 @@ public:
                 {
                     assert(es.exp && es.exp.op == EXP.assert_);
                     buf.writestring(" (");
-                    (cast(AssertExp)es.exp).e1.expressionToBuffer(buf, hgs);
+                    (cast(AssertExp)es.exp).e1.expressionToBuffer(*buf, hgs);
                     buf.writeByte(')');
                     buf.writenl();
                     requireDo = false;
@@ -1635,7 +1586,7 @@ public:
                 else
                 {
                     buf.writenl();
-                    frequire.statementToBuffer(buf, hgs);
+                    frequire.statementToBuffer(*buf, hgs);
                     requireDo = true;
                 }
             }
@@ -1655,7 +1606,7 @@ public:
                         buf.writestring(fensure.id.toString());
                     }
                     buf.writestring("; ");
-                    (cast(AssertExp)es.exp).e1.expressionToBuffer(buf, hgs);
+                    (cast(AssertExp)es.exp).e1.expressionToBuffer(*buf, hgs);
                     buf.writeByte(')');
                     buf.writenl();
                     requireDo = false;
@@ -1669,7 +1620,7 @@ public:
                         buf.writeByte(')');
                     }
                     buf.writenl();
-                    fensure.ensure.statementToBuffer(buf, hgs);
+                    fensure.ensure.statementToBuffer(*buf, hgs);
                     requireDo = true;
                 }
             }
@@ -1717,7 +1668,7 @@ public:
         buf.writeByte('{');
         buf.writenl();
         buf.level++;
-        f.fbody.statementToBuffer(buf, hgs);
+        f.fbody.statementToBuffer(*buf, hgs);
         buf.level--;
         buf.writeByte('}');
         buf.writenl();
@@ -1740,8 +1691,8 @@ public:
         TypeFunction tf = cast(TypeFunction)f.type;
 
         if (!f.inferRetType && tf.next)
-            typeToBuffer(tf.next, null, buf, hgs);
-        parametersToBuffer(tf.parameterList, buf, hgs);
+            typeToBuffer(tf.next, null, *buf, hgs);
+        parametersToBuffer(tf.parameterList, *buf, hgs);
 
         // https://issues.dlang.org/show_bug.cgi?id=20074
         void printAttribute(string str)
@@ -1764,7 +1715,7 @@ public:
         if (rs && rs.exp)
         {
             buf.writestring(" => ");
-            rs.exp.expressionToBuffer(buf, hgs);
+            rs.exp.expressionToBuffer(*buf, hgs);
         }
         else
         {
@@ -1776,7 +1727,7 @@ public:
 
     override void visit(PostBlitDeclaration d)
     {
-        if (stcToBuffer(buf, d.storage_class))
+        if (stcToBuffer(*buf, d.storage_class))
             buf.writeByte(' ');
         buf.writestring("this(this)");
         bodyToBuffer(d);
@@ -1784,7 +1735,7 @@ public:
 
     override void visit(DtorDeclaration d)
     {
-        if (stcToBuffer(buf, d.storage_class))
+        if (stcToBuffer(*buf, d.storage_class))
             buf.writeByte(' ');
         buf.writestring("~this()");
         bodyToBuffer(d);
@@ -1792,7 +1743,7 @@ public:
 
     override void visit(StaticCtorDeclaration d)
     {
-        if (stcToBuffer(buf, d.storage_class & ~STC.static_))
+        if (stcToBuffer(*buf, d.storage_class & ~STC.static_))
             buf.writeByte(' ');
         if (d.isSharedStaticCtorDeclaration())
             buf.writestring("shared ");
@@ -1808,7 +1759,7 @@ public:
 
     override void visit(StaticDtorDeclaration d)
     {
-        if (stcToBuffer(buf, d.storage_class & ~STC.static_))
+        if (stcToBuffer(*buf, d.storage_class & ~STC.static_))
             buf.writeByte(' ');
         if (d.isSharedStaticDtorDeclaration())
             buf.writestring("shared ");
@@ -1826,14 +1777,14 @@ public:
     {
         if (hgs.hdrgen)
             return;
-        if (stcToBuffer(buf, d.storage_class))
+        if (stcToBuffer(*buf, d.storage_class))
             buf.writeByte(' ');
         buf.writestring("invariant");
         if(auto es = d.fbody.isExpStatement())
         {
             assert(es.exp && es.exp.op == EXP.assert_);
             buf.writestring(" (");
-            (cast(AssertExp)es.exp).e1.expressionToBuffer(buf, hgs);
+            (cast(AssertExp)es.exp).e1.expressionToBuffer(*buf, hgs);
             buf.writestring(");");
             buf.writenl();
         }
@@ -1847,7 +1798,7 @@ public:
     {
         if (hgs.hdrgen)
             return;
-        if (stcToBuffer(buf, d.storage_class))
+        if (stcToBuffer(*buf, d.storage_class))
             buf.writeByte(' ');
         buf.writestring("unittest");
         bodyToBuffer(d);
@@ -1855,33 +1806,88 @@ public:
 
     override void visit(BitFieldDeclaration d)
     {
-        if (stcToBuffer(buf, d.storage_class))
+        if (stcToBuffer(*buf, d.storage_class))
             buf.writeByte(' ');
         Identifier id = d.isAnonymous() ? null : d.ident;
-        typeToBuffer(d.type, id, buf, hgs);
+        typeToBuffer(d.type, id, *buf, hgs);
         buf.writestring(" : ");
-        d.width.expressionToBuffer(buf, hgs);
+        d.width.expressionToBuffer(*buf, hgs);
         buf.writeByte(';');
         buf.writenl();
     }
 
     override void visit(NewDeclaration d)
     {
-        if (stcToBuffer(buf, d.storage_class & ~STC.static_))
+        if (stcToBuffer(*buf, d.storage_class & ~STC.static_))
             buf.writeByte(' ');
         buf.writestring("new();");
     }
 
     override void visit(Module m)
     {
-        moduleToBuffer2(m, buf, hgs);
+        moduleToBuffer2(m, *buf, hgs);
+    }
+}
+
+/*******************************************
+ * Pretty-print a VarDeclaration to buf.
+ */
+private void visitVarDecl(VarDeclaration v, bool anywritten, ref OutBuffer buf, ref HdrGenState hgs)
+{
+    const bool isextern = hgs.hdrgen &&
+        !hgs.insideFuncBody &&
+        !hgs.tpltMember &&
+        !hgs.insideAggregate &&
+        !(v.storage_class & STC.manifest);
+
+    void vinit(VarDeclaration v)
+    {
+        auto ie = v._init.isExpInitializer();
+        if (ie && (ie.exp.op == EXP.construct || ie.exp.op == EXP.blit))
+            (cast(AssignExp)ie.exp).e2.expressionToBuffer(buf, &hgs);
+        else
+            v._init.initializerToBuffer(buf, &hgs);
+    }
+
+    if (anywritten)
+    {
+        buf.writestring(", ");
+        buf.writestring(v.ident.toString());
+    }
+    else
+    {
+        const bool useTypeof = isextern && v._init && !v.type;
+        auto stc = v.storage_class;
+        if (isextern)
+            stc |= STC.extern_;
+        if (useTypeof)
+            stc &= ~STC.auto_;
+        if (stcToBuffer(buf, stc))
+            buf.writeByte(' ');
+        if (v.type)
+            typeToBuffer(v.type, v.ident, buf, &hgs);
+        else if (useTypeof)
+        {
+            buf.writestring("typeof(");
+            vinit(v);
+            buf.writestring(") ");
+            buf.writestring(v.ident.toString());
+        }
+        else
+            buf.writestring(v.ident.toString());
+    }
+    if (v._init && !isextern)
+    {
+        buf.writestring(" = ");
+        vinit(v);
     }
 }
 
+
 /*********************************************
  * Print expression to buffer.
  */
-private void expressionPrettyPrint(Expression e, OutBuffer* buf, HdrGenState* hgs)
+private void expressionPrettyPrint(Expression e, ref OutBuffer buf, HdrGenState* hgs)
 {
     void visit(Expression e)
     {
@@ -1922,7 +1928,7 @@ private void expressionPrettyPrint(Expression e, OutBuffer* buf, HdrGenState* hg
             case Tdchar:
                 {
                     const o = buf.length;
-                    writeSingleCharLiteral(*buf, cast(dchar) v);
+                    writeSingleCharLiteral(buf, cast(dchar) v);
                     if (hgs.ddoc)
                         escapeDdocString(buf, o);
                     break;
@@ -2064,7 +2070,7 @@ private void expressionPrettyPrint(Expression e, OutBuffer* buf, HdrGenState* hg
         const o = buf.length;
         foreach (i; 0 .. e.len)
         {
-            writeCharLiteral(*buf, e.getCodeUnit(i));
+            writeCharLiteral(buf, e.getCodeUnit(i));
         }
         if (hgs.ddoc)
             escapeDdocString(buf, o);
@@ -2251,8 +2257,7 @@ private void expressionPrettyPrint(Expression e, OutBuffer* buf, HdrGenState* hg
             //   which isn't correct as regular D code.
                 buf.writeByte('(');
 
-                scope v = new DsymbolPrettyPrintVisitor(buf, hgs);
-                v.visitVarDecl(var, false);
+                visitVarDecl(var, false, buf, *hgs);
 
                 buf.writeByte(';');
                 buf.writeByte(')');
@@ -2308,7 +2313,7 @@ private void expressionPrettyPrint(Expression e, OutBuffer* buf, HdrGenState* hg
         if (e.parameters && e.parameters.length)
         {
             buf.writestring(", ");
-            scope v = new DsymbolPrettyPrintVisitor(buf, hgs);
+            scope v = new DsymbolPrettyPrintVisitor(&buf, hgs);
             v.visitTemplateParameters(e.parameters);
         }
         buf.writeByte(')');
@@ -2717,7 +2722,7 @@ private void expressionPrettyPrint(Expression e, OutBuffer* buf, HdrGenState* hg
  *   allowHex = whether hex floating point literals may be used
  *              for greater accuracy
  */
-void floatToBuffer(Type type, const real_t value, OutBuffer* buf, const bool allowHex)
+void floatToBuffer(Type type, const real_t value, ref OutBuffer buf, const bool allowHex)
 {
     /** sizeof(value)*3 is because each byte of mantissa is max
         of 256 (3 characters). The string will be "-M.MMMMe-4932".
@@ -2762,9 +2767,9 @@ void floatToBuffer(Type type, const real_t value, OutBuffer* buf, const bool all
     }
 }
 
-private void templateParameterToBuffer(TemplateParameter tp, OutBuffer* buf, HdrGenState* hgs)
+private void templateParameterToBuffer(TemplateParameter tp, ref OutBuffer buf, HdrGenState* hgs)
 {
-    scope v = new TemplateParameterPrettyPrintVisitor(buf, hgs);
+    scope v = new TemplateParameterPrettyPrintVisitor(&buf, hgs);
     tp.accept(v);
 }
 
@@ -2787,12 +2792,12 @@ public:
         if (tp.specType)
         {
             buf.writestring(" : ");
-            typeToBuffer(tp.specType, null, buf, hgs);
+            typeToBuffer(tp.specType, null, *buf, hgs);
         }
         if (tp.defaultType)
         {
             buf.writestring(" = ");
-            typeToBuffer(tp.defaultType, null, buf, hgs);
+            typeToBuffer(tp.defaultType, null, *buf, hgs);
         }
     }
 
@@ -2806,33 +2811,33 @@ public:
     {
         buf.writestring("alias ");
         if (tp.specType)
-            typeToBuffer(tp.specType, tp.ident, buf, hgs);
+            typeToBuffer(tp.specType, tp.ident, *buf, hgs);
         else
             buf.writestring(tp.ident.toString());
         if (tp.specAlias)
         {
             buf.writestring(" : ");
-            objectToBuffer(tp.specAlias, buf, hgs);
+            objectToBuffer(tp.specAlias, *buf, hgs);
         }
         if (tp.defaultAlias)
         {
             buf.writestring(" = ");
-            objectToBuffer(tp.defaultAlias, buf, hgs);
+            objectToBuffer(tp.defaultAlias, *buf, hgs);
         }
     }
 
     override void visit(TemplateValueParameter tp)
     {
-        typeToBuffer(tp.valType, tp.ident, buf, hgs);
+        typeToBuffer(tp.valType, tp.ident, *buf, hgs);
         if (tp.specValue)
         {
             buf.writestring(" : ");
-            tp.specValue.expressionToBuffer(buf, hgs);
+            tp.specValue.expressionToBuffer(*buf, hgs);
         }
         if (tp.defaultValue)
         {
             buf.writestring(" = ");
-            tp.defaultValue.expressionToBuffer(buf, hgs);
+            tp.defaultValue.expressionToBuffer(*buf, hgs);
         }
     }
 
@@ -2843,9 +2848,9 @@ public:
     }
 }
 
-private void conditionToBuffer(Condition c, OutBuffer* buf, HdrGenState* hgs)
+private void conditionToBuffer(Condition c, ref OutBuffer buf, HdrGenState* hgs)
 {
-    scope v = new ConditionPrettyPrintVisitor(buf, hgs);
+    scope v = new ConditionPrettyPrintVisitor(&buf, hgs);
     c.accept(v);
 }
 
@@ -2885,42 +2890,42 @@ public:
     override void visit(StaticIfCondition c)
     {
         buf.writestring("static if (");
-        c.exp.expressionToBuffer(buf, hgs);
+        c.exp.expressionToBuffer(*buf, hgs);
         buf.writeByte(')');
     }
 }
 
-void toCBuffer(const Statement s, OutBuffer* buf, HdrGenState* hgs)
+void toCBuffer(const Statement s, ref OutBuffer buf, ref HdrGenState hgs)
 {
-    (cast()s).statementToBuffer(buf, hgs);
+    (cast()s).statementToBuffer(buf, &hgs);
 }
 
-void toCBuffer(const Type t, OutBuffer* buf, const Identifier ident, HdrGenState* hgs)
+void toCBuffer(const Type t, ref OutBuffer buf, const Identifier ident, ref HdrGenState hgs)
 {
-    typeToBuffer(cast() t, ident, buf, hgs);
+    typeToBuffer(cast() t, ident, buf, &hgs);
 }
 
-void toCBuffer(Dsymbol s, OutBuffer* buf, HdrGenState* hgs)
+void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs)
 {
-    scope v = new DsymbolPrettyPrintVisitor(buf, hgs);
+    scope v = new DsymbolPrettyPrintVisitor(&buf, &hgs);
     s.accept(v);
 }
 
 // used from TemplateInstance::toChars() and TemplateMixin::toChars()
-void toCBufferInstance(const TemplateInstance ti, OutBuffer* buf, bool qualifyTypes = false)
+void toCBufferInstance(const TemplateInstance ti, ref OutBuffer buf, bool qualifyTypes = false)
 {
     HdrGenState hgs;
     hgs.fullQual = qualifyTypes;
-    scope v = new DsymbolPrettyPrintVisitor(buf, &hgs);
+    scope v = new DsymbolPrettyPrintVisitor(&buf, &hgs);
     v.visit(cast() ti);
 }
 
-void toCBuffer(const Initializer iz, OutBuffer* buf, HdrGenState* hgs)
+void toCBuffer(const Initializer iz, ref OutBuffer buf, ref HdrGenState hgs)
 {
-    initializerToBuffer(cast() iz, buf, hgs);
+    initializerToBuffer(cast() iz, buf, &hgs);
 }
 
-bool stcToBuffer(OutBuffer* buf, StorageClass stc) @safe
+bool stcToBuffer(ref OutBuffer buf, StorageClass stc) @safe
 {
     //printf("stc: %llx\n", stc);
     bool result = false;
@@ -3039,7 +3044,7 @@ string stcToString(ref StorageClass stc) @safe
     return null;
 }
 
-private void linkageToBuffer(OutBuffer* buf, LINK linkage) @safe
+private void linkageToBuffer(ref OutBuffer buf, LINK linkage) @safe
 {
     const s = linkageToString(linkage);
     if (s.length)
@@ -3077,7 +3082,7 @@ string linkageToString(LINK linkage) pure nothrow @safe
     }
 }
 
-void visibilityToBuffer(OutBuffer* buf, Visibility vis)
+void visibilityToBuffer(ref OutBuffer buf, Visibility vis)
 {
     buf.writestring(visibilityToString(vis.kind));
     if (vis.kind == Visibility.Kind.package_ && vis.pkg)
@@ -3121,28 +3126,28 @@ extern (D) string visibilityToString(Visibility.Kind kind) nothrow pure @safe
 }
 
 // Print the full function signature with correct ident, attributes and template args
-void functionToBufferFull(TypeFunction tf, OutBuffer* buf, const Identifier ident, HdrGenState* hgs, TemplateDeclaration td)
+void functionToBufferFull(TypeFunction tf, ref OutBuffer buf, const Identifier ident, HdrGenState* hgs, TemplateDeclaration td)
 {
     //printf("TypeFunction::toCBuffer() this = %p\n", this);
     visitFuncIdentWithPrefix(tf, ident, td, buf, hgs);
 }
 
 // ident is inserted before the argument list and will be "function" or "delegate" for a type
-void functionToBufferWithIdent(TypeFunction tf, OutBuffer* buf, const(char)* ident, bool isStatic)
+void functionToBufferWithIdent(TypeFunction tf, ref OutBuffer buf, const(char)* ident, bool isStatic)
 {
     HdrGenState hgs;
     visitFuncIdentWithPostfix(tf, ident.toDString(), buf, &hgs, isStatic);
 }
 
-void toCBuffer(const Expression e, OutBuffer* buf, HdrGenState* hgs)
+void toCBuffer(const Expression e, ref OutBuffer buf, ref HdrGenState hgs)
 {
-    expressionPrettyPrint(cast()e, buf, hgs);
+    expressionPrettyPrint(cast()e, buf, &hgs);
 }
 
 /**************************************************
  * Write out argument types to buf.
  */
-void argExpTypesToCBuffer(OutBuffer* buf, Expressions* arguments)
+void argExpTypesToCBuffer(ref OutBuffer buf, Expressions* arguments)
 {
     if (!arguments || !arguments.length)
         return;
@@ -3155,13 +3160,13 @@ void argExpTypesToCBuffer(OutBuffer* buf, Expressions* arguments)
     }
 }
 
-void toCBuffer(const TemplateParameter tp, OutBuffer* buf, HdrGenState* hgs)
+void toCBuffer(const TemplateParameter tp, ref OutBuffer buf, ref HdrGenState hgs)
 {
-    scope v = new TemplateParameterPrettyPrintVisitor(buf, hgs);
+    scope v = new TemplateParameterPrettyPrintVisitor(&buf, &hgs);
     (cast() tp).accept(v);
 }
 
-void arrayObjectsToBuffer(OutBuffer* buf, Objects* objects)
+void arrayObjectsToBuffer(ref OutBuffer buf, Objects* objects)
 {
     if (!objects || !objects.length)
         return;
@@ -3184,7 +3189,7 @@ extern (C++) const(char)* parametersTypeToChars(ParameterList pl)
 {
     OutBuffer buf;
     HdrGenState hgs;
-    parametersToBuffer(pl, &buf, &hgs);
+    parametersToBuffer(pl, buf, &hgs);
     return buf.extractChars();
 }
 
@@ -3202,7 +3207,7 @@ const(char)* parameterToChars(Parameter parameter, TypeFunction tf, bool fullQua
     HdrGenState hgs;
     hgs.fullQual = fullQual;
 
-    parameterToBuffer(parameter, &buf, &hgs);
+    parameterToBuffer(parameter, buf, &hgs);
 
     if (tf.parameterList.varargs == VarArg.typesafe && parameter == tf.parameterList[tf.parameterList.parameters.length - 1])
     {
@@ -3220,7 +3225,7 @@ const(char)* parameterToChars(Parameter parameter, TypeFunction tf, bool fullQua
  *      hgs = context
  */
 
-private void parametersToBuffer(ParameterList pl, OutBuffer* buf, HdrGenState* hgs)
+private void parametersToBuffer(ParameterList pl, ref OutBuffer buf, HdrGenState* hgs)
 {
     buf.writeByte('(');
     foreach (i; 0 .. pl.length)
@@ -3258,7 +3263,7 @@ private void parametersToBuffer(ParameterList pl, OutBuffer* buf, HdrGenState* h
  *      buf = buffer to write it to
  *      hgs = context
  */
-private void parameterToBuffer(Parameter p, OutBuffer* buf, HdrGenState* hgs)
+private void parameterToBuffer(Parameter p, ref OutBuffer buf, HdrGenState* hgs)
 {
     if (p.userAttribDecl)
     {
@@ -3330,7 +3335,7 @@ private void parameterToBuffer(Parameter p, OutBuffer* buf, HdrGenState* hgs)
  *     basis = replace `null`s in argument list with this expression (for sparse array literals)
  *     names = if non-null, use these as the names for the arguments
  */
-private void argsToBuffer(Expressions* expressions, OutBuffer* buf, HdrGenState* hgs, Expression basis = null, Identifiers* names = null)
+private void argsToBuffer(Expressions* expressions, ref OutBuffer buf, HdrGenState* hgs, Expression basis = null, Identifiers* names = null)
 {
     if (!expressions || !expressions.length)
         return;
@@ -3381,7 +3386,7 @@ private void argsToBuffer(Expressions* expressions, OutBuffer* buf, HdrGenState*
     }
 }
 
-private void sizeToBuffer(Expression e, OutBuffer* buf, HdrGenState* hgs)
+private void sizeToBuffer(Expression e, ref OutBuffer buf, HdrGenState* hgs)
 {
     if (e.type == Type.tsize_t)
     {
@@ -3409,7 +3414,7 @@ private void sizeToBuffer(Expression e, OutBuffer* buf, HdrGenState* hgs)
     expToBuffer(e, PREC.assign, buf, hgs);
 }
 
-private void expressionToBuffer(Expression e, OutBuffer* buf, HdrGenState* hgs)
+private void expressionToBuffer(Expression e, ref OutBuffer buf, HdrGenState* hgs)
 {
     expressionPrettyPrint(e, buf, hgs);
 }
@@ -3418,7 +3423,7 @@ private void expressionToBuffer(Expression e, OutBuffer* buf, HdrGenState* hgs)
  * Write expression out to buf, but wrap it
  * in ( ) if its precedence is less than pr.
  */
-private void expToBuffer(Expression e, PREC pr, OutBuffer* buf, HdrGenState* hgs)
+private void expToBuffer(Expression e, PREC pr, ref OutBuffer buf, HdrGenState* hgs)
 {
     debug
     {
@@ -3452,7 +3457,7 @@ private void expToBuffer(Expression e, PREC pr, OutBuffer* buf, HdrGenState* hgs
 /**************************************************
  * An entry point to pretty-print type.
  */
-private void typeToBuffer(Type t, const Identifier ident, OutBuffer* buf, HdrGenState* hgs,
+private void typeToBuffer(Type t, const Identifier ident, ref OutBuffer buf, HdrGenState* hgs,
                           ubyte modMask = 0)
 {
     if (auto tf = t.isTypeFunction())
@@ -3468,7 +3473,7 @@ private void typeToBuffer(Type t, const Identifier ident, OutBuffer* buf, HdrGen
     }
 }
 
-private void visitWithMask(Type t, ubyte modMask, OutBuffer* buf, HdrGenState* hgs)
+private void visitWithMask(Type t, ubyte modMask, ref OutBuffer buf, HdrGenState* hgs)
 {
     // Tuples and functions don't use the type constructor syntax
     if (modMask == t.mod || t.ty == Tfunction || t.ty == Ttuple)
@@ -3504,7 +3509,7 @@ private void visitWithMask(Type t, ubyte modMask, OutBuffer* buf, HdrGenState* h
 }
 
 
-private void dumpTemplateInstance(TemplateInstance ti, OutBuffer* buf, HdrGenState* hgs)
+private void dumpTemplateInstance(TemplateInstance ti, ref OutBuffer buf, HdrGenState* hgs)
 {
     buf.writeByte('{');
     buf.writenl();
@@ -3527,7 +3532,7 @@ private void dumpTemplateInstance(TemplateInstance ti, OutBuffer* buf, HdrGenSta
 
 }
 
-private void tiargsToBuffer(TemplateInstance ti, OutBuffer* buf, HdrGenState* hgs)
+private void tiargsToBuffer(TemplateInstance ti, ref OutBuffer buf, HdrGenState* hgs)
 {
     buf.writeByte('!');
     if (ti.nest)
@@ -3576,7 +3581,7 @@ private void tiargsToBuffer(TemplateInstance ti, OutBuffer* buf, HdrGenState* hg
  * This makes a 'pretty' version of the template arguments.
  * It's analogous to genIdent() which makes a mangled version.
  */
-private void objectToBuffer(RootObject oarg, OutBuffer* buf, HdrGenState* hgs)
+private void objectToBuffer(RootObject oarg, ref OutBuffer buf, HdrGenState* hgs)
 {
     //printf("objectToBuffer()\n");
     /* The logic of this should match what genIdent() does. The _dynamic_cast()
@@ -3629,7 +3634,7 @@ private void objectToBuffer(RootObject oarg, OutBuffer* buf, HdrGenState* hgs)
 }
 
 
-private void visitFuncIdentWithPostfix(TypeFunction t, const char[] ident, OutBuffer* buf, HdrGenState* hgs, bool isStatic)
+private void visitFuncIdentWithPostfix(TypeFunction t, const char[] ident, ref OutBuffer buf, HdrGenState* hgs, bool isStatic)
 {
     if (t.inuse)
     {
@@ -3674,7 +3679,7 @@ private void visitFuncIdentWithPostfix(TypeFunction t, const char[] ident, OutBu
 }
 
 private void visitFuncIdentWithPrefix(TypeFunction t, const Identifier ident, TemplateDeclaration td,
-    OutBuffer* buf, HdrGenState* hgs)
+    ref OutBuffer buf, HdrGenState* hgs)
 {
     if (t.inuse)
     {
@@ -3743,7 +3748,7 @@ private void visitFuncIdentWithPrefix(TypeFunction t, const Identifier ident, Te
 }
 
 
-private void initializerToBuffer(Initializer inx, OutBuffer* buf, HdrGenState* hgs)
+private void initializerToBuffer(Initializer inx, ref OutBuffer buf, HdrGenState* hgs)
 {
     void visitError(ErrorInitializer iz)
     {
@@ -3811,7 +3816,7 @@ private void initializerToBuffer(Initializer inx, OutBuffer* buf, HdrGenState* h
                     if (d.exp)
                     {
                         buf.writeByte('[');
-                        toCBuffer(d.exp, buf, hgs);
+                        toCBuffer(d.exp, buf, *hgs);
                         buf.writeByte(']');
                     }
                     else
@@ -3832,7 +3837,7 @@ private void initializerToBuffer(Initializer inx, OutBuffer* buf, HdrGenState* h
 }
 
 
-private void typeToBufferx(Type t, OutBuffer* buf, HdrGenState* hgs)
+private void typeToBufferx(Type t, ref OutBuffer buf, HdrGenState* hgs)
 {
     void visitType(Type t)
     {
@@ -4020,7 +4025,7 @@ private void typeToBufferx(Type t, OutBuffer* buf, HdrGenState* hgs)
         buf.writeByte(' ');
         if (t.id)
             buf.writestring(t.id.toChars());
-        if (t.tok == TOK.enum_ && t.base.ty != TY.Tint32)
+        if (t.tok == TOK.enum_ && t.base && t.base.ty != TY.Tint32)
         {
             buf.writestring(" : ");
             visitWithMask(t.base, t.mod, buf, hgs);
diff --git a/gcc/d/dmd/hdrgen.h b/gcc/d/dmd/hdrgen.h
index 43fea34255f..e43a35510c2 100644
--- a/gcc/d/dmd/hdrgen.h
+++ b/gcc/d/dmd/hdrgen.h
@@ -15,7 +15,7 @@
 
 class Module;
 
-void genhdrfile(Module *m);
+void genhdrfile(Module *m, OutBuffer &buf);
 void genCppHdrFiles(Modules &ms);
-void moduleToBuffer(OutBuffer *buf, Module *m);
+void moduleToBuffer(OutBuffer& buf, Module *m);
 const char *parametersTypeToChars(ParameterList pl);
diff --git a/gcc/d/dmd/iasmgcc.d b/gcc/d/dmd/iasmgcc.d
index 1d4dea47b81..5494fecd70c 100644
--- a/gcc/d/dmd/iasmgcc.d
+++ b/gcc/d/dmd/iasmgcc.d
@@ -330,7 +330,7 @@ extern (C++) public Statement gccAsmSemantic(GccAsmStatement s, Scope *sc)
     s.insn = semanticString(sc, s.insn, "asm instruction template");
 
     if (s.labels && s.outputargs)
-        s.error("extended asm statements with labels cannot have output constraints");
+        error(s.loc, "extended asm statements with labels cannot have output constraints");
 
     // Analyse all input and output operands.
     if (s.args)
diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d
index 43b2e5f5a50..62fb51f752e 100644
--- a/gcc/d/dmd/id.d
+++ b/gcc/d/dmd/id.d
@@ -114,6 +114,7 @@ immutable Msgtable[] msgtable =
     { "returnLabel", "__returnLabel" },
     { "line" },
     { "empty", "" },
+    { "dotdotdot", "..." }, // use for error messages
     { "p" },
     { "__vptr" },
     { "__monitor" },
@@ -305,6 +306,7 @@ immutable Msgtable[] msgtable =
     { "aaKeys", "_aaKeys" },
     { "aaValues", "_aaValues" },
     { "aaRehash", "_aaRehash" },
+    { "_aaAsStruct" },
     { "monitorenter", "_d_monitorenter" },
     { "monitorexit", "_d_monitorexit" },
     { "criticalenter", "_d_criticalenter2" },
diff --git a/gcc/d/dmd/init.d b/gcc/d/dmd/init.d
index e7cf9051034..4501185b393 100644
--- a/gcc/d/dmd/init.d
+++ b/gcc/d/dmd/init.d
@@ -61,7 +61,7 @@ extern (C++) class Initializer : ASTNode
     {
         OutBuffer buf;
         HdrGenState hgs;
-        .toCBuffer(this, &buf, &hgs);
+        toCBuffer(this, buf, hgs);
         return buf.extractChars();
     }
 
diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d
index c60b4311ff5..45f09af8733 100644
--- a/gcc/d/dmd/initsem.d
+++ b/gcc/d/dmd/initsem.d
@@ -53,31 +53,38 @@ import dmd.typesem;
  */
 Expression toAssocArrayLiteral(ArrayInitializer ai)
 {
-    Expression e;
-    //printf("ArrayInitializer::toAssocArrayInitializer()\n");
+    //printf("ArrayInitializer::toAssocArrayInitializer(%s)\n", ai.toChars());
     //static int i; if (++i == 2) assert(0);
     const dim = ai.value.length;
+    if (!dim)
+    {
+        error(ai.loc, "invalid associative array initializer `%s`, use `null` instead",
+            ai.toChars());
+        return ErrorExp.get();
+    }
+    auto no(const char* format, Initializer i)
+    {
+        error(i.loc, format, i.toChars());
+        return ErrorExp.get();
+    }
+    Expression e;
     auto keys = new Expressions(dim);
     auto values = new Expressions(dim);
     for (size_t i = 0; i < dim; i++)
     {
-        e = ai.index[i];
-        if (!e)
-            goto Lno;
-        (*keys)[i] = e;
         Initializer iz = ai.value[i];
-        if (!iz)
-            goto Lno;
+        assert(iz);
         e = iz.initializerToExpression();
         if (!e)
-            goto Lno;
+            return no("invalid value `%s` in initializer", iz);
         (*values)[i] = e;
+        e = ai.index[i];
+        if (!e)
+            return no("missing key for value `%s` in initializer", iz);
+        (*keys)[i] = e;
     }
     e = new AssocArrayLiteralExp(ai.loc, keys, values);
     return e;
-Lno:
-    error(ai.loc, "not an associative array initializer");
-    return ErrorExp.get();
 }
 
 /******************************************
diff --git a/gcc/d/dmd/json.d b/gcc/d/dmd/json.d
index 96899869d52..c803bf80cc0 100644
--- a/gcc/d/dmd/json.d
+++ b/gcc/d/dmd/json.d
@@ -810,17 +810,14 @@ public:
     Params:
      modules = array of the "root modules"
     */
-    private void generateModules(Modules* modules)
+    private void generateModules(ref Modules modules)
     {
         arrayStart();
-        if (modules)
+        foreach (m; modules)
         {
-            foreach (m; *modules)
-            {
-                if (global.params.verbose)
-                    message("json gen %s", m.toChars());
-                m.accept(this);
-            }
+            if (global.params.verbose)
+                message("json gen %s", m.toChars());
+            m.accept(this);
         }
         arrayEnd();
     }
@@ -981,9 +978,15 @@ public:
     }
 }
 
-extern (C++) void json_generate(OutBuffer* buf, Modules* modules)
+/***********************************
+ * Generate json for the modules.
+ * Params:
+ *      modules = array of Modules
+ *      buf = write json output to buf
+ */
+extern (C++) void json_generate(ref Modules modules, ref OutBuffer buf)
 {
-    scope ToJsonVisitor json = new ToJsonVisitor(buf);
+    scope ToJsonVisitor json = new ToJsonVisitor(&buf);
     // write trailing newline
     scope(exit) buf.writeByte('\n');
 
diff --git a/gcc/d/dmd/json.h b/gcc/d/dmd/json.h
index 7a238979e20..09fdecdb9ee 100644
--- a/gcc/d/dmd/json.h
+++ b/gcc/d/dmd/json.h
@@ -15,5 +15,5 @@
 
 struct OutBuffer;
 
-void json_generate(OutBuffer *, Modules *);
+void json_generate(Modules &, OutBuffer &);
 JsonFieldFlags tryParseJsonField(const char *fieldName);
diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d
index c28fe5c2220..28ffbf8ed6d 100644
--- a/gcc/d/dmd/lexer.d
+++ b/gcc/d/dmd/lexer.d
@@ -51,7 +51,7 @@ struct CompileEnv
     bool previewIn;          /// `in` means `[ref] scope const`, accepts rvalues
     bool ddocOutput;         /// collect embedded documentation comments
     bool shortenedMethods = true;   /// allow => in normal function declarations
-    bool obsolete;           /// warn on use of legacy code
+    bool masm;               /// use MASM inline asm syntax
 }
 
 /***********************************************************
@@ -484,6 +484,12 @@ class Lexer
                     goto default;
                 wysiwygStringConstant(t);
                 return;
+            case 'x':
+                if (p[1] != '"')
+                    goto case_ident;
+                p++;
+                t.value = hexStringConstant(t);
+                return;
             case 'q':
                 if (Ccompile)
                     goto case_ident;
@@ -526,7 +532,7 @@ class Lexer
             //case 'u':
             case 'v':
             case 'w':
-            case 'x':
+                /*case 'x':*/
             case 'y':
             case 'z':
             case 'A':
@@ -1476,6 +1482,84 @@ class Lexer
         }
     }
 
+    /**************************************
+     * Lex hex strings:
+     *      x"0A ae 34FE BD"
+     */
+    final TOK hexStringConstant(Token* t)
+    {
+        Loc start = loc();
+        uint n = 0;
+        uint v = ~0; // dead assignment, needed to suppress warning
+        p++;
+        stringbuffer.setsize(0);
+        while (1)
+        {
+            dchar c = *p++;
+            switch (c)
+            {
+            case ' ':
+            case '\t':
+            case '\v':
+            case '\f':
+                continue; // skip white space
+            case '\r':
+                if (*p == '\n')
+                    continue; // ignore '\r' if followed by '\n'
+                // Treat isolated '\r' as if it were a '\n'
+                goto case '\n';
+            case '\n':
+                endOfLine();
+                continue;
+            case 0:
+            case 0x1A:
+                error("unterminated string constant starting at %s", start.toChars());
+                t.setString();
+                // decrement `p`, because it needs to point to the next token (the 0 or 0x1A character is the TOK.endOfFile token).
+                p--;
+                return TOK.hexadecimalString;
+            case '"':
+                if (n & 1)
+                {
+                    error("odd number (%d) of hex characters in hex string", n);
+                    stringbuffer.writeByte(v);
+                }
+                t.setString(stringbuffer);
+                stringPostfix(t);
+                return TOK.hexadecimalString;
+            default:
+                if (c >= '0' && c <= '9')
+                    c -= '0';
+                else if (c >= 'a' && c <= 'f')
+                    c -= 'a' - 10;
+                else if (c >= 'A' && c <= 'F')
+                    c -= 'A' - 10;
+                else if (c & 0x80)
+                {
+                    p--;
+                    const u = decodeUTF();
+                    p++;
+                    if (u == PS || u == LS)
+                        endOfLine();
+                    else
+                        error("non-hex character \\u%04x in hex string", u);
+                }
+                else
+                    error("non-hex character '%c' in hex string", c);
+                if (n & 1)
+                {
+                    v = (v << 4) | c;
+                    stringbuffer.writeByte(v);
+                }
+                else
+                    v = c;
+                n++;
+                break;
+            }
+        }
+        assert(0); // see bug 15731
+    }
+
     /**
     Lex a delimited string. Some examples of delimited strings are:
     ---
diff --git a/gcc/d/dmd/location.d b/gcc/d/dmd/location.d
index 0f3b9a7aa44..ef2bd0af779 100644
--- a/gcc/d/dmd/location.d
+++ b/gcc/d/dmd/location.d
@@ -38,8 +38,8 @@ debug info etc.
 struct Loc
 {
     private uint _linnum;
-    private ushort _charnum;
-    private ushort fileIndex; // index into filenames[], starting from 1 (0 means no filename)
+    private uint _charnum;
+    private uint fileIndex; // index into filenames[], starting from 1 (0 means no filename)
     version (LocOffset)
         uint fileOffset; /// utf8 code unit index relative to start of file, starting from 0
 
@@ -67,7 +67,7 @@ nothrow:
     extern (D) this(const(char)* filename, uint linnum, uint charnum) @safe
     {
         this._linnum = linnum;
-        this._charnum = cast(ushort) charnum;
+        this._charnum = charnum;
         this.filename = filename;
     }
 
@@ -80,7 +80,7 @@ nothrow:
     /// ditto
     extern (C++) uint charnum(uint num) @nogc @safe
     {
-        return _charnum = cast(ushort) num;
+        return _charnum = num;
     }
 
     /// line number, starting from 1
@@ -114,8 +114,16 @@ nothrow:
         {
             //printf("setting %s\n", name);
             filenames.push(name);
-            fileIndex = cast(ushort)filenames.length;
-            assert(fileIndex);  // no overflow
+            fileIndex = cast(uint)filenames.length;
+            if (!fileIndex)
+            {
+                import dmd.globals : global;
+                import dmd.errors : error, fatal;
+
+                global.gag = 0; // ensure error message gets printed
+                error(Loc.initial, "internal compiler error: file name index overflow!");
+                fatal();
+            }
         }
         else
             fileIndex = 0;
diff --git a/gcc/d/dmd/module.h b/gcc/d/dmd/module.h
index 8b481108f8c..ce512667694 100644
--- a/gcc/d/dmd/module.h
+++ b/gcc/d/dmd/module.h
@@ -142,7 +142,7 @@ public:
 
     int doppelganger;           // sub-module
     Symbol *cov;                // private uint[] __coverage;
-    unsigned *covb;             // bit array of valid code line numbers
+    DArray<unsigned> covb;      // bit array of valid code line numbers
 
     Symbol *sictor;             // module order independent constructor
     Symbol *sctor;              // module constructor
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index 9d83db13b67..63e20ed89d0 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -157,7 +157,7 @@ MOD MODmerge(MOD mod1, MOD mod2) pure nothrow @nogc @safe
 /*********************************
  * Store modifier name into buf.
  */
-void MODtoBuffer(OutBuffer* buf, MOD mod) nothrow @safe
+void MODtoBuffer(ref OutBuffer buf, MOD mod) nothrow @safe
 {
     buf.writestring(MODtoString(mod));
 }
@@ -787,7 +787,7 @@ extern (C++) abstract class Type : ASTNode
         HdrGenState hgs;
         hgs.fullQual = (ty == Tclass && !mod);
 
-        .toCBuffer(this, &buf, null, &hgs);
+        toCBuffer(this, buf, null, hgs);
         return buf.extractChars();
     }
 
@@ -799,7 +799,7 @@ extern (C++) abstract class Type : ASTNode
         HdrGenState hgs;
         hgs.fullQual = QualifyTypes;
 
-        .toCBuffer(this, &buf, null, &hgs);
+        toCBuffer(this, buf, null, hgs);
         return buf.extractChars();
     }
 
@@ -973,7 +973,7 @@ extern (C++) abstract class Type : ASTNode
     /*********************************
      * Store this type's modifier name into buf.
      */
-    final void modToBuffer(OutBuffer* buf) nothrow const
+    final void modToBuffer(ref OutBuffer buf) nothrow const
     {
         if (mod)
         {
@@ -989,7 +989,7 @@ extern (C++) abstract class Type : ASTNode
     {
         OutBuffer buf;
         buf.reserve(16);
-        modToBuffer(&buf);
+        modToBuffer(buf);
         return buf.extractChars();
     }
 
@@ -4563,7 +4563,7 @@ extern (C++) final class TypeFunction : TypeNext
                 continue;
             if (params == parameterList.parameters)
                 params = parameterList.parameters.copy();
-            (*params)[i] = new Parameter(p.storageClass, t, null, null, null);
+            (*params)[i] = new Parameter(p.loc, p.storageClass, t, null, null, null);
         }
         if (next == tret && params == parameterList.parameters)
             return this;
@@ -6218,7 +6218,7 @@ extern (C++) final class TypeTuple : Type
                 Expression e = (*exps)[i];
                 if (e.type.ty == Ttuple)
                     e.error("cannot form sequence of sequences");
-                auto arg = new Parameter(STC.undefined_, e.type, null, null, null);
+                auto arg = new Parameter(e.loc, STC.undefined_, e.type, null, null, null);
                 (*arguments)[i] = arg;
             }
         }
@@ -6244,15 +6244,15 @@ extern (C++) final class TypeTuple : Type
     {
         super(Ttuple);
         arguments = new Parameters();
-        arguments.push(new Parameter(0, t1, null, null, null));
+        arguments.push(new Parameter(Loc.initial, 0, t1, null, null, null));
     }
 
     extern (D) this(Type t1, Type t2)
     {
         super(Ttuple);
         arguments = new Parameters();
-        arguments.push(new Parameter(0, t1, null, null, null));
-        arguments.push(new Parameter(0, t2, null, null, null));
+        arguments.push(new Parameter(Loc.initial, 0, t1, null, null, null));
+        arguments.push(new Parameter(Loc.initial, 0, t2, null, null, null));
     }
 
     static TypeTuple create() @safe
@@ -6661,14 +6661,16 @@ extern (C++) final class Parameter : ASTNode
 {
     import dmd.attrib : UserAttributeDeclaration;
 
+    Loc loc;
     StorageClass storageClass;
     Type type;
     Identifier ident;
     Expression defaultArg;
     UserAttributeDeclaration userAttribDecl; // user defined attributes
 
-    extern (D) this(StorageClass storageClass, Type type, Identifier ident, Expression defaultArg, UserAttributeDeclaration userAttribDecl) @safe
+    extern (D) this(const ref Loc loc, StorageClass storageClass, Type type, Identifier ident, Expression defaultArg, UserAttributeDeclaration userAttribDecl) @safe
     {
+        this.loc = loc;
         this.type = type;
         this.ident = ident;
         this.storageClass = storageClass;
@@ -6676,14 +6678,14 @@ extern (C++) final class Parameter : ASTNode
         this.userAttribDecl = userAttribDecl;
     }
 
-    static Parameter create(StorageClass storageClass, Type type, Identifier ident, Expression defaultArg, UserAttributeDeclaration userAttribDecl) @safe
+    static Parameter create(const ref Loc loc, StorageClass storageClass, Type type, Identifier ident, Expression defaultArg, UserAttributeDeclaration userAttribDecl) @safe
     {
-        return new Parameter(storageClass, type, ident, defaultArg, userAttribDecl);
+        return new Parameter(loc, storageClass, type, ident, defaultArg, userAttribDecl);
     }
 
     Parameter syntaxCopy()
     {
-        return new Parameter(storageClass, type ? type.syntaxCopy() : null, ident, defaultArg ? defaultArg.syntaxCopy() : null, userAttribDecl ? userAttribDecl.syntaxCopy(null) : null);
+        return new Parameter(loc, storageClass, type ? type.syntaxCopy() : null, ident, defaultArg ? defaultArg.syntaxCopy() : null, userAttribDecl ? userAttribDecl.syntaxCopy(null) : null);
     }
 
     /****************************************************
@@ -7688,3 +7690,28 @@ pure string visitTYCase(string handler) @safe
     }
     assert(0);
 }
+
+
+/**
+ * Returns:
+ *     `TypeIdentifier` corresponding to `object.Throwable`
+ */
+TypeIdentifier getThrowable()
+{
+    auto tid = new TypeIdentifier(Loc.initial, Id.empty);
+    tid.addIdent(Id.object);
+    tid.addIdent(Id.Throwable);
+    return tid;
+}
+
+/**
+ * Returns:
+ *      TypeIdentifier corresponding to `object.Exception`
+ */
+TypeIdentifier getException()
+{
+    auto tid = new TypeIdentifier(Loc.initial, Id.empty);
+    tid.addIdent(Id.object);
+    tid.addIdent(Id.Exception);
+    return tid;
+}
diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h
index 457b91f1cee..aeeee8c7dad 100644
--- a/gcc/d/dmd/mtype.h
+++ b/gcc/d/dmd/mtype.h
@@ -237,7 +237,7 @@ public:
     virtual unsigned alignsize();
     Type *trySemantic(const Loc &loc, Scope *sc);
     Type *merge2();
-    void modToBuffer(OutBuffer *buf) const;
+    void modToBuffer(OutBuffer& buf) const;
     char *modToChars() const;
 
     virtual bool isintegral();
@@ -563,13 +563,14 @@ enum class PURE : unsigned char
 class Parameter final : public ASTNode
 {
 public:
+    Loc loc;
     StorageClass storageClass;
     Type *type;
     Identifier *ident;
     Expression *defaultArg;
     UserAttributeDeclaration *userAttribDecl;   // user defined attributes
 
-    static Parameter *create(StorageClass storageClass, Type *type, Identifier *ident,
+    static Parameter *create(const Loc &loc, StorageClass storageClass, Type *type, Identifier *ident,
                              Expression *defaultArg, UserAttributeDeclaration *userAttribDecl);
     Parameter *syntaxCopy();
     Type *isLazyArray();
diff --git a/gcc/d/dmd/opover.d b/gcc/d/dmd/opover.d
index 457e8b6479c..f9de1ee5a11 100644
--- a/gcc/d/dmd/opover.d
+++ b/gcc/d/dmd/opover.d
@@ -1767,10 +1767,10 @@ private FuncDeclaration findBestOpApplyMatch(Expression ethis, FuncDeclaration f
 
     if (fd_ambig)
     {
-        .error(ethis.loc, "`%s.%s` matches more than one declaration:\n`%s`:     `%s`\nand:\n`%s`:     `%s`",
-            ethis.toChars(), fstart.ident.toChars(),
-            fd_best.loc.toChars(), fd_best.type.toChars(),
-            fd_ambig.loc.toChars(), fd_ambig.type.toChars());
+        .error(ethis.loc, "`%s.%s` matches more than one declaration:",
+            ethis.toChars(), fstart.ident.toChars());
+        .errorSupplemental(fd_best.loc, "`%s`\nand:", fd_best.type.toChars());
+        .errorSupplemental(fd_ambig.loc, "`%s`", fd_ambig.type.toChars());
         return null;
     }
 
diff --git a/gcc/d/dmd/optimize.d b/gcc/d/dmd/optimize.d
index f98e7c76bcc..37563826a2d 100644
--- a/gcc/d/dmd/optimize.d
+++ b/gcc/d/dmd/optimize.d
@@ -1280,19 +1280,25 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
         //printf("CatExp::optimize(%d) %s\n", result, e.toChars());
         if (binOptimize(e, result))
             return;
-        if (auto ce1 = e.e1.isCatExp())
-        {
-            // https://issues.dlang.org/show_bug.cgi?id=12798
-            // optimize ((expr ~ str1) ~ str2)
-            scope CatExp cex = new CatExp(e.loc, ce1.e2, e.e2);
-            cex.type = e.type;
-            Expression ex = Expression_optimize(cex, result, false);
-            if (ex != cex)
+
+        if (e.type == Type.tstring)
+            if (auto ce1 = e.e1.isCatExp())
             {
-                e.e1 = ce1.e1;
-                e.e2 = ex;
+                // https://issues.dlang.org/show_bug.cgi?id=12798
+                // optimize ((expr ~ str1) ~ str2)
+                // https://issues.dlang.org/show_bug.cgi?id=24078
+                // This optimization is only valid if `expr` is a string.
+                // Otherwise it leads to:
+                // `["c"] ~ "a" ~ "b"` becoming `["c"] ~ "ab"`
+                scope CatExp cex = new CatExp(e.loc, ce1.e2, e.e2);
+                cex.type = e.type;
+                Expression ex = Expression_optimize(cex, result, false);
+                if (ex != cex)
+                {
+                    e.e1 = ce1.e1;
+                    e.e2 = ex;
+                }
             }
-        }
         // optimize "str"[] -> "str"
         if (auto se1 = e.e1.isSliceExp())
         {
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index 13bba4fb284..2a964151be5 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -1204,7 +1204,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         if (orig & added)
         {
             OutBuffer buf;
-            AST.stcToBuffer(&buf, added);
+            AST.stcToBuffer(buf, added);
             error("redundant attribute `%s`", buf.peekChars());
             return orig | added;
         }
@@ -2007,6 +2007,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         case TOK.wcharLiteral:
         case TOK.dcharLiteral:
         case TOK.string_:
+        case TOK.hexadecimalString:
         case TOK.file:
         case TOK.fileFullPath:
         case TOK.line:
@@ -2545,7 +2546,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         else if (StorageClass modStc = stc & STC.TYPECTOR)
         {
             OutBuffer buf;
-            AST.stcToBuffer(&buf, modStc);
+            AST.stcToBuffer(buf, modStc);
             error(loc, "static constructor cannot be `%s`", buf.peekChars());
         }
         stc &= ~(STC.static_ | STC.TYPECTOR);
@@ -2580,7 +2581,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         else if (StorageClass modStc = stc & STC.TYPECTOR)
         {
             OutBuffer buf;
-            AST.stcToBuffer(&buf, modStc);
+            AST.stcToBuffer(buf, modStc);
             error(loc, "static destructor cannot be `%s`", buf.peekChars());
         }
         stc &= ~(STC.static_ | STC.TYPECTOR);
@@ -2619,7 +2620,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         else if (StorageClass modStc = stc & STC.TYPECTOR)
         {
             OutBuffer buf;
-            AST.stcToBuffer(&buf, modStc);
+            AST.stcToBuffer(buf, modStc);
             error(loc, "shared static constructor cannot be `%s`", buf.peekChars());
         }
         stc &= ~(STC.static_ | STC.TYPECTOR);
@@ -2653,7 +2654,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         else if (StorageClass modStc = stc & STC.TYPECTOR)
         {
             OutBuffer buf;
-            AST.stcToBuffer(&buf, modStc);
+            AST.stcToBuffer(buf, modStc);
             error(loc, "shared static destructor cannot be `%s`", buf.peekChars());
         }
         stc &= ~(STC.static_ | STC.TYPECTOR);
@@ -2837,7 +2838,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                     if (varargsStc & ~VarArgsStc)
                     {
                         OutBuffer buf;
-                        AST.stcToBuffer(&buf, varargsStc & ~VarArgsStc);
+                        AST.stcToBuffer(buf, varargsStc & ~VarArgsStc);
                         error("variadic parameter cannot have attributes `%s`", buf.peekChars());
                         varargsStc &= VarArgsStc;
                     }
@@ -2935,11 +2936,12 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                             //error("scope cannot be ref or out");
 
                         const tv = peekNext();
+                        Loc loc;
                         if (tpl && token.value == TOK.identifier &&
                             (tv == TOK.comma || tv == TOK.rightParenthesis || tv == TOK.dotDotDot))
                         {
                             Identifier id = Identifier.generateId("__T");
-                            const loc = token.loc;
+                            loc = token.loc;
                             at = new AST.TypeIdentifier(loc, id);
                             if (!*tpl)
                                 *tpl = new AST.TemplateParameters();
@@ -2951,7 +2953,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                         }
                         else
                         {
-                            at = parseType(&ai);
+                            at = parseType(&ai, null, &loc);
                         }
                         ae = null;
                         if (token.value == TOK.assign) // = defaultArg
@@ -2959,7 +2961,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                             nextToken();
                             ae = parseDefaultInitExp();
                         }
-                        auto param = new AST.Parameter(storageClass | STC.parameter, at, ai, ae, null);
+                        auto param = new AST.Parameter(loc, storageClass | STC.parameter, at, ai, ae, null);
                         if (udas)
                         {
                             auto a = new AST.Dsymbols();
@@ -3083,7 +3085,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                                 else
                                 {
                                     OutBuffer buf;
-                                    AST.stcToBuffer(&buf, _stc);
+                                    AST.stcToBuffer(buf, _stc);
                                     error(attributeErrorMessage, buf.peekChars());
                                 }
                                 nextToken();
@@ -3284,8 +3286,14 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             if (token.value != TOK.rightCurly)
             {
                 /* { */
-                error(token.loc, "`}` expected following members in `%s` declaration at %s",
-                    Token.toChars(tok), loc.toChars());
+                error(token.loc, "`}` expected following members in `%s` declaration",
+                    Token.toChars(tok));
+                if (id)
+                    eSink.errorSupplemental(loc, "%s `%s` starts here",
+                        Token.toChars(tok), id.toChars());
+                else
+                    eSink.errorSupplemental(loc, "%s starts here",
+                        Token.toChars(tok));
             }
             nextToken();
         }
@@ -3481,8 +3489,9 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
      * Params:
      *  pident       = set to Identifier if there is one, null if not
      *  ptpl         = if !null, then set to TemplateParameterList
+     *  pdeclLoc     = if !null, then set to location of the declarator
      */
-    AST.Type parseType(Identifier* pident = null, AST.TemplateParameters** ptpl = null)
+    AST.Type parseType(Identifier* pident = null, AST.TemplateParameters** ptpl = null, Loc* pdeclLoc = null)
     {
         /* Take care of the storage class prefixes that
          * serve as type attributes:
@@ -3539,6 +3548,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         AST.Type t;
         t = parseBasicType();
 
+        if (pdeclLoc)
+            *pdeclLoc = token.loc;
         int alt = 0;
         t = parseDeclarator(t, alt, pident, ptpl);
         checkCstyleTypeSyntax(typeLoc, t, alt, pident ? *pident : null);
@@ -4575,8 +4586,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             }
             else if (t.ty == Tfunction)
             {
+                /* @@@DEPRECATED_2.115@@@
+                 * change to error, deprecated in 2.105.1 */
                 if (storage_class & STC.manifest)
-                    error("function cannot have enum storage class");
+                    deprecation("function cannot have enum storage class");
 
                 AST.Expression constraint = null;
                 //printf("%s funcdecl t = %s, storage_class = x%lx\n", loc.toChars(), t.toChars(), storage_class);
@@ -4953,7 +4966,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                         if (remStc)
                         {
                             OutBuffer buf;
-                            AST.stcToBuffer(&buf, remStc);
+                            AST.stcToBuffer(buf, remStc);
                             // @@@DEPRECATED_2.103@@@
                             // Deprecated in 2020-07, can be made an error in 2.103
                             eSink.deprecation(token.loc, "storage class `%s` has no effect in type aliases", buf.peekChars());
@@ -5108,7 +5121,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                     if (save == TOK.function_)
                     {
                         OutBuffer buf;
-                        AST.stcToBuffer(&buf, modStc);
+                        AST.stcToBuffer(buf, modStc);
                         error("function literal cannot be `%s`", buf.peekChars());
                     }
                     else
@@ -5126,7 +5139,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                 parameterList.parameters = new AST.Parameters();
                 Identifier id = Identifier.generateId("__T");
                 AST.Type t = new AST.TypeIdentifier(loc, id);
-                parameterList.parameters.push(new AST.Parameter(STC.parameter, t, token.ident, null, null));
+                parameterList.parameters.push(new AST.Parameter(loc, STC.parameter, t, token.ident, null, null));
 
                 tpl = new AST.TemplateParameters();
                 AST.TemplateParameter tp = new AST.TemplateTypeParameter(loc, id, null, null);
@@ -5443,6 +5456,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         {
             Identifier ai = null;
             AST.Type at;
+            Loc aloc;
 
             StorageClass storageClass = 0;
             StorageClass stc = 0;
@@ -5524,6 +5538,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                     lastai = token.ident;
                     ai = token.ident;
                     at = null; // infer argument type
+                    aloc = token.loc;
                     nextToken();
                     goto Larg;
                 }
@@ -5532,7 +5547,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             if (!ai)
                 noIdentifierForDeclarator(at);
         Larg:
-            auto p = new AST.Parameter(storageClass, at, ai, null, null);
+            auto p = new AST.Parameter(aloc, storageClass, at, ai, null, null);
             parameters.push(p);
             if (token.value == TOK.comma)
             {
@@ -5684,16 +5699,18 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         {
             Identifier ai = token.ident;
             AST.Type at = null; // infer parameter type
+            const aloc = token.loc;
             nextToken();
             check(TOK.assign);
-            param = new AST.Parameter(storageClass, at, ai, null, null);
+            param = new AST.Parameter(aloc, storageClass, at, ai, null, null);
         }
         else if (isDeclaration(&token, NeedDeclaratorId.must, TOK.assign, null))
         {
             Identifier ai;
+            const aloc = token.loc;
             AST.Type at = parseType(&ai);
             check(TOK.assign);
-            param = new AST.Parameter(storageClass, at, ai, null, null);
+            param = new AST.Parameter(aloc, storageClass, at, ai, null, null);
         }
         else if (storageClass != 0)
             error("found `%s` while expecting `=` or identifier", n.toChars());
@@ -5789,6 +5806,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         case TOK.true_:
         case TOK.false_:
         case TOK.string_:
+        case TOK.hexadecimalString:
         case TOK.leftParenthesis:
         case TOK.cast_:
         case TOK.mul:
@@ -5816,7 +5834,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                 AST.Expression exp = parseExpression();
                 /* https://issues.dlang.org/show_bug.cgi?id=15103
                  * Improve declaration / initialization syntax error message
-                 * Error: found 'foo' when expecting ';' following statement
+                 * Error: found 'foo' when expecting ';' following expression
                  * becomes Error: found `(` when expecting `;` or `=`, did you mean `Foo foo = 42`?
                  */
                 if (token.value == TOK.identifier && exp.op == EXP.identifier)
@@ -5841,11 +5859,14 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                      * otherwise we fall back on the old path (advancing the token).
                      */
                     if (token.value != TOK.semicolon && peek(&token).value == TOK.semicolon)
-                        error("found `%s` when expecting `;` following statement", token.toChars());
+                        error("found `%s` when expecting `;` following expression", token.toChars());
                     else
                     {
                         if (token.value != TOK.semicolon)
-                            error("found `%s` when expecting `;` following statement `%s` on line %s", token.toChars(), exp.toChars(), exp.loc.toChars());
+                        {
+                            error("found `%s` when expecting `;` following expression", token.toChars());
+                            eSink.errorSupplemental(exp.loc, "expression: `%s`", exp.toChars());
+                        }
                         nextToken();
                     }
                 }
@@ -6580,7 +6601,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             }
 
         case TOK.asm_:
-            s = parseAsm();
+            s = parseAsm(false);
             break;
 
         case TOK.import_:
@@ -6951,10 +6972,12 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
      *   AsmInstruction ;
      *   AsmInstruction ; AsmInstruction
      *
+     * Params:
+     *   endOfLine = true if EOL means end of asm statement
      * Returns:
      *   inline assembler block as a Statement
      */
-    AST.Statement parseAsm()
+    AST.Statement parseAsm(bool endOfLine)
     {
         // Parse the asm block into a sequence of AsmStatements,
         // each AsmStatement is one instruction.
@@ -6977,6 +7000,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         size_t nestlevel = 0;
         while (1)
         {
+            if (endOfLine)
+                nextDefineLine();
             switch (token.value)
             {
             case TOK.identifier:
@@ -7011,6 +7036,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                 }
                 break;
 
+            case TOK.endOfLine:
+                nextDefineLine();
+                goto case;
+
             case TOK.semicolon:
                 if (nestlevel != 0)
                     error("mismatched number of curly brackets");
@@ -7018,7 +7047,9 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                 if (toklist || label)
                 {
                     // Create AsmStatement from list of tokens we've saved
-                    AST.Statement s = new AST.AsmStatement(token.loc, toklist);
+                    AST.AsmStatement as = new AST.AsmStatement(token.loc, toklist);
+                    as.caseSensitive = !endOfLine;
+                    AST.Statement s = as;
                     toklist = null;
                     ptoklist = &toklist;
                     if (label)
@@ -7062,6 +7093,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             break;
         }
         nextToken();
+        if (token.value == TOK.endOfLine)
+            nextToken();
         auto s = new AST.CompoundAsmStatement(loc, statements, stc);
         return s;
     }
@@ -7291,6 +7324,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                     case TOK.wcharLiteral:
                     case TOK.dcharLiteral:
                     case TOK.string_:
+                    case TOK.hexadecimalString:
                     case TOK.file:
                     case TOK.fileFullPath:
                     case TOK.line:
@@ -7562,7 +7596,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                 }
                 continue;
 
-            // Valid tokens that follow a declaration
+            // Valid tokens that follow the start of a declaration
             case TOK.rightParenthesis:
             case TOK.rightBracket:
             case TOK.assign:
@@ -7581,6 +7615,23 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                 }
                 return false;
 
+            // To recognize the shortened function declaration syntax
+            case TOK.goesTo:
+                /*
+                    1. https://issues.dlang.org/show_bug.cgi?id=24088
+
+                    2. We need to make sure the would-be
+                       declarator has an identifier otherwise function literals
+                       are handled incorrectly. Some special treatment is required
+                       here, it turns out that a lot of code in the compiler relies
+                       on this mess (in the parser), i.e. having isDeclarator be more
+                       precise the parsing of other things go kaboom, so we do it in a
+                       separate case.
+                */
+                if (*haveId)
+                    goto case TOK.do_;
+                goto default;
+
             case TOK.identifier:
                 if (t.ident == Id._body)
                 {
@@ -8148,6 +8199,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             break;
 
         case TOK.string_:
+        case TOK.hexadecimalString:
             {
                 // cat adjacent strings
                 auto s = token.ustring;
@@ -8157,7 +8209,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                 {
                     const prev = token;
                     nextToken();
-                    if (token.value == TOK.string_)
+                    if (token.value == TOK.string_ || token.value == TOK.hexadecimalString)
                     {
                         if (token.postfix)
                         {
@@ -9549,7 +9601,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
 
     void usageOfBodyKeyword()
     {
-        if (compileEnv.obsolete)
+        version (none)  // disable obsolete warning
         {
             eSink.warning(token.loc, "usage of identifer `body` as a keyword is obsolete. Use `do` instead.");
         }
diff --git a/gcc/d/dmd/printast.d b/gcc/d/dmd/printast.d
index e43ffad2570..e1deb2c8786 100644
--- a/gcc/d/dmd/printast.d
+++ b/gcc/d/dmd/printast.d
@@ -64,7 +64,7 @@ extern (C++) final class PrintASTVisitor : Visitor
         import dmd.hdrgen : floatToBuffer;
         import dmd.common.outbuffer : OutBuffer;
         OutBuffer buf;
-        floatToBuffer(e.type, e.value, &buf, false);
+        floatToBuffer(e.type, e.value, buf, false);
         printf("Real %s %s\n", buf.peekChars(), e.type ? e.type.toChars() : "");
     }
 
diff --git a/gcc/d/dmd/safe.d b/gcc/d/dmd/safe.d
index c3fa90d7f79..bd531c0081e 100644
--- a/gcc/d/dmd/safe.d
+++ b/gcc/d/dmd/safe.d
@@ -51,7 +51,7 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg)
     DotVarExp dve = cast(DotVarExp)e;
     if (VarDeclaration v = dve.var.isVarDeclaration())
     {
-        if (sc.intypeof || !sc.func || !sc.func.isSafeBypassingInference())
+        if (!sc.func)
             return false;
         auto ad = v.isMember2();
         if (!ad)
@@ -65,6 +65,11 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg)
                 return true;
         }
 
+        // This branch shouldn't be here, but unfortunately calling `ad.determineSize`
+        // breaks code with circular reference errors. Specifically, test23589.d fails
+        if (ad.sizeok != Sizeok.done && !sc.func.isSafeBypassingInference())
+            return false;
+
         // needed to set v.overlapped and v.overlapUnsafe
         if (ad.sizeok != Sizeok.done)
             ad.determineSize(ad.loc);
@@ -74,9 +79,23 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg)
         {
             if (v.overlapped)
             {
-                if (sc.setUnsafe(!printmsg, e.loc,
+                if (sc.func.isSafeBypassingInference() && sc.setUnsafe(!printmsg, e.loc,
                     "field `%s.%s` cannot access pointers in `@safe` code that overlap other fields", ad, v))
+                {
                     return true;
+                }
+                else
+                {
+                    import dmd.globals : FeatureState;
+                    // @@@DEPRECATED_2.116@@@
+                    // https://issues.dlang.org/show_bug.cgi?id=20655
+                    // Inferring `@system` because of union access breaks code,
+                    // so make it a deprecation safety violation as of 2.106
+                    // To turn into an error, remove `isSafeBypassingInference` check in the
+                    // above if statement and remove the else branch
+                    sc.setUnsafePreview(FeatureState.default_, !printmsg, e.loc,
+                        "field `%s.%s` cannot access pointers in `@safe` code that overlap other fields", ad, v);
+                }
             }
         }
 
diff --git a/gcc/d/dmd/semantic2.d b/gcc/d/dmd/semantic2.d
index 53c8714510c..e2d2e041162 100644
--- a/gcc/d/dmd/semantic2.d
+++ b/gcc/d/dmd/semantic2.d
@@ -275,6 +275,7 @@ private extern(C++) final class Semantic2Visitor : Visitor
             // https://issues.dlang.org/show_bug.cgi?id=20417
             // Don't run CTFE for the temporary variables inside typeof or __traits(compiles)
             vd._init = vd._init.initializerSemantic(sc, vd.type, sc.intypeof == 1 || sc.flags & SCOPE.compile ? INITnointerpret : INITinterpret);
+            lowerStaticAAs(vd, sc);
             vd.inuse--;
         }
         if (vd._init && vd.storage_class & STC.manifest)
@@ -819,3 +820,55 @@ private void doGNUABITagSemantic(ref Expression e, ref Expression* lastTag)
     }
     ale.elements.sort!predicate;
 }
+
+/**
+ * Try lower a variable's static Associative Array to a newaa struct.
+ * Params:
+ *   vd = Variable to lower
+ *   sc = Scope
+ */
+void lowerStaticAAs(VarDeclaration vd, Scope* sc)
+{
+    if (vd.storage_class & STC.manifest)
+        return;
+    if (auto ei = vd._init.isExpInitializer())
+    {
+        scope v = new StaticAAVisitor(sc);
+        v.vd = vd;
+        ei.exp.accept(v);
+    }
+}
+
+/// Visit Associative Array literals and lower them to structs for static initialization
+private extern(C++) final class StaticAAVisitor : SemanticTimeTransitiveVisitor
+{
+    alias visit = SemanticTimeTransitiveVisitor.visit;
+    Scope* sc;
+    VarDeclaration vd;
+
+    this(Scope* sc) scope @safe
+    {
+        this.sc = sc;
+    }
+
+    override void visit(AssocArrayLiteralExp aaExp)
+    {
+        if (!verifyHookExist(aaExp.loc, *sc, Id._aaAsStruct, "initializing static associative arrays", Id.object))
+            return;
+
+        Expression hookFunc = new IdentifierExp(aaExp.loc, Id.empty);
+        hookFunc = new DotIdExp(aaExp.loc, hookFunc, Id.object);
+        hookFunc = new DotIdExp(aaExp.loc, hookFunc, Id._aaAsStruct);
+        auto arguments = new Expressions();
+        arguments.push(aaExp.syntaxCopy());
+        Expression loweredExp = new CallExp(aaExp.loc, hookFunc, arguments);
+
+        sc = sc.startCTFE();
+        loweredExp = loweredExp.expressionSemantic(sc);
+        loweredExp = resolveProperties(sc, loweredExp);
+        sc = sc.endCTFE();
+        loweredExp = loweredExp.ctfeInterpret();
+
+        aaExp.lowering = loweredExp;
+    }
+}
diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d
index bff89f8eaf3..04f57a4c021 100644
--- a/gcc/d/dmd/semantic3.d
+++ b/gcc/d/dmd/semantic3.d
@@ -471,7 +471,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
                         stc |= STC.temp;
                     }
                     Type vtype = fparam.type;
-                    auto v = new VarDeclaration(funcdecl.loc, vtype, id, null);
+                    auto v = new VarDeclaration(fparam.loc, vtype, id, null);
                     //printf("declaring parameter %s of type %s\n", v.toChars(), v.type.toChars());
                     stc |= STC.parameter;
                     if (f.parameterList.varargs == VarArg.typesafe && i + 1 == nparams)
@@ -749,7 +749,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
                 funcdecl.buildEnsureRequire();
 
                 // Check for errors related to 'nothrow'.
-                const blockexit = funcdecl.fbody.blockExit(funcdecl, f.isnothrow);
+                const blockexit = funcdecl.fbody.blockExit(funcdecl, f.isnothrow ? global.errorSink : null);
                 if (f.isnothrow && blockexit & BE.throw_)
                     error(funcdecl.loc, "%s `%s` may throw but is marked as `nothrow`", funcdecl.kind(), funcdecl.toPrettyChars());
 
@@ -993,7 +993,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
                 freq = freq.statementSemantic(sc2);
 
                 // @@@DEPRECATED_2.111@@@ - pass `isnothrow` instead of `false` to print a more detailed error msg`
-                const blockExit = freq.blockExit(funcdecl, false);
+                const blockExit = freq.blockExit(funcdecl, null);
                 if (blockExit & BE.throw_)
                 {
                     if (isnothrow)
@@ -1040,7 +1040,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
                 fens = fens.statementSemantic(sc2);
 
                 // @@@DEPRECATED_2.111@@@ - pass `isnothrow` instead of `false` to print a more detailed error msg`
-                const blockExit = fens.blockExit(funcdecl, false);
+                const blockExit = fens.blockExit(funcdecl, null);
                 if (blockExit & BE.throw_)
                 {
                     if (isnothrow)
@@ -1177,7 +1177,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
 
                             s = s.statementSemantic(sc2);
 
-                            const blockexit = s.blockExit(funcdecl, isnothrow);
+                            const blockexit = s.blockExit(funcdecl, isnothrow ? global.errorSink : null);
                             if (blockexit & BE.throw_)
                             {
                                 funcdecl.hasNoEH = false;
@@ -1187,7 +1187,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
                                     f.isnothrow = false;
                             }
 
-                            if (sbody.blockExit(funcdecl, f.isnothrow) == BE.fallthru)
+                            if (sbody.blockExit(funcdecl, f.isnothrow ? global.errorSink : null) == BE.fallthru)
                                 sbody = new CompoundStatement(Loc.initial, sbody, s);
                             else
                                 sbody = new TryFinallyStatement(Loc.initial, sbody, s);
@@ -1453,7 +1453,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
             {
                 // storage_class is apparently not set for dtor & ctor
                 OutBuffer ob;
-                stcToBuffer(&ob,
+                stcToBuffer(ob,
                     (ngErr ? STC.nogc : 0) |
                     (puErr ? STC.pure_ : 0) |
                     (saErr ? STC.system : 0)
diff --git a/gcc/d/dmd/statement.d b/gcc/d/dmd/statement.d
index 607dd51e087..58550fe6ca4 100644
--- a/gcc/d/dmd/statement.d
+++ b/gcc/d/dmd/statement.d
@@ -16,20 +16,14 @@ module dmd.statement;
 import core.stdc.stdarg;
 import core.stdc.stdio;
 
-import dmd.aggregate;
 import dmd.arraytypes;
 import dmd.astenums;
 import dmd.ast_node;
+import dmd.errors;
 import dmd.gluelayer;
 import dmd.cond;
-import dmd.dclass;
 import dmd.declaration;
-import dmd.denum;
-import dmd.dimport;
-import dmd.dscope;
 import dmd.dsymbol;
-import dmd.dtemplate;
-import dmd.errors;
 import dmd.expression;
 import dmd.func;
 import dmd.globals;
@@ -37,40 +31,14 @@ import dmd.hdrgen;
 import dmd.id;
 import dmd.identifier;
 import dmd.location;
-import dmd.dinterpret;
 import dmd.mtype;
 import dmd.common.outbuffer;
 import dmd.root.rootobject;
 import dmd.sapply;
-import dmd.sideeffect;
 import dmd.staticassert;
 import dmd.tokens;
 import dmd.visitor;
 
-/**
- * Returns:
- *     `TypeIdentifier` corresponding to `object.Throwable`
- */
-TypeIdentifier getThrowable()
-{
-    auto tid = new TypeIdentifier(Loc.initial, Id.empty);
-    tid.addIdent(Id.object);
-    tid.addIdent(Id.Throwable);
-    return tid;
-}
-
-/**
- * Returns:
- *      TypeIdentifier corresponding to `object.Exception`
- */
-TypeIdentifier getException()
-{
-    auto tid = new TypeIdentifier(Loc.initial, Id.empty);
-    tid.addIdent(Id.object);
-    tid.addIdent(Id.Exception);
-    return tid;
-}
-
 /***********************************************************
  * Specification: https://dlang.org/spec/statement.html
  */
@@ -118,64 +86,11 @@ extern (C++) abstract class Statement : ASTNode
     {
         HdrGenState hgs;
         OutBuffer buf;
-        .toCBuffer(this, &buf, &hgs);
+        toCBuffer(this, buf, hgs);
         buf.writeByte(0);
         return buf.extractSlice().ptr;
     }
 
-    static if (__VERSION__ < 2092)
-    {
-        final void error(const(char)* format, ...)
-        {
-            va_list ap;
-            va_start(ap, format);
-            .verrorReport(loc, format, ap, ErrorKind.error);
-            va_end(ap);
-        }
-
-        final void warning(const(char)* format, ...)
-        {
-            va_list ap;
-            va_start(ap, format);
-            .verrorReport(loc, format, ap, ErrorKind.warning);
-            va_end(ap);
-        }
-
-        final void deprecation(const(char)* format, ...)
-        {
-            va_list ap;
-            va_start(ap, format);
-            .verrorReport(loc, format, ap, ErrorKind.deprecation);
-            va_end(ap);
-        }
-    }
-    else
-    {
-        pragma(printf) final void error(const(char)* format, ...)
-        {
-            va_list ap;
-            va_start(ap, format);
-            .verrorReport(loc, format, ap, ErrorKind.error);
-            va_end(ap);
-        }
-
-        pragma(printf) final void warning(const(char)* format, ...)
-        {
-            va_list ap;
-            va_start(ap, format);
-            .verrorReport(loc, format, ap, ErrorKind.warning);
-            va_end(ap);
-        }
-
-        pragma(printf) final void deprecation(const(char)* format, ...)
-        {
-            va_list ap;
-            va_start(ap, format);
-            .verrorReport(loc, format, ap, ErrorKind.deprecation);
-            va_end(ap);
-        }
-    }
-
     Statement getRelatedLabeled()
     {
         return this;
@@ -1252,9 +1167,10 @@ extern (C++) final class SwitchStatement : Statement
                 if (v.isDataseg() || (v.storage_class & (STC.manifest | STC.temp) && vd.ident != Id.withSym) || v._init.isVoidInitializer())
                     continue;
                 if (vd.ident == Id.withSym)
-                    error("`switch` skips declaration of `with` temporary at %s", v.loc.toChars());
+                    error(loc, "`switch` skips declaration of `with` temporary");
                 else
-                    error("`switch` skips declaration of variable `%s` at %s", v.toPrettyChars(), v.loc.toChars());
+                    error(loc, "`switch` skips declaration of variable `%s`", v.toPrettyChars());
+                errorSupplemental(v.loc, "declared here");
                 return true;
             }
             return false;
@@ -1813,22 +1729,22 @@ extern (C++) final class GotoStatement : Statement
             else
             {
                 if (label.statement.os)
-                    error("cannot `goto` in to `%s` block", Token.toChars(label.statement.os.tok));
+                    error(loc, "cannot `goto` in to `%s` block", Token.toChars(label.statement.os.tok));
                 else
-                    error("cannot `goto` out of `%s` block", Token.toChars(os.tok));
+                    error(loc, "cannot `goto` out of `%s` block", Token.toChars(os.tok));
                 return true;
             }
         }
 
         if (label.statement.tf != tf)
         {
-            error("cannot `goto` in or out of `finally` block");
+            error(loc, "cannot `goto` in or out of `finally` block");
             return true;
         }
 
         if (label.statement.inCtfeBlock && !inCtfeBlock)
         {
-            error("cannot `goto` into `if (__ctfe)` block");
+            error(loc, "cannot `goto` into `if (__ctfe)` block");
             return true;
         }
 
@@ -1837,7 +1753,7 @@ extern (C++) final class GotoStatement : Statement
         {
             if (!stb)
             {
-                error("cannot `goto` into `try` block");
+                error(loc, "cannot `goto` into `try` block");
                 return true;
             }
             if (auto stf = stb.isTryFinallyStatement())
@@ -1863,17 +1779,15 @@ extern (C++) final class GotoStatement : Statement
         {
             // Lifetime ends at end of expression, so no issue with skipping the statement
         }
-        else if (vd.ident == Id.withSym)
-        {
-            error("`goto` skips declaration of `with` temporary at %s", vd.loc.toChars());
-            return true;
-        }
         else
         {
-            error("`goto` skips declaration of variable `%s` at %s", vd.toPrettyChars(), vd.loc.toChars());
+            if (vd.ident == Id.withSym)
+                error(loc, "`goto` skips declaration of `with` temporary");
+            else
+                error(loc, "`goto` skips declaration of variable `%s`", vd.toPrettyChars());
+            errorSupplemental(vd.loc, "declared here");
             return true;
         }
-
         return false;
     }
 
@@ -1959,6 +1873,7 @@ extern (C++) final class LabelDsymbol : Dsymbol
 extern (C++) class AsmStatement : Statement
 {
     Token* tokens;
+    bool caseSensitive;  // for register names
 
     extern (D) this(const ref Loc loc, Token* tokens) @safe
     {
diff --git a/gcc/d/dmd/statement.h b/gcc/d/dmd/statement.h
index eb4849dfc1b..dd8b9f21c05 100644
--- a/gcc/d/dmd/statement.h
+++ b/gcc/d/dmd/statement.h
@@ -116,7 +116,7 @@ public:
     const char *toChars() const override final;
 
     void error(const char *format, ...);
-    void warning(const char *format, ...);
+    void warning(unsigned flag, const char *format, ...);
     void deprecation(const char *format, ...);
     virtual Statement *getRelatedLabeled() { return this; }
     virtual bool hasBreak() const;
@@ -712,6 +712,7 @@ class AsmStatement : public Statement
 {
 public:
     Token *tokens;
+    bool caseSensitive;  // for register names
 
     AsmStatement *syntaxCopy() override;
     void accept(Visitor *v) override { v->visit(this); }
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index 178cef5af8c..304cb862f32 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -38,6 +38,7 @@ import dmd.dsymbol;
 import dmd.dsymbolsem;
 import dmd.dtemplate;
 import dmd.errors;
+import dmd.errorsink;
 import dmd.escape;
 import dmd.expression;
 import dmd.expressionsem;
@@ -349,7 +350,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                     Identifier id = Identifier.generateId("__o");
 
                     Statement handler = new PeelStatement(sexception);
-                    if (sexception.blockExit(sc.func, false) & BE.fallthru)
+                    if (sexception.blockExit(sc.func, null) & BE.fallthru)
                     {
                         auto ts = new ThrowStatement(Loc.initial, new IdentifierExp(Loc.initial, id));
                         ts.internalThrow = true;
@@ -704,7 +705,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
             {
                 if (!p.type)
                 {
-                    fs.error("cannot infer type for `foreach` variable `%s`, perhaps set it explicitly", p.ident.toChars());
+                    error(fs.loc, "cannot infer type for `foreach` variable `%s`, perhaps set it explicitly", p.ident.toChars());
                     p.type = Type.terror;
                     result = true;
                 }
@@ -753,7 +754,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
         {
             assert(oaggr.type);
 
-            fs.error("invalid `%s` aggregate `%s` of type `%s`",
+            error(fs.loc, "invalid `%s` aggregate `%s` of type `%s`",
                 Token.toChars(fs.op), oaggr.toChars(), oaggr.type.toPrettyChars());
 
             if (auto ad = isAggregate(fs.aggr.type))
@@ -815,11 +816,11 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
             if (foundMismatch && dim != foreachParamCount)
             {
                 const(char)* plural = foreachParamCount > 1 ? "s" : "";
-                fs.error("cannot infer argument types, expected %llu argument%s, not %llu",
+                error(fs.loc, "cannot infer argument types, expected %llu argument%s, not %llu",
                     cast(ulong) foreachParamCount, plural, cast(ulong) dim);
             }
             else
-                fs.error("cannot uniquely infer `foreach` argument types");
+                error(fs.loc, "cannot uniquely infer `foreach` argument types");
 
             return setError();
         }
@@ -845,11 +846,11 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
         {
             if (p.storageClass & STC.manifest)
             {
-                fs.error("cannot declare `enum` loop variables for non-unrolled foreach");
+                error(fs.loc, "cannot declare `enum` loop variables for non-unrolled foreach");
             }
             if (p.storageClass & STC.alias_)
             {
-                fs.error("cannot declare `alias` loop variables for non-unrolled foreach");
+                error(fs.loc, "cannot declare `alias` loop variables for non-unrolled foreach");
             }
         }
 
@@ -861,7 +862,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
 
         void rangeError()
         {
-            fs.error("cannot infer argument types");
+            error(fs.loc, "cannot infer argument types");
             return retError();
         }
 
@@ -959,7 +960,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
 
                 if (dim < 1 || dim > 2)
                 {
-                    fs.error("only one or two arguments for array `foreach`");
+                    error(fs.loc, "only one or two arguments for array `foreach`");
                     return retError();
                 }
 
@@ -978,7 +979,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                     Type tindex = (*fs.parameters)[0].type;
                     if (!tindex.isintegral())
                     {
-                        fs.error("foreach: key cannot be of non-integral type `%s`", tindex.toChars());
+                        error(fs.loc, "foreach: key cannot be of non-integral type `%s`", tindex.toChars());
                         return retError();
                     }
                     /* What cases to deprecate implicit conversions for:
@@ -990,7 +991,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                          (tn.ty != tv.ty && tn.ty.isSomeChar && tv.ty.isSomeChar)) &&
                         !Type.tsize_t.implicitConvTo(tindex))
                     {
-                        fs.deprecation("foreach: loop index implicitly converted from `size_t` to `%s`",
+                        deprecation(fs.loc, "foreach: loop index implicitly converted from `size_t` to `%s`",
                                        tindex.toChars());
                     }
                 }
@@ -1007,7 +1008,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                     {
                         if (p.storageClass & STC.ref_)
                         {
-                            fs.error("`foreach`: value of UTF conversion cannot be `ref`");
+                            error(fs.loc, "`foreach`: value of UTF conversion cannot be `ref`");
                             return retError();
                         }
                         if (dim == 2)
@@ -1015,7 +1016,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                             p = (*fs.parameters)[0];
                             if (p.storageClass & STC.ref_)
                             {
-                                fs.error("`foreach`: key cannot be `ref`");
+                                error(fs.loc, "`foreach`: key cannot be `ref`");
                                 return retError();
                             }
                         }
@@ -1036,7 +1037,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                     {
                         if (fs.key.type.constConv(p.type) == MATCH.nomatch)
                         {
-                            fs.error("key type mismatch, `%s` to `ref %s`",
+                            error(fs.loc, "key type mismatch, `%s` to `ref %s`",
                                      fs.key.type.toChars(), p.type.toChars());
                             return retError();
                         }
@@ -1048,7 +1049,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                         dimrange.imax = SignExtendedNumber(dimrange.imax.value-1);
                         if (!IntRange.fromType(fs.key.type).contains(dimrange))
                         {
-                            fs.error("index type `%s` cannot cover index range 0..%llu",
+                            error(fs.loc, "index type `%s` cannot cover index range 0..%llu",
                                      p.type.toChars(), ta.dim.toInteger());
                             return retError();
                         }
@@ -1071,7 +1072,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                         Type t = tab.nextOf();
                         if (t.constConv(p.type) == MATCH.nomatch)
                         {
-                            fs.error("argument type mismatch, `%s` to `ref %s`",
+                            error(fs.loc, "argument type mismatch, `%s` to `ref %s`",
                                      t.toChars(), p.type.toChars());
                             return retError();
                         }
@@ -1197,13 +1198,13 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
             }
         case Taarray:
             if (fs.op == TOK.foreach_reverse_)
-                fs.warning("cannot use `foreach_reverse` with an associative array");
+                warning(fs.loc, "cannot use `foreach_reverse` with an associative array");
             if (checkForArgTypes(fs))
                 return retError();
 
             if (dim < 1 || dim > 2)
             {
-                fs.error("only one or two arguments for associative array `foreach`");
+                error(fs.loc, "only one or two arguments for associative array `foreach`");
                 return retError();
             }
             return retStmt(apply());
@@ -1308,7 +1309,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                 }
                 if (tfront.ty == Tvoid)
                 {
-                    fs.error("`%s.front` is `void` and has no value", oaggr.toChars());
+                    error(fs.loc, "`%s.front` is `void` and has no value", oaggr.toChars());
                     return retError();
                 }
 
@@ -1348,7 +1349,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                     if (exps.length != dim)
                     {
                         const(char)* plural = exps.length > 1 ? "s" : "";
-                        fs.error("cannot infer argument types, expected %llu argument%s, not %llu",
+                        error(fs.loc, "cannot infer argument types, expected %llu argument%s, not %llu",
                             cast(ulong) exps.length, plural, cast(ulong) dim);
                         return retError();
                     }
@@ -1371,7 +1372,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                         p.type = p.type.addStorageClass(sc).typeSemantic(loc, sc2);
                         if (!exp.implicitConvTo(p.type))
                         {
-                            fs.error("cannot implicilty convert range element of type `%s` to variable `%s` of type `%s`",
+                            error(fs.loc, "cannot implicilty convert range element of type `%s` to variable `%s` of type `%s`",
                                 exp.type.toChars(), p.toChars(), p.type.toChars());
                             return retError();
                         }
@@ -1399,12 +1400,12 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
             }
         case Tdelegate:
             if (fs.op == TOK.foreach_reverse_)
-                fs.deprecation("cannot use `foreach_reverse` with a delegate");
+                deprecation(fs.loc, "cannot use `foreach_reverse` with a delegate");
             return retStmt(apply());
         case Terror:
             return retError();
         default:
-            fs.error("`foreach`: `%s` is not an aggregate type", fs.aggr.type.toChars());
+            error(fs.loc, "`foreach`: `%s` is not an aggregate type", fs.aggr.type.toChars());
             return retError();
         }
     }
@@ -1421,7 +1422,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
         fs.lwr = fs.lwr.optimize(WANTvalue);
         if (!fs.lwr.type)
         {
-            fs.error("invalid range lower bound `%s`", fs.lwr.toChars());
+            error(fs.loc, "invalid range lower bound `%s`", fs.lwr.toChars());
             return setError();
         }
 
@@ -1430,7 +1431,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
         fs.upr = fs.upr.optimize(WANTvalue);
         if (!fs.upr.type)
         {
-            fs.error("invalid range upper bound `%s`", fs.upr.toChars());
+            error(fs.loc, "invalid range upper bound `%s`", fs.upr.toChars());
             return setError();
         }
 
@@ -1584,7 +1585,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
         {
             if (fs.key.type.constConv(fs.prm.type) == MATCH.nomatch)
             {
-                fs.error("argument type mismatch, `%s` to `ref %s`", fs.key.type.toChars(), fs.prm.type.toChars());
+                error(fs.loc, "argument type mismatch, `%s` to `ref %s`", fs.key.type.toChars(), fs.prm.type.toChars());
                 return setError();
             }
         }
@@ -1762,14 +1763,14 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
             {
                 /* Should this be allowed?
                  */
-                ps.error("`pragma(lib)` not allowed as statement");
+                error(ps.loc, "`pragma(lib)` not allowed as statement");
                 return setError();
             }
             else
             {
                 if (!ps.args || ps.args.length != 1)
                 {
-                    ps.error("`string` expected for library name");
+                    error(ps.loc, "`string` expected for library name");
                     return setError();
                 }
                 else
@@ -1789,7 +1790,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
         {
             /* Should this be allowed?
              */
-            ps.error("`pragma(linkerDirective)` not allowed as statement");
+            error(ps.loc, "`pragma(linkerDirective)` not allowed as statement");
             return setError();
         }
         else if (ps.ident == Id.startaddress)
@@ -1805,13 +1806,32 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
             }
             else
             {
-                ps.error("`pragma(inline)` is not inside a function");
+                error(ps.loc, "`pragma(inline)` is not inside a function");
                 return setError();
             }
         }
+        else if (ps.ident == Id.mangle)
+        {
+            auto es = ps._body ? ps._body.isExpStatement() : null;
+            auto de = es ? es.exp.isDeclarationExp() : null;
+            if (!de)
+            {
+                error(ps.loc, "`pragma(mangle)` must be attached to a declaration");
+                return setError();
+            }
+            const se = ps.args && (*ps.args).length == 1 ? semanticString(sc, (*ps.args)[0], "pragma mangle argument") : null;
+            if (!se)
+            {
+                error(ps.loc, "`pragma(mangle)` takes a single argument that must be a string literal");
+                return setError();
+            }
+            const cnt = setMangleOverride(de.declaration, cast(const(char)[])se.peekData());
+            if (cnt != 1)
+                assert(0);
+        }
         else if (!global.params.ignoreUnsupportedPragmas)
         {
-            ps.error("unrecognized `pragma(%s)`", ps.ident.toChars());
+            error(ps.loc, "unrecognized `pragma(%s)`", ps.ident.toChars());
             return setError();
         }
 
@@ -1819,7 +1839,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
         {
             if (ps.ident == Id.msg || ps.ident == Id.startaddress)
             {
-                ps.error("`pragma(%s)` is missing a terminating `;`", ps.ident.toChars());
+                error(ps.loc, "`pragma(%s)` is missing a terminating `;`", ps.ident.toChars());
                 return setError();
             }
             ps._body = ps._body.statementSemantic(sc);
@@ -1885,7 +1905,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
 
             if (!ss.condition.isErrorExp())
             {
-                ss.error("`%s` must be of integral or string type, it is a `%s`",
+                error(ss.loc, "`%s` must be of integral or string type, it is a `%s`",
                     ss.condition.toChars(), ss.condition.type.toChars());
                 conditionError = true;
                 break;
@@ -1924,7 +1944,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
         {
             if (!gcs.exp)
             {
-                gcs.error("no `case` statement following `goto case;`");
+                error(gcs.loc, "no `case` statement following `goto case;`");
                 sc.pop();
                 return setError();
             }
@@ -1942,7 +1962,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                     }
                 }
             }
-            gcs.error("`case %s` not found", gcs.exp.toChars());
+            error(gcs.loc, "`case %s` not found", gcs.exp.toChars());
             sc.pop();
             return setError();
         }
@@ -1975,7 +1995,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                                 continue Lmembers;
                         }
                         if (missingMembers == 0)
-                            ss.error("missing cases for `enum` members in `final switch`:");
+                            error(ss.loc, "missing cases for `enum` members in `final switch`:");
 
                         if (missingMembers < maxShown)
                             errorSupplemental(ss.loc, "`%s`", em.toChars());
@@ -2000,7 +2020,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
             ss.hasNoDefault = 1;
 
             if (!ss.isFinal && (!ss._body || !ss._body.isErrorStatement()) && !(sc.flags & SCOPE.Cfile))
-                ss.error("`switch` statement without a `default`; use `final switch` or add `default: assert(0);` or add `default: break;`");
+                error(ss.loc, "`switch` statement without a `default`; use `final switch` or add `default: assert(0);` or add `default: break;`");
 
             // Generate runtime error if the default is hit
             auto a = new Statements();
@@ -2051,7 +2071,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
             a.reserve(2);
             sc.sw.sdefault = new DefaultStatement(ss.loc, s);
             a.push(ss._body);
-            if (ss._body.blockExit(sc.func, false) & BE.fallthru)
+            if (ss._body.blockExit(sc.func, null) & BE.fallthru)
                 a.push(new BreakStatement(Loc.initial, null));
             a.push(sc.sw.sdefault);
             cs = new CompoundStatement(ss.loc, a);
@@ -2193,12 +2213,12 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                     */
                     if (!v.isConst() && !v.isImmutable())
                     {
-                        cs.error("`case` variables have to be `const` or `immutable`");
+                        error(cs.loc, "`case` variables have to be `const` or `immutable`");
                     }
 
                     if (sw.isFinal)
                     {
-                        cs.error("`case` variables not allowed in `final switch` statements");
+                        error(cs.loc, "`case` variables not allowed in `final switch` statements");
                         errors = true;
                     }
 
@@ -2213,7 +2233,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
 
                         if (!scx.search(cs.exp.loc, v.ident, null))
                         {
-                            cs.error("`case` variable `%s` declared at %s cannot be declared in `switch` body",
+                            error(cs.loc, "`case` variable `%s` declared at %s cannot be declared in `switch` body",
                                 v.toChars(), v.loc.toChars());
                             errors = true;
                         }
@@ -2229,7 +2249,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                 cs.exp = se;
             else if (!cs.exp.isIntegerExp() && !cs.exp.isErrorExp())
             {
-                cs.error("`case` expression must be a compile-time `string` or an integral constant, not `%s`", cs.exp.toChars());
+                error(cs.loc, "`case` expression must be a compile-time `string` or an integral constant, not `%s`", cs.exp.toChars());
                 errors = true;
             }
 
@@ -2242,7 +2262,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                 if (cs2.exp.equals(cs.exp))
                 {
                     // https://issues.dlang.org/show_bug.cgi?id=15909
-                    cs.error("duplicate `case %s` in `switch` statement", initialExp.toChars());
+                    error(cs.loc, "duplicate `case %s` in `switch` statement", initialExp.toChars());
                     errors = true;
                     break;
                 }
@@ -2265,18 +2285,18 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
 
             if (sc.sw.tf != sc.tf)
             {
-                cs.error("`switch` and `case` are in different `finally` blocks");
+                error(cs.loc, "`switch` and `case` are in different `finally` blocks");
                 errors = true;
             }
             if (sc.sw.tryBody != sc.tryBody)
             {
-                cs.error("case cannot be in different `try` block level from `switch`");
+                error(cs.loc, "case cannot be in different `try` block level from `switch`");
                 errors = true;
             }
         }
         else
         {
-            cs.error("`case` not in `switch` statement");
+            error(cs.loc, "`case` not in `switch` statement");
             errors = true;
         }
 
@@ -2299,7 +2319,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
         SwitchStatement sw = sc.sw;
         if (sw is null)
         {
-            crs.error("case range not in `switch` statement");
+            error(crs.loc, "case range not in `switch` statement");
             return setError();
         }
 
@@ -2307,7 +2327,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
         bool errors = false;
         if (sw.isFinal)
         {
-            crs.error("case ranges not allowed in `final switch`");
+            error(crs.loc, "case ranges not allowed in `final switch`");
             errors = true;
         }
 
@@ -2336,14 +2356,14 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
         uinteger_t lval = crs.last.toInteger();
         if ((crs.first.type.isunsigned() && fval > lval) || (!crs.first.type.isunsigned() && cast(sinteger_t)fval > cast(sinteger_t)lval))
         {
-            crs.error("first `case %s` is greater than last `case %s`", crs.first.toChars(), crs.last.toChars());
+            error(crs.loc, "first `case %s` is greater than last `case %s`", crs.first.toChars(), crs.last.toChars());
             errors = true;
             lval = fval;
         }
 
         if (lval - fval > 256)
         {
-            crs.error("had %llu cases which is more than 257 cases in case range", 1 + lval - fval);
+            error(crs.loc, "had %llu cases which is more than 257 cases in case range", 1 + lval - fval);
             errors = true;
             lval = fval + 256;
         }
@@ -2385,30 +2405,30 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
         {
             if (sc.sw.sdefault)
             {
-                ds.error("`switch` statement already has a default");
+                error(ds.loc, "`switch` statement already has a default");
                 errors = true;
             }
             sc.sw.sdefault = ds;
 
             if (sc.sw.tf != sc.tf)
             {
-                ds.error("`switch` and `default` are in different `finally` blocks");
+                error(ds.loc, "`switch` and `default` are in different `finally` blocks");
                 errors = true;
             }
             if (sc.sw.tryBody != sc.tryBody)
             {
-                ds.error("default cannot be in different `try` block level from `switch`");
+                error(ds.loc, "default cannot be in different `try` block level from `switch`");
                 errors = true;
             }
             if (sc.sw.isFinal)
             {
-                ds.error("`default` statement not allowed in `final switch` statement");
+                error(ds.loc, "`default` statement not allowed in `final switch` statement");
                 errors = true;
             }
         }
         else
         {
-            ds.error("`default` not in `switch` statement");
+            error(ds.loc, "`default` not in `switch` statement");
             errors = true;
         }
 
@@ -2429,12 +2449,12 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
         gds.sw = sc.sw;
         if (!gds.sw)
         {
-            gds.error("`goto default` not in `switch` statement");
+            error(gds.loc, "`goto default` not in `switch` statement");
             return setError();
         }
         if (gds.sw.isFinal)
         {
-            gds.error("`goto default` not allowed in `final switch` statement");
+            error(gds.loc, "`goto default` not allowed in `final switch` statement");
             return setError();
         }
         result = gds;
@@ -2447,7 +2467,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
 
         if (!sc.sw)
         {
-            gcs.error("`goto case` not in `switch` statement");
+            error(gcs.loc, "`goto case` not in `switch` statement");
             return setError();
         }
 
@@ -2512,7 +2532,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
         bool errors = false;
         if (sc.flags & SCOPE.contract)
         {
-            rs.error("`return` statements cannot be in contracts");
+            error(rs.loc, "`return` statements cannot be in contracts");
             errors = true;
         }
         if (sc.os)
@@ -2521,18 +2541,18 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
             // Deprecated in 2.100, transform into an error in 2.112
             if (sc.os.tok == TOK.onScopeFailure)
             {
-                rs.deprecation("`return` statements cannot be in `scope(failure)` bodies.");
+                deprecation(rs.loc, "`return` statements cannot be in `scope(failure)` bodies.");
                 deprecationSupplemental(rs.loc, "Use try-catch blocks for this purpose");
             }
             else
             {
-                rs.error("`return` statements cannot be in `%s` bodies", Token.toChars(sc.os.tok));
+                error(rs.loc, "`return` statements cannot be in `%s` bodies", Token.toChars(sc.os.tok));
                 errors = true;
             }
         }
         if (sc.tf)
         {
-            rs.error("`return` statements cannot be in `finally` bodies");
+            error(rs.loc, "`return` statements cannot be in `finally` bodies");
             errors = true;
         }
 
@@ -2540,7 +2560,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
         {
             if (rs.exp)
             {
-                rs.error("cannot return expression from constructor");
+                error(rs.loc, "cannot return expression from constructor");
                 errors = true;
             }
 
@@ -2595,7 +2615,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
             {
                 if (!convToVoid)
                 {
-                    rs.error("cannot return non-void from `void` function");
+                    error(rs.loc, "cannot return non-void from `void` function");
                     errors = true;
                     rs.exp = new CastExp(rs.loc, rs.exp, Type.tvoid);
                     rs.exp = rs.exp.expressionSemantic(sc);
@@ -2655,7 +2675,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                     }
                     else if (!rs.exp.isErrorExp())
                     {
-                        rs.error("expected return type of `%s`, not `%s`:",
+                        error(rs.loc, "expected return type of `%s`, not `%s`:",
                                  tret.toChars(),
                                  rs.exp.type.toChars());
                         errorSupplemental((fd.returns) ? (*fd.returns)[0].loc : fd.loc,
@@ -2697,7 +2717,12 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                 {
                     /* May return by ref
                      */
-                    if (checkReturnEscapeRef(sc, rs.exp, true))
+                    Scope* sc2 = sc.push();
+                    sc2.eSink = global.errorSinkNull;
+                    bool err = checkReturnEscapeRef(sc2, rs.exp, true);
+                    sc2.pop();
+
+                    if (err)
                         turnOffRef(() { checkReturnEscapeRef(sc, rs.exp, false); });
                     else if (!rs.exp.type.constConv(tf.next))
                         turnOffRef(
@@ -2736,7 +2761,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                 {
                     if (tf.next.ty != Terror)
                     {
-                        rs.error("mismatched function return type inference of `void` and `%s`", tf.next.toChars());
+                        error(rs.loc, "mismatched function return type inference of `void` and `%s`", tf.next.toChars());
                     }
                     errors = true;
                     tf.next = Type.terror;
@@ -2755,15 +2780,15 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                 if (tbret.ty != Terror)
                 {
                     if (e0)
-                        rs.error("expected return type of `%s`, not `%s`", tret.toChars(), resType.toChars());
+                        error(rs.loc, "expected return type of `%s`, not `%s`", tret.toChars(), resType.toChars());
                     else if (tbret.isTypeNoreturn())
                     {
-                        rs.error("cannot return from `noreturn` function");
+                        error(rs.loc, "cannot return from `noreturn` function");
                         .errorSupplemental(rs.loc,
                             "Consider adding an endless loop, `assert(0)`, or another `noreturn` expression");
                     }
                     else
-                        rs.error("`return` expression expected");
+                        error(rs.loc, "`return` expression expected");
                 }
                 errors = true;
             }
@@ -2777,7 +2802,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
         // If any branches have called a ctor, but this branch hasn't, it's an error
         if (sc.ctorflow.callSuper & CSX.any_ctor && !(sc.ctorflow.callSuper & (CSX.this_ctor | CSX.super_ctor)))
         {
-            rs.error("`return` without calling constructor");
+            error(rs.loc, "`return` without calling constructor");
             errors = true;
         }
 
@@ -2790,7 +2815,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                 bool mustInit = (v.storage_class & STC.nodefaultctor || v.type.needsNested());
                 if (mustInit && !(sc.ctorflow.fieldinit[i].csx & CSX.this_ctor))
                 {
-                    rs.error("an earlier `return` statement skips field `%s` initialization", v.toChars());
+                    error(rs.loc, "an earlier `return` statement skips field `%s` initialization", v.toChars());
                     errors = true;
                 }
             }
@@ -2904,9 +2929,9 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                 {
                     Statement s = ls.statement;
                     if (!s || !s.hasBreak())
-                        bs.error("label `%s` has no `break`", bs.ident.toChars());
+                        error(bs.loc, "label `%s` has no `break`", bs.ident.toChars());
                     else if (ls.tf != sc.tf)
-                        bs.error("cannot break out of `finally` block");
+                        error(bs.loc, "cannot break out of `finally` block");
                     else
                     {
                         ls.breaks = true;
@@ -2916,14 +2941,14 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                     return setError();
                 }
             }
-            bs.error("enclosing label `%s` for `break` not found", bs.ident.toChars());
+            error(bs.loc, "enclosing label `%s` for `break` not found", bs.ident.toChars());
             return setError();
         }
         else if (!sc.sbreak)
         {
             if (sc.os && sc.os.tok != TOK.onScopeFailure)
             {
-                bs.error("`break` is not allowed inside `%s` bodies", Token.toChars(sc.os.tok));
+                error(bs.loc, "`break` is not allowed inside `%s` bodies", Token.toChars(sc.os.tok));
             }
             else if (sc.fes)
             {
@@ -2932,12 +2957,12 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                 return;
             }
             else
-                bs.error("`break` is not inside a loop or `switch`");
+                error(bs.loc, "`break` is not inside a loop or `switch`");
             return setError();
         }
         else if (sc.sbreak.isForwardingStatement())
         {
-            bs.error("must use labeled `break` within `static foreach`");
+            error(bs.loc, "must use labeled `break` within `static foreach`");
         }
         result = bs;
     }
@@ -2992,9 +3017,9 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                 {
                     Statement s = ls.statement;
                     if (!s || !s.hasContinue())
-                        cs.error("label `%s` has no `continue`", cs.ident.toChars());
+                        error(cs.loc, "label `%s` has no `continue`", cs.ident.toChars());
                     else if (ls.tf != sc.tf)
-                        cs.error("cannot continue out of `finally` block");
+                        error(cs.loc, "cannot continue out of `finally` block");
                     else
                     {
                         result = cs;
@@ -3003,14 +3028,14 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                     return setError();
                 }
             }
-            cs.error("enclosing label `%s` for `continue` not found", cs.ident.toChars());
+            error(cs.loc, "enclosing label `%s` for `continue` not found", cs.ident.toChars());
             return setError();
         }
         else if (!sc.scontinue)
         {
             if (sc.os && sc.os.tok != TOK.onScopeFailure)
             {
-                cs.error("`continue` is not allowed inside `%s` bodies", Token.toChars(sc.os.tok));
+                error(cs.loc, "`continue` is not allowed inside `%s` bodies", Token.toChars(sc.os.tok));
             }
             else if (sc.fes)
             {
@@ -3019,12 +3044,12 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                 return;
             }
             else
-                cs.error("`continue` is not inside a loop");
+                error(cs.loc, "`continue` is not inside a loop");
             return setError();
         }
         else if (sc.scontinue.isForwardingStatement())
         {
-            cs.error("must use labeled `continue` within `static foreach`");
+            error(cs.loc, "must use labeled `continue` within `static foreach`");
         }
         result = cs;
     }
@@ -3050,7 +3075,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
             ClassDeclaration cd = ss.exp.type.isClassHandle();
             if (!cd)
             {
-                ss.error("can only `synchronize` on class objects, not `%s`", ss.exp.type.toChars());
+                error(ss.loc, "can only `synchronize` on class objects, not `%s`", ss.exp.type.toChars());
                 return setError();
             }
             else if (cd.isInterfaceDeclaration())
@@ -3060,7 +3085,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                  */
                 if (!ClassDeclaration.object)
                 {
-                    ss.error("missing or corrupt object.d");
+                    error(ss.loc, "missing or corrupt object.d");
                     fatal();
                 }
 
@@ -3085,7 +3110,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                 cs.push(new ExpStatement(ss.loc, tmp));
 
                 auto args = new Parameters();
-                args.push(new Parameter(0, ClassDeclaration.object.type, null, null, null));
+                args.push(new Parameter(Loc.initial, 0, ClassDeclaration.object.type, null, null, null));
 
                 FuncDeclaration fdenter = FuncDeclaration.genCfunc(args, Type.tvoid, Id.monitorenter);
                 Expression e = new CallExp(ss.loc, fdenter, new VarExp(ss.loc, tmp));
@@ -3127,7 +3152,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
             cs.push(new ExpStatement(ss.loc, v));
 
             auto enterArgs = new Parameters();
-            enterArgs.push(new Parameter(0, t.pointerTo(), null, null, null));
+            enterArgs.push(new Parameter(Loc.initial, 0, t.pointerTo(), null, null, null));
 
             FuncDeclaration fdenter = FuncDeclaration.genCfunc(enterArgs, Type.tvoid, Id.criticalenter, STC.nothrow_);
             Expression e = new AddrExp(ss.loc, tmpExp);
@@ -3137,7 +3162,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
             cs.push(new ExpStatement(ss.loc, e));
 
             auto exitArgs = new Parameters();
-            exitArgs.push(new Parameter(0, t, null, null, null));
+            exitArgs.push(new Parameter(Loc.initial, 0, t, null, null, null));
 
             FuncDeclaration fdexit = FuncDeclaration.genCfunc(exitArgs, Type.tvoid, Id.criticalexit, STC.nothrow_);
             e = new CallExp(ss.loc, fdexit, tmpExp);
@@ -3177,7 +3202,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
             Dsymbol s = (cast(TypeExp)ws.exp).type.toDsymbol(sc);
             if (!s || !s.isScopeDsymbol())
             {
-                ws.error("`with` type `%s` has no members", ws.exp.toChars());
+                error(ws.loc, "`with` type `%s` has no members", ws.exp.toChars());
                 return setError();
             }
             sym = new WithScopeSymbol(ws);
@@ -3252,7 +3277,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
             }
             else
             {
-                ws.error("`with` expression types must be enums or aggregates or pointers to them, not `%s`", olde.type.toChars());
+                error(ws.loc, "`with` expression types must be enums or aggregates or pointers to them, not `%s`", olde.type.toChars());
                 return setError();
             }
         }
@@ -3281,13 +3306,13 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
 
         if (!global.params.useExceptions)
         {
-            tcs.error("cannot use try-catch statements with -betterC");
+            error(tcs.loc, "cannot use try-catch statements with %s", global.params.betterC ? "-betterC".ptr : "-nothrow".ptr);
             return setError();
         }
 
         if (!ClassDeclaration.throwable)
         {
-            tcs.error("cannot use try-catch statements because `object.Throwable` was not declared");
+            error(tcs.loc, "cannot use try-catch statements because `object.Throwable` was not declared");
             return setError();
         }
 
@@ -3320,7 +3345,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                 const sj = cj.loc.toChars();
                 if (c.type.toBasetype().implicitConvTo(cj.type.toBasetype()))
                 {
-                    tcs.error("`catch` at %s hides `catch` at %s", sj, si);
+                    error(tcs.loc, "`catch` at %s hides `catch` at %s", sj, si);
                     catchErrors = true;
                 }
             }
@@ -3331,7 +3356,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
             sc.func.hasCatches = true;
             if (flags == (FLAGcpp | FLAGd))
             {
-                tcs.error("cannot mix catching D and C++ exceptions in the same try-catch");
+                error(tcs.loc, "cannot mix catching D and C++ exceptions in the same try-catch");
                 catchErrors = true;
             }
         }
@@ -3353,7 +3378,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
         /* If the try body never throws, we can eliminate any catches
          * of recoverable exceptions.
          */
-        if (!(tcs._body.blockExit(sc.func, false) & BE.throw_) && ClassDeclaration.exception)
+        if (!(tcs._body.blockExit(sc.func, null) & BE.throw_) && ClassDeclaration.exception)
         {
             foreach_reverse (i; 0 .. tcs.catches.length)
             {
@@ -3403,7 +3428,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
             return;
         }
 
-        auto blockexit = tfs._body.blockExit(sc.func, false);
+        auto blockexit = tfs._body.blockExit(sc.func, null);
 
         // if not worrying about exceptions
         if (!(global.params.useExceptions && ClassDeclaration.throwable))
@@ -3429,7 +3454,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
             // https://issues.dlang.org/show_bug.cgi?id=23159
             if (!global.params.useExceptions)
             {
-                oss.error("`%s` cannot be used with -betterC", Token.toChars(oss.tok));
+                error(oss.loc, "`%s` cannot be used with -betterC", Token.toChars(oss.tok));
                 return setError();
             }
 
@@ -3439,12 +3464,12 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
             if (sc.os && sc.os.tok != TOK.onScopeFailure)
             {
                 // If enclosing is scope(success) or scope(exit), this will be placed in finally block.
-                oss.error("cannot put `%s` statement inside `%s`", Token.toChars(oss.tok), Token.toChars(sc.os.tok));
+                error(oss.loc, "cannot put `%s` statement inside `%s`", Token.toChars(oss.tok), Token.toChars(sc.os.tok));
                 return setError();
             }
             if (sc.tf)
             {
-                oss.error("cannot put `%s` statement inside `finally` block", Token.toChars(oss.tok));
+                error(oss.loc, "cannot put `%s` statement inside `finally` block", Token.toChars(oss.tok));
                 return setError();
             }
         }
@@ -3556,12 +3581,12 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
             if (ls.loc == ls2.loc)
             {
                 ls2.duplicated = true;
-                ls.error("label `%s` is duplicated", ls2.toChars());
+                error(ls.loc, "label `%s` is duplicated", ls2.toChars());
                 .errorSupplemental(ls2.loc, "labels cannot be used in a static foreach with more than 1 iteration");
             }
             else
             {
-                ls.error("label `%s` is already defined", ls2.toChars());
+                error(ls.loc, "label `%s` is already defined", ls2.toChars());
                 .errorSupplemental(ls2.loc, "first definition is here");
             }
             return setError();
@@ -3620,14 +3645,14 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
 
         assert(sc.func);
         if (!(cas.stc & STC.pure_) && sc.func.setImpure(cas.loc, "`asm` statement is assumed to be impure - mark it with `pure` if it is not"))
-            cas.error("`asm` statement is assumed to be impure - mark it with `pure` if it is not");
+            error(cas.loc, "`asm` statement is assumed to be impure - mark it with `pure` if it is not");
         if (!(cas.stc & STC.nogc) && sc.func.setGC(cas.loc, "`asm` statement in %s `%s` is assumed to use the GC - mark it with `@nogc` if it does not"))
-            cas.error("`asm` statement is assumed to use the GC - mark it with `@nogc` if it does not");
+            error(cas.loc, "`asm` statement is assumed to use the GC - mark it with `@nogc` if it does not");
         // @@@DEPRECATED_2.114@@@
         // change deprecation() to error(), add `else` and remove `| STC.safe`
         // to turn deprecation into an error when deprecation cycle is over
         if (cas.stc & STC.safe)
-            cas.deprecation("`asm` statement cannot be marked `@safe`, use `@system` or `@trusted` instead");
+            deprecation(cas.loc, "`asm` statement cannot be marked `@safe`, use `@system` or `@trusted` instead");
         if (!(cas.stc & (STC.trusted | STC.safe)))
         {
             sc.setUnsafe(false, cas.loc, "`asm` statement is assumed to be `@system` - mark it with `@trusted` if it is not");
@@ -3696,7 +3721,7 @@ public bool throwSemantic(const ref Loc loc, ref Expression exp, Scope* sc)
 {
     if (!global.params.useExceptions)
     {
-        loc.error("cannot use `throw` statements with -betterC");
+        loc.error("cannot use `throw` statements with %s", global.params.betterC ? "-betterC".ptr : "-nothrow".ptr);
         return false;
     }
 
@@ -3767,7 +3792,7 @@ private extern(D) Expression applyOpApply(ForeachStatement fs, Expression flde,
         return null;
     if (ec.type != Type.tint32)
     {
-        fs.error("`opApply()` function for `%s` must return an `int`", tab.toChars());
+        error(fs.loc, "`opApply()` function for `%s` must return an `int`", tab.toChars());
         return null;
     }
     return ec;
@@ -3792,7 +3817,7 @@ private extern(D) Expression applyDelegate(ForeachStatement fs, Expression flde,
         return null;
     if (ec.type != Type.tint32)
     {
-        fs.error("`opApply()` function for `%s` must return an `int`", tab.toChars());
+        error(fs.loc, "`opApply()` function for `%s` must return an `int`", tab.toChars());
         return null;
     }
     return ec;
@@ -3841,13 +3866,13 @@ private extern(D) Expression applyArray(ForeachStatement fs, Expression flde,
     FuncDeclaration fdapply;
     TypeDelegate dgty;
     auto params = new Parameters();
-    params.push(new Parameter(STC.in_, tn.arrayOf(), null, null, null));
+    params.push(new Parameter(Loc.initial, STC.in_, tn.arrayOf(), null, null, null));
     auto dgparams = new Parameters();
-    dgparams.push(new Parameter(0, Type.tvoidptr, null, null, null));
+    dgparams.push(new Parameter(Loc.initial, 0, Type.tvoidptr, null, null, null));
     if (dim == 2)
-        dgparams.push(new Parameter(0, Type.tvoidptr, null, null, null));
+        dgparams.push(new Parameter(Loc.initial, 0, Type.tvoidptr, null, null, null));
     dgty = new TypeDelegate(new TypeFunction(ParameterList(dgparams), Type.tint32, LINK.d));
-    params.push(new Parameter(0, dgty, null, null, null));
+    params.push(new Parameter(Loc.initial, 0, dgty, null, null, null));
     fdapply = FuncDeclaration.genCfunc(params, Type.tint32, fdname.ptr);
 
     if (tab.isTypeSArray())
@@ -3879,7 +3904,7 @@ private extern(D) Expression applyAssocArray(ForeachStatement fs, Expression fld
         Type ti = (isRef ? taa.index.addMod(MODFlags.const_) : taa.index);
         if (isRef ? !ti.constConv(ta) : !ti.implicitConvTo(ta))
         {
-            fs.error("`foreach`: index must be type `%s`, not `%s`",
+            error(fs.loc, "`foreach`: index must be type `%s`, not `%s`",
                      ti.toChars(), ta.toChars());
             return null;
         }
@@ -3890,7 +3915,7 @@ private extern(D) Expression applyAssocArray(ForeachStatement fs, Expression fld
     Type taav = taa.nextOf();
     if (isRef ? !taav.constConv(ta) : !taav.implicitConvTo(ta))
     {
-        fs.error("`foreach`: value must be type `%s`, not `%s`",
+        error(fs.loc, "`foreach`: value must be type `%s`, not `%s`",
                  taav.toChars(), ta.toChars());
         return null;
     }
@@ -3908,14 +3933,14 @@ private extern(D) Expression applyAssocArray(ForeachStatement fs, Expression fld
     if (!fdapply[i])
     {
         auto params = new Parameters();
-        params.push(new Parameter(0, Type.tvoid.pointerTo(), null, null, null));
-        params.push(new Parameter(STC.const_, Type.tsize_t, null, null, null));
+        params.push(new Parameter(Loc.initial, 0, Type.tvoid.pointerTo(), null, null, null));
+        params.push(new Parameter(Loc.initial, STC.const_, Type.tsize_t, null, null, null));
         auto dgparams = new Parameters();
-        dgparams.push(new Parameter(0, Type.tvoidptr, null, null, null));
+        dgparams.push(new Parameter(Loc.initial, 0, Type.tvoidptr, null, null, null));
         if (dim == 2)
-            dgparams.push(new Parameter(0, Type.tvoidptr, null, null, null));
+            dgparams.push(new Parameter(Loc.initial, 0, Type.tvoidptr, null, null, null));
         fldeTy[i] = new TypeDelegate(new TypeFunction(ParameterList(dgparams), Type.tint32, LINK.d));
-        params.push(new Parameter(0, fldeTy[i], null, null, null));
+        params.push(new Parameter(Loc.initial, 0, fldeTy[i], null, null, null));
         fdapply[i] = FuncDeclaration.genCfunc(params, Type.tint32, i ? Id._aaApply2 : Id._aaApply);
     }
 
@@ -4000,7 +4025,7 @@ private FuncExp foreachBodyToFunction(Scope* sc, ForeachStatement fs, TypeFuncti
             {
                 if (!(prm.storageClass & STC.ref_))
                 {
-                    fs.error("`foreach`: cannot make `%s` `ref`", p.ident.toChars());
+                    error(fs.loc, "`foreach`: cannot make `%s` `ref`", p.ident.toChars());
                     return null;
                 }
                 goto LcopyArg;
@@ -4026,7 +4051,7 @@ private FuncExp foreachBodyToFunction(Scope* sc, ForeachStatement fs, TypeFuncti
             Statement s = new ExpStatement(fs.loc, v);
             fs._body = new CompoundStatement(fs.loc, s, fs._body);
         }
-        params.push(new Parameter(stc, p.type, id, null, null));
+        params.push(new Parameter(fs.loc, stc, p.type, id, null, null));
     }
     // https://issues.dlang.org/show_bug.cgi?id=13840
     // Throwable nested function inside nothrow function is acceptable.
@@ -4328,7 +4353,7 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState
     const bool skipCheck = isStatic && needExpansion;
     if (!skipCheck && (dim < 1 || dim > 2))
     {
-        fs.error("only one (value) or two (key,value) arguments allowed for sequence `foreach`");
+        error(fs.loc, "only one (value) or two (key,value) arguments allowed for sequence `foreach`");
         return returnEarly();
     }
 
@@ -4390,7 +4415,7 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState
             // Declare key
             if (p.isReference() || p.isLazy())
             {
-                fs.error("no storage class for key `%s`", p.ident.toChars());
+                error(fs.loc, "no storage class for key `%s`", p.ident.toChars());
                 return returnEarly();
             }
 
@@ -4405,7 +4430,7 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState
 
             if (!p.type.isintegral())
             {
-                fs.error("foreach: key cannot be of non-integral type `%s`",
+                error(fs.loc, "foreach: key cannot be of non-integral type `%s`",
                          p.type.toChars());
                 return returnEarly();
             }
@@ -4416,7 +4441,7 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState
             dimrange.imax = SignExtendedNumber(dimrange.imax.value-1);
             if (!IntRange.fromType(p.type).contains(dimrange))
             {
-                fs.error("index type `%s` cannot cover index range 0..%llu",
+                error(fs.loc, "index type `%s` cannot cover index range 0..%llu",
                          p.type.toChars(), cast(ulong)length);
                 return returnEarly();
             }
@@ -4450,7 +4475,7 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState
             if (storageClass & (STC.out_ | STC.lazy_) ||
                 storageClass & STC.ref_ && !te)
             {
-                fs.error("no storage class for value `%s`", ident.toChars());
+                error(fs.loc, "no storage class for value `%s`", ident.toChars());
                 return false;
             }
             Declaration var;
@@ -4478,7 +4503,7 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState
                 }
                 else if (storageClass & STC.alias_)
                 {
-                    fs.error("`foreach` loop variable cannot be both `enum` and `alias`");
+                    error(fs.loc, "`foreach` loop variable cannot be both `enum` and `alias`");
                     return false;
                 }
 
@@ -4487,12 +4512,12 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState
                     var = new AliasDeclaration(loc, ident, ds);
                     if (storageClass & STC.ref_)
                     {
-                        fs.error("symbol `%s` cannot be `ref`", ds.toChars());
+                        error(fs.loc, "symbol `%s` cannot be `ref`", ds.toChars());
                         return false;
                     }
                     if (paramtype)
                     {
-                        fs.error("cannot specify element type for symbol `%s`", ds.toChars());
+                        error(fs.loc, "cannot specify element type for symbol `%s`", ds.toChars());
                         return false;
                     }
                 }
@@ -4501,7 +4526,7 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState
                     var = new AliasDeclaration(loc, ident, e.type);
                     if (paramtype)
                     {
-                        fs.error("cannot specify element type for type `%s`", e.type.toChars());
+                        error(fs.loc, "cannot specify element type for type `%s`", e.type.toChars());
                         return false;
                     }
                 }
@@ -4522,17 +4547,17 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState
                         {
                             if (!isStatic)
                             {
-                                fs.error("constant value `%s` cannot be `ref`", ie.toChars());
+                                error(fs.loc, "constant value `%s` cannot be `ref`", ie.toChars());
                             }
                             else
                             {
                                 if (!needExpansion)
                                 {
-                                    fs.error("constant value `%s` cannot be `ref`", ie.toChars());
+                                    error(fs.loc, "constant value `%s` cannot be `ref`", ie.toChars());
                                 }
                                 else
                                 {
-                                    fs.error("constant value `%s` cannot be `ref`", ident.toChars());
+                                    error(fs.loc, "constant value `%s` cannot be `ref`", ident.toChars());
                                 }
                             }
                             return false;
@@ -4548,7 +4573,7 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState
                 var = new AliasDeclaration(loc, ident, t);
                 if (paramtype)
                 {
-                    fs.error("cannot specify element type for symbol `%s`", fs.toChars());
+                    error(fs.loc, "cannot specify element type for symbol `%s`", fs.toChars());
                     return false;
                 }
             }
diff --git a/gcc/d/dmd/tokens.d b/gcc/d/dmd/tokens.d
index 950c830cb33..c76d549550a 100644
--- a/gcc/d/dmd/tokens.d
+++ b/gcc/d/dmd/tokens.d
@@ -124,6 +124,7 @@ enum TOK : ubyte
     // Leaf operators
     identifier,
     string_,
+    hexadecimalString,
     this_,
     super_,
     error,
@@ -855,6 +856,7 @@ extern (C++) struct Token
         TOK.wcharLiteral: "wcharv",
         TOK.dcharLiteral: "dcharv",
         TOK.wchar_tLiteral: "wchar_tv",
+        TOK.hexadecimalString: "xstring",
         TOK.endOfLine: "\\n",
         TOK.whitespace: "whitespace",
 
@@ -898,7 +900,7 @@ extern (C++) struct Token
 
 nothrow:
 
-    int isKeyword() const @safe
+    int isKeyword() pure const @safe @nogc
     {
         foreach (kw; keywords)
         {
@@ -1014,6 +1016,24 @@ nothrow:
                 p = buf.extractChars();
             }
             break;
+        case TOK.hexadecimalString:
+            {
+                OutBuffer buf;
+                buf.writeByte('x');
+                buf.writeByte('"');
+                foreach (size_t i; 0 .. len)
+                {
+                    if (i)
+                        buf.writeByte(' ');
+                    buf.printf("%02x", ustring[i]);
+                }
+                buf.writeByte('"');
+                if (postfix)
+                    buf.writeByte(postfix);
+                buf.writeByte(0);
+                p = buf.extractData();
+                break;
+            }
         case TOK.identifier:
         case TOK.enum_:
         case TOK.struct_:
diff --git a/gcc/d/dmd/tokens.h b/gcc/d/dmd/tokens.h
index 6c1b9792dbb..b1f633fb9d9 100644
--- a/gcc/d/dmd/tokens.h
+++ b/gcc/d/dmd/tokens.h
@@ -133,6 +133,7 @@ enum class TOK : unsigned char
     // Leaf operators
     identifier,
     string_,
+    hexadecimalString,
     this_,
     super_,
     error,
diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d
index 0d9c95ff173..2bde9f2aee9 100644
--- a/gcc/d/dmd/traits.d
+++ b/gcc/d/dmd/traits.d
@@ -1920,7 +1920,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         StringExp se = ex ? ex.ctfeInterpret().toStringExp() : null;
         if (!ex || !se || se.len == 0)
         {
-            e.error("string expected as argument of __traits `%s` instead of `%s`", e.ident.toChars(), ex.toChars());
+            e.error("string expected as argument of __traits `%s` instead of `%s`", e.ident.toChars(), (*e.args)[0].toChars());
             return ErrorExp.get();
         }
         se = se.toUTF8(sc);
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index a80aa80a89d..1422689dce0 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -1170,8 +1170,8 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
                             StorageClass stc2 =   narg.storageClass & (STC.ref_ | STC.out_ | STC.lazy_);
                             if (stc1 && stc2 && stc1 != stc2)
                             {
-                                OutBuffer buf1;  stcToBuffer(&buf1, stc1 | ((stc1 & STC.ref_) ? (fparam.storageClass & STC.auto_) : 0));
-                                OutBuffer buf2;  stcToBuffer(&buf2, stc2);
+                                OutBuffer buf1;  stcToBuffer(buf1, stc1 | ((stc1 & STC.ref_) ? (fparam.storageClass & STC.auto_) : 0));
+                                OutBuffer buf2;  stcToBuffer(buf2, stc2);
 
                                 .error(loc, "incompatible parameter storage classes `%s` and `%s`",
                                     buf1.peekChars(), buf2.peekChars());
@@ -1179,7 +1179,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
                                 stc = stc1 | (stc & ~(STC.ref_ | STC.out_ | STC.lazy_));
                             }
                             (*newparams)[j] = new Parameter(
-                                stc, narg.type, narg.ident, narg.defaultArg, narg.userAttribDecl);
+                                loc, stc, narg.type, narg.ident, narg.defaultArg, narg.userAttribDecl);
                         }
                         fparam.type = new TypeTuple(newparams);
                         fparam.type = fparam.type.typeSemantic(loc, argsc);
@@ -2089,6 +2089,7 @@ Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier iden
             {
                 e = new StringExp(loc, mt.deco.toDString());
                 Scope sc;
+                sc.eSink = global.errorSink;
                 e = e.expressionSemantic(&sc);
             }
         }
@@ -2097,6 +2098,7 @@ Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier iden
             const s = mt.toChars();
             e = new StringExp(loc, s.toDString());
             Scope sc;
+            sc.eSink = global.errorSink;
             e = e.expressionSemantic(&sc);
         }
         else if (flag && mt != Type.terror)
@@ -2127,7 +2129,9 @@ Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier iden
                         error(loc, "no property `%s` for `%s` of type `%s`", ident.toChars(), src.toChars(), mt.toPrettyChars(true));
                     else
                         error(loc, "no property `%s` for type `%s`", ident.toChars(), mt.toPrettyChars(true));
+
                     if (auto dsym = mt.toDsymbol(scope_))
+                    {
                         if (auto sym = dsym.isAggregateDeclaration())
                         {
                             if (auto fd = search_function(sym, Id.opDispatch))
@@ -2135,6 +2139,9 @@ Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier iden
                             else if (!sym.members)
                                 errorSupplemental(sym.loc, "`%s %s` is opaque and has no members.", sym.kind, mt.toPrettyChars(true));
                         }
+                        errorSupplemental(dsym.loc, "%s `%s` defined here",
+                            dsym.kind, dsym.toChars());
+                    }
                 }
             }
             e = ErrorExp.get();
@@ -3482,7 +3489,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag
             if (fd_aaLen is null)
             {
                 auto fparams = new Parameters();
-                fparams.push(new Parameter(STC.const_ | STC.scope_, mt, null, null, null));
+                fparams.push(new Parameter(Loc.initial, STC.const_ | STC.scope_, mt, null, null, null));
                 fd_aaLen = FuncDeclaration.genCfunc(fparams, Type.tsize_t, Id.aaLen);
                 TypeFunction tf = fd_aaLen.type.toTypeFunction();
                 tf.purity = PURE.const_;
@@ -3938,6 +3945,8 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag
                     e.error("no property `%s` for type `%s`", ident.toChars(),
                         mt.toChars());
 
+                errorSupplemental(mt.sym.loc, "%s `%s` defined here",
+                    mt.sym.kind, mt.toChars());
                 return ErrorExp.get();
             }
             return res;
@@ -4791,7 +4800,7 @@ Type stripDefaultArgs(Type t)
         {
             Type t = stripDefaultArgs(p.type);
             return (t != p.type || p.defaultArg || p.ident || p.userAttribDecl)
-                ? new Parameter(p.storageClass, t, null, null, null)
+                ? new Parameter(p.loc, p.storageClass, t, null, null, null)
                 : null;
         }
 
diff --git a/gcc/d/dmd/utils.d b/gcc/d/dmd/utils.d
index dfb4cb5ee2d..bb389b65903 100644
--- a/gcc/d/dmd/utils.d
+++ b/gcc/d/dmd/utils.d
@@ -53,12 +53,6 @@ const(char)* toWinPath(const(char)* src)
  *   loc = The line number information from where the call originates
  *   filename = Path to file
  */
-Buffer readFile(Loc loc, const(char)* filename)
-{
-    return readFile(loc, filename.toDString());
-}
-
-/// Ditto
 Buffer readFile(Loc loc, const(char)[] filename)
 {
     auto result = File.read(filename);
@@ -78,15 +72,19 @@ Buffer readFile(Loc loc, const(char)[] filename)
  *   loc = The line number information from where the call originates
  *   filename = Path to file
  *   data = Full content of the file to be written
+ * Returns:
+ *   false on error
  */
-extern (D) void writeFile(Loc loc, const(char)[] filename, const void[] data)
+extern (D) bool writeFile(Loc loc, const(char)[] filename, const void[] data)
 {
-    ensurePathToNameExists(Loc.initial, filename);
+    if (!ensurePathToNameExists(Loc.initial, filename))
+        return false;
     if (!File.update(filename, data))
     {
         error(loc, "error writing file '%.*s'", cast(int) filename.length, filename.ptr);
-        fatal();
+        return false;
     }
+    return true;
 }
 
 
@@ -97,8 +95,10 @@ extern (D) void writeFile(Loc loc, const(char)[] filename, const void[] data)
  * Params:
  *   loc = The line number information from where the call originates
  *   name = a path to check (the name is stripped)
+ * Returns:
+ *      false on error
  */
-void ensurePathToNameExists(Loc loc, const(char)[] name)
+bool ensurePathToNameExists(Loc loc, const(char)[] name)
 {
     const char[] pt = FileName.path(name);
     if (pt.length)
@@ -106,10 +106,12 @@ void ensurePathToNameExists(Loc loc, const(char)[] name)
         if (!FileName.ensurePathExists(pt))
         {
             error(loc, "cannot create directory %*.s", cast(int) pt.length, pt.ptr);
-            fatal();
+            FileName.free(pt.ptr);
+            return false;
         }
     }
     FileName.free(pt.ptr);
+    return true;
 }
 
 
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index 551d004c241..cc4aa03dfb9 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -2725,6 +2725,15 @@ public:
 
   void visit (AssocArrayLiteralExp *e) final override
   {
+    if (e->lowering != NULL)
+      {
+	/* When an associative array literal gets lowered, it's converted into a
+	   struct literal suitable for static initialization.  */
+	gcc_assert (this->constp_);
+	this->result_ = build_expr (e->lowering, this->constp_, true);
+	return ;
+      }
+
     /* Want the mutable type for typeinfo reference.  */
     Type *tb = e->type->toBasetype ()->mutableOf ();
 
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_StructDeclaration.d b/gcc/testsuite/gdc.test/compilable/dtoh_StructDeclaration.d
index 2e36c7d02be..f8448d943e9 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_StructDeclaration.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_StructDeclaration.d
@@ -224,6 +224,15 @@ struct Params final
         ddocfiles(ddocfiles)
         {}
 };
+
+struct Loc final
+{
+    static int32_t showColumns;
+    void toChars(int32_t showColumns = Loc::showColumns);
+    Loc()
+    {
+    }
+};
 ---
 */
 
@@ -337,3 +346,9 @@ extern (C++) struct Params
     bool obj = true;
     Array ddocfiles;
 }
+
+extern (C++) struct Loc
+{
+    __gshared int showColumns;
+    void toChars(int showColumns = Loc.showColumns) {}
+}
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_functions.d b/gcc/testsuite/gdc.test/compilable/dtoh_functions.d
index 38607f6d4b1..90223cca81e 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_functions.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_functions.d
@@ -45,10 +45,10 @@ struct S final
     int32_t get(int32_t , int32_t );
     static int32_t get();
     static const int32_t staticVar;
-    void useVars(int32_t pi = i, int32_t psv = staticVar);
+    void useVars(int32_t pi = i, int32_t psv = S::staticVar);
     struct Nested final
     {
-        void useStaticVar(int32_t i = staticVar);
+        void useStaticVar(int32_t i = S::staticVar);
         Nested()
         {
         }
diff --git a/gcc/testsuite/gdc.test/compilable/issue22682.d b/gcc/testsuite/gdc.test/compilable/issue22682.d
new file mode 100644
index 00000000000..5301a5163cd
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/issue22682.d
@@ -0,0 +1,8 @@
+module issue22682;
+
+void main()
+{
+    pragma(mangle, "put" ~ "s")
+    extern(C) static int libcPuts(const char*);
+    libcPuts("issue 22682");
+}
diff --git a/gcc/testsuite/gdc.test/compilable/obsolete_body.d b/gcc/testsuite/gdc.test/compilable/obsolete_body.d
new file mode 100644
index 00000000000..71906e8f25e
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/obsolete_body.d
@@ -0,0 +1,5 @@
+/* REQUIRED_ARGS: -w
+*/
+
+void test()
+in { } body { }
diff --git a/gcc/testsuite/gdc.test/compilable/shortened_methods.d b/gcc/testsuite/gdc.test/compilable/shortened_methods.d
index 71350af8739..785cb8e5cd0 100644
--- a/gcc/testsuite/gdc.test/compilable/shortened_methods.d
+++ b/gcc/testsuite/gdc.test/compilable/shortened_methods.d
@@ -27,7 +27,12 @@ string test() => "hello"; // works at any scope
 static assert(test() == "hello"); // works normally
 static assert(is(typeof(&test) == string function())); // same normal type
 
+struct S(T) {}
+
 void func() {
     int a;
     int nested() => a; // and at nested scopes too
+
+    // Issue 24088 - https://issues.dlang.org/show_bug.cgi?id=24088
+    S!int f() => S!int();
 }
diff --git a/gcc/testsuite/gdc.test/compilable/test23145.d b/gcc/testsuite/gdc.test/compilable/test23145.d
index 18eabfb51b5..c6bb55181b1 100644
--- a/gcc/testsuite/gdc.test/compilable/test23145.d
+++ b/gcc/testsuite/gdc.test/compilable/test23145.d
@@ -1,11 +1,4 @@
-/* REQUIRED_ARGS: -wo -wi
-TEST_OUTPUT:
----
-compilable/test23145.d(117): Warning: `scope` allocation of `c` requires that constructor be annotated with `scope`
-compilable/test23145.d(111):        is the location of the constructor
-compilable/test23145.d(124): Warning: `scope` allocation of `c` requires that constructor be annotated with `scope`
-compilable/test23145.d(111):        is the location of the constructor
----
+/* REQUIRED_ARGS: -wi
 */
 
 // https://issues.dlang.org/show_bug.cgi?id=23145
@@ -28,14 +21,14 @@ class C
 C foo(D d) @nogc @safe
 {
     scope e = new C(1);  // ok
-    scope c = new C(d);  // deprecation
+    scope c = new C(d);  // obsolete
     return c.d.c;
 }
 
 C bax(D d) @safe
 {
     scope e = new C(1);  // ok
-    scope c = new C(d);  // deprecation
+    scope c = new C(d);  // obsolete
     return c.d.c;
 }
 
diff --git a/gcc/testsuite/gdc.test/compilable/test24066.d b/gcc/testsuite/gdc.test/compilable/test24066.d
new file mode 100644
index 00000000000..4b8a0b345bc
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test24066.d
@@ -0,0 +1,11 @@
+// https://issues.dlang.org/show_bug.cgi?id=24066
+
+/*
+TEST_OUTPUT:
+---
+false
+---
+*/
+
+class C;
+pragma(msg, __traits(isAbstractClass, C));
diff --git a/gcc/testsuite/gdc.test/compilable/test24107.d b/gcc/testsuite/gdc.test/compilable/test24107.d
new file mode 100644
index 00000000000..d16c259f16c
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test24107.d
@@ -0,0 +1,17 @@
+// https://issues.dlang.org/show_bug.cgi?id=24107
+
+/*
+TEST_OUTPUT:
+---
+This should not output an error message: false
+---
+*/
+
+bool recurse ()
+{
+    return recurse();
+}
+
+pragma(msg,
+        "This should not output an error message: ",
+       __traits(compiles, {enum bool r = recurse();}));
diff --git a/gcc/testsuite/gdc.test/compilable/test24109.d b/gcc/testsuite/gdc.test/compilable/test24109.d
new file mode 100644
index 00000000000..67d03b58b06
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test24109.d
@@ -0,0 +1,17 @@
+// https://issues.dlang.org/show_bug.cgi?id=24109
+
+struct Outer
+{
+    void method1() {}
+
+    void method2()
+    {
+        class Inner
+        {
+            void innerMethod()
+            {
+                method1();
+            }
+        }
+    }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test24118.d b/gcc/testsuite/gdc.test/compilable/test24118.d
new file mode 100644
index 00000000000..25376b73b18
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test24118.d
@@ -0,0 +1,15 @@
+// https://issues.dlang.org/show_bug.cgi?id=24118
+
+void map(alias fun, T)(T[] arr)
+{
+    fun(arr);
+}
+
+
+void foo()
+{
+    if( __ctfe )
+    {
+        ["a", "b", "c"].map!( a => " " ~ a[0] );
+    }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/aa_init.d b/gcc/testsuite/gdc.test/fail_compilation/aa_init.d
new file mode 100644
index 00000000000..b1473c136da
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/aa_init.d
@@ -0,0 +1,16 @@
+/*
+REQUIRED_ARGS: -vcolumns
+TEST_OUTPUT:
+---
+fail_compilation/aa_init.d(13,18): Error: invalid associative array initializer `[]`, use `null` instead
+fail_compilation/aa_init.d(14,24): Error: missing key for value `4` in initializer
+fail_compilation/aa_init.d(15,9): Error: cannot implicitly convert expression `[]` of type `void[]` to `int[int]`
+---
+*/
+
+void main()
+{
+    int[int] a = [];
+    int[int] b = [2:3, 4];
+    a = [];
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/body.d b/gcc/testsuite/gdc.test/fail_compilation/body.d
deleted file mode 100644
index 7b718c25060..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/body.d
+++ /dev/null
@@ -1,11 +0,0 @@
-/* REQUIRED_ARGS: -wo -w
-TEST_OUTPUT:
----
-fail_compilation/body.d(11): Warning: usage of identifer `body` as a keyword is obsolete. Use `do` instead.
-Error: warnings are treated as errors
-       Use -wi if you wish to treat warnings only as informational.
----
-*/
-
-void test()
-in { } body { }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/chkformat.d b/gcc/testsuite/gdc.test/fail_compilation/chkformat.d
index eb75f4267b9..bd924665e3a 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/chkformat.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/chkformat.d
@@ -24,6 +24,7 @@ fail_compilation/chkformat.d(122): Deprecation: argument `0LU` for format specif
 fail_compilation/chkformat.d(122):        C `long` is 4 bytes on your system|32=
 fail_compilation/chkformat.d(122): Deprecation: argument `0LU` for format specification `"%lu"` must be `uint`, not `ulong`
 fail_compilation/chkformat.d(122):        C `long` is 4 bytes on your system$
+fail_compilation/chkformat.d(123): Deprecation: argument `p` for format specification `"%n"` must be `int*`, not `const(int)*`
 fail_compilation/chkformat.d(201): Deprecation: argument `0L` for format specification `"%d"` must be `int*`, not `long`
 fail_compilation/chkformat.d(202): Deprecation: more format specifiers than 1 arguments
 fail_compilation/chkformat.d(203): Deprecation: argument `0L` for format specification `"%d"` must be `int*`, not `long`
@@ -86,6 +87,7 @@ void test19() { int u; printf("%ls\n", &u); }
 //void test20() { int u; char[] s; sprintf(&s[0], "%d\n", &u); }
 //void test21() { int u; fprintf(null, "%d\n", &u); }
 void test20() { printf("%lu", ulong.init); }
+void test22() { int i; const(int)* p = &i; printf("%n", p); }
 
 #line 200
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/dephexstrings.d b/gcc/testsuite/gdc.test/fail_compilation/dephexstrings.d
deleted file mode 100644
index 553a0c64a20..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/dephexstrings.d
+++ /dev/null
@@ -1,9 +0,0 @@
-// REQUIRED_ARGS: -de
-/*
-TEST_OUTPUT:
----
-fail_compilation/dephexstrings.d(9): Error: semicolon expected following auto declaration, not `"60"`
-fail_compilation/dephexstrings.d(9): Error: declaration expected, not `"60"`
----
-*/
-enum xstr = x"60";
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag10169.d b/gcc/testsuite/gdc.test/fail_compilation/diag10169.d
index 84d0ad4696b..e21a334548d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag10169.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag10169.d
@@ -2,7 +2,8 @@
 EXTRA_FILES: imports/a10169.d
 TEST_OUTPUT:
 ---
-fail_compilation/diag10169.d(12): Error: no property `x` for `B(0)` of type `imports.a10169.B`
+fail_compilation/diag10169.d(13): Error: no property `x` for `B(0)` of type `imports.a10169.B`
+fail_compilation/imports/a10169.d(3):        struct `B` defined here
 ---
 */
 import imports.a10169;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag10783.d b/gcc/testsuite/gdc.test/fail_compilation/diag10783.d
index 80c7f5e56ea..e69eddbec03 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag10783.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag10783.d
@@ -1,8 +1,9 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag10783.d(14): Error: no property `type` for `event` of type `diag10783.Event`
-fail_compilation/diag10783.d(14): Error: undefined identifier `En`
+fail_compilation/diag10783.d(15): Error: no property `type` for `event` of type `diag10783.Event`
+fail_compilation/diag10783.d(10):        struct `Event` defined here
+fail_compilation/diag10783.d(15): Error: undefined identifier `En`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag12063.d b/gcc/testsuite/gdc.test/fail_compilation/diag12063.d
index 882a8091076..3e9535ab421 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag12063.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag12063.d
@@ -1,8 +1,13 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag12063.d(11): Error: no property `max` for type `Foo`, perhaps `import std.algorithm;` is needed?
-fail_compilation/diag12063.d(14): Error: incompatible types for `(Foo()) + (1)`: `Bar` and `int`
+fail_compilation/diag12063.d(19): Error: cannot check `diag12063.Bar.b` value for overflow
+fail_compilation/diag12063.d(16): Error: no property `max` for type `Foo`, perhaps `import std.algorithm;` is needed?
+fail_compilation/diag12063.d(19): Error: cannot generate value for `diag12063.Bar.b`
+fail_compilation/diag12063.d(19): Error: incompatible types for `(Foo()) + (1)`: `Bar` and `int`
+fail_compilation/diag12063.d(29): Error: cannot check `diag12063.b` value for overflow
+fail_compilation/diag12063.d(29): Error: incompatible types for `(S()) == (1)`: `S` and `int`
+fail_compilation/diag12063.d(38): Error: enum member `diag12063.d` initialization with `__anonymous.c+1` causes overflow for type `Q`
 ---
 */
 
@@ -11,5 +16,36 @@ struct Foo {}
 enum Bar : Foo
 {
     a = Foo(),
-    b
+    b // no max, can't +1
+}
+
+struct S {
+    S opBinary(string s: "+")(int) => this;
+    enum max = 1; // wrong type
+}
+
+enum {
+    a = S(),
+    b // can't do S() == 1
+}
+
+struct Q {
+    enum max = Q();
+}
+
+enum {
+    c = Q(),
+    d // overflow detected
+}
+
+struct R {
+    int i;
+    R opBinary(string s: "+")(int) => this;
+    enum max = R(1);
+}
+
+enum ER
+{
+    e = R(),
+    f // OK
 }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag12829.d b/gcc/testsuite/gdc.test/fail_compilation/diag12829.d
index 1d37a1ecbfe..aaedd0f7217 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag12829.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag12829.d
@@ -1,11 +1,14 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag12829.d(12): Error: function `diag12829.test1` is `@nogc` yet allocates closure for `test1()` with the GC
-fail_compilation/diag12829.d(15):        `diag12829.test1.__lambda2` closes over variable `x` at fail_compilation/diag12829.d(14)
-fail_compilation/diag12829.d(19):        `diag12829.test1.bar` closes over variable `x` at fail_compilation/diag12829.d(14)
-fail_compilation/diag12829.d(26): Error: function `diag12829.test2` is `@nogc` yet allocates closure for `test2()` with the GC
-fail_compilation/diag12829.d(31):        `diag12829.test2.S.foo` closes over variable `x` at fail_compilation/diag12829.d(28)
+fail_compilation/diag12829.d(15): Error: function `diag12829.test1` is `@nogc` yet allocates closure for `test1()` with the GC
+fail_compilation/diag12829.d(18):        delegate `diag12829.test1.__lambda2` closes over variable `x`
+fail_compilation/diag12829.d(17):        `x` declared here
+fail_compilation/diag12829.d(22):        function `diag12829.test1.bar` closes over variable `x`
+fail_compilation/diag12829.d(17):        `x` declared here
+fail_compilation/diag12829.d(29): Error: function `diag12829.test2` is `@nogc` yet allocates closure for `test2()` with the GC
+fail_compilation/diag12829.d(34):        function `diag12829.test2.S.foo` closes over variable `x`
+fail_compilation/diag12829.d(31):        `x` declared here
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag13609a.d b/gcc/testsuite/gdc.test/fail_compilation/diag13609a.d
index 039129e770f..7d0e259e41b 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag13609a.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag13609a.d
@@ -1,10 +1,15 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag13609a.d(11): Error: `}` expected following members in `class` declaration at fail_compilation/diag13609a.d(8)
+fail_compilation/diag13609a.d(16): Error: `}` expected following members in `struct` declaration
+fail_compilation/diag13609a.d(15):        struct starts here
+fail_compilation/diag13609a.d(16): Error: `}` expected following members in `class` declaration
+fail_compilation/diag13609a.d(11):        class `C` starts here
 ---
 */
 
 class C
 {
     void foo() {}
+
+    struct {
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag14145.d b/gcc/testsuite/gdc.test/fail_compilation/diag14145.d
index fa7c6114ad6..fee73078e30 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag14145.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag14145.d
@@ -1,10 +1,11 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag14145.d(15): Error: no property `i` for `_` of type `diag14145.main.Capture!(i)`
-fail_compilation/diag14145.d(15):        potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message
-fail_compilation/diag14145.d(34): Error: expression `*this.ptr` of type `shared(int)` is not implicitly convertible to return type `ref int`
-fail_compilation/diag14145.d(16): Error: template instance `diag14145.main.Capture!(i).Capture.opDispatch!"i"` error instantiating
+fail_compilation/diag14145.d(16): Error: no property `i` for `_` of type `diag14145.main.Capture!(i)`
+fail_compilation/diag14145.d(16):        potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message
+fail_compilation/diag14145.d(26):        struct `Capture` defined here
+fail_compilation/diag14145.d(35): Error: expression `*this.ptr` of type `shared(int)` is not implicitly convertible to return type `ref int`
+fail_compilation/diag14145.d(17): Error: template instance `diag14145.main.Capture!(i).Capture.opDispatch!"i"` error instantiating
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag15713.d b/gcc/testsuite/gdc.test/fail_compilation/diag15713.d
index e4cb2a7603a..00713449a5f 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag15713.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag15713.d
@@ -1,10 +1,11 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag15713.d(19): Error: no property `widthSign` for `this` of type `diag15713.WrData.Data`
-fail_compilation/diag15713.d(39): Error: template instance `diag15713.conwritefImpl!("parse-int", "width", "\n", Data(null))` error instantiating
-fail_compilation/diag15713.d(44):        instantiated from here: `conwritefImpl!("main", "\n", Data(null))`
-fail_compilation/diag15713.d(49):        instantiated from here: `fdwritef!()`
+fail_compilation/diag15713.d(20): Error: no property `widthSign` for `this` of type `diag15713.WrData.Data`
+fail_compilation/diag15713.d(16):        struct `Data` defined here
+fail_compilation/diag15713.d(40): Error: template instance `diag15713.conwritefImpl!("parse-int", "width", "\n", Data(null))` error instantiating
+fail_compilation/diag15713.d(45):        instantiated from here: `conwritefImpl!("main", "\n", Data(null))`
+fail_compilation/diag15713.d(50):        instantiated from here: `fdwritef!()`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag3913.d b/gcc/testsuite/gdc.test/fail_compilation/diag3913.d
index abf70b84ce7..41c08b0a76e 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag3913.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag3913.d
@@ -1,8 +1,10 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag3913.d(12): Error: no property `foobardoo` for type `Foo`
-fail_compilation/diag3913.d(13): Error: no property `secon` for type `Foo`. Did you mean `Foo.second` ?
+fail_compilation/diag3913.d(14): Error: no property `foobardoo` for type `Foo`
+fail_compilation/diag3913.d(13):        enum `Foo` defined here
+fail_compilation/diag3913.d(15): Error: no property `secon` for type `Foo`. Did you mean `Foo.second` ?
+fail_compilation/diag3913.d(13):        enum `Foo` defined here
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag5385.d b/gcc/testsuite/gdc.test/fail_compilation/diag5385.d
index 60455eca206..368fdfff529 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag5385.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag5385.d
@@ -2,14 +2,22 @@
 EXTRA_FILES: imports/fail5385.d
 TEST_OUTPUT:
 ---
-fail_compilation/diag5385.d(20): Error: no property `privX` for type `imports.fail5385.C`
-fail_compilation/diag5385.d(21): Error: no property `packX` for type `imports.fail5385.C`
-fail_compilation/diag5385.d(22): Error: no property `privX2` for type `imports.fail5385.C`
-fail_compilation/diag5385.d(23): Error: no property `packX2` for type `imports.fail5385.C`
-fail_compilation/diag5385.d(24): Error: no property `privX` for type `imports.fail5385.S`
-fail_compilation/diag5385.d(25): Error: no property `packX` for type `imports.fail5385.S`
-fail_compilation/diag5385.d(26): Error: no property `privX2` for type `imports.fail5385.S`
-fail_compilation/diag5385.d(27): Error: no property `packX2` for type `imports.fail5385.S`
+fail_compilation/diag5385.d(28): Error: no property `privX` for type `imports.fail5385.C`
+fail_compilation/imports/fail5385.d(3):        class `C` defined here
+fail_compilation/diag5385.d(29): Error: no property `packX` for type `imports.fail5385.C`
+fail_compilation/imports/fail5385.d(3):        class `C` defined here
+fail_compilation/diag5385.d(30): Error: no property `privX2` for type `imports.fail5385.C`
+fail_compilation/imports/fail5385.d(3):        class `C` defined here
+fail_compilation/diag5385.d(31): Error: no property `packX2` for type `imports.fail5385.C`
+fail_compilation/imports/fail5385.d(3):        class `C` defined here
+fail_compilation/diag5385.d(32): Error: no property `privX` for type `imports.fail5385.S`
+fail_compilation/imports/fail5385.d(11):        struct `S` defined here
+fail_compilation/diag5385.d(33): Error: no property `packX` for type `imports.fail5385.S`
+fail_compilation/imports/fail5385.d(11):        struct `S` defined here
+fail_compilation/diag5385.d(34): Error: no property `privX2` for type `imports.fail5385.S`
+fail_compilation/imports/fail5385.d(11):        struct `S` defined here
+fail_compilation/diag5385.d(35): Error: no property `packX2` for type `imports.fail5385.S`
+fail_compilation/imports/fail5385.d(11):        struct `S` defined here
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag7477.d b/gcc/testsuite/gdc.test/fail_compilation/diag7477.d
index b82b33de946..b14a3c5df65 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag7477.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag7477.d
@@ -1,8 +1,8 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag7477.d(13): Error: integral constant must be scalar type, not `Foo`
-fail_compilation/diag7477.d(20): Error: integral constant must be scalar type, not `string`
+fail_compilation/diag7477.d(13): Error: cannot generate 0 value of type `Foo` for `a`
+fail_compilation/diag7477.d(20): Error: cannot generate 0 value of type `string` for `a`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag8697.d b/gcc/testsuite/gdc.test/fail_compilation/diag8697.d
index a2abad58764..bcc0be09897 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag8697.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag8697.d
@@ -1,7 +1,8 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag8697.d(10): Error: no property `Invalid` for type `diag8697.Base`
+fail_compilation/diag8697.d(11): Error: no property `Invalid` for type `diag8697.Base`
+fail_compilation/diag8697.d(9):        class `Base` defined here
 ---
 */
 interface InterBase : InterRoot { }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag8894.d b/gcc/testsuite/gdc.test/fail_compilation/diag8894.d
index 7cf3023aedb..e8e0c74cc32 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag8894.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag8894.d
@@ -1,10 +1,14 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag8894.d(16): Error: no property `x` for `f` of type `diag8894.Foo`
-fail_compilation/diag8894.d(17): Error: no property `y` for `f` of type `diag8894.Foo`
-fail_compilation/diag8894.d(18): Error: no property `x` for `f` of type `diag8894.Foo`
-fail_compilation/diag8894.d(19): Error: no property `x` for `f` of type `diag8894.Foo`
+fail_compilation/diag8894.d(20): Error: no property `x` for `f` of type `diag8894.Foo`
+fail_compilation/diag8894.d(15):        struct `Foo` defined here
+fail_compilation/diag8894.d(21): Error: no property `y` for `f` of type `diag8894.Foo`
+fail_compilation/diag8894.d(15):        struct `Foo` defined here
+fail_compilation/diag8894.d(22): Error: no property `x` for `f` of type `diag8894.Foo`
+fail_compilation/diag8894.d(15):        struct `Foo` defined here
+fail_compilation/diag8894.d(23): Error: no property `x` for `f` of type `diag8894.Foo`
+fail_compilation/diag8894.d(15):        struct `Foo` defined here
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/dip1000_deprecation.d b/gcc/testsuite/gdc.test/fail_compilation/dip1000_deprecation.d
index e591a1428a5..77ab52046fc 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/dip1000_deprecation.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/dip1000_deprecation.d
@@ -1,17 +1,14 @@
 /*
-REQUIRED_ARGS: -de -wo
+REQUIRED_ARGS: -de
 TEST_OUTPUT:
 ---
-fail_compilation/dip1000_deprecation.d(20): Deprecation: `@safe` function `main` calling `inferred`
-fail_compilation/dip1000_deprecation.d(28):        which wouldn't be `@safe` because of:
-fail_compilation/dip1000_deprecation.d(28):        scope variable `x0` may not be returned
-fail_compilation/dip1000_deprecation.d(22): Deprecation: `@safe` function `main` calling `inferredC`
-fail_compilation/dip1000_deprecation.d(39):        which calls `dip1000_deprecation.inferred`
-fail_compilation/dip1000_deprecation.d(28):        which wouldn't be `@safe` because of:
-fail_compilation/dip1000_deprecation.d(28):        scope variable `x0` may not be returned
-fail_compilation/dip1000_deprecation.d(54): Warning: escaping reference to stack allocated value returned by `S(null)`
-fail_compilation/dip1000_deprecation.d(55): Warning: escaping reference to stack allocated value returned by `createS()`
-fail_compilation/dip1000_deprecation.d(58): Warning: returning `s.incorrectReturnRef()` escapes a reference to local variable `s`
+fail_compilation/dip1000_deprecation.d(17): Deprecation: `@safe` function `main` calling `inferred`
+fail_compilation/dip1000_deprecation.d(25):        which wouldn't be `@safe` because of:
+fail_compilation/dip1000_deprecation.d(25):        scope variable `x0` may not be returned
+fail_compilation/dip1000_deprecation.d(19): Deprecation: `@safe` function `main` calling `inferredC`
+fail_compilation/dip1000_deprecation.d(36):        which calls `dip1000_deprecation.inferred`
+fail_compilation/dip1000_deprecation.d(25):        which wouldn't be `@safe` because of:
+fail_compilation/dip1000_deprecation.d(25):        scope variable `x0` may not be returned
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/dip22a.d b/gcc/testsuite/gdc.test/fail_compilation/dip22a.d
index 324d21733af..661ebc33fa6 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/dip22a.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/dip22a.d
@@ -2,11 +2,13 @@
 EXTRA_FILES: imports/dip22a.d
 TEST_OUTPUT:
 ---
-fail_compilation/dip22a.d(16): Error: no property `bar` for `new Klass` of type `imports.dip22a.Klass`
-fail_compilation/dip22a.d(17): Error: no property `bar` for `Struct()` of type `imports.dip22a.Struct`
-fail_compilation/dip22a.d(18): Error: undefined identifier `bar` in module `imports.dip22a`
-fail_compilation/dip22a.d(19): Error: no property `bar` for `Template!int` of type `void`
-fail_compilation/dip22a.d(20): Error: no property `bar` for `12` of type `int`
+fail_compilation/dip22a.d(18): Error: no property `bar` for `new Klass` of type `imports.dip22a.Klass`
+fail_compilation/imports/dip22a.d(3):        class `Klass` defined here
+fail_compilation/dip22a.d(19): Error: no property `bar` for `Struct()` of type `imports.dip22a.Struct`
+fail_compilation/imports/dip22a.d(8):        struct `Struct` defined here
+fail_compilation/dip22a.d(20): Error: undefined identifier `bar` in module `imports.dip22a`
+fail_compilation/dip22a.d(21): Error: no property `bar` for `Template!int` of type `void`
+fail_compilation/dip22a.d(22): Error: no property `bar` for `12` of type `int`
 ---
 */
 import imports.dip22a;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/enum_function.d b/gcc/testsuite/gdc.test/fail_compilation/enum_function.d
index b22f2ceccef..52b71d12f5d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/enum_function.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/enum_function.d
@@ -1,10 +1,11 @@
 /*
+REQUIRED_ARGS: -de
 TEST_OUTPUT:
 ---
-fail_compilation/enum_function.d(10): Error: function cannot have enum storage class
-fail_compilation/enum_function.d(11): Error: function cannot have enum storage class
-fail_compilation/enum_function.d(12): Error: function cannot have enum storage class
-fail_compilation/enum_function.d(13): Error: function cannot have enum storage class
+fail_compilation/enum_function.d(11): Deprecation: function cannot have enum storage class
+fail_compilation/enum_function.d(12): Deprecation: function cannot have enum storage class
+fail_compilation/enum_function.d(13): Deprecation: function cannot have enum storage class
+fail_compilation/enum_function.d(14): Deprecation: function cannot have enum storage class
 ---
 */
 enum void f1() { return; }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail10528.d b/gcc/testsuite/gdc.test/fail_compilation/fail10528.d
index 38c5a23a529..3b3f5bb7f79 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail10528.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail10528.d
@@ -2,14 +2,18 @@
 EXTRA_FILES: imports/a10528.d
 TEST_OUTPUT:
 ---
-fail_compilation/fail10528.d(20): Error: undefined identifier `a`
-fail_compilation/fail10528.d(21): Error: undefined identifier `a` in module `a10528`
-fail_compilation/fail10528.d(23): Error: undefined identifier `b`
-fail_compilation/fail10528.d(24): Error: undefined identifier `b` in module `a10528`
-fail_compilation/fail10528.d(26): Error: no property `c` for type `a10528.S`
-fail_compilation/fail10528.d(27): Error: no property `c` for type `a10528.S`
-fail_compilation/fail10528.d(29): Error: no property `d` for type `a10528.C`
-fail_compilation/fail10528.d(30): Error: no property `d` for type `a10528.C`
+fail_compilation/fail10528.d(24): Error: undefined identifier `a`
+fail_compilation/fail10528.d(25): Error: undefined identifier `a` in module `a10528`
+fail_compilation/fail10528.d(27): Error: undefined identifier `b`
+fail_compilation/fail10528.d(28): Error: undefined identifier `b` in module `a10528`
+fail_compilation/fail10528.d(30): Error: no property `c` for type `a10528.S`
+fail_compilation/imports/a10528.d(4):        struct `S` defined here
+fail_compilation/fail10528.d(31): Error: no property `c` for type `a10528.S`
+fail_compilation/imports/a10528.d(4):        struct `S` defined here
+fail_compilation/fail10528.d(33): Error: no property `d` for type `a10528.C`
+fail_compilation/imports/a10528.d(5):        class `C` defined here
+fail_compilation/fail10528.d(34): Error: no property `d` for type `a10528.C`
+fail_compilation/imports/a10528.d(5):        class `C` defined here
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail10534.d b/gcc/testsuite/gdc.test/fail_compilation/fail10534.d
index fac37f444e3..b5bb67c2678 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail10534.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail10534.d
@@ -1,22 +1,22 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail10534.d(28): Error: `a` is not of arithmetic type, it is a `int delegate()`
-fail_compilation/fail10534.d(28): Error: `b` is not of arithmetic type, it is a `int delegate()`
-fail_compilation/fail10534.d(29): Error: `a` is not of arithmetic type, it is a `int delegate()`
-fail_compilation/fail10534.d(29): Error: `b` is not of arithmetic type, it is a `int delegate()`
-fail_compilation/fail10534.d(30): Error: `a` is not of arithmetic type, it is a `int delegate()`
-fail_compilation/fail10534.d(30): Error: `b` is not of arithmetic type, it is a `int delegate()`
-fail_compilation/fail10534.d(31): Error: `a` is not of arithmetic type, it is a `int delegate()`
-fail_compilation/fail10534.d(31): Error: `b` is not of arithmetic type, it is a `int delegate()`
-fail_compilation/fail10534.d(36): Error: `a` is not of arithmetic type, it is a `int function()`
-fail_compilation/fail10534.d(36): Error: `b` is not of arithmetic type, it is a `int function()`
-fail_compilation/fail10534.d(37): Error: `a` is not of arithmetic type, it is a `int function()`
-fail_compilation/fail10534.d(37): Error: `b` is not of arithmetic type, it is a `int function()`
-fail_compilation/fail10534.d(38): Error: `a` is not of arithmetic type, it is a `int function()`
-fail_compilation/fail10534.d(38): Error: `b` is not of arithmetic type, it is a `int function()`
-fail_compilation/fail10534.d(39): Error: `a` is not of arithmetic type, it is a `int function()`
-fail_compilation/fail10534.d(39): Error: `b` is not of arithmetic type, it is a `int function()`
+fail_compilation/fail10534.d(28): Error: illegal operator `+` for `a` of type `int delegate()`
+fail_compilation/fail10534.d(28): Error: illegal operator `+` for `b` of type `int delegate()`
+fail_compilation/fail10534.d(29): Error: illegal operator `-` for `a` of type `int delegate()`
+fail_compilation/fail10534.d(29): Error: illegal operator `-` for `b` of type `int delegate()`
+fail_compilation/fail10534.d(30): Error: illegal operator `/` for `a` of type `int delegate()`
+fail_compilation/fail10534.d(30): Error: illegal operator `/` for `b` of type `int delegate()`
+fail_compilation/fail10534.d(31): Error: illegal operator `*` for `a` of type `int delegate()`
+fail_compilation/fail10534.d(31): Error: illegal operator `*` for `b` of type `int delegate()`
+fail_compilation/fail10534.d(36): Error: illegal operator `+` for `a` of type `int function()`
+fail_compilation/fail10534.d(36): Error: illegal operator `+` for `b` of type `int function()`
+fail_compilation/fail10534.d(37): Error: illegal operator `-` for `a` of type `int function()`
+fail_compilation/fail10534.d(37): Error: illegal operator `-` for `b` of type `int function()`
+fail_compilation/fail10534.d(38): Error: illegal operator `/` for `a` of type `int function()`
+fail_compilation/fail10534.d(38): Error: illegal operator `/` for `b` of type `int function()`
+fail_compilation/fail10534.d(39): Error: illegal operator `*` for `a` of type `int function()`
+fail_compilation/fail10534.d(39): Error: illegal operator `*` for `b` of type `int function()`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail109.d b/gcc/testsuite/gdc.test/fail_compilation/fail109.d
index 87297dbacd7..003e65f9b80 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail109.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail109.d
@@ -34,6 +34,7 @@ enum E1 : short
 /* https://issues.dlang.org/show_bug.cgi?id=14950
 TEST_OUTPUT:
 ---
+fail_compilation/fail109.d(50): Error: cannot check `fail109.B.end` value for overflow
 fail_compilation/fail109.d(50): Error: comparison between different enumeration types `B` and `C`; If this behavior is intended consider using `std.conv.asOriginalType`
 fail_compilation/fail109.d(50): Error: enum member `fail109.B.end` initialization with `B.start+1` causes overflow for type `C`
 ---
@@ -43,7 +44,6 @@ enum C
     start,
     end
 }
-
 enum B
 {
     start = C.end,
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail121.d b/gcc/testsuite/gdc.test/fail_compilation/fail121.d
index 8d5af747ce1..110547be7ca 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail121.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail121.d
@@ -3,8 +3,9 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail121.d(23): Error: no property `typeinfo` for `list[1]` of type `fail121.myobject`
-fail_compilation/fail121.d(23): Error: no property `typeinfo` for `i` of type `int`
+fail_compilation/fail121.d(24): Error: no property `typeinfo` for `list[1]` of type `fail121.myobject`
+fail_compilation/fail121.d(12):        struct `myobject` defined here
+fail_compilation/fail121.d(24): Error: no property `typeinfo` for `i` of type `int`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail136.d b/gcc/testsuite/gdc.test/fail_compilation/fail136.d
index 16659b5fdc1..3bc86537ed6 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail136.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail136.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail136.d(10): Error: found `"EF BB BF"` when expecting `;` following statement
+fail_compilation\fail136.d(10): Error: `"\xef\xbb\xbf"` has no effect
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail17570.d b/gcc/testsuite/gdc.test/fail_compilation/fail17570.d
index bee61cf0b22..9be7cd4b05f 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail17570.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail17570.d
@@ -1,9 +1,10 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail17570.d(11): Error: cannot use function constraints for non-template functions. Use `static if` instead
-fail_compilation/fail17570.d(11): Error: declaration expected, not `if`
-fail_compilation/fail17570.d(14): Error: `}` expected following members in `struct` declaration at fail_compilation/fail17570.d(10)
+fail_compilation/fail17570.d(12): Error: cannot use function constraints for non-template functions. Use `static if` instead
+fail_compilation/fail17570.d(12): Error: declaration expected, not `if`
+fail_compilation/fail17570.d(15): Error: `}` expected following members in `struct` declaration
+fail_compilation/fail17570.d(11):        struct `S` starts here
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail17969.d b/gcc/testsuite/gdc.test/fail_compilation/fail17969.d
index e6b95564b44..29bc3f448d8 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail17969.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail17969.d
@@ -1,6 +1,7 @@
 /* TEST_OUTPUT:
 ---
-fail_compilation/fail17969.d(9): Error: no property `sum` for type `fail17969.__lambda6!(int[]).__lambda6.MapResult2!((b) => b)`
+fail_compilation/fail17969.d(10): Error: no property `sum` for type `fail17969.__lambda6!(int[]).__lambda6.MapResult2!((b) => b)`
+fail_compilation/fail17969.d(16):        struct `MapResult2` defined here
 ---
  * https://issues.dlang.org/show_bug.cgi?id=17969
  */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail18219.d b/gcc/testsuite/gdc.test/fail_compilation/fail18219.d
index f3ec6806f6b..bf4b189f6eb 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail18219.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail18219.d
@@ -3,10 +3,11 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail18219.d(16): Error: no property `Foobar` for type `AST`, did you mean `b18219.Foobar`?
-fail_compilation/fail18219.d(17): Error: no property `Bar` for type `a18219.AST`
-fail_compilation/fail18219.d(18): Error: no property `fun` for type `AST`, did you mean `b18219.fun`?
-fail_compilation/fail18219.d(19): Error: no property `Foobar` for type `AST`, did you mean `b18219.Foobar`?
+fail_compilation/fail18219.d(17): Error: no property `Foobar` for type `AST`, did you mean `b18219.Foobar`?
+fail_compilation/fail18219.d(18): Error: no property `Bar` for type `a18219.AST`
+fail_compilation/imports/a18219.d(3):        struct `AST` defined here
+fail_compilation/fail18219.d(19): Error: no property `fun` for type `AST`, did you mean `b18219.fun`?
+fail_compilation/fail18219.d(20): Error: no property `Foobar` for type `AST`, did you mean `b18219.Foobar`?
 ---
 */
 import imports.a18219;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail18892.d b/gcc/testsuite/gdc.test/fail_compilation/fail18892.d
index 0fb56d315e9..381ef3c7ef5 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail18892.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail18892.d
@@ -1,8 +1,10 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail18892.d(20): Error: no property `foo` for `a` of type `fail18892.MT`
-fail_compilation/fail18892.d(21): Error: no property `foo` for `MT` of type `fail18892.MT`
+fail_compilation/fail18892.d(22): Error: no property `foo` for `a` of type `fail18892.MT`
+fail_compilation/fail18892.d(13):        struct `MT` defined here
+fail_compilation/fail18892.d(23): Error: no property `foo` for `MT` of type `fail18892.MT`
+fail_compilation/fail18892.d(13):        struct `MT` defined here
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail18970.d b/gcc/testsuite/gdc.test/fail_compilation/fail18970.d
index a8156fe7d1e..9b1ec1d4589 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail18970.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail18970.d
@@ -1,10 +1,12 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail18970.d(24): Error: no property `y` for `S()` of type `fail18970.S`
-fail_compilation/fail18970.d(24):        potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message
-fail_compilation/fail18970.d(31): Error: no property `yyy` for `this` of type `fail18970.S2`
-fail_compilation/fail18970.d(31):        potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message
+fail_compilation/fail18970.d(26): Error: no property `y` for `S()` of type `fail18970.S`
+fail_compilation/fail18970.d(26):        potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message
+fail_compilation/fail18970.d(15):        struct `S` defined here
+fail_compilation/fail18970.d(33): Error: no property `yyy` for `this` of type `fail18970.S2`
+fail_compilation/fail18970.d(33):        potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message
+fail_compilation/fail18970.d(29):        struct `S2` defined here
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail18979.d b/gcc/testsuite/gdc.test/fail_compilation/fail18979.d
index 04e36f623ff..9b7c59acd5b 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail18979.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail18979.d
@@ -2,7 +2,8 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail18979.d(13): Error: no property `__ctor` for `Foo()` of type `imports.imp18979.Foo`
+fail_compilation/fail18979.d(14): Error: no property `__ctor` for `Foo()` of type `imports.imp18979.Foo`
+fail_compilation/imports/imp18979.d(3):        struct `Foo` defined here
 ----
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail1900.d b/gcc/testsuite/gdc.test/fail_compilation/fail1900.d
index edc463018db..7e5f05692b5 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail1900.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail1900.d
@@ -3,9 +3,9 @@ EXTRA_FILES: imports/fail1900a.d imports/fail1900b.d
 TEST_OUTPUT:
 ---
 fail_compilation/fail1900.d(27): Error: template `fail1900.Mix1a!().Foo` matches more than one template declaration:
-fail_compilation/fail1900.d(14):     `Foo(ubyte x)`
-and
-fail_compilation/fail1900.d(15):     `Foo(byte x)`
+fail_compilation/fail1900.d(14):        `Foo(ubyte x)`
+and:
+fail_compilation/fail1900.d(15):        `Foo(byte x)`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19076.d b/gcc/testsuite/gdc.test/fail_compilation/fail19076.d
index 2441d6f3cae..05ae21bf613 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail19076.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19076.d
@@ -1,8 +1,9 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail19076.d(11): Error: no property `V` for type `fail19076.I`
-fail_compilation/fail19076.d(11): Error: `(I).V` cannot be resolved
+fail_compilation/fail19076.d(12): Error: no property `V` for type `fail19076.I`
+fail_compilation/fail19076.d(11):        interface `I` defined here
+fail_compilation/fail19076.d(12): Error: `(I).V` cannot be resolved
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19103.d b/gcc/testsuite/gdc.test/fail_compilation/fail19103.d
index 40fafcdc1ae..c1abd0df90a 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail19103.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19103.d
@@ -1,9 +1,11 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail19103.d(12): Error: no property `puts` for `new C` of type `fail19103.C`
-fail_compilation/fail19103.d(14): Error: no property `puts` for `s1` of type `fail19103.S1`
-fail_compilation/fail19103.d(16): Error: no property `puts` for type `S2`, did you mean `core.stdc.stdio.puts`?
+fail_compilation/fail19103.d(14): Error: no property `puts` for `new C` of type `fail19103.C`
+fail_compilation/fail19103.d(26):        class `C` defined here
+fail_compilation/fail19103.d(16): Error: no property `puts` for `s1` of type `fail19103.S1`
+fail_compilation/fail19103.d(30):        struct `S1` defined here
+fail_compilation/fail19103.d(18): Error: no property `puts` for type `S2`, did you mean `core.stdc.stdio.puts`?
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail196.d b/gcc/testsuite/gdc.test/fail_compilation/fail196.d
index cdad5c491db..78c596390b5 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail196.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail196.d
@@ -1,26 +1,35 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail196.d(29): Error: delimited string must end in `)"`
-fail_compilation/fail196.d(29): Error: implicit string concatenation is error-prone and disallowed in D
-fail_compilation/fail196.d(29):        Use the explicit syntax instead (concatenating literals is `@nogc`): "foo(xxx)" ~ ";\n    assert(s == "
-fail_compilation/fail196.d(30): Error: semicolon needed to end declaration of `s`, instead of `foo`
-fail_compilation/fail196.d(29):        `s` declared here
-fail_compilation/fail196.d(30): Error: found `");\n\n    s = q"` when expecting `;` following statement `foo(xxx)` on line fail_compilation/fail196.d(30)
-fail_compilation/fail196.d(32): Error: found `";\n    assert(s == "` when expecting `;` following statement `[foo[xxx]]` on line fail_compilation/fail196.d(32)
-fail_compilation/fail196.d(33): Error: found `");\n\n    s = q"` when expecting `;` following statement `foo[xxx]` on line fail_compilation/fail196.d(33)
-fail_compilation/fail196.d(35): Error: found `{` when expecting `;` following statement `foo` on line fail_compilation/fail196.d(35)
-fail_compilation/fail196.d(35): Error: found `}` when expecting `;` following statement `xxx` on line fail_compilation/fail196.d(35)
-fail_compilation/fail196.d(36): Error: found `foo` when expecting `;` following statement `";\n    assert(s == "` on line fail_compilation/fail196.d(35)
-fail_compilation/fail196.d(36): Error: found `}` when expecting `;` following statement `xxx` on line fail_compilation/fail196.d(36)
-fail_compilation/fail196.d(38): Error: found `<` when expecting `;` following statement `");\n\n    s = q" < foo` on line fail_compilation/fail196.d(36)
-fail_compilation/fail196.d(39): Error: found `foo` when expecting `;` following statement `xxx >> ";\n    assert(s == "` on line fail_compilation/fail196.d(38)
-fail_compilation/fail196.d(39): Error: found `<` instead of statement
-fail_compilation/fail196.d(45): Error: unterminated string constant starting at fail_compilation/fail196.d(45)
-fail_compilation/fail196.d(47): Error: matching `}` expected following compound statement, not `End of File`
-fail_compilation/fail196.d(36):        unmatched `{`
-fail_compilation/fail196.d(47): Error: matching `}` expected following compound statement, not `End of File`
-fail_compilation/fail196.d(28):        unmatched `{`
+fail_compilation/fail196.d(38): Error: delimited string must end in `)"`
+fail_compilation/fail196.d(38): Error: implicit string concatenation is error-prone and disallowed in D
+fail_compilation/fail196.d(38):        Use the explicit syntax instead (concatenating literals is `@nogc`): "foo(xxx)" ~ ";\n    assert(s == "
+fail_compilation/fail196.d(39): Error: semicolon needed to end declaration of `s`, instead of `foo`
+fail_compilation/fail196.d(38):        `s` declared here
+fail_compilation/fail196.d(39): Error: found `");\n\n    s = q"` when expecting `;` following expression
+fail_compilation/fail196.d(39):        expression: `foo(xxx)`
+fail_compilation/fail196.d(41): Error: found `";\n    assert(s == "` when expecting `;` following expression
+fail_compilation/fail196.d(41):        expression: `[foo[xxx]]`
+fail_compilation/fail196.d(42): Error: found `");\n\n    s = q"` when expecting `;` following expression
+fail_compilation/fail196.d(42):        expression: `foo[xxx]`
+fail_compilation/fail196.d(44): Error: found `{` when expecting `;` following expression
+fail_compilation/fail196.d(44):        expression: `foo`
+fail_compilation/fail196.d(44): Error: found `}` when expecting `;` following expression
+fail_compilation/fail196.d(44):        expression: `xxx`
+fail_compilation/fail196.d(45): Error: found `foo` when expecting `;` following expression
+fail_compilation/fail196.d(44):        expression: `";\n    assert(s == "`
+fail_compilation/fail196.d(45): Error: found `}` when expecting `;` following expression
+fail_compilation/fail196.d(45):        expression: `xxx`
+fail_compilation/fail196.d(47): Error: found `<` when expecting `;` following expression
+fail_compilation/fail196.d(45):        expression: `");\n\n    s = q" < foo`
+fail_compilation/fail196.d(48): Error: found `foo` when expecting `;` following expression
+fail_compilation/fail196.d(47):        expression: `xxx >> ";\n    assert(s == "`
+fail_compilation/fail196.d(48): Error: found `<` instead of statement
+fail_compilation/fail196.d(54): Error: unterminated string constant starting at fail_compilation/fail196.d(54)
+fail_compilation/fail196.d(56): Error: matching `}` expected following compound statement, not `End of File`
+fail_compilation/fail196.d(45):        unmatched `{`
+fail_compilation/fail196.d(56): Error: matching `}` expected following compound statement, not `End of File`
+fail_compilation/fail196.d(37):        unmatched `{`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail20637.d b/gcc/testsuite/gdc.test/fail_compilation/fail20637.d
index 77c69eaa6e6..dd0a5f52b87 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail20637.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail20637.d
@@ -2,7 +2,8 @@
 EXTRA_FILES: imports/fail20637b.d
 TEST_OUTPUT:
 ---
-fail_compilation/fail20637.d(12): Error: no property `foo` for type `imports.fail20637b.A`
+fail_compilation/fail20637.d(13): Error: no property `foo` for type `imports.fail20637b.A`
+fail_compilation/imports/fail20637b.d(3):        class `A` defined here
 ---
 */
 module fail20637;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22054.d b/gcc/testsuite/gdc.test/fail_compilation/fail22054.d
index c172f089d9c..8b525d85fb2 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail22054.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail22054.d
@@ -3,10 +3,12 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail22054.d(21): Error: no property `what` for type `fail22054.exception`
-fail_compilation/fail22054.d(16):        `class fail22054.exception` is opaque and has no members.
-fail_compilation/fail22054.d(22): Error: no property `what` for type `fail22054.exception2`
-fail_compilation/fail22054.d(17):        `struct fail22054.exception2` is opaque and has no members.
+fail_compilation/fail22054.d(23): Error: no property `what` for type `fail22054.exception`
+fail_compilation/fail22054.d(18):        `class fail22054.exception` is opaque and has no members.
+fail_compilation/fail22054.d(18):        class `exception` defined here
+fail_compilation/fail22054.d(24): Error: no property `what` for type `fail22054.exception2`
+fail_compilation/fail22054.d(19):        `struct fail22054.exception2` is opaque and has no members.
+fail_compilation/fail22054.d(19):        struct `exception2` defined here
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22529.d b/gcc/testsuite/gdc.test/fail_compilation/fail22529.d
index 3bec3c0f7d3..62eac25680d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail22529.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail22529.d
@@ -3,7 +3,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail22529.d(13): Error: found `return` when expecting `;` following statement
+fail_compilation/fail22529.d(13): Error: found `return` when expecting `;` following expression
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail23109.d b/gcc/testsuite/gdc.test/fail_compilation/fail23109.d
index 5c5c11b7195..ee560759e41 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail23109.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail23109.d
@@ -5,7 +5,9 @@ EXTRA_SOURCES: extra-files/test23109/object.d
 TEST_OUTPUT:
 ---
 Error: no property `getHash` for `typeid(const(Ensure[]))` of type `object.TypeInfo_Const`
+fail_compilation/extra-files/test23109/object.d(7):        class `TypeInfo_Const` defined here
 Error: no property `getHash` for `typeid(const(Ensure[1]))` of type `object.TypeInfo_Const`
+fail_compilation/extra-files/test23109/object.d(7):        class `TypeInfo_Const` defined here
 fail_compilation/imports/test23109a.d(10): Error: template instance `imports.test23109a.Array!(Ensure)` error instantiating
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail61.d b/gcc/testsuite/gdc.test/fail_compilation/fail61.d
index a2f01d7e3ef..e7175b44245 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail61.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail61.d
@@ -1,10 +1,13 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail61.d(22): Error: no property `B` for type `fail61.A.B`
-fail_compilation/fail61.d(23): Error: no property `B` for type `fail61.A.B`
-fail_compilation/fail61.d(32): Error: no property `A2` for type `fail61.B2`
-fail_compilation/fail61.d(41): Error: calling non-static function `foo` requires an instance of type `B3`
+fail_compilation/fail61.d(25): Error: no property `B` for type `fail61.A.B`
+fail_compilation/fail61.d(16):        class `B` defined here
+fail_compilation/fail61.d(26): Error: no property `B` for type `fail61.A.B`
+fail_compilation/fail61.d(16):        class `B` defined here
+fail_compilation/fail61.d(35): Error: no property `A2` for type `fail61.B2`
+fail_compilation/fail61.d(30):        class `B2` defined here
+fail_compilation/fail61.d(44): Error: calling non-static function `foo` requires an instance of type `B3`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail7861.d b/gcc/testsuite/gdc.test/fail_compilation/fail7861.d
index c7018c95762..a24eb95fbdf 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail7861.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail7861.d
@@ -1,7 +1,8 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail7861.d(17): Error: no property `nonexistent` for type `test.B`
+fail_compilation/fail7861.d(18): Error: no property `nonexistent` for type `test.B`
+fail_compilation/fail7861.d(14):        struct `B` defined here
 ---
 */
 module test;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail9.d b/gcc/testsuite/gdc.test/fail_compilation/fail9.d
index 08789954bb1..080ac1e5ebe 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail9.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail9.d
@@ -1,7 +1,8 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail9.d(23): Error: no property `Vector` for type `fail9.Vector!int`
+fail_compilation/fail9.d(24): Error: no property `Vector` for type `fail9.Vector!int`
+fail_compilation/fail9.d(13):        class `Vector` defined here
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d b/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d
index 8508b27d164..a9e5429366a 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d
@@ -1,23 +1,21 @@
 /*
-REQUIRED_ARGS: -wo
 TEST_OUTPUT:
 ---
-fail_compilation/fail_scope.d(30): Deprecation: scope parameter `da` may not be returned
-fail_compilation/fail_scope.d(32): Deprecation: scope parameter `o` may not be returned
-fail_compilation/fail_scope.d(33): Deprecation: scope parameter `dg` may not be returned
-fail_compilation/fail_scope.d(40): Deprecation: scope parameter `p` may not be returned
-fail_compilation/fail_scope.d(45): Error: returning `cast(char[])string` escapes a reference to local variable `string`
-fail_compilation/fail_scope.d(63): Error: returning `s.bar()` escapes a reference to local variable `s`
-fail_compilation/fail_scope.d(74): Error: `fail_scope.foo8` called with argument types `(int)` matches both:
-fail_compilation/fail_scope.d(68):     `fail_scope.foo8(ref int x)`
+fail_compilation/fail_scope.d(28): Deprecation: scope parameter `da` may not be returned
+fail_compilation/fail_scope.d(30): Deprecation: scope parameter `o` may not be returned
+fail_compilation/fail_scope.d(31): Deprecation: scope parameter `dg` may not be returned
+fail_compilation/fail_scope.d(38): Deprecation: scope parameter `p` may not be returned
+fail_compilation/fail_scope.d(43): Error: returning `cast(char[])string` escapes a reference to local variable `string`
+fail_compilation/fail_scope.d(61): Error: returning `s.bar()` escapes a reference to local variable `s`
+fail_compilation/fail_scope.d(72): Error: `fail_scope.foo8` called with argument types `(int)` matches both:
+fail_compilation/fail_scope.d(66):     `fail_scope.foo8(ref int x)`
 and:
-fail_compilation/fail_scope.d(69):     `fail_scope.foo8(return ref int x)`
-fail_compilation/fail_scope.d(82): Error: returning `& string` escapes a reference to local variable `string`
-fail_compilation/fail_scope.d(92): Error: returning `cast(int[])a` escapes a reference to local variable `a`
-fail_compilation/fail_scope.d(100): Error: returning `cast(int[])a` escapes a reference to local variable `a`
-fail_compilation/fail_scope.d(108): Error: escaping reference to outer local variable `x`
-fail_compilation/fail_scope.d(127): Warning: returning `s.bar()` escapes a reference to local variable `s`
-fail_compilation/fail_scope.d(137): Error: returning `foo16226(i)` escapes a reference to local variable `i`
+fail_compilation/fail_scope.d(67):     `fail_scope.foo8(return ref int x)`
+fail_compilation/fail_scope.d(80): Error: returning `& string` escapes a reference to local variable `string`
+fail_compilation/fail_scope.d(90): Error: returning `cast(int[])a` escapes a reference to local variable `a`
+fail_compilation/fail_scope.d(98): Error: returning `cast(int[])a` escapes a reference to local variable `a`
+fail_compilation/fail_scope.d(106): Error: escaping reference to outer local variable `x`
+fail_compilation/fail_scope.d(135): Error: returning `foo16226(i)` escapes a reference to local variable `i`
 ---
 //fail_compilation/fail_scope.d(35): Error: scope variable `da` may not be returned
 //fail_compilation/fail_scope.d(37): Error: scope variable `o` may not be returned
diff --git a/gcc/testsuite/gdc.test/fail_compilation/faildottypeinfo.d b/gcc/testsuite/gdc.test/fail_compilation/faildottypeinfo.d
index c44b289ccec..9b62c26edd0 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/faildottypeinfo.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/faildottypeinfo.d
@@ -1,8 +1,9 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/faildottypeinfo.d(11): Error: no property `typeinfo` for `0` of type `int`
-fail_compilation/faildottypeinfo.d(12): Error: no property `typeinfo` for type `object.Object`
+fail_compilation/faildottypeinfo.d(12): Error: no property `typeinfo` for `0` of type `int`
+fail_compilation/faildottypeinfo.d(13): Error: no property `typeinfo` for type `object.Object`
+$p:druntime/import/object.d$($n$):        class `Object` defined here
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fnconstraint.d b/gcc/testsuite/gdc.test/fail_compilation/fnconstraint.d
index 5862f7a8c88..21603f725f6 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fnconstraint.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fnconstraint.d
@@ -1,11 +1,12 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fnconstraint.d(13): Error: template constraint must follow parameter lists and attributes
-fail_compilation/fnconstraint.d(13): Error: declaration expected, not `if`
-fail_compilation/fnconstraint.d(22): Error: template constraint must follow parameter lists and attributes
-fail_compilation/fnconstraint.d(22): Error: declaration expected, not `if`
-fail_compilation/fnconstraint.d(26): Error: `}` expected following members in `struct` declaration at fail_compilation/fnconstraint.d(18)
+fail_compilation/fnconstraint.d(14): Error: template constraint must follow parameter lists and attributes
+fail_compilation/fnconstraint.d(14): Error: declaration expected, not `if`
+fail_compilation/fnconstraint.d(23): Error: template constraint must follow parameter lists and attributes
+fail_compilation/fnconstraint.d(23): Error: declaration expected, not `if`
+fail_compilation/fnconstraint.d(27): Error: `}` expected following members in `struct` declaration
+fail_compilation/fnconstraint.d(19):        struct `S` starts here
 ---
 */
 void foo()()
diff --git a/gcc/testsuite/gdc.test/fail_compilation/goto_skip.d b/gcc/testsuite/gdc.test/fail_compilation/goto_skip.d
new file mode 100644
index 00000000000..21bce5d2ec2
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/goto_skip.d
@@ -0,0 +1,57 @@
+/*
+REQUIRED_ARGS: -verrors=context
+TEST_OUTPUT:
+---
+fail_compilation/goto_skip.d(28): Error: `goto` skips declaration of variable `goto_skip.skip.ch`
+        goto Lskip;
+        ^
+fail_compilation/goto_skip.d(29):        declared here
+    char ch = '!';
+         ^
+fail_compilation/goto_skip.d(36): Error: `goto` skips declaration of `with` temporary
+    goto L1;
+    ^
+fail_compilation/goto_skip.d(38):        declared here
+    with (S()) {
+    ^
+fail_compilation/goto_skip.d(46): Error: `goto` skips declaration of variable `goto_skip.test8.e`
+  goto L2;
+  ^
+fail_compilation/goto_skip.d(51):        declared here
+  catch (Exception e) {
+  ^
+---
+*/
+char skip(bool b)
+{
+    if (b)
+        goto Lskip;
+    char ch = '!';
+Lskip:
+    return ch;
+}
+
+int f()
+{
+    goto L1;
+    struct S { int e = 5; }
+    with (S()) {
+L1:
+        return e;
+    }
+}
+
+void test8(int a)
+{
+  goto L2;
+
+  try {
+      a += 2;
+  }
+  catch (Exception e) {
+      a += 3;
+L2: ;
+      a += 100;
+  }
+  assert(a == 100);
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice10713.d b/gcc/testsuite/gdc.test/fail_compilation/ice10713.d
index f3680329941..e59a594da8a 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice10713.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice10713.d
@@ -1,7 +1,8 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice10713.d(10): Error: no property `nonExistingField` for type `ice10713.S`
+fail_compilation/ice10713.d(11): Error: no property `nonExistingField` for type `ice10713.S`
+fail_compilation/ice10713.d(9):        struct `S` defined here
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice10938.d b/gcc/testsuite/gdc.test/fail_compilation/ice10938.d
index d21ee47dec7..4d107c9e7b2 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice10938.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice10938.d
@@ -1,8 +1,9 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice10938.d(13): Error: no property `opts` for `this` of type `ice10938.C`
-fail_compilation/ice10938.d(13):        potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message
+fail_compilation/ice10938.d(14): Error: no property `opts` for `this` of type `ice10938.C`
+fail_compilation/ice10938.d(14):        potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message
+fail_compilation/ice10938.d(10):        class `C` defined here
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice11518.d b/gcc/testsuite/gdc.test/fail_compilation/ice11518.d
index c8542f77252..4e4f6170a61 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice11518.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice11518.d
@@ -2,9 +2,9 @@
 TEST_OUTPUT:
 ---
 fail_compilation/ice11518.d(17): Error: class `ice11518.B` matches more than one template declaration:
-fail_compilation/ice11518.d(12):     `B(T : A!T)`
-and
-fail_compilation/ice11518.d(13):     `B(T : A!T)`
+fail_compilation/ice11518.d(12):        `B(T : A!T)`
+and:
+fail_compilation/ice11518.d(13):        `B(T : A!T)`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice11982.d b/gcc/testsuite/gdc.test/fail_compilation/ice11982.d
index 0886df61678..f500700f674 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice11982.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice11982.d
@@ -1,20 +1,22 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice11982.d(20): Error: basic type expected, not `scope`
-fail_compilation/ice11982.d(20): Error: found `scope` when expecting `;` following statement `new _error_` on line fail_compilation/ice11982.d(20)
-fail_compilation/ice11982.d(20): Error: basic type expected, not `}`
-fail_compilation/ice11982.d(20): Error: missing `{ ... }` for function literal
-fail_compilation/ice11982.d(20): Error: C style cast illegal, use `cast(funk)function _error_()
+fail_compilation/ice11982.d(22): Error: basic type expected, not `scope`
+fail_compilation/ice11982.d(22): Error: found `scope` when expecting `;` following expression
+fail_compilation/ice11982.d(22):        expression: `new _error_`
+fail_compilation/ice11982.d(22): Error: basic type expected, not `}`
+fail_compilation/ice11982.d(22): Error: missing `{ ... }` for function literal
+fail_compilation/ice11982.d(22): Error: C style cast illegal, use `cast(funk)function _error_()
 {
 }
 `
-fail_compilation/ice11982.d(20): Error: found `}` when expecting `;` following statement `cast(funk)function _error_()
+fail_compilation/ice11982.d(22): Error: found `}` when expecting `;` following expression
+fail_compilation/ice11982.d(22):        expression: `cast(funk)function _error_()
 {
 }
-` on line fail_compilation/ice11982.d(20)
-fail_compilation/ice11982.d(21): Error: matching `}` expected following compound statement, not `End of File`
-fail_compilation/ice11982.d(20):        unmatched `{`
+`
+fail_compilation/ice11982.d(23): Error: matching `}` expected following compound statement, not `End of File`
+fail_compilation/ice11982.d(22):        unmatched `{`
 ---
 */
 void main() { new scope ( funk ) function }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice8100.d b/gcc/testsuite/gdc.test/fail_compilation/ice8100.d
index dc68cfcce2b..b8b3155b688 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice8100.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice8100.d
@@ -1,9 +1,10 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice8100.d(10): Error: no property `Q` for type `ice8100.Bar!bool`
-fail_compilation/ice8100.d(11): Error: template instance `ice8100.Foo!(Bar!bool)` error instantiating
-fail_compilation/ice8100.d(12):        instantiated from here: `Bar!bool`
+fail_compilation/ice8100.d(11): Error: no property `Q` for type `ice8100.Bar!bool`
+fail_compilation/ice8100.d(12):        class `Bar` defined here
+fail_compilation/ice8100.d(12): Error: template instance `ice8100.Foo!(Bar!bool)` error instantiating
+fail_compilation/ice8100.d(13):        instantiated from here: `Bar!bool`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/issue12652.d b/gcc/testsuite/gdc.test/fail_compilation/issue12652.d
deleted file mode 100644
index 0ddd6b48b53..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/issue12652.d
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
-TEST_OUTPUT:
-----
-fail_compilation/issue12652.d(18): Error: static initializations of associative arrays is not allowed.
-fail_compilation/issue12652.d(18):        associative arrays must be initialized at runtime: https://dlang.org/spec/hash-map.html#runtime_initialization
----
-*/
-
-enum A
-{
-    x,
-    y,
-    z
-}
-
-struct S
-{
-    string[A] t = [A.x : "aaa", A.y : "bbb"];
-}
-
-void main ()
-{
-    S s;
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/issue22682.d b/gcc/testsuite/gdc.test/fail_compilation/issue22682.d
new file mode 100644
index 00000000000..80e8311b3a7
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/issue22682.d
@@ -0,0 +1,18 @@
+/* TEST_OUTPUT:
+---
+fail_compilation/issue22682.d(14): Error: `pragma(mangle)` must be attached to a declaration
+fail_compilation/issue22682.d(15): Error: `pragma(mangle)` takes a single argument that must be a string literal
+fail_compilation/issue22682.d(16): Error: `string` expected for pragma mangle argument, not `(0)` of type `int`
+fail_compilation/issue22682.d(16): Error: `pragma(mangle)` takes a single argument that must be a string literal
+fail_compilation/issue22682.d(17): Error: `pragma(mangle)` must be attached to a declaration
+---
+ */
+module issue22682;
+
+void main()
+{
+    pragma(mangle) {}
+    pragma(mangle) static int i0;
+    pragma(mangle, 0) static int i1;
+    pragma(mangle);
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/lexer1.d b/gcc/testsuite/gdc.test/fail_compilation/lexer1.d
index 0ad3f01156a..7fe2a537481 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/lexer1.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/lexer1.d
@@ -1,8 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/lexer1.d(30): Error: no identifier for declarator `x`
-fail_compilation/lexer1.d(30): Error: declaration expected, not `"01 02 03"w`
+fail_compilation/lexer1.d(30): Error: declaration expected, not `x"01 02 03"w`
 fail_compilation/lexer1.d(31): Error: declaration expected, not `2147483649U`
 fail_compilation/lexer1.d(32): Error: declaration expected, not `0.1`
 fail_compilation/lexer1.d(33): Error: declaration expected, not `0.1f`
@@ -26,6 +25,7 @@ fail_compilation/lexer1.d(52): Error: escape octal sequence \400 is larger than
 fail_compilation/lexer1.d(53): Error: html entity requires 2 code units, use a string instead of a character
 ---
 */
+
 // https://dlang.dawg.eu/coverage/src/lexer.c.gcov.html
 x"01 02 03"w;
 0x80000001;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/lexer2.d b/gcc/testsuite/gdc.test/fail_compilation/lexer2.d
index f895e644c44..f8fae85c9b3 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/lexer2.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/lexer2.d
@@ -1,16 +1,16 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/lexer2.d(16): Error: semicolon expected following auto declaration, not `"123"`
-fail_compilation/lexer2.d(16): Error: declaration expected, not `"123"`
-fail_compilation/lexer2.d(17): Error: semicolon expected following auto declaration, not `"123G"`
-fail_compilation/lexer2.d(17): Error: declaration expected, not `"123G"`
+fail_compilation/lexer2.d(16): Error: odd number (3) of hex characters in hex string
+fail_compilation/lexer2.d(17): Error: non-hex character 'G' in hex string
 fail_compilation/lexer2.d(18): Error: heredoc rest of line should be blank
 fail_compilation/lexer2.d(20): Error: unterminated delimited string constant starting at fail_compilation/lexer2.d(20)
 fail_compilation/lexer2.d(22): Error: semicolon expected following auto declaration, not `End of File`
 ---
 */
 
+
+
 // https://dlang.dawg.eu/coverage/src/lexer.c.gcov.html
 
 static s1 = x"123";
diff --git a/gcc/testsuite/gdc.test/fail_compilation/main.d b/gcc/testsuite/gdc.test/fail_compilation/main.d
new file mode 100644
index 00000000000..42a8a43062f
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/main.d
@@ -0,0 +1,9 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/main.d(9): Error: only one entry point `main`$?:windows=, `WinMain` or `DllMain`$ is allowed
+fail_compilation/main.d(8):        previously found `void main()` here
+---
+*/
+void main() {}
+void main(string[] args) {}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/match_func_ptr.d b/gcc/testsuite/gdc.test/fail_compilation/match_func_ptr.d
new file mode 100644
index 00000000000..7f59183f2ce
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/match_func_ptr.d
@@ -0,0 +1,17 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/match_func_ptr.d(13): Error: cannot match delegate literal to function pointer type `void function()`
+fail_compilation/match_func_ptr.d(14): Error: cannot match function literal to delegate type `void delegate()`
+fail_compilation/match_func_ptr.d(15): Error: cannot infer parameter types from `int function()`
+fail_compilation/match_func_ptr.d(16): Error: cannot infer parameter types from `int delegate(int, int)`
+---
+*/
+
+void main()
+{
+    void function() f = delegate {};
+    void delegate() d = function {};
+    int function() f2 = i => 2;
+    int delegate(int, int) d2 = i => 2;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d b/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d
index 57706b59e41..9de436b0119 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d
@@ -23,7 +23,8 @@ fail_compilation/misc_parser_err_cov1.d(40): Error: semicolon expected following
 fail_compilation/misc_parser_err_cov1.d(40): Error: identifier or `new` expected following `.`, not `+`
 fail_compilation/misc_parser_err_cov1.d(41): Error: identifier or new keyword expected following `(...)`.
 fail_compilation/misc_parser_err_cov1.d(41): Error: expression expected, not `;`
-fail_compilation/misc_parser_err_cov1.d(42): Error: found `}` when expecting `;` following statement `(__error) + 0` on line fail_compilation/misc_parser_err_cov1.d(41)
+fail_compilation/misc_parser_err_cov1.d(42): Error: found `}` when expecting `;` following expression
+fail_compilation/misc_parser_err_cov1.d(41):        expression: `(__error) + 0`
 fail_compilation/misc_parser_err_cov1.d(43): Error: matching `}` expected following compound statement, not `End of File`
 fail_compilation/misc_parser_err_cov1.d(33):        unmatched `{`
 ---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/nogc3.d b/gcc/testsuite/gdc.test/fail_compilation/nogc3.d
index 3bd7167acba..b53903ffbc0 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/nogc3.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/nogc3.d
@@ -43,10 +43,12 @@ fail_compilation/nogc3.d(35): Error: `@nogc` function `nogc3.testCall` cannot ca
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/nogc3.d(52): Error: function `nogc3.testClosure1` is `@nogc` yet allocates closure for `testClosure1()` with the GC
-fail_compilation/nogc3.d(55):        `nogc3.testClosure1.bar` closes over variable `x` at fail_compilation/nogc3.d(54)
-fail_compilation/nogc3.d(64): Error: function `nogc3.testClosure3` is `@nogc` yet allocates closure for `testClosure3()` with the GC
-fail_compilation/nogc3.d(67):        `nogc3.testClosure3.bar` closes over variable `x` at fail_compilation/nogc3.d(66)
+fail_compilation/nogc3.d(54): Error: function `nogc3.testClosure1` is `@nogc` yet allocates closure for `testClosure1()` with the GC
+fail_compilation/nogc3.d(57):        function `nogc3.testClosure1.bar` closes over variable `x`
+fail_compilation/nogc3.d(56):        `x` declared here
+fail_compilation/nogc3.d(66): Error: function `nogc3.testClosure3` is `@nogc` yet allocates closure for `testClosure3()` with the GC
+fail_compilation/nogc3.d(69):        function `nogc3.testClosure3.bar` closes over variable `x`
+fail_compilation/nogc3.d(68):        `x` declared here
 ---
 */
 @nogc auto testClosure1()
@@ -73,10 +75,10 @@ fail_compilation/nogc3.d(67):        `nogc3.testClosure3.bar` closes over variab
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/nogc3.d(85): Error: array literal in `@nogc` function `nogc3.foo13702` may cause a GC allocation
-fail_compilation/nogc3.d(86): Error: array literal in `@nogc` function `nogc3.foo13702` may cause a GC allocation
-fail_compilation/nogc3.d(92): Error: array literal in `@nogc` function `nogc3.bar13702` may cause a GC allocation
-fail_compilation/nogc3.d(91): Error: array literal in `@nogc` function `nogc3.bar13702` may cause a GC allocation
+fail_compilation/nogc3.d(87): Error: array literal in `@nogc` function `nogc3.foo13702` may cause a GC allocation
+fail_compilation/nogc3.d(88): Error: array literal in `@nogc` function `nogc3.foo13702` may cause a GC allocation
+fail_compilation/nogc3.d(94): Error: array literal in `@nogc` function `nogc3.bar13702` may cause a GC allocation
+fail_compilation/nogc3.d(93): Error: array literal in `@nogc` function `nogc3.bar13702` may cause a GC allocation
 ---
 */
 int[] foo13702(bool b) @nogc
diff --git a/gcc/testsuite/gdc.test/fail_compilation/noreturn_expr.d b/gcc/testsuite/gdc.test/fail_compilation/noreturn_expr.d
new file mode 100644
index 00000000000..c72bade8fa5
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/noreturn_expr.d
@@ -0,0 +1,16 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/noreturn_expr.d(10): Error: type `noreturn` is not an expression
+---
+*/
+
+int v(e)()
+{
+    return e + 0;
+}
+
+int main()
+{
+    return v!(noreturn)();
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/noreturn_expr2.d b/gcc/testsuite/gdc.test/fail_compilation/noreturn_expr2.d
new file mode 100644
index 00000000000..f5e0054823b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/noreturn_expr2.d
@@ -0,0 +1,14 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/noreturn_expr2.d(8): Error: cannot cast `noreturn` to `int` at compile time
+---
+*/
+
+enum E {e1 = 1, e2 = 2, illegal = noreturn}
+
+void main()
+{
+    E e;
+    e = E.illegal;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/operator_undefined.d b/gcc/testsuite/gdc.test/fail_compilation/operator_undefined.d
new file mode 100644
index 00000000000..3065bdb8e79
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/operator_undefined.d
@@ -0,0 +1,20 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/operator_undefined.d(19): Error: operator `-` is not defined for `toJson(2)` of type `Json`
+---
+*/
+
+import std.stdio;
+
+struct Json
+{
+    //int opUnary(string op : "-")();
+}
+
+Json toJson(int);
+
+void main()
+{
+    auto x = -2.toJson;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/parseStc.d b/gcc/testsuite/gdc.test/fail_compilation/parseStc.d
index d13006db0ab..9a24741689e 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/parseStc.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/parseStc.d
@@ -3,12 +3,12 @@ TEST_OUTPUT:
 ---
 fail_compilation/parseStc.d(12): Error: missing closing `)` after `if (x`
 fail_compilation/parseStc.d(12): Error: use `{ }` for an empty statement, not `;`
-fail_compilation/parseStc.d(12): Error: found `)` when expecting `;` following statement `1` on line fail_compilation/parseStc.d(12)
+fail_compilation/parseStc.d(12): Error: found `)` when expecting `;` following expression
+fail_compilation/parseStc.d(12):        expression: `1`
 fail_compilation/parseStc.d(13): Error: redundant attribute `const`
 ---
 */
-void test1()
-{
+void test1() {
     if (x; 1) {}
     if (const const auto x = 1) {}
 }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/retscope.d b/gcc/testsuite/gdc.test/fail_compilation/retscope.d
index c08747fa7e3..ce983c01fc6 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/retscope.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/retscope.d
@@ -55,7 +55,7 @@ void test2(scope int* p, int[] a ...) @safe
 TEST_OUTPUT:
 ---
 fail_compilation/retscope.d(75): Error: function `retscope.HTTP.Impl.onReceive` is `@nogc` yet allocates closure for `onReceive()` with the GC
-fail_compilation/retscope.d(77):        `retscope.HTTP.Impl.onReceive.__lambda1` closes over variable `this` at fail_compilation/retscope.d(75)
+fail_compilation/retscope.d(77):        delegate `retscope.HTTP.Impl.onReceive.__lambda1` closes over variable `this`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/skip.d b/gcc/testsuite/gdc.test/fail_compilation/skip.d
index 0f3a9ec7e56..6207a106ddb 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/skip.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/skip.d
@@ -2,8 +2,10 @@
  * REQUIRED_ARGS: -de
  * TEST_OUTPUT:
 ---
-fail_compilation/skip.d(21): Error: `switch` skips declaration of `with` temporary at fail_compilation/skip.d(26)
-fail_compilation/skip.d(43): Error: `switch` skips declaration of variable `skip.test14532.n` at fail_compilation/skip.d(45)
+fail_compilation/skip.d(23): Error: `switch` skips declaration of `with` temporary
+fail_compilation/skip.d(28):        declared here
+fail_compilation/skip.d(45): Error: `switch` skips declaration of variable `skip.test14532.n`
+fail_compilation/skip.d(47):        declared here
 ---
  */
 // https://issues.dlang.org/show_bug.cgi?id=10524
diff --git a/gcc/testsuite/gdc.test/fail_compilation/switch_skip.d b/gcc/testsuite/gdc.test/fail_compilation/switch_skip.d
new file mode 100644
index 00000000000..7141fb16ba8
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/switch_skip.d
@@ -0,0 +1,48 @@
+/*
+REQUIRED_ARGS: -verrors=context
+TEST_OUTPUT:
+---
+fail_compilation/switch_skip.d(22): Error: `switch` skips declaration of variable `switch_skip.test3.j`
+    switch (i)
+    ^
+fail_compilation/switch_skip.d(26):        declared here
+            int j;
+                ^
+fail_compilation/switch_skip.d(39): Error: `switch` skips declaration of variable `switch_skip.test.z`
+    final switch(n)
+    ^
+fail_compilation/switch_skip.d(41):        declared here
+        int z = 5;
+            ^
+---
+*/
+
+void test3(int i)
+{
+    switch (i)
+    {
+        case 1:
+        {
+            int j;
+        case 2:
+            ++j;
+            break;
+        }
+        default:
+            break;
+    }
+}
+
+// https://issues.dlang.org/show_bug.cgi?id=18858
+int test(int n)
+{
+    final switch(n)
+    {
+        int z = 5;
+        enum e = 6;
+
+        case 1:
+            int y = 2;
+            return y;
+    }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/switches.d b/gcc/testsuite/gdc.test/fail_compilation/switches.d
index b53fb4c6375..06652c8cf34 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/switches.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/switches.d
@@ -1,13 +1,11 @@
-/************************************************************/
-
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/switches.d(105): Error: `case 2` not found
+fail_compilation/switches.d(14): Error: `case 2` not found
+fail_compilation/switches.d(25): Error: no `case` statement following `goto case;`
 ---
 */
 
-#line 100
 void test1(int i)
 {
     switch (i)
@@ -19,16 +17,6 @@ void test1(int i)
     }
 }
 
-/************************************************************/
-
-/*
-TEST_OUTPUT:
----
-fail_compilation/switches.d(205): Error: no `case` statement following `goto case;`
----
-*/
-
-#line 200
 void test2(int i)
 {
     switch (i)
@@ -39,55 +27,3 @@ void test2(int i)
             break;
     }
 }
-
-/************************************************************/
-
-/*
-TEST_OUTPUT:
----
-fail_compilation/switches.d(302): Error: `switch` skips declaration of variable `switches.test3.j` at fail_compilation/switches.d(306)
----
-*/
-
-#line 300
-void test3(int i)
-{
-    switch (i)
-    {
-        case 1:
-        {
-            int j;
-        case 2:
-            ++j;
-            break;
-        }
-        default:
-            break;
-    }
-}
-
-
-/************************************************************/
-
-/*
-TEST_OUTPUT:
----
-fail_compilation/switches.d(404): Error: `switch` skips declaration of variable `switches.test.z` at fail_compilation/switches.d(406)
----
-*/
-
-#line 400
-// https://issues.dlang.org/show_bug.cgi?id=18858
-
-int test(int n)
-{
-    final switch(n)
-    {
-        int z = 5;
-        enum e = 6;
-
-        case 1:
-            int y = 2;
-            return y;
-    }
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test13536.d b/gcc/testsuite/gdc.test/fail_compilation/test13536.d
index 4a4bb2672be..eff807ab5a3 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test13536.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test13536.d
@@ -1,9 +1,8 @@
-/* REQUIRED_ARGS: -wo
+/*
 TEST_OUTPUT:
 ---
-fail_compilation/test13536.d(23): Error: field `U.sysDg` cannot access pointers in `@safe` code that overlap other fields
-fail_compilation/test13536.d(23): Warning: address of variable `s` assigned to `u` with longer lifetime
-fail_compilation/test13536.d(24): Error: field `U.safeDg` cannot access pointers in `@safe` code that overlap other fields
+fail_compilation/test13536.d(22): Error: field `U.sysDg` cannot access pointers in `@safe` code that overlap other fields
+fail_compilation/test13536.d(23): Error: field `U.safeDg` cannot access pointers in `@safe` code that overlap other fields
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test15785.d b/gcc/testsuite/gdc.test/fail_compilation/test15785.d
index 594b5d35e75..fc61e3db070 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test15785.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test15785.d
@@ -2,8 +2,9 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/test15785.d(16): Error: no property `foo` for `super` of type `imports.test15785.Base`
-fail_compilation/test15785.d(17): Error: undefined identifier `bar`
+fail_compilation/test15785.d(17): Error: no property `foo` for `super` of type `imports.test15785.Base`
+fail_compilation/imports/test15785.d(3):        class `Base` defined here
+fail_compilation/test15785.d(18): Error: undefined identifier `bar`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test15897.d b/gcc/testsuite/gdc.test/fail_compilation/test15897.d
index db554cb9e15..c911263718f 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test15897.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test15897.d
@@ -3,7 +3,8 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/test15897.d(19): Error: no property `create` for `cat` of type `imports.test15897.Cat`
+fail_compilation/test15897.d(20): Error: no property `create` for `cat` of type `imports.test15897.Cat`
+fail_compilation/imports/test15897.d(4):        class `Cat` defined here
 ---
 */
 module test15897;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test16188.d b/gcc/testsuite/gdc.test/fail_compilation/test16188.d
index bdaae94a6ca..0bd052ca6db 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test16188.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test16188.d
@@ -3,6 +3,7 @@
 ---
 fail_compilation/test16188.d(101): Error: no property `name` for `Where()` of type `test16188.Where`
 fail_compilation/test16188.d(101):        potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message
+fail_compilation/test16188.d(103):        struct `Where` defined here
 ---
  */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test16193.d b/gcc/testsuite/gdc.test/fail_compilation/test16193.d
index 6c80471c77b..39399cf01d8 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test16193.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test16193.d
@@ -2,8 +2,9 @@
 REQUIRED_ARGS: -preview=dip1000
 TEST_OUTPUT:
 ---
-fail_compilation/test16193.d(38): Error: function `test16193.abc` is `@nogc` yet allocates closure for `abc()` with the GC
-fail_compilation/test16193.d(40):        `test16193.abc.__foreachbody2` closes over variable `x` at fail_compilation/test16193.d(39)
+fail_compilation/test16193.d(39): Error: function `test16193.abc` is `@nogc` yet allocates closure for `abc()` with the GC
+fail_compilation/test16193.d(41):        delegate `test16193.abc.__foreachbody2` closes over variable `x`
+fail_compilation/test16193.d(40):        `x` declared here
 ---
 */
 //fail_compilation/test16193.d(22): To enforce `@safe`, the compiler allocates a closure unless `opApply()` uses `scope`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test16365.d b/gcc/testsuite/gdc.test/fail_compilation/test16365.d
index 4d49365659c..5bfa5f8dba6 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test16365.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test16365.d
@@ -1,10 +1,9 @@
-/* REQUIRED_ARGS: -wo
+/*
 TEST_OUTPUT:
 ---
-fail_compilation/test16365.d(21): Error: `this` reference necessary to take address of member `f1` in `@safe` function `main`
-fail_compilation/test16365.d(23): Error: cannot implicitly convert expression `&f2` of type `void delegate() pure nothrow @nogc @safe` to `void function() @safe`
-fail_compilation/test16365.d(27): Warning: address of variable `s` assigned to `dg` with longer lifetime
-fail_compilation/test16365.d(28): Error: `dg.funcptr` cannot be used in `@safe` code
+fail_compilation/test16365.d(20): Error: `this` reference necessary to take address of member `f1` in `@safe` function `main`
+fail_compilation/test16365.d(22): Error: cannot implicitly convert expression `&f2` of type `void delegate() pure nothrow @nogc @safe` to `void function() @safe`
+fail_compilation/test16365.d(27): Error: `dg.funcptr` cannot be used in `@safe` code
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test17380spec.d b/gcc/testsuite/gdc.test/fail_compilation/test17380spec.d
index f523337037a..8ab8739d978 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test17380spec.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test17380spec.d
@@ -1,9 +1,10 @@
 /* REQUIRED_ARGS: -verrors=spec
 TEST_OUTPUT:
 ---
-(spec:1) fail_compilation/test17380spec.d(14): Error: cannot resolve identifier `ThisTypeDoesNotExistAndCrashesTheCompiler`
-(spec:1) fail_compilation/test17380spec.d(14): Error: no property `ThisTypeDoesNotExistAndCrashesTheCompiler` for `this.opCast()` of type `test17380spec.Uint128`
-fail_compilation/test17380spec.d(14): Error: undefined identifier `ThisTypeDoesNotExistAndCrashesTheCompiler`
+(spec:1) fail_compilation/test17380spec.d(15): Error: cannot resolve identifier `ThisTypeDoesNotExistAndCrashesTheCompiler`
+(spec:1) fail_compilation/test17380spec.d(15): Error: no property `ThisTypeDoesNotExistAndCrashesTheCompiler` for `this.opCast()` of type `test17380spec.Uint128`
+(spec:1) fail_compilation/test17380spec.d(20):        struct `Uint128` defined here
+fail_compilation/test17380spec.d(15): Error: undefined identifier `ThisTypeDoesNotExistAndCrashesTheCompiler`
 ---
  */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test20655.d b/gcc/testsuite/gdc.test/fail_compilation/test20655.d
new file mode 100644
index 00000000000..c3bb70af492
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test20655.d
@@ -0,0 +1,32 @@
+/*
+REQUIRED_ARGS: -de
+TEST_OUTPUT:
+---
+fail_compilation/test20655.d(29): Deprecation: `@safe` function `g` calling `f1`
+fail_compilation/test20655.d(24):        which wouldn't be `@safe` because of:
+fail_compilation/test20655.d(24):        field `U.s` cannot access pointers in `@safe` code that overlap other fields
+fail_compilation/test20655.d(30): Deprecation: `@safe` function `g` calling `f2`
+fail_compilation/test20655.d(25):        which wouldn't be `@safe` because of:
+fail_compilation/test20655.d(25):        field `U.s` cannot access pointers in `@safe` code that overlap other fields
+fail_compilation/test20655.d(31): Deprecation: `@safe` function `g` calling `f3`
+fail_compilation/test20655.d(28):        which wouldn't be `@safe` because of:
+fail_compilation/test20655.d(28):        field `U.s` cannot access pointers in `@safe` code that overlap other fields
+---
+*/
+
+union U
+{
+    string s;
+    int x;
+}
+U u;
+
+auto f1() { auto s = u.s; } /* Should be inferred as @system. */
+void f2()() { auto s = u.s; } /* ditto */
+void g() @safe
+{
+    void f3() { auto s = u.s; } /* ditto */
+    f1(); /* Should be rejected with error "cannot call @system function". */
+    f2(); /* ditto */
+    f3(); /* ditto */
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21353.d b/gcc/testsuite/gdc.test/fail_compilation/test21353.d
index 55c84f996a1..14fa26dcce7 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test21353.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21353.d
@@ -2,11 +2,14 @@
 EXTRA_FILES: imports/imp21353.d
 TEST_OUTPUT:
 ---
-fail_compilation/test21353.d(19): Error: no property `A` for type `imports.imp21353.B`
-fail_compilation/test21353.d(20): Error: no property `A` for type `imports.imp21353.B`
-fail_compilation/test21353.d(21): Error: no property `A` for type `imports.imp21353.B`
-fail_compilation/test21353.d(23): Error: undefined identifier `P` in module `imports.imp21353`
-fail_compilation/test21353.d(24): Error: undefined identifier `P` in module `imports.imp21353`
+fail_compilation/test21353.d(22): Error: no property `A` for type `imports.imp21353.B`
+fail_compilation/imports/imp21353.d(5):        struct `B` defined here
+fail_compilation/test21353.d(23): Error: no property `A` for type `imports.imp21353.B`
+fail_compilation/imports/imp21353.d(5):        struct `B` defined here
+fail_compilation/test21353.d(24): Error: no property `A` for type `imports.imp21353.B`
+fail_compilation/imports/imp21353.d(5):        struct `B` defined here
+fail_compilation/test21353.d(26): Error: undefined identifier `P` in module `imports.imp21353`
+fail_compilation/test21353.d(27): Error: undefined identifier `P` in module `imports.imp21353`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21912.d b/gcc/testsuite/gdc.test/fail_compilation/test21912.d
index 9b07eba0df6..f8bcb40b5df 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test21912.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21912.d
@@ -2,14 +2,18 @@
 PERMUTE_ARGS: -preview=dip1000
 TEST_OUTPUT:
 ---
-fail_compilation/test21912.d(24): Error: function `test21912.escapeParam` is `@nogc` yet allocates closure for `escapeParam()` with the GC
-fail_compilation/test21912.d(26):        `test21912.escapeParam.__lambda2` closes over variable `i` at fail_compilation/test21912.d(24)
-fail_compilation/test21912.d(29): Error: function `test21912.escapeAssign` is `@nogc` yet allocates closure for `escapeAssign()` with the GC
-fail_compilation/test21912.d(31):        `test21912.escapeAssign.__lambda3` closes over variable `i` at fail_compilation/test21912.d(29)
-fail_compilation/test21912.d(40): Error: function `test21912.escapeAssignRef` is `@nogc` yet allocates closure for `escapeAssignRef()` with the GC
-fail_compilation/test21912.d(42):        `test21912.escapeAssignRef.__lambda3` closes over variable `i` at fail_compilation/test21912.d(40)
-fail_compilation/test21912.d(51): Error: function `test21912.escapeParamInferred` is `@nogc` yet allocates closure for `escapeParamInferred()` with the GC
-fail_compilation/test21912.d(53):        `test21912.escapeParamInferred.__lambda2` closes over variable `i` at fail_compilation/test21912.d(51)
+fail_compilation/test21912.d(28): Error: function `test21912.escapeParam` is `@nogc` yet allocates closure for `escapeParam()` with the GC
+fail_compilation/test21912.d(30):        delegate `test21912.escapeParam.__lambda2` closes over variable `i`
+fail_compilation/test21912.d(28):        `i` declared here
+fail_compilation/test21912.d(33): Error: function `test21912.escapeAssign` is `@nogc` yet allocates closure for `escapeAssign()` with the GC
+fail_compilation/test21912.d(35):        delegate `test21912.escapeAssign.__lambda3` closes over variable `i`
+fail_compilation/test21912.d(33):        `i` declared here
+fail_compilation/test21912.d(44): Error: function `test21912.escapeAssignRef` is `@nogc` yet allocates closure for `escapeAssignRef()` with the GC
+fail_compilation/test21912.d(46):        delegate `test21912.escapeAssignRef.__lambda3` closes over variable `i`
+fail_compilation/test21912.d(44):        `i` declared here
+fail_compilation/test21912.d(55): Error: function `test21912.escapeParamInferred` is `@nogc` yet allocates closure for `escapeParamInferred()` with the GC
+fail_compilation/test21912.d(57):        delegate `test21912.escapeParamInferred.__lambda2` closes over variable `i`
+fail_compilation/test21912.d(55):        `i` declared here
 ---
 */
 @nogc:
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test22329.d b/gcc/testsuite/gdc.test/fail_compilation/test22329.d
index 237f9c76667..25c83f5142d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test22329.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test22329.d
@@ -4,8 +4,9 @@
 TEST_OUTPUT:
 ---
 fail_compilation/imports/imp22329.d(3): Error: no property `values` for type `test22329.Foo`
+fail_compilation/test22329.d(13):        struct `Foo` defined here
 fail_compilation/imports/imp22329.d(3): Error: incompatible types for `(arg) + (1)`: `Foo` and `int`
-fail_compilation/test22329.d(20): Error: template instance `imp22329.func!(Foo)` error instantiating
+fail_compilation/test22329.d(21): Error: template instance `imp22329.func!(Foo)` error instantiating
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test23112.d b/gcc/testsuite/gdc.test/fail_compilation/test23112.d
index 325d89bd6c2..9bbab80e48c 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test23112.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test23112.d
@@ -2,7 +2,8 @@
 TEST_OUTPUT:
 ---
 fail_compilation/test23112.d(106): Error: function `test23112.bar` is `@nogc` yet allocates closure for `bar()` with the GC
-fail_compilation/test23112.d(108):        `test23112.bar.f` closes over variable `a` at fail_compilation/test23112.d(106)
+fail_compilation/test23112.d(108):        function `test23112.bar.f` closes over variable `a`
+fail_compilation/test23112.d(106):        `a` declared here
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test24015.d b/gcc/testsuite/gdc.test/fail_compilation/test24015.d
new file mode 100644
index 00000000000..c9bc42e055e
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test24015.d
@@ -0,0 +1,20 @@
+/* REQUIRED_ARGS: -preview=dip1000
+ * TEST_OUTPUT:
+---
+fail_compilation/test24015.d(19): Error: scope variable `v` assigned to non-scope parameter `...` calling `jer`
+---
+*/
+
+// https://issues.dlang.org/show_bug.cgi?id=24105
+
+@safe:
+
+extern (C) void ben(int i, scope ...);
+
+extern (C) void jer(int i, ...);
+
+void bar(scope const char* v)
+{
+    ben(3, v);
+    jer(3, v);
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test24036.d b/gcc/testsuite/gdc.test/fail_compilation/test24036.d
new file mode 100644
index 00000000000..da529f90ee9
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test24036.d
@@ -0,0 +1,21 @@
+/*
+https://issues.dlang.org/show_bug.cgi?id=24036
+Issue 24036 - assert message in CTFE becomes `['m', 'e', 's', 's', 'a', 'g', 'e'][0..7]` if produced using std.format.format
+
+TEST_OUTPUT:
+---
+fail_compilation/test24036.d(19): Error: message
+fail_compilation/test24036.d(21):        called from here: `(*function () pure nothrow @safe => 42)()`
+---
+*/
+
+auto format()
+{
+    return ['m', 'e', 's', 's', 'a', 'g', 'e'][0 .. 7];
+}
+
+immutable ctfeThing = ()
+{
+    assert(0, format());
+    return 42;
+}();
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test24065.d b/gcc/testsuite/gdc.test/fail_compilation/test24065.d
new file mode 100644
index 00000000000..9e4ebbf4d16
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test24065.d
@@ -0,0 +1,18 @@
+// https://issues.dlang.org/show_bug.cgi?id=24065
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test24065.d(12): Error: string expected as argument of __traits `getTargetInfo` instead of `int`
+fail_compilation/test24065.d(15): Error: string expected as argument of __traits `getTargetInfo` instead of `foo`
+fail_compilation/test24065.d(18): Error: string expected as argument of __traits `getTargetInfo` instead of `e`
+---
+*/
+
+auto s1 = __traits(getTargetInfo, int);
+
+void foo() {}
+auto s2 = __traits(getTargetInfo, foo);
+
+enum e;
+auto s3 = __traits(getTargetInfo, e);
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test24084.d b/gcc/testsuite/gdc.test/fail_compilation/test24084.d
new file mode 100644
index 00000000000..51de15ea21a
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test24084.d
@@ -0,0 +1,28 @@
+/* REQUIRED_ARGS: -nothrow
+ * TEST_OUTPUT:
+---
+fail_compilation/test24084.d(110): Error: cannot use `throw` statements with -nothrow
+fail_compilation/test24084.d(112): Error: cannot use try-catch statements with -nothrow
+---
+ */
+
+// https://issues.dlang.org/show_bug.cgi?id=24084
+
+#line 100
+
+struct S
+{
+    int x;
+    ~this() { }
+}
+
+void xyzzy()
+{
+    S s;
+    throw new Exception("xx");
+
+    try
+    {
+        int y;
+    } catch (Exception) { }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test24110.d b/gcc/testsuite/gdc.test/fail_compilation/test24110.d
new file mode 100644
index 00000000000..acf7788c6e0
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test24110.d
@@ -0,0 +1,12 @@
+// https://issues.dlang.org/show_bug.cgi?id=24110
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test24110.d(12): Error: static assert:  `__traits(compiles, __error)` is false
+---
+*/
+
+struct S { int x; }
+alias T = shared S;
+static assert(__traits(compiles, (T[] a, T[] b) => a < b));
diff --git a/gcc/testsuite/gdc.test/fail_compilation/testOpApply.d b/gcc/testsuite/gdc.test/fail_compilation/testOpApply.d
index 9203685fdc8..8d6c736e5af 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/testOpApply.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/testOpApply.d
@@ -48,9 +48,9 @@ void testSameAttr() @system
 TEST_OUTPUT:
 ---
 fail_compilation/testOpApply.d(217): Error: `sa.opApply` matches more than one declaration:
-`fail_compilation/testOpApply.d(203)`:     `int(int delegate(int) dg)`
+fail_compilation/testOpApply.d(203):        `int(int delegate(int) dg)`
 and:
-`fail_compilation/testOpApply.d(208)`:     `int(int delegate(string) dg)`
+fail_compilation/testOpApply.d(208):        `int(int delegate(string) dg)`
 fail_compilation/testOpApply.d(217): Error: cannot uniquely infer `foreach` argument types
 ---
 +/
@@ -79,9 +79,9 @@ void testDifferentTypes()
 TEST_OUTPUT:
 ---
 fail_compilation/testOpApply.d(317): Error: `sa.opApply` matches more than one declaration:
-`fail_compilation/testOpApply.d(303)`:     `int(int delegate(int) dg)`
+fail_compilation/testOpApply.d(303):        `int(int delegate(int) dg)`
 and:
-`fail_compilation/testOpApply.d(308)`:     `int(int delegate(long) dg)`
+fail_compilation/testOpApply.d(308):        `int(int delegate(long) dg)`
 fail_compilation/testOpApply.d(317): Error: cannot uniquely infer `foreach` argument types
 ---
 +/
@@ -112,9 +112,9 @@ See https://issues.dlang.org/show_bug.cgi?id=21683
 TEST_OUTPUT:
 ---
 fail_compilation/testOpApply.d(420): Error: `sa.opApply` matches more than one declaration:
-`fail_compilation/testOpApply.d(404)`:     `int(int delegate(int) dg)`
+fail_compilation/testOpApply.d(404):        `int(int delegate(int) dg)`
 and:
-`fail_compilation/testOpApply.d(410)`:     `int(int delegate(ref int) dg)`
+fail_compilation/testOpApply.d(410):        `int(int delegate(ref int) dg)`
 fail_compilation/testOpApply.d(420): Error: cannot uniquely infer `foreach` argument types
 ---
 +/
@@ -146,9 +146,9 @@ void testDifferentQualifiers()
 TEST_OUTPUT:
 ---
 fail_compilation/testOpApply.d(504): Error: `sa.opApply` matches more than one declaration:
-`fail_compilation/testOpApply.d(404)`:     `int(int delegate(int) dg)`
+fail_compilation/testOpApply.d(404):        `int(int delegate(int) dg)`
 and:
-`fail_compilation/testOpApply.d(410)`:     `int(int delegate(ref int) dg)`
+fail_compilation/testOpApply.d(410):        `int(int delegate(ref int) dg)`
 fail_compilation/testOpApply.d(504): Error: cannot uniquely infer `foreach` argument types
 ---
 +/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/testsemi.d b/gcc/testsuite/gdc.test/fail_compilation/testsemi.d
index fc9bc651070..77601a5e446 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/testsemi.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/testsemi.d
@@ -8,7 +8,8 @@ fail_compilation/testsemi.d(117): Error: found `int` when expecting `;` followin
 fail_compilation/testsemi.d(117): Error: no identifier for declarator `x`
 fail_compilation/testsemi.d(123): Error: found `int` when expecting `;` following mixin
 fail_compilation/testsemi.d(129): Error: found `int` when expecting `;` following `import` Expression
-fail_compilation/testsemi.d(131): Error: `}` expected following members in `class` declaration at fail_compilation/testsemi.d(112)
+fail_compilation/testsemi.d(131): Error: `}` expected following members in `class` declaration
+fail_compilation/testsemi.d(112):        class `C` starts here
 ---
  */
 
diff --git a/gcc/testsuite/gdc.test/runnable/staticaa.d b/gcc/testsuite/gdc.test/runnable/staticaa.d
new file mode 100644
index 00000000000..38678c92901
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/staticaa.d
@@ -0,0 +1,126 @@
+// https://issues.dlang.org/show_bug.cgi?id=23103
+// Issue 23103 - static initialization of associative arrays is not implemented
+
+nothrow @safe:
+
+/////////////////////////////////////////////
+
+int[int] globalAA = [1: 10, 2: 20];
+
+void testSimple()
+{
+    assert(globalAA[1] == 10);
+    assert(globalAA[2] == 20);
+    assert(!(30 in globalAA));
+
+    foreach (i; 0 .. 1000)
+    {
+        globalAA[i] = i * 10;
+        assert(globalAA[i] == i * 10);
+    }
+}
+
+/////////////////////////////////////////////
+
+struct Composit
+{
+    string[string][] aa;
+}
+
+auto getAA() { return ["a": "A"]; }
+
+immutable Composit compositAA = Composit([getAA(), ["b": "B"]]);
+
+void testComposit() pure
+{
+    assert(compositAA.aa[0]["a"] == "A");
+    assert(compositAA.aa[1]["b"] == "B");
+}
+
+/////////////////////////////////////////////
+
+struct Destructing
+{
+    int v;
+    static int destructorsCalled = 0;
+
+    ~this() nothrow
+    {
+        // FIXME: the lowering to newaa calls the destructor at CTFE, so we can't modify globals in it
+        if (!__ctfe)
+            destructorsCalled++;
+    }
+}
+
+struct Key
+{
+    int v;
+    bool opEquals(ref const Key o) const { return v == o.v; }
+    size_t toHash() const { return v; }
+}
+
+Destructing[Key] dAa = [Key(1): Destructing(10), Key(2): Destructing(20)];
+
+void testDestructor()
+{
+    assert(dAa[Key(1)].v == 10);
+    assert(dAa[Key(2)].v == 20);
+    assert(Destructing.destructorsCalled == 0);
+    dAa[Key(1)] = Destructing(100);
+    assert(dAa[Key(1)].v == 100);
+    assert(Destructing.destructorsCalled == 1);
+}
+
+/////////////////////////////////////////////
+
+enum A
+{
+    x, y, z
+}
+
+struct S
+{
+    string[A] t = [A.x : "A.x", A.y : "A.y"];
+}
+
+void testStructInit()
+{
+    S s;
+    assert(s.t[A.x] == "A.x");
+    assert(s.t[A.y] == "A.y");
+}
+
+/////////////////////////////////////////////
+
+class C
+{
+    string[int] t = [0 : "zero"];
+}
+
+void testClassInit()
+{
+    C c = new C();
+    assert(c.t[0] == "zero");
+}
+
+/////////////////////////////////////////////
+
+immutable(string)[immutable(int)] immutableAA = [1: "one", 2: "two"];
+
+void testImmutable()
+{
+    assert(immutableAA[1] == "one");
+    assert(immutableAA[2] == "two");
+}
+
+/////////////////////////////////////////////
+
+void main()
+{
+    testSimple();
+    testComposit();
+    testDestructor();
+    testStructInit();
+    testClassInit();
+    testImmutable();
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test24078.d b/gcc/testsuite/gdc.test/runnable/test24078.d
new file mode 100644
index 00000000000..99d74400cf8
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/test24078.d
@@ -0,0 +1,6 @@
+//https://issues.dlang.org/show_bug.cgi?id=24078
+
+void main()
+{
+    assert(["c"] ~ "a" ~ "b" == ["c", "a", "b"]);
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test24139.d b/gcc/testsuite/gdc.test/runnable/test24139.d
new file mode 100644
index 00000000000..af6215dd2ac
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/test24139.d
@@ -0,0 +1,25 @@
+// https://issues.dlang.org/show_bug.cgi?id=24139
+
+struct S1
+{
+    int x;
+    extern(C++) ~this() { assert(&this == s1); }
+}
+
+extern(C++) struct S2
+{
+    int x;
+    ~this() { assert(&this == s2); }
+}
+
+S1* s1;
+S2* s2;
+
+void main()
+{
+    s1 = new S1;
+    s2 = new S2;
+
+    typeid(S1).destroy(s1);
+    typeid(S2).destroy(s2);
+}
diff --git a/gcc/testsuite/lib/gdc-utils.exp b/gcc/testsuite/lib/gdc-utils.exp
index 25574cb8ec7..cbd25e9b9e3 100644
--- a/gcc/testsuite/lib/gdc-utils.exp
+++ b/gcc/testsuite/lib/gdc-utils.exp
@@ -163,6 +163,9 @@ proc gdc-convert-args { args } {
 	    upvar 2 compilable_do_what compilable_do_what
 	    set compilable_do_what "compile"
 
+	} elseif [string match "-nothrow" $arg] {
+	    lappend out "-fno-exceptions"
+
 	} elseif [string match "-vgc" $arg] {
 	    lappend out "-ftransition=nogc"
 
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index dc267787cab..d5dfe0d0edd 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@
-4574d1728d1f7e52ff40e6733b8c39889d128349
+f9efc98fd7954741333f72c6a50af273f3863a1a
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 832a0524ab3..0aefbf22ca6 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -186,9 +186,9 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	core/internal/gc/impl/manual/gc.d core/internal/gc/impl/proto/gc.d \
 	core/internal/gc/os.d core/internal/gc/pooltable.d \
 	core/internal/gc/proxy.d core/internal/hash.d core/internal/lifetime.d \
-	core/internal/moving.d core/internal/parseoptions.d \
-	core/internal/postblit.d core/internal/qsort.d \
-	core/internal/spinlock.d core/internal/string.d \
+	core/internal/moving.d core/internal/newaa.d \
+	core/internal/parseoptions.d core/internal/postblit.d \
+	core/internal/qsort.d core/internal/spinlock.d core/internal/string.d \
 	core/internal/switch_.d core/internal/traits.d core/internal/utf.d \
 	core/internal/util/array.d core/internal/util/math.d core/lifetime.d \
 	core/math.d core/memory.d core/runtime.d core/simd.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 61a2a770888..39066dd33cc 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -213,21 +213,21 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
 	core/internal/gc/impl/proto/gc.lo core/internal/gc/os.lo \
 	core/internal/gc/pooltable.lo core/internal/gc/proxy.lo \
 	core/internal/hash.lo core/internal/lifetime.lo \
-	core/internal/moving.lo core/internal/parseoptions.lo \
-	core/internal/postblit.lo core/internal/qsort.lo \
-	core/internal/spinlock.lo core/internal/string.lo \
-	core/internal/switch_.lo core/internal/traits.lo \
-	core/internal/utf.lo core/internal/util/array.lo \
-	core/internal/util/math.lo core/lifetime.lo core/math.lo \
-	core/memory.lo core/runtime.lo core/simd.lo \
-	core/stdc/assert_.lo core/stdc/complex.lo core/stdc/config.lo \
-	core/stdc/ctype.lo core/stdc/errno.lo core/stdc/fenv.lo \
-	core/stdc/float_.lo core/stdc/inttypes.lo core/stdc/limits.lo \
-	core/stdc/locale.lo core/stdc/math.lo core/stdc/signal.lo \
-	core/stdc/stdarg.lo core/stdc/stddef.lo core/stdc/stdint.lo \
-	core/stdc/stdio.lo core/stdc/stdlib.lo core/stdc/string.lo \
-	core/stdc/tgmath.lo core/stdc/time.lo core/stdc/wchar_.lo \
-	core/stdc/wctype.lo core/sync/barrier.lo \
+	core/internal/moving.lo core/internal/newaa.lo \
+	core/internal/parseoptions.lo core/internal/postblit.lo \
+	core/internal/qsort.lo core/internal/spinlock.lo \
+	core/internal/string.lo core/internal/switch_.lo \
+	core/internal/traits.lo core/internal/utf.lo \
+	core/internal/util/array.lo core/internal/util/math.lo \
+	core/lifetime.lo core/math.lo core/memory.lo core/runtime.lo \
+	core/simd.lo core/stdc/assert_.lo core/stdc/complex.lo \
+	core/stdc/config.lo core/stdc/ctype.lo core/stdc/errno.lo \
+	core/stdc/fenv.lo core/stdc/float_.lo core/stdc/inttypes.lo \
+	core/stdc/limits.lo core/stdc/locale.lo core/stdc/math.lo \
+	core/stdc/signal.lo core/stdc/stdarg.lo core/stdc/stddef.lo \
+	core/stdc/stdint.lo core/stdc/stdio.lo core/stdc/stdlib.lo \
+	core/stdc/string.lo core/stdc/tgmath.lo core/stdc/time.lo \
+	core/stdc/wchar_.lo core/stdc/wctype.lo core/sync/barrier.lo \
 	core/sync/condition.lo core/sync/config.lo core/sync/event.lo \
 	core/sync/exception.lo core/sync/mutex.lo core/sync/package.lo \
 	core/sync/rwmutex.lo core/sync/semaphore.lo \
@@ -859,9 +859,9 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	core/internal/gc/impl/manual/gc.d core/internal/gc/impl/proto/gc.d \
 	core/internal/gc/os.d core/internal/gc/pooltable.d \
 	core/internal/gc/proxy.d core/internal/hash.d core/internal/lifetime.d \
-	core/internal/moving.d core/internal/parseoptions.d \
-	core/internal/postblit.d core/internal/qsort.d \
-	core/internal/spinlock.d core/internal/string.d \
+	core/internal/moving.d core/internal/newaa.d \
+	core/internal/parseoptions.d core/internal/postblit.d \
+	core/internal/qsort.d core/internal/spinlock.d core/internal/string.d \
 	core/internal/switch_.d core/internal/traits.d core/internal/utf.d \
 	core/internal/util/array.d core/internal/util/math.d core/lifetime.d \
 	core/math.d core/memory.d core/runtime.d core/simd.d \
@@ -1268,6 +1268,7 @@ core/internal/gc/proxy.lo: core/internal/gc/$(am__dirstamp)
 core/internal/hash.lo: core/internal/$(am__dirstamp)
 core/internal/lifetime.lo: core/internal/$(am__dirstamp)
 core/internal/moving.lo: core/internal/$(am__dirstamp)
+core/internal/newaa.lo: core/internal/$(am__dirstamp)
 core/internal/parseoptions.lo: core/internal/$(am__dirstamp)
 core/internal/postblit.lo: core/internal/$(am__dirstamp)
 core/internal/qsort.lo: core/internal/$(am__dirstamp)
diff --git a/libphobos/libdruntime/core/internal/newaa.d b/libphobos/libdruntime/core/internal/newaa.d
new file mode 100644
index 00000000000..314f2554103
--- /dev/null
+++ b/libphobos/libdruntime/core/internal/newaa.d
@@ -0,0 +1,144 @@
+/**
+   Turn an Associative Array into a binary compatible struct for static initialization.
+
+   This does not implement all the pieces of
+   the associative array type in druntime, just enough to create an AA from an
+   existing range of key/value pairs.
+
+   Copyright: Copyright Digital Mars 2000 - 2015, Steven Schveighoffer 2022.
+   License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
+   Authors:   Martin Nowak, Steven Schveighoffer
+*/
+module core.internal.newaa;
+
+import core.memory;
+
+// grow threshold
+private enum GROW_NUM = 4;
+private enum GROW_DEN = 5;
+// shrink threshold
+private enum SHRINK_NUM = 1;
+private enum SHRINK_DEN = 8;
+// grow factor
+private enum GROW_FAC = 4;
+// growing the AA doubles it's size, so the shrink threshold must be
+// smaller than half the grow threshold to have a hysteresis
+static assert(GROW_FAC * SHRINK_NUM * GROW_DEN < GROW_NUM * SHRINK_DEN);
+// initial load factor (for literals), mean of both thresholds
+private enum INIT_NUM = (GROW_DEN * SHRINK_NUM + GROW_NUM * SHRINK_DEN) / 2;
+private enum INIT_DEN = SHRINK_DEN * GROW_DEN;
+
+private enum INIT_NUM_BUCKETS = 8;
+// magic hash constants to distinguish empty, deleted, and filled buckets
+private enum HASH_EMPTY = 0;
+private enum HASH_FILLED_MARK = size_t(1) << 8 * size_t.sizeof - 1;
+
+private struct Bucket
+{
+    size_t hash;
+    void *entry;
+}
+
+struct Impl
+{
+    Bucket[] buckets;
+    uint used;
+    uint deleted;
+    TypeInfo_Struct entryTI;
+    uint firstUsed;
+    immutable uint keysz;
+    immutable uint valsz;
+    immutable uint valoff;
+    Flags flags;
+
+    enum Flags : ubyte
+    {
+        none = 0x0,
+        keyHasPostblit = 0x1,
+        hasPointers = 0x2,
+    }
+}
+
+private struct AAShell
+{
+    Impl *impl;
+}
+
+private size_t mix(size_t h) @safe pure nothrow @nogc
+{
+    // final mix function of MurmurHash2
+    enum m = 0x5bd1e995;
+    h ^= h >> 13;
+    h *= m;
+    h ^= h >> 15;
+    return h;
+}
+
+struct Entry(K, V)
+{
+    /*const*/ K key; // this really should be const, but legacy issues.
+    V value;
+}
+
+
+// create a binary-compatible AA structure that can be used directly as an
+// associative array.
+AAShell makeAA(K, V)(V[K] src)
+{
+    immutable srclen = src.length;
+    assert(srclen <= uint.max);
+    alias E = Entry!(K, V);
+    if (srclen == 0)
+        return AAShell.init;
+    // first, determine the size that would be used if we grew the bucket list
+    // one element at a time using the standard AA algorithm.
+    size_t dim = INIT_NUM_BUCKETS;
+    while (srclen * GROW_DEN > dim * GROW_NUM)
+        dim = dim * GROW_FAC;
+
+    Bucket[] buckets;
+    // Allocate and fill the buckets
+    if (__ctfe)
+        buckets = new Bucket[dim];
+    else
+        assert(0);
+
+    assert(buckets.length >= dim);
+
+    immutable mask = dim - 1;
+    assert((dim & mask) == 0); // must be a power of 2
+
+    Bucket* findSlotInsert(immutable size_t hash)
+    {
+        for (size_t i = hash & mask, j = 1;; ++j)
+        {
+            if (buckets[i].hash == HASH_EMPTY)
+                return &buckets[i];
+            i = (i + j) & mask;
+        }
+    }
+
+    uint firstUsed = cast(uint) buckets.length;
+    foreach (k, v; src)
+    {
+        immutable h = hashOf(k).mix | HASH_FILLED_MARK;
+        auto location = findSlotInsert(h);
+        immutable nfu = cast(uint) (location - &buckets[0]);
+        if (nfu < firstUsed)
+            firstUsed = nfu;
+        *location = Bucket(h, new E(k, v));
+    }
+
+    enum flags = () {
+        import core.internal.traits;
+        Impl.Flags flags;
+        static if (__traits(hasPostblit, K))
+            flags |= flags.keyHasPostblit;
+        static if (hasIndirections!E)
+            flags |= flags.hasPointers;
+        return flags;
+    } ();
+    // return the new implementation
+    return AAShell(new Impl(buckets, cast(uint)srclen, 0, typeid(E), firstUsed,
+            K.sizeof, V.sizeof, E.value.offsetof, flags));
+}
diff --git a/libphobos/libdruntime/core/stdc/math.d b/libphobos/libdruntime/core/stdc/math.d
index 2666c952992..76b32b44de1 100644
--- a/libphobos/libdruntime/core/stdc/math.d
+++ b/libphobos/libdruntime/core/stdc/math.d
@@ -4129,7 +4129,18 @@ else version (CRuntime_UClibc)
     ///
     pure float   modff(float value, float* iptr);
     ///
-    extern(D) pure real modfl(real value, real *iptr) { return modf(cast(double) value, cast(double*) iptr); }
+    extern(D) pure real modfl(real value, real *iptr)
+    {
+        static if (double.sizeof == real.sizeof)
+             return modf(cast(double) value, cast(double*) iptr);
+        else
+        {
+            double i;
+            double r = modf(cast(double) value, &i);
+            *iptr = i;
+            return r;
+        }
+    }
 
     ///
     double  scalbn(double x, int n);
diff --git a/libphobos/libdruntime/core/stdcpp/string.d b/libphobos/libdruntime/core/stdcpp/string.d
index defbd8330eb..722b82fe418 100644
--- a/libphobos/libdruntime/core/stdcpp/string.d
+++ b/libphobos/libdruntime/core/stdcpp/string.d
@@ -155,7 +155,7 @@ extern(D):
     ///
     alias opDollar = length;
     ///
-    bool empty() const nothrow @safe                                        { return size() == 0; }
+    bool empty() const nothrow @trusted                                     { return size() == 0; }
 
     ///
     size_t[2] opSlice(size_t dim : 0)(size_t start, size_t end) const pure nothrow @safe @nogc { return [start, end]; }
@@ -1918,7 +1918,7 @@ extern(D):
         ///
         size_type capacity() const nothrow                                  { return (__is_long() ? __get_long_cap() : __min_cap) - 1; }
         ///
-        inout(T)* data() inout @safe                                        { return __get_pointer(); }
+        inout(T)* data() inout @trusted                                     { return __get_pointer(); }
         ///
         inout(T)[] as_array() scope return inout nothrow @trusted           { return __get_pointer()[0 .. size()]; }
         ///
@@ -2355,7 +2355,7 @@ extern(D):
                 }
             }
             void __set_long_size(size_type __s) nothrow                         { __r_.first().__l.__size_ = __s; }
-            size_type __get_long_size() const nothrow                           { return __r_.first().__l.__size_; }
+            size_type __get_long_size() const nothrow @trusted                  { return __r_.first().__l.__size_; }
             void __set_size(size_type __s) nothrow                              { if (__is_long()) __set_long_size(__s); else __set_short_size(__s); }
 
             void __set_long_cap(size_type __s) nothrow                          { __r_.first().__l.__cap_  = __long_mask | __s; }
diff --git a/libphobos/libdruntime/core/sys/posix/fcntl.d b/libphobos/libdruntime/core/sys/posix/fcntl.d
index 0a58034087d..df66b27f723 100644
--- a/libphobos/libdruntime/core/sys/posix/fcntl.d
+++ b/libphobos/libdruntime/core/sys/posix/fcntl.d
@@ -135,6 +135,27 @@ version (linux)
     enum F_SETLK        = 6;
     enum F_SETLKW       = 7;
   }
+  else version (MIPS_N64)
+  {
+    enum F_GETLK        = 14;
+    enum F_SETLK        = 6;
+    enum F_SETLKW       = 7;
+  }
+  else version (MIPS_Any)
+  {
+    static if ( __USE_FILE_OFFSET64 )
+    {
+      enum F_GETLK      = 33;
+      enum F_SETLK      = 34;
+      enum F_SETLKW     = 35;
+    }
+    else
+    {
+      enum F_GETLK      = 14;
+      enum F_SETLK      = 6;
+      enum F_SETLKW     = 7;
+    }
+  }
   else
   static if ( __USE_FILE_OFFSET64 )
   {
diff --git a/libphobos/libdruntime/core/sys/posix/signal.d b/libphobos/libdruntime/core/sys/posix/signal.d
index f722bc4df62..a2e229f6018 100644
--- a/libphobos/libdruntime/core/sys/posix/signal.d
+++ b/libphobos/libdruntime/core/sys/posix/signal.d
@@ -2390,11 +2390,23 @@ version (CRuntime_Glibc)
     //ucontext_t (defined in core.sys.posix.ucontext)
     //mcontext_t (defined in core.sys.posix.ucontext)
 
-    struct stack_t
+    version (MIPS_Any)
     {
-        void*   ss_sp;
-        int     ss_flags;
-        size_t  ss_size;
+        struct stack_t
+        {
+            void*   ss_sp;
+            size_t  ss_size;
+            int     ss_flags;
+        }
+    }
+    else
+    {
+        struct stack_t
+        {
+            void*   ss_sp;
+            int     ss_flags;
+            size_t  ss_size;
+        }
     }
 
     struct sigstack
@@ -2760,7 +2772,7 @@ else version (CRuntime_UClibc)
     enum MINSIGSTKSZ    = 2048;
     enum SIGSTKSZ       = 8192;
 
-    version (MIPS32)
+    version (MIPS_Any)
     {
         struct stack_t
         {
diff --git a/libphobos/libdruntime/core/sys/posix/sys/resource.d b/libphobos/libdruntime/core/sys/posix/sys/resource.d
index b997f112e4d..3a9a1876393 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/resource.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/resource.d
@@ -22,6 +22,9 @@ else version (TVOS)
 else version (WatchOS)
     version = Darwin;
 
+version (MIPS32)  version = MIPS_Any;
+version (MIPS64)  version = MIPS_Any;
+
 nothrow @nogc extern(C):
 
 //
@@ -120,15 +123,31 @@ version (linux)
             c_long[16] __reserved;
     }
 
-    enum
+    version (MIPS_Any)
     {
-        RLIMIT_CORE   = 4,
-        RLIMIT_CPU    = 0,
-        RLIMIT_DATA   = 2,
-        RLIMIT_FSIZE  = 1,
-        RLIMIT_NOFILE = 7,
-        RLIMIT_STACK  = 3,
-        RLIMIT_AS     = 9,
+        enum
+        {
+            RLIMIT_CORE   = 4,
+            RLIMIT_CPU    = 0,
+            RLIMIT_DATA   = 2,
+            RLIMIT_FSIZE  = 1,
+            RLIMIT_NOFILE = 5,
+            RLIMIT_STACK  = 3,
+            RLIMIT_AS     = 6,
+        }
+    }
+    else
+    {
+        enum
+        {
+            RLIMIT_CORE   = 4,
+            RLIMIT_CPU    = 0,
+            RLIMIT_DATA   = 2,
+            RLIMIT_FSIZE  = 1,
+            RLIMIT_NOFILE = 7,
+            RLIMIT_STACK  = 3,
+            RLIMIT_AS     = 9,
+        }
     }
 }
 else version (Darwin)
diff --git a/libphobos/libdruntime/core/sys/windows/sql.d b/libphobos/libdruntime/core/sys/windows/sql.d
index 58c6d42bd04..9054ce589e8 100644
--- a/libphobos/libdruntime/core/sys/windows/sql.d
+++ b/libphobos/libdruntime/core/sys/windows/sql.d
@@ -1,4 +1,7 @@
 /**
+$(RED Warning:
+      This binding is out-of-date and does not allow use on non-Windows platforms. Use `etc.c.odbc.sql` instead.)
+
  * Windows API header module
  *
  * Translated from MinGW Windows headers
@@ -6,6 +9,7 @@
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
  * Source: $(DRUNTIMESRC core/sys/windows/_sql.d)
  */
+
 module core.sys.windows.sql;
 version (Windows):
 
diff --git a/libphobos/libdruntime/core/sys/windows/sqlext.d b/libphobos/libdruntime/core/sys/windows/sqlext.d
index 8702cda3359..b871fbbbb84 100644
--- a/libphobos/libdruntime/core/sys/windows/sqlext.d
+++ b/libphobos/libdruntime/core/sys/windows/sqlext.d
@@ -1,4 +1,7 @@
 /**
+$(RED Warning:
+      This binding is out-of-date and does not allow use on non-Windows platforms. Use `etc.c.odbc.sqlext` instead.)
+
  * Windows API header module
  *
  * Translated from MinGW Windows headers
@@ -6,6 +9,7 @@
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
  * Source: $(DRUNTIMESRC core/sys/windows/_sqlext.d)
  */
+
 module core.sys.windows.sqlext;
 version (Windows):
 
diff --git a/libphobos/libdruntime/core/sys/windows/sqltypes.d b/libphobos/libdruntime/core/sys/windows/sqltypes.d
index e86834faa6d..04fac6bac6a 100644
--- a/libphobos/libdruntime/core/sys/windows/sqltypes.d
+++ b/libphobos/libdruntime/core/sys/windows/sqltypes.d
@@ -1,4 +1,7 @@
 /**
+$(RED Warning:
+      This binding is out-of-date and does not allow use on non-Windows platforms. Use `etc.c.odbc.sqltypes` instead.)
+
  * Windows API header module
  *
  * Translated from MinGW Windows headers
@@ -6,6 +9,7 @@
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
  * Source: $(DRUNTIMESRC core/sys/windows/_sqltypes.d)
  */
+
 module core.sys.windows.sqltypes;
 version (Windows):
 
diff --git a/libphobos/libdruntime/core/sys/windows/sqlucode.d b/libphobos/libdruntime/core/sys/windows/sqlucode.d
index d4f03f62d94..e7ae1d276be 100644
--- a/libphobos/libdruntime/core/sys/windows/sqlucode.d
+++ b/libphobos/libdruntime/core/sys/windows/sqlucode.d
@@ -1,4 +1,7 @@
 /**
+$(RED Warning:
+      This binding is out-of-date and does not allow use on non-Windows platforms. Use `etc.c.odbc.sqlucode` instead.)
+
  * Windows API header module
  *
  * Translated from MinGW Windows headers
@@ -6,6 +9,7 @@
  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
  * Source: $(DRUNTIMESRC core/sys/windows/_sqlucode.d)
  */
+
 module core.sys.windows.sqlucode;
 version (Windows):
 
diff --git a/libphobos/libdruntime/core/sys/windows/winnt.d b/libphobos/libdruntime/core/sys/windows/winnt.d
index 3bd9966e33e..ca4a903fb6a 100644
--- a/libphobos/libdruntime/core/sys/windows/winnt.d
+++ b/libphobos/libdruntime/core/sys/windows/winnt.d
@@ -1199,7 +1199,7 @@ enum size_t
 
 PIMAGE_SECTION_HEADER IMAGE_FIRST_SECTION(PIMAGE_NT_HEADERS h) {
     return cast(PIMAGE_SECTION_HEADER)
-        (&h.OptionalHeader + h.FileHeader.SizeOfOptionalHeader);
+        (cast(ubyte*) &h.OptionalHeader + h.FileHeader.SizeOfOptionalHeader);
 }
 
 // ImageDirectoryEntryToDataEx()
diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d
index f3af2097b39..294d34dbe35 100644
--- a/libphobos/libdruntime/object.d
+++ b/libphobos/libdruntime/object.d
@@ -2903,6 +2903,14 @@ void* aaLiteral(Key, Value)(Key[] keys, Value[] values) @trusted pure
     return _d_assocarrayliteralTX(typeid(Value[Key]), *cast(void[]*)&keys, *cast(void[]*)&values);
 }
 
+// Lower an Associative Array to a newaa struct for static initialization.
+auto _aaAsStruct(K, V)(V[K] aa) @safe
+{
+    import core.internal.newaa : makeAA;
+    assert(__ctfe);
+    return makeAA!(K, V)(aa);
+}
+
 alias AssociativeArray(Key, Value) = Value[Key];
 
 /***********************************
diff --git a/libphobos/libdruntime/rt/aaA.d b/libphobos/libdruntime/rt/aaA.d
index f264b014789..4014862b4e4 100644
--- a/libphobos/libdruntime/rt/aaA.d
+++ b/libphobos/libdruntime/rt/aaA.d
@@ -974,3 +974,22 @@ unittest
     GC.runFinalizers((cast(char*)(&entryDtor))[0 .. 1]);
     assert(T.dtor == 6 && T.postblit == 2);
 }
+
+// Ensure the newaa struct layout (used for static initialization) is in sync
+unittest
+{
+    import newaa = core.internal.newaa;
+    static assert(newaa.Impl.sizeof == Impl.sizeof);
+    // ensure compatible types and offsets
+    static foreach (i; 0 .. Impl.tupleof.length)
+    {
+        // for bucket array and Flags, we "compatible" types, not exactly the same types.
+        static if (__traits(identifier, Impl.tupleof[i]) == "buckets"
+            || __traits(identifier, Impl.tupleof[i]) == "flags")
+            static assert(Impl.tupleof[i].sizeof == newaa.Impl.tupleof[i].sizeof);
+        else
+            static assert(is(typeof(Impl.tupleof[i]) == typeof(newaa.Impl.tupleof[i])));
+
+        static assert(Impl.tupleof[i].offsetof == newaa.Impl.tupleof[i].offsetof);
+    }
+}
diff --git a/libphobos/libdruntime/rt/minfo.d b/libphobos/libdruntime/rt/minfo.d
index b5c868f70bc..9bc10558981 100644
--- a/libphobos/libdruntime/rt/minfo.d
+++ b/libphobos/libdruntime/rt/minfo.d
@@ -267,10 +267,16 @@ struct ModuleGroup
                             edge[nEdges++] = *impidx;
                     }
                 }
-                // trim space to what is needed.
-                edges[i] = nEdges > 0
-                    ? (cast(int*)realloc(edge, int.sizeof * nEdges))[0 .. nEdges]
-                    : null;
+                if (nEdges > 0)
+                {
+                    // trim space to what is needed
+                    edges[i] = (cast(int*)realloc(edge, int.sizeof * nEdges))[0 .. nEdges];
+                }
+                else
+                {
+                    edges[i] = null;
+                    .free(edge);
+                }
             }
         }
 
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE
index 0424d7b0cfa..455825b8781 100644
--- a/libphobos/src/MERGE
+++ b/libphobos/src/MERGE
@@ -1,4 +1,4 @@
-d7e79f024606f18e989ae8b5fe298f9d07c7dced
+a3f22129dd2a134338ca02b79ff0de242d7f016e
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/phobos repository.
diff --git a/libphobos/src/std/int128.d b/libphobos/src/std/int128.d
index b20fa1fdddc..92895445aed 100644
--- a/libphobos/src/std/int128.d
+++ b/libphobos/src/std/int128.d
@@ -147,7 +147,7 @@ public struct Int128
 
     /** Support casting to a bool
      * Params: T = bool
-     * Returns: boolean result
+     * Returns: true if value is not zero
      */
     bool opCast(T : bool)() const
     {
@@ -155,6 +155,50 @@ public struct Int128
     }
   } // @safe pure nothrow @nogc
 
+    /** Support casting to an integral type
+     * Params: T = integral type
+     * Returns: low bits of value reinterpreted as T
+     */
+    T opCast(T : long)() const
+    if (is(byte : T))
+    {
+        return cast(T) this.data.lo;
+    }
+
+    ///
+    @safe unittest
+    {
+        const Int128 a = Int128(0xffff_ffff_ffff_ffffL, 0x0123_4567_89ab_cdefL);
+        assert(cast(long) a == 0x0123_4567_89ab_cdefL);
+        assert(cast(int)  a ==           0x89ab_cdef);
+        assert(cast(byte) a == cast(byte) 0xef);
+    }
+
+    /** Support casting to floating point type
+     * Params: T = floating point type
+     * Returns: value cast to floating point with environment-dependent
+     * rounding if the value is not exactly representable
+     */
+    T opCast(T : real)() const
+    {
+        import core.math : ldexp;
+        if (cast(long) this.data.hi >= 0)
+            return ldexp(cast(T) this.data.hi, 64) + this.data.lo;
+        else
+        {
+            const absData = neg(this.data);
+            return -ldexp(cast(T) absData.hi, 64) - absData.lo;
+        }
+    }
+
+    ///
+    @safe unittest
+    {
+        const Int128 a = Int128(-1L << 60);
+        assert(cast(double) a == -(2.0 ^^ 60));
+        assert(cast(double) (a * a) == 2.0 ^^ 120);
+    }
+
     /** Support binary arithmetic operators + - * / % & | ^ << >> >>>
      * Params:
      *   op = one of the arithmetic binary operators
diff --git a/libphobos/src/std/string.d b/libphobos/src/std/string.d
index b1063ee0040..ca14c23747e 100644
--- a/libphobos/src/std/string.d
+++ b/libphobos/src/std/string.d
@@ -3815,6 +3815,7 @@ unittest
     assert(chomp(" hello world  \n\n" ~ [lineSep]) == " hello world  \n\n");
     assert(chomp(" hello world  \n\n" ~ [paraSep]) == " hello world  \n\n");
     assert(chomp(" hello world  \n\n" ~ [ nelSep]) == " hello world  \n\n");
+    assert(chomp(" hello world ") == " hello world ");
     assert(chomp(" hello world") == " hello world");
     assert(chomp("") == "");
 
diff --git a/libphobos/testsuite/libphobos.hash/test_hash.d b/libphobos/testsuite/libphobos.hash/test_hash.d
index a6d7e5a5788..0ad2443c826 100644
--- a/libphobos/testsuite/libphobos.hash/test_hash.d
+++ b/libphobos/testsuite/libphobos.hash/test_hash.d
@@ -290,14 +290,14 @@ void issue22076()
     extern(C++) static class C0
     {
         int foo() { return 0; } // Need at least one function in vtable.
-        S0 a; alias a this; // { dg-warning "is deprecated" }
+        S0 a; alias a this;
     }
 
     extern(C++) static class C1
     {
         S1 a;
         inout(S1)* b() inout nothrow { return &a; }
-        alias b this;       // { dg-warning "is deprecated" }
+        alias b this;
     }
 
     cast(void) hashOf(S0.init);
diff --git a/libphobos/testsuite/libphobos.phobos/phobos.exp b/libphobos/testsuite/libphobos.phobos/phobos.exp
index 374ef491d3c..fdd80ab0f80 100644
--- a/libphobos/testsuite/libphobos.phobos/phobos.exp
+++ b/libphobos/testsuite/libphobos.phobos/phobos.exp
@@ -46,7 +46,7 @@ dg-init
 foreach test $tests {
     set libphobos_test_name "$subdir/[dg-trim-dirname $srcdir/../src $test]"
     dg-runtest $test "-static-libphobos" \
-	"-fmain -fbuilding-libphobos-tests $version_flags"
+	"-Wno-deprecated -fmain -fbuilding-libphobos-tests $version_flags"
     set libphobos_test_name ""
 }
 
diff --git a/libphobos/testsuite/libphobos.phobos_shared/phobos_shared.exp b/libphobos/testsuite/libphobos.phobos_shared/phobos_shared.exp
index 6c67b0828a0..0ea42cbf253 100644
--- a/libphobos/testsuite/libphobos.phobos_shared/phobos_shared.exp
+++ b/libphobos/testsuite/libphobos.phobos_shared/phobos_shared.exp
@@ -46,7 +46,7 @@ dg-init
 foreach test $tests {
     set libphobos_test_name "$subdir/[dg-trim-dirname $srcdir/../src $test]"
     dg-runtest $test "-shared-libphobos" \
-	"-fmain -fbuilding-libphobos-tests -fno-moduleinfo $version_flags"
+	"-Wno-deprecated -fmain -fbuilding-libphobos-tests -fno-moduleinfo $version_flags"
     set libphobos_test_name ""
 }

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-10-15 11:12 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-10-15 11:12 [gcc r14-4644] d: Merge upstream dmd, druntime f9efc98fd7, phobos a3f22129d Iain Buclaw

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