public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-4663] d: Merge upstream dmd, druntime 4c18eed967, phobos d945686a4.
@ 2023-10-16 17:49 Iain Buclaw
  0 siblings, 0 replies; only message in thread
From: Iain Buclaw @ 2023-10-16 17:49 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:964fd402c9b48eb4da91fb3e4e45d4560d6c676c

commit r14-4663-g964fd402c9b48eb4da91fb3e4e45d4560d6c676c
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sun Oct 15 19:09:05 2023 +0200

    d: Merge upstream dmd, druntime 4c18eed967, phobos d945686a4.
    
    D front-end changes:
    
            - Import latest fixes to mainline.
    
    D runtime changes:
    
            - Import latest fixes to mainline.
    
    Phobos changes:
    
            - Import latest fixes to mainline.
    
    gcc/d/ChangeLog:
    
            * dmd/MERGE: Merge upstream dmd 4c18eed967.
            * d-diagnostic.cc (verrorReport): Update for new front-end interface.
            (verrorReportSupplemental): Likewise.
            * d-lang.cc (d_init_options): Likewise.
            (d_handle_option): Likewise.
            (d_post_options): Likewise.
            (d_parse_file): Likewise.
            * decl.cc (get_symbol_decl): Likewise.
    
    libphobos/ChangeLog:
    
            * libdruntime/MERGE: Merge upstream druntime 4c18eed967.
            * src/MERGE: Merge upstream phobos d945686a4.

Diff:
---
 gcc/d/d-diagnostic.cc                              |   4 +-
 gcc/d/d-lang.cc                                    |  86 +--
 gcc/d/decl.cc                                      |   4 +-
 gcc/d/dmd/MERGE                                    |   2 +-
 gcc/d/dmd/access.d                                 |   3 +-
 gcc/d/dmd/aggregate.d                              |  11 +-
 gcc/d/dmd/aggregate.h                              |   1 +
 gcc/d/dmd/arrayop.d                                |  11 +-
 gcc/d/dmd/attrib.d                                 |   7 +-
 gcc/d/dmd/blockexit.d                              |  19 +-
 gcc/d/dmd/canthrow.d                               |  43 +-
 gcc/d/dmd/clone.d                                  |   2 +-
 gcc/d/dmd/compiler.d                               |   1 -
 gcc/d/dmd/cond.d                                   |   4 +
 gcc/d/dmd/constfold.d                              |  18 +-
 gcc/d/dmd/cparse.d                                 |   5 +-
 gcc/d/dmd/cppmangle.d                              |  10 +-
 gcc/d/dmd/ctfe.h                                   |   1 -
 gcc/d/dmd/ctfeexpr.d                               |   8 +-
 gcc/d/dmd/dcast.d                                  |  53 +-
 gcc/d/dmd/dclass.d                                 |  58 +-
 gcc/d/dmd/declaration.d                            |  16 +-
 gcc/d/dmd/denum.d                                  |   5 +-
 gcc/d/dmd/dimport.d                                |   2 +-
 gcc/d/dmd/dinterpret.d                             | 296 ++++----
 gcc/d/dmd/dmangle.d                                |  20 +-
 gcc/d/dmd/dmodule.d                                |  44 +-
 gcc/d/dmd/doc.d                                    |   2 +-
 gcc/d/dmd/dstruct.d                                |   2 +-
 gcc/d/dmd/dsymbol.d                                |  87 +--
 gcc/d/dmd/dsymbol.h                                |   4 -
 gcc/d/dmd/dsymbolsem.d                             | 306 ++++-----
 gcc/d/dmd/dtemplate.d                              |  69 +-
 gcc/d/dmd/dtoh.d                                   |  20 +
 gcc/d/dmd/dversion.d                               |  13 +-
 gcc/d/dmd/expression.d                             | 336 +++------
 gcc/d/dmd/expression.h                             |   6 +-
 gcc/d/dmd/expressionsem.d                          | 439 ++++++------
 gcc/d/dmd/func.d                                   |  36 +-
 gcc/d/dmd/globals.d                                |  57 +-
 gcc/d/dmd/globals.h                                |  48 +-
 gcc/d/dmd/hdrgen.d                                 | 760 +++++++++++----------
 gcc/d/dmd/iasm.d                                   |   1 +
 gcc/d/dmd/id.d                                     |   2 +
 gcc/d/dmd/importc.d                                |   5 +-
 gcc/d/dmd/init.d                                   |   8 -
 gcc/d/dmd/init.h                                   |   2 -
 gcc/d/dmd/initsem.d                                |  31 +-
 gcc/d/dmd/json.d                                   |   4 +-
 gcc/d/dmd/lexer.d                                  |  75 +-
 gcc/d/dmd/mtype.d                                  |   6 +-
 gcc/d/dmd/mustuse.d                                |   3 +-
 gcc/d/dmd/nogc.d                                   |   4 +-
 gcc/d/dmd/nspace.d                                 |   3 +-
 gcc/d/dmd/ob.d                                     |  20 +-
 gcc/d/dmd/objc.d                                   |  32 +-
 gcc/d/dmd/opover.d                                 |  32 +-
 gcc/d/dmd/optimize.d                               |  53 +-
 gcc/d/dmd/parse.d                                  |  15 +-
 gcc/d/dmd/root/filename.d                          |   7 +-
 gcc/d/dmd/root/rootobject.d                        |   6 +-
 gcc/d/dmd/semantic2.d                              |  34 +-
 gcc/d/dmd/semantic3.d                              |  48 +-
 gcc/d/dmd/sideeffect.d                             |   9 +-
 gcc/d/dmd/statement.d                              | 167 +----
 gcc/d/dmd/statement.h                              |   8 +-
 gcc/d/dmd/statementsem.d                           | 192 +++++-
 gcc/d/dmd/staticcond.d                             |   3 +-
 gcc/d/dmd/traits.d                                 | 104 +--
 gcc/d/dmd/typesem.d                                |  42 +-
 gcc/d/dmd/typinf.d                                 |   4 +
 .../gdc.test/compilable/dtoh_TemplateDeclaration.d |   2 -
 gcc/testsuite/gdc.test/compilable/issue24174.d     |  36 +
 .../testpull1810.d                                 |   2 +-
 .../{fail_compilation => compilable}/warn12809.d   |  28 +-
 gcc/testsuite/gdc.test/fail_compilation/ccast.d    |  10 +-
 gcc/testsuite/gdc.test/fail_compilation/fail235.d  |   4 +-
 .../gdc.test/fail_compilation/hexstring.d          |  18 +
 gcc/testsuite/gdc.test/fail_compilation/ice6538.d  |   2 +-
 .../gdc.test/fail_compilation/issue11070.d         |  17 +
 .../gdc.test/fail_compilation/issue3396.d          |  24 +
 .../gdc.test/fail_compilation/reserved_version.d   |  98 +--
 .../fail_compilation/reserved_version_switch.d     |  12 +
 .../gdc.test/fail_compilation/test20522.d          |  23 +
 gcc/testsuite/gdc.test/runnable/issue11070.d       |  19 +
 gcc/testsuite/gdc.test/runnable/staticaa.d         |  27 +
 gcc/testsuite/gdc.test/runnable/template9.d        |   7 +
 libphobos/libdruntime/MERGE                        |   2 +-
 libphobos/libdruntime/core/stdc/errno.d            | 103 +++
 libphobos/libdruntime/core/stdc/fenv.d             |  31 +
 libphobos/libdruntime/core/stdc/math.d             |   7 +
 libphobos/libdruntime/core/sys/linux/dlfcn.d       |  14 +
 libphobos/libdruntime/core/sys/linux/epoll.d       |   8 +
 libphobos/libdruntime/core/sys/linux/link.d        |   6 +
 libphobos/libdruntime/core/sys/linux/perf_event.d  |   4 +
 libphobos/libdruntime/core/sys/linux/sys/eventfd.d |   6 +
 libphobos/libdruntime/core/sys/linux/sys/inotify.d |   5 +
 libphobos/libdruntime/core/sys/linux/sys/mman.d    |  24 +
 libphobos/libdruntime/core/sys/posix/dlfcn.d       |  12 +
 libphobos/libdruntime/core/sys/posix/fcntl.d       |  35 +-
 libphobos/libdruntime/core/sys/posix/setjmp.d      |  15 +
 libphobos/libdruntime/core/sys/posix/signal.d      |  34 +
 libphobos/libdruntime/core/sys/posix/sys/mman.d    |   2 +
 libphobos/libdruntime/core/sys/posix/sys/msg.d     |   1 +
 libphobos/libdruntime/core/sys/posix/sys/socket.d  |  34 +
 libphobos/libdruntime/core/sys/posix/sys/stat.d    |  60 ++
 libphobos/libdruntime/core/sys/posix/sys/types.d   |  12 +
 libphobos/libdruntime/core/sys/posix/ucontext.d    |  27 +
 libphobos/libdruntime/core/thread/fiber.d          |  26 +
 libphobos/src/MERGE                                |   2 +-
 libphobos/src/std/algorithm/iteration.d            |   6 +-
 libphobos/src/std/range/primitives.d               |  24 +-
 112 files changed, 2727 insertions(+), 1941 deletions(-)

diff --git a/gcc/d/d-diagnostic.cc b/gcc/d/d-diagnostic.cc
index b698d4e49b85..b3ad60cb099b 100644
--- a/gcc/d/d-diagnostic.cc
+++ b/gcc/d/d-diagnostic.cc
@@ -233,7 +233,7 @@ verrorReport (const Loc& loc, const char *format, va_list ap, ErrorKind kind,
       if (global.gag)
 	global.gaggedErrors++;
 
-      if (global.gag && !global.params.showGaggedErrors)
+      if (global.gag && !global.params.v.showGaggedErrors)
 	return;
 
       diag_kind = global.gag ? DK_ANACHRONISM : DK_ERROR;
@@ -308,7 +308,7 @@ verrorReportSupplemental (const Loc& loc, const char* format, va_list ap,
 {
   if (kind == ErrorKind::error)
     {
-      if (global.gag && !global.params.showGaggedErrors)
+      if (global.gag && !global.params.v.showGaggedErrors)
 	return;
     }
   else if (kind == ErrorKind::warning)
diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc
index 6509d766708d..902fd86b5abc 100644
--- a/gcc/d/d-lang.cc
+++ b/gcc/d/d-lang.cc
@@ -295,7 +295,6 @@ d_init_options (unsigned int, cl_decoded_option *decoded_options)
 
   global.compileEnv.vendor = lang_hooks.name;
   global.params.argv0 = xstrdup (decoded_options[0].arg);
-  global.params.errorLimit = flag_max_errors;
 
   /* Default extern(C++) mangling to C++17.  */
   global.params.cplusplus = CppStdRevisionCpp17;
@@ -303,7 +302,8 @@ d_init_options (unsigned int, cl_decoded_option *decoded_options)
   /* Warnings and deprecations are disabled by default.  */
   global.params.useDeprecated = DIAGNOSTICinform;
   global.params.warnings = DIAGNOSTICoff;
-  global.params.messageStyle = MessageStyle::gnu;
+  global.params.v.errorLimit = flag_max_errors;
+  global.params.v.messageStyle = MessageStyle::gnu;
 
   global.params.imppath = d_gc_malloc<Strings> ();
   global.params.fileImppath = d_gc_malloc<Strings> ();
@@ -458,9 +458,7 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
     case OPT_fdebug_:
       if (Identifier::isValidIdentifier (CONST_CAST (char *, arg)))
 	{
-	  if (!global.params.debugids)
-	    global.params.debugids = d_gc_malloc<Strings> ();
-	  global.params.debugids->push (arg);
+	  DebugCondition::addGlobalIdent (arg);
 	  break;
 	}
 
@@ -662,30 +660,30 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
       break;
 
     case OPT_ftransition_all:
-      global.params.vfield = value;
-      global.params.vgc = value;
-      global.params.vin = value;
-      global.params.vtls = value;
+      global.params.v.field = value;
+      global.params.v.gc = value;
+      global.params.v.vin = value;
+      global.params.v.tls = value;
       break;
 
     case OPT_ftransition_field:
-      global.params.vfield = value;
+      global.params.v.field = value;
       break;
 
     case OPT_ftransition_in:
-      global.params.vin = value;
+      global.params.v.vin = value;
       break;
 
     case OPT_ftransition_nogc:
-      global.params.vgc = value;
+      global.params.v.gc = value;
       break;
 
     case OPT_ftransition_templates:
-      global.params.vtemplates = value;
+      global.params.v.templates = value;
       break;
 
     case OPT_ftransition_tls:
-      global.params.vtls = value;
+      global.params.v.tls = value;
       break;
 
     case OPT_funittest:
@@ -695,9 +693,7 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
     case OPT_fversion_:
       if (Identifier::isValidIdentifier (CONST_CAST (char *, arg)))
 	{
-	  if (!global.params.versionids)
-	    global.params.versionids = d_gc_malloc<Strings> ();
-	  global.params.versionids->push (arg);
+	  VersionCondition::addGlobalIdent (arg);
 	  break;
 	}
 
@@ -773,7 +769,7 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
       break;
 
     case OPT_v:
-      global.params.verbose = value;
+      global.params.v.verbose = value;
       break;
 
     case OPT_Wall:
@@ -792,7 +788,7 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
 
     case OPT_Wspeculative:
       if (value)
-	global.params.showGaggedErrors = 1;
+	global.params.v.showGaggedErrors = 1;
       break;
 
     case OPT_Xf:
@@ -916,19 +912,20 @@ d_post_options (const char ** fn)
       && global.params.warnings == DIAGNOSTICerror)
     global.params.useDeprecated = DIAGNOSTICerror;
 
-  /* Make -fmax-errors visible to frontend's diagnostic machinery.  */
-  if (OPTION_SET_P (flag_max_errors))
-    global.params.errorLimit = flag_max_errors;
-
   if (flag_excess_precision == EXCESS_PRECISION_DEFAULT)
     flag_excess_precision = EXCESS_PRECISION_STANDARD;
 
   global.params.useInline = flag_inline_functions;
-  global.params.showColumns = flag_show_column;
-  global.params.printErrorContext = flag_diagnostics_show_caret;
+
+  /* Make -fmax-errors visible to frontend's diagnostic machinery.  */
+  if (OPTION_SET_P (flag_max_errors))
+    global.params.v.errorLimit = flag_max_errors;
+
+  global.params.v.showColumns = flag_show_column;
+  global.params.v.printErrorContext = flag_diagnostics_show_caret;
 
   /* Keep the front-end location type in sync with params.  */
-  Loc::set (global.params.showColumns, global.params.messageStyle);
+  Loc::set (global.params.v.showColumns, global.params.v.messageStyle);
 
   if (global.params.useInline)
     global.params.dihdr.fullOutput = true;
@@ -941,25 +938,6 @@ d_post_options (const char ** fn)
   global.compileEnv.ddocOutput = global.params.ddoc.doOutput;
   global.compileEnv.shortenedMethods = global.params.shortenedMethods;
 
-  /* Add in versions given on the command line.  */
-  if (global.params.versionids)
-    {
-      for (size_t i = 0; i < global.params.versionids->length; i++)
-	{
-	  const char *s = (*global.params.versionids)[i];
-	  VersionCondition::addGlobalIdent (s);
-	}
-    }
-
-  if (global.params.debugids)
-    {
-      for (size_t i = 0; i < global.params.debugids->length; i++)
-	{
-	  const char *s = (*global.params.debugids)[i];
-	  DebugCondition::addGlobalIdent (s);
-	}
-    }
-
   if (warn_return_type == -1)
     warn_return_type = 0;
 
@@ -1065,7 +1043,7 @@ d_generate_ddoc_file (Module *m, OutBuffer &ddocbuf)
 static void
 d_parse_file (void)
 {
-  if (global.params.verbose)
+  if (global.params.v.verbose)
     {
       message ("binary    %s", global.params.argv0.ptr);
       message ("version   %s", global.versionChars ());
@@ -1175,7 +1153,7 @@ d_parse_file (void)
     {
       Module *m = modules[i];
 
-      if (global.params.verbose)
+      if (global.params.v.verbose)
 	message ("parse     %s", m->toChars ());
 
       if (!Module::rootModule)
@@ -1227,7 +1205,7 @@ d_parse_file (void)
 	      || (d_option.fonly && m != Module::rootModule))
 	    continue;
 
-	  if (global.params.verbose)
+	  if (global.params.v.verbose)
 	    message ("import    %s", m->toChars ());
 
 	  OutBuffer buf;
@@ -1246,7 +1224,7 @@ d_parse_file (void)
     {
       Module *m = modules[i];
 
-      if (global.params.verbose)
+      if (global.params.v.verbose)
 	message ("importall %s", m->toChars ());
 
       m->importAll (NULL);
@@ -1270,7 +1248,7 @@ d_parse_file (void)
 	  continue;
 	}
 
-      if (global.params.verbose)
+      if (global.params.v.verbose)
 	message ("semantic  %s", m->toChars ());
 
       dsymbolSemantic (m, NULL);
@@ -1301,7 +1279,7 @@ d_parse_file (void)
     {
       Module *m = modules[i];
 
-      if (global.params.verbose)
+      if (global.params.v.verbose)
 	message ("semantic2 %s", m->toChars ());
 
       semantic2 (m, NULL);
@@ -1317,7 +1295,7 @@ d_parse_file (void)
     {
       Module *m = modules[i];
 
-      if (global.params.verbose)
+      if (global.params.v.verbose)
 	message ("semantic3 %s", m->toChars ());
 
       semantic3 (m, NULL);
@@ -1365,7 +1343,7 @@ d_parse_file (void)
 		    (char *) obstack_finish (&buffer));
     }
 
-  if (global.params.vtemplates)
+  if (global.params.v.templates)
     printTemplateStats ();
 
   /* Generate JSON files.  */
@@ -1417,7 +1395,7 @@ d_parse_file (void)
 	  || (d_option.fonly && m != Module::rootModule))
 	continue;
 
-      if (global.params.verbose)
+      if (global.params.v.verbose)
 	message ("code      %s", m->toChars ());
 
       if (!flag_syntax_only)
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index 7e612e1cbbce..c80bb8aebd7b 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -968,7 +968,7 @@ public:
 	return;
       }
 
-    if (global.params.verbose)
+    if (global.params.v.verbose)
       message ("function  %s", d->toPrettyChars ());
 
     tree old_context = start_function (d);
@@ -1554,7 +1554,7 @@ get_symbol_decl (Declaration *decl)
   /* Symbol is going in thread local storage.  */
   if (decl->isThreadlocal () && !DECL_ARTIFICIAL (decl->csym))
     {
-      if (global.params.vtls)
+      if (global.params.v.tls)
 	message (decl->loc, "`%s` is thread local", decl->toChars ());
 
       set_decl_tls_model (decl->csym, decl_default_tls_model (decl->csym));
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index d5dfe0d0eddf..794600274a3b 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-f9efc98fd7954741333f72c6a50af273f3863a1a
+4c18eed9674e04c1ca89fbc8bd5c4e483eb5477c
 
 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/access.d b/gcc/d/dmd/access.d
index ab9b5d9da485..1010c140b68e 100644
--- a/gcc/d/dmd/access.d
+++ b/gcc/d/dmd/access.d
@@ -20,6 +20,7 @@ import dmd.dmodule;
 import dmd.dscope;
 import dmd.dstruct;
 import dmd.dsymbol;
+import dmd.errors;
 import dmd.expression;
 import dmd.location;
 import dmd.tokens;
@@ -47,7 +48,7 @@ bool checkAccess(AggregateDeclaration ad, Loc loc, Scope* sc, Dsymbol smember)
 
     if (!symbolIsVisible(sc, smember))
     {
-        ad.error(loc, "%s `%s` is not accessible", smember.kind(), smember.toChars());
+        error(loc, "%s `%s` %s `%s` is not accessible", ad.kind(), ad.toPrettyChars(), smember.kind(), smember.toChars());
         //printf("smember = %s %s, vis = %d, semanticRun = %d\n",
         //        smember.kind(), smember.toPrettyChars(), smember.visible() smember.semanticRun);
         return true;
diff --git a/gcc/d/dmd/aggregate.d b/gcc/d/dmd/aggregate.d
index 4ae6b6bc5cc2..68b5f1b48f19 100644
--- a/gcc/d/dmd/aggregate.d
+++ b/gcc/d/dmd/aggregate.d
@@ -31,6 +31,7 @@ import dmd.errors;
 import dmd.expression;
 import dmd.func;
 import dmd.globals;
+import dmd.hdrgen;
 import dmd.id;
 import dmd.identifier;
 import dmd.location;
@@ -213,7 +214,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
 
         if (!members)
         {
-            error(loc, "unknown size");
+            .error(loc, "%s `%s` unknown size", kind, toPrettyChars);
             return false;
         }
 
@@ -243,7 +244,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
     Lfail:
         // There's unresolvable forward reference.
         if (type != Type.terror)
-            error(loc, "no size because of forward reference");
+            error(loc, "%s `%s` no size because of forward reference", kind, toPrettyChars);
         // Don't cache errors from speculative semantic, might be resolvable later.
         // https://issues.dlang.org/show_bug.cgi?id=16574
         if (!global.gag)
@@ -337,7 +338,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
                 else if (v2._init && i < j)
                 {
                     .error(v2.loc, "union field `%s` with default initialization `%s` must be before field `%s`",
-                        v2.toChars(), v2._init.toChars(), vd.toChars());
+                        v2.toChars(), dmd.hdrgen.toChars(v2._init), vd.toChars());
                     errors = true;
                 }
             }
@@ -452,7 +453,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
                     assert(!vx._init.isVoidInitializer());
                     if (vx.inuse)   // https://issues.dlang.org/show_bug.cgi?id=18057
                     {
-                        vx.error(loc, "recursive initialization of field");
+                        .error(loc, "%s `%s` recursive initialization of field", vx.kind(), vx.toPrettyChars());
                         errors = true;
                     }
                     else
@@ -753,7 +754,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
                   s.isTemplateDeclaration() ||
                   s.isOverloadSet()))
             {
-                s.error("is not a constructor; identifiers starting with `__` are reserved for the implementation");
+                .error(s.loc, "%s `%s` is not a constructor; identifiers starting with `__` are reserved for the implementation", s.kind(), s.toPrettyChars());
                 errors = true;
                 s = null;
             }
diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h
index 03fe478685cf..4b107e0f2a9b 100644
--- a/gcc/d/dmd/aggregate.h
+++ b/gcc/d/dmd/aggregate.h
@@ -279,6 +279,7 @@ public:
     ObjcClassDeclaration objc;          // Data for a class declaration that is needed for the Objective-C integration
     Symbol *cpp_type_info_ptr_sym;      // cached instance of class Id.cpp_type_info_ptr
 
+    void classError(const char* fmt, const char* arg);
     static ClassDeclaration *create(const Loc &loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject);
     const char *toPrettyChars(bool QualifyTypes = false) override;
     ClassDeclaration *syntaxCopy(Dsymbol *s) override;
diff --git a/gcc/d/dmd/arrayop.d b/gcc/d/dmd/arrayop.d
index d8430733428d..25bbb3f32ad4 100644
--- a/gcc/d/dmd/arrayop.d
+++ b/gcc/d/dmd/arrayop.d
@@ -19,6 +19,7 @@ import dmd.astenums;
 import dmd.declaration;
 import dmd.dscope;
 import dmd.dsymbol;
+import dmd.errors;
 import dmd.expression;
 import dmd.expressionsem;
 import dmd.func;
@@ -92,7 +93,7 @@ bool checkNonAssignmentArrayOp(Expression e, bool suggestion = false)
         const(char)* s = "";
         if (suggestion)
             s = " (possible missing [])";
-        e.error("array operation `%s` without destination memory not allowed%s", e.toChars(), s);
+        error(e.loc, "array operation `%s` without destination memory not allowed%s", e.toChars(), s);
         return true;
     }
     return false;
@@ -121,7 +122,7 @@ Expression arrayOp(BinExp e, Scope* sc)
     Type tbn = tb.nextOf().toBasetype();
     if (tbn.ty == Tvoid)
     {
-        e.error("cannot perform array operations on `void[]` arrays");
+        error(e.loc, "cannot perform array operations on `void[]` arrays");
         return ErrorExp.get();
     }
     if (!isArrayOpValid(e))
@@ -164,7 +165,7 @@ Expression arrayOp(BinAssignExp e, Scope* sc)
 
     if (tn && (!tn.isMutable() || !tn.isAssignable()))
     {
-        e.error("slice `%s` is not mutable", e.e1.toChars());
+        error(e.loc, "slice `%s` is not mutable", e.e1.toChars());
         if (e.op == EXP.addAssign)
             checkPossibleAddCatError!(AddAssignExp, CatAssignExp)(e.isAddAssignExp);
         return ErrorExp.get();
@@ -370,7 +371,7 @@ bool isArrayOpOperand(Expression e)
 
 ErrorExp arrayOpInvalidError(Expression e)
 {
-    e.error("invalid array operation `%s` (possible missing [])", e.toChars());
+    error(e.loc, "invalid array operation `%s` (possible missing [])", e.toChars());
     if (e.op == EXP.add)
         checkPossibleAddCatError!(AddExp, CatExp)(e.isAddExp());
     else if (e.op == EXP.addAssign)
@@ -383,5 +384,5 @@ private void checkPossibleAddCatError(AddT, CatT)(AddT ae)
     if (!ae.e2.type || ae.e2.type.ty != Tarray || !ae.e2.type.implicitConvTo(ae.e1.type))
         return;
     CatT ce = new CatT(ae.loc, ae.e1, ae.e2);
-    ae.errorSupplemental("did you mean to concatenate (`%s`) instead ?", ce.toChars());
+    errorSupplemental(ae.loc, "did you mean to concatenate (`%s`) instead ?", ce.toChars());
 }
diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d
index 5a91bc742291..7b5def1f765b 100644
--- a/gcc/d/dmd/attrib.d
+++ b/gcc/d/dmd/attrib.d
@@ -33,6 +33,7 @@ import dmd.dmodule;
 import dmd.dscope;
 import dmd.dsymbol;
 import dmd.dsymbolsem : dsymbolSemantic;
+import dmd.errors;
 import dmd.expression;
 import dmd.expressionsem;
 import dmd.func;
@@ -664,7 +665,7 @@ extern (C++) final class VisibilityDeclaration : AttribDeclaration
             {
                 Package pkg = m.parent ? m.parent.isPackage() : null;
                 if (!pkg || !visibility.pkg.isAncestorPackageOf(pkg))
-                    error("does not bind to one of ancestor packages of module `%s`", m.toPrettyChars(true));
+                    .error(loc, "%s `%s` does not bind to one of ancestor packages of module `%s`", kind(), toPrettyChars(false), m.toPrettyChars(true));
             }
         }
         return AttribDeclaration.addMember(sc, sds);
@@ -1473,12 +1474,12 @@ extern (C++) final class UserAttributeDeclaration : AttribDeclaration
             {
                 if (sym.isCPPNamespaceDeclaration() || sym.isNspace())
                 {
-                    exp.error("`@%s` cannot be applied to namespaces", Id.udaGNUAbiTag.toChars());
+                    .error(exp.loc, "`@%s` cannot be applied to namespaces", Id.udaGNUAbiTag.toChars());
                     sym.errors = true;
                 }
                 else if (linkage != LINK.cpp)
                 {
-                    exp.error("`@%s` can only apply to C++ symbols", Id.udaGNUAbiTag.toChars());
+                    .error(exp.loc, "`@%s` can only apply to C++ symbols", Id.udaGNUAbiTag.toChars());
                     sym.errors = true;
                 }
                 // Only one `@gnuAbiTag` is allowed by semantic2
diff --git a/gcc/d/dmd/blockexit.d b/gcc/d/dmd/blockexit.d
index a0da77a2898c..31a32cf258cb 100644
--- a/gcc/d/dmd/blockexit.d
+++ b/gcc/d/dmd/blockexit.d
@@ -98,7 +98,7 @@ int blockExit(Statement s, FuncDeclaration func, ErrorSink eSink)
                 if (s.exp.type && s.exp.type.toBasetype().isTypeNoreturn())
                     result = BE.halt;
 
-                result |= canThrow(s.exp, func, eSink !is null);
+                result |= canThrow(s.exp, func, eSink);
             }
         }
 
@@ -153,6 +153,7 @@ int blockExit(Statement s, FuncDeclaration func, ErrorSink eSink)
 
                     if (!(result & BE.fallthru) && !s.comeFrom())
                     {
+                        version (none) // this warning is completely useless due to insane false positive rate in real life template code
                         if (blockExit(s, func, eSink) != BE.halt && s.hasCode() &&
                             s.loc != Loc.initial) // don't emit warning for generated code
                             global.errorSink.warning(s.loc, "statement is not reachable");
@@ -211,7 +212,7 @@ int blockExit(Statement s, FuncDeclaration func, ErrorSink eSink)
                 result = BE.fallthru;
             if (result & BE.fallthru)
             {
-                result |= canThrow(s.condition, func, eSink !is null);
+                result |= canThrow(s.condition, func, eSink);
 
                 if (!(result & BE.break_) && s.condition.toBool().hasValue(true))
                     result &= ~BE.fallthru;
@@ -230,7 +231,7 @@ int blockExit(Statement s, FuncDeclaration func, ErrorSink eSink)
             }
             if (s.condition)
             {
-                result |= canThrow(s.condition, func, eSink !is null);
+                result |= canThrow(s.condition, func, eSink);
 
                 const opt = s.condition.toBool();
                 if (opt.hasValue(true))
@@ -248,13 +249,13 @@ int blockExit(Statement s, FuncDeclaration func, ErrorSink eSink)
                 result |= r & ~(BE.fallthru | BE.break_ | BE.continue_);
             }
             if (s.increment)
-                result |= canThrow(s.increment, func, eSink !is null);
+                result |= canThrow(s.increment, func, eSink);
         }
 
         void visitForeach(ForeachStatement s)
         {
             result = BE.fallthru;
-            result |= canThrow(s.aggr, func, eSink !is null);
+            result |= canThrow(s.aggr, func, eSink);
 
             if (s._body)
                 result |= blockExit(s._body, func, eSink) & ~(BE.break_ | BE.continue_);
@@ -270,7 +271,7 @@ int blockExit(Statement s, FuncDeclaration func, ErrorSink eSink)
         {
             //printf("IfStatement::blockExit(%p)\n", s);
             result = BE.none;
-            result |= canThrow(s.condition, func, eSink !is null);
+            result |= canThrow(s.condition, func, eSink);
 
             const opt = s.condition.toBool();
             if (opt.hasValue(true))
@@ -309,7 +310,7 @@ int blockExit(Statement s, FuncDeclaration func, ErrorSink eSink)
         void visitSwitch(SwitchStatement s)
         {
             result = BE.none;
-            result |= canThrow(s.condition, func, eSink !is null);
+            result |= canThrow(s.condition, func, eSink);
 
             if (s._body)
             {
@@ -354,7 +355,7 @@ int blockExit(Statement s, FuncDeclaration func, ErrorSink eSink)
         {
             result = BE.return_;
             if (s.exp)
-                result |= canThrow(s.exp, func, eSink !is null);
+                result |= canThrow(s.exp, func, eSink);
         }
 
         void visitBreak(BreakStatement s)
@@ -376,7 +377,7 @@ int blockExit(Statement s, FuncDeclaration func, ErrorSink eSink)
         void visitWith(WithStatement s)
         {
             result = BE.none;
-            result |= canThrow(s.exp, func, eSink !is null);
+            result |= canThrow(s.exp, func, eSink);
             result |= blockExit(s._body, func, eSink);
         }
 
diff --git a/gcc/d/dmd/canthrow.d b/gcc/d/dmd/canthrow.d
index 4cead300f40a..bb1fd6fc974f 100644
--- a/gcc/d/dmd/canthrow.d
+++ b/gcc/d/dmd/canthrow.d
@@ -20,6 +20,7 @@ import dmd.astenums;
 import dmd.blockexit : BE, checkThrow;
 import dmd.declaration;
 import dmd.dsymbol;
+import dmd.errorsink;
 import dmd.expression;
 import dmd.func;
 import dmd.globals;
@@ -47,25 +48,25 @@ enum CT : BE
 }
 
 /********************************************
- * Returns true if the expression may throw exceptions.
- * If 'mustNotThrow' is true, generate an error if it throws
+ * If `eSink` is not null, generate an error if `e` throws
+ * Params:
+ *      e = expression to check for throwing
+ *      func = function
+ *      eSink = if !null, then send error messages to eSink
+ * Returns: `CT.exception` or `CT.error` if the expression may throw exceptions.
  */
-extern (C++) /* CT */ BE canThrow(Expression e, FuncDeclaration func, bool mustNotThrow)
+extern (C++) /* CT */ BE canThrow(Expression e, FuncDeclaration func, ErrorSink eSink)
 {
     //printf("Expression::canThrow(%d) %s\n", mustNotThrow, e.toChars());
     // stop walking if we determine this expression can throw
     extern (C++) final class CanThrow : StoppableVisitor
     {
         alias visit = typeof(super).visit;
-        FuncDeclaration func;
-        bool mustNotThrow;
         CT result;
 
     public:
-        extern (D) this(FuncDeclaration func, bool mustNotThrow) scope @safe
+        extern (D) this() scope @safe
         {
-            this.func = func;
-            this.mustNotThrow = mustNotThrow;
         }
 
         void checkFuncThrows(Expression e, FuncDeclaration f)
@@ -73,9 +74,9 @@ extern (C++) /* CT */ BE canThrow(Expression e, FuncDeclaration func, bool mustN
             auto tf = f.type.toBasetype().isTypeFunction();
             if (tf && !tf.isnothrow)
             {
-                if (mustNotThrow)
+                if (eSink)
                 {
-                    e.error("%s `%s` is not `nothrow`", f.kind(), f.toPrettyChars());
+                    eSink.error(e.loc, "%s `%s` is not `nothrow`", f.kind(), f.toPrettyChars());
                     if (!f.isDtorDeclaration())
                         errorSupplementalInferredAttr(f, 10, false, STC.nothrow_);
 
@@ -95,7 +96,7 @@ extern (C++) /* CT */ BE canThrow(Expression e, FuncDeclaration func, bool mustN
 
         override void visit(DeclarationExp de)
         {
-            result |= Dsymbol_canThrow(de.declaration, func, mustNotThrow);
+            result |= Dsymbol_canThrow(de.declaration, func, eSink);
         }
 
         override void visit(CallExp ce)
@@ -138,12 +139,12 @@ extern (C++) /* CT */ BE canThrow(Expression e, FuncDeclaration func, bool mustN
 
             if (ce.f)
                 checkFuncThrows(ce, ce.f);
-            else if (mustNotThrow)
+            else if (eSink)
             {
                 auto e1 = ce.e1;
                 if (auto pe = e1.isPtrExp())   // print 'fp' if e1 is (*fp)
                     e1 = pe.e1;
-                ce.error("`%s` is not `nothrow`", e1.toChars());
+                eSink.error(ce.loc, "`%s` is not `nothrow`", e1.toChars());
             }
             result |= CT.exception;
         }
@@ -202,7 +203,7 @@ extern (C++) /* CT */ BE canThrow(Expression e, FuncDeclaration func, bool mustN
 
         override void visit(ThrowExp te)
         {
-            const res = checkThrow(te.loc, te.e1, func, mustNotThrow ? global.errorSink : null);
+            const res = checkThrow(te.loc, te.e1, func, eSink);
             assert((res & ~(CT.exception | CT.error)) == 0);
             result |= res;
         }
@@ -213,22 +214,22 @@ extern (C++) /* CT */ BE canThrow(Expression e, FuncDeclaration func, bool mustN
         }
     }
 
-    scope CanThrow ct = new CanThrow(func, mustNotThrow);
+    scope CanThrow ct = new CanThrow();
     walkPostorder(e, ct);
     return ct.result;
 }
 
 /**************************************
- * Does symbol, when initialized, throw?
+ * Does symbol `s`, when initialized, throw?
  * Mirrors logic in Dsymbol_toElem().
  */
-private CT Dsymbol_canThrow(Dsymbol s, FuncDeclaration func, bool mustNotThrow)
+private CT Dsymbol_canThrow(Dsymbol s, FuncDeclaration func, ErrorSink eSink)
 {
     CT result;
 
     int symbolDg(Dsymbol s)
     {
-        result |= Dsymbol_canThrow(s, func, mustNotThrow);
+        result |= Dsymbol_canThrow(s, func, eSink);
         return 0;
     }
 
@@ -237,7 +238,7 @@ private CT Dsymbol_canThrow(Dsymbol s, FuncDeclaration func, bool mustNotThrow)
     {
         s = s.toAlias();
         if (s != vd)
-            return Dsymbol_canThrow(s, func, mustNotThrow);
+            return Dsymbol_canThrow(s, func, eSink);
         if (vd.storage_class & STC.manifest)
         {
         }
@@ -249,10 +250,10 @@ private CT Dsymbol_canThrow(Dsymbol s, FuncDeclaration func, bool mustNotThrow)
             if (vd._init)
             {
                 if (auto ie = vd._init.isExpInitializer())
-                    result |= canThrow(ie.exp, func, mustNotThrow);
+                    result |= canThrow(ie.exp, func, eSink);
             }
             if (vd.needsScopeDtor())
-                result |= canThrow(vd.edtor, func, mustNotThrow);
+                result |= canThrow(vd.edtor, func, eSink);
         }
     }
     else if (auto ad = s.isAttribDeclaration())
diff --git a/gcc/d/dmd/clone.d b/gcc/d/dmd/clone.d
index 181268ec26c4..ca7f398ae7ae 100644
--- a/gcc/d/dmd/clone.d
+++ b/gcc/d/dmd/clone.d
@@ -1201,7 +1201,7 @@ FuncDeclaration buildInv(AggregateDeclaration ad, Scope* sc)
                 version (all)
                 {
                     // currently rejects
-                    ad.error(inv.loc, "mixing invariants with different `shared`/`synchronized` qualifiers is not supported");
+                    .error(inv.loc, "%s `%s` mixing invariants with different `shared`/`synchronized` qualifiers is not supported", ad.kind(), ad.toPrettyChars());
                     e = null;
                     break;
                 }
diff --git a/gcc/d/dmd/compiler.d b/gcc/d/dmd/compiler.d
index 68ec1d3848dd..e85cc202281d 100644
--- a/gcc/d/dmd/compiler.d
+++ b/gcc/d/dmd/compiler.d
@@ -13,7 +13,6 @@ module dmd.compiler;
 
 import dmd.arraytypes;
 import dmd.dmodule;
-import dmd.dscope;
 import dmd.expression;
 import dmd.mtype;
 import dmd.root.array;
diff --git a/gcc/d/dmd/cond.d b/gcc/d/dmd/cond.d
index 76cef77d8eda..70a7c882eb31 100644
--- a/gcc/d/dmd/cond.d
+++ b/gcc/d/dmd/cond.d
@@ -691,6 +691,10 @@ extern (C++) final class VersionCondition : DVCondition
             case "LDC":
             case "linux":
             case "LittleEndian":
+            case "LoongArch32":
+            case "LoongArch64":
+            case "LoongArch_HardFloat":
+            case "LoongArch_SoftFloat":
             case "MinGW":
             case "MIPS32":
             case "MIPS64":
diff --git a/gcc/d/dmd/constfold.d b/gcc/d/dmd/constfold.d
index e5526a1c9aaa..ef408cb5b772 100644
--- a/gcc/d/dmd/constfold.d
+++ b/gcc/d/dmd/constfold.d
@@ -336,7 +336,7 @@ UnionExp Div(const ref Loc loc, Type type, Expression e1, Expression e2)
         n2 = e2.toInteger();
         if (n2 == 0)
         {
-            e2.error("divide by 0");
+            error(e2.loc, "divide by 0");
             emplaceExp!(ErrorExp)(&ue);
             return ue;
         }
@@ -345,13 +345,13 @@ UnionExp Div(const ref Loc loc, Type type, Expression e1, Expression e2)
             // Check for int.min / -1
             if (n1 == 0xFFFFFFFF80000000UL && type.toBasetype().ty != Tint64)
             {
-                e2.error("integer overflow: `int.min / -1`");
+                error(e2.loc, "integer overflow: `int.min / -1`");
                 emplaceExp!(ErrorExp)(&ue);
                 return ue;
             }
             else if (n1 == 0x8000000000000000L) // long.min / -1
             {
-                e2.error("integer overflow: `long.min / -1L`");
+                error(e2.loc, "integer overflow: `long.min / -1L`");
                 emplaceExp!(ErrorExp)(&ue);
                 return ue;
             }
@@ -401,7 +401,7 @@ UnionExp Mod(const ref Loc loc, Type type, Expression e1, Expression e2)
         n2 = e2.toInteger();
         if (n2 == 0)
         {
-            e2.error("divide by 0");
+            error(e2.loc, "divide by 0");
             emplaceExp!(ErrorExp)(&ue);
             return ue;
         }
@@ -410,13 +410,13 @@ UnionExp Mod(const ref Loc loc, Type type, Expression e1, Expression e2)
             // Check for int.min % -1
             if (n1 == 0xFFFFFFFF80000000UL && type.toBasetype().ty != Tint64)
             {
-                e2.error("integer overflow: `int.min %% -1`");
+                error(e2.loc, "integer overflow: `int.min %% -1`");
                 emplaceExp!(ErrorExp)(&ue);
                 return ue;
             }
             else if (n1 == 0x8000000000000000L) // long.min % -1
             {
-                e2.error("integer overflow: `long.min %% -1L`");
+                error(e2.loc, "integer overflow: `long.min %% -1L`");
                 emplaceExp!(ErrorExp)(&ue);
                 return ue;
             }
@@ -1135,7 +1135,7 @@ UnionExp Index(Type type, Expression e1, Expression e2, bool indexIsInBounds)
         uinteger_t i = e2.toInteger();
         if (i >= es1.len)
         {
-            e1.error("string index %llu is out of bounds `[0 .. %llu]`", i, cast(ulong)es1.len);
+            error(e1.loc, "string index %llu is out of bounds `[0 .. %llu]`", i, cast(ulong)es1.len);
             emplaceExp!(ErrorExp)(&ue);
         }
         else
@@ -1151,7 +1151,7 @@ UnionExp Index(Type type, Expression e1, Expression e2, bool indexIsInBounds)
         if (i >= length && (e1.op == EXP.arrayLiteral || !indexIsInBounds))
         {
             // C code only checks bounds if an ArrayLiteralExp
-            e1.error("array index %llu is out of bounds `%s[0 .. %llu]`", i, e1.toChars(), length);
+            error(e1.loc, "array index %llu is out of bounds `%s[0 .. %llu]`", i, e1.toChars(), length);
             emplaceExp!(ErrorExp)(&ue);
         }
         else if (ArrayLiteralExp ale = e1.isArrayLiteralExp())
@@ -1174,7 +1174,7 @@ UnionExp Index(Type type, Expression e1, Expression e2, bool indexIsInBounds)
         {
             if (i >= ale.elements.length)
             {
-                e1.error("array index %llu is out of bounds `%s[0 .. %llu]`", i, e1.toChars(), cast(ulong) ale.elements.length);
+                error(e1.loc, "array index %llu is out of bounds `%s[0 .. %llu]`", i, e1.toChars(), cast(ulong) ale.elements.length);
                 emplaceExp!(ErrorExp)(&ue);
             }
             else
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index b05d81d3b149..d183b8227c88 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -231,6 +231,9 @@ final class CParser(AST) : Parser!AST
                     }
                     goto Lexp;  // function call
 
+                case TOK.semicolon:
+                    goto Lexp;
+
                 default:
                 {
                     /* If tokens look like a declaration, assume it is one
@@ -501,7 +504,7 @@ final class CParser(AST) : Parser!AST
             auto condition = cparseExpression();
             check(TOK.rightParenthesis);
             auto _body = cparseStatement(ParseStatementFlags.scope_);
-            s = new AST.SwitchStatement(loc, condition, _body, false);
+            s = new AST.SwitchStatement(loc, null, condition, _body, false, token.loc);
             break;
         }
 
diff --git a/gcc/d/dmd/cppmangle.d b/gcc/d/dmd/cppmangle.d
index 0c32fad78034..230bfec17ea9 100644
--- a/gcc/d/dmd/cppmangle.d
+++ b/gcc/d/dmd/cppmangle.d
@@ -483,7 +483,7 @@ private final class CppMangleVisitor : Visitor
             }
             else
             {
-                ti.error("internal compiler error: C++ `%s` template value parameter is not supported", tv.valType.toChars());
+                .error(ti.loc, "%s `%s` internal compiler error: C++ `%s` template value parameter is not supported", ti.kind, ti.toPrettyChars, tv.valType.toChars());
                 fatal();
             }
         }
@@ -518,13 +518,13 @@ private final class CppMangleVisitor : Visitor
             }
             else
             {
-                ti.error("internal compiler error: C++ `%s` template alias parameter is not supported", o.toChars());
+                .error(ti.loc, "%s `%s` internal compiler error: C++ `%s` template alias parameter is not supported", ti.kind, ti.toPrettyChars, o.toChars());
                 fatal();
             }
         }
         else if (tp.isTemplateThisParameter())
         {
-            ti.error("internal compiler error: C++ `%s` template this parameter is not supported", o.toChars());
+            .error(ti.loc, "%s `%s` internal compiler error: C++ `%s` template this parameter is not supported", ti.kind, ti.toPrettyChars, o.toChars());
             fatal();
         }
         else
@@ -573,7 +573,7 @@ private final class CppMangleVisitor : Visitor
                     Type t = isType((*ti.tiargs)[j]);
                     if (t is null)
                     {
-                        ti.error("internal compiler error: C++ `%s` template value parameter is not supported", (*ti.tiargs)[j].toChars());
+                        .error(ti.loc, "%s `%s` internal compiler error: C++ `%s` template value parameter is not supported", ti.kind, ti.toPrettyChars, (*ti.tiargs)[j].toChars());
                         fatal();
                     }
                     t.accept(this);
@@ -1011,7 +1011,7 @@ private final class CppMangleVisitor : Visitor
         // fake mangling for fields to fix https://issues.dlang.org/show_bug.cgi?id=16525
         if (!(d.storage_class & (STC.extern_ | STC.field | STC.gshared)))
         {
-            d.error("internal compiler error: C++ static non-`__gshared` non-`extern` variables not supported");
+            .error(d.loc, "%s `%s` internal compiler error: C++ static non-`__gshared` non-`extern` variables not supported", d.kind, d.toPrettyChars);
             fatal();
         }
         Dsymbol p = d.toParent();
diff --git a/gcc/d/dmd/ctfe.h b/gcc/d/dmd/ctfe.h
index 1071edf7c931..bb92778e2534 100644
--- a/gcc/d/dmd/ctfe.h
+++ b/gcc/d/dmd/ctfe.h
@@ -37,7 +37,6 @@ class VoidInitExp final : public Expression
 public:
     VarDeclaration *var;
 
-    const char *toChars() const override;
     void accept(Visitor *v) override { v->visit(this); }
 };
 
diff --git a/gcc/d/dmd/ctfeexpr.d b/gcc/d/dmd/ctfeexpr.d
index c0a2ca6a2a55..ddfb57d22d70 100644
--- a/gcc/d/dmd/ctfeexpr.d
+++ b/gcc/d/dmd/ctfeexpr.d
@@ -147,7 +147,7 @@ extern (C++) final class ThrownExceptionExp : Expression
         UnionExp ue = void;
         Expression e = resolveSlice((*thrown.value.elements)[0], &ue);
         StringExp se = e.toStringExp();
-        thrown.error("uncaught CTFE exception `%s(%s)`", thrown.type.toChars(), se ? se.toChars() : e.toChars());
+        error(thrown.loc, "uncaught CTFE exception `%s(%s)`", thrown.type.toChars(), se ? se.toChars() : e.toChars());
         /* Also give the line where the throw statement was. We won't have it
          * in the case where the ThrowStatement is generated internally
          * (eg, in ScopeStatement)
@@ -435,7 +435,7 @@ UnionExp copyLiteral(Expression e)
         emplaceExp!(UnionExp)(&ue, e);
         return ue;
     }
-    e.error("CTFE internal error: literal `%s`", e.toChars());
+    error(e.loc, "CTFE internal error: literal `%s`", e.toChars());
     assert(0);
 }
 
@@ -506,7 +506,7 @@ private UnionExp paintTypeOntoLiteralCopy(Type type, Expression lit)
         // Can't type paint from struct to struct*; this needs another
         // level of indirection
         if (lit.op == EXP.structLiteral && isPointer(type))
-            lit.error("CTFE internal error: painting `%s`", type.toChars());
+            error(lit.loc, "CTFE internal error: painting `%s`", type.toChars());
         ue = copyLiteral(lit);
     }
     ue.exp().type = type;
@@ -1919,7 +1919,7 @@ bool isCtfeValueValid(Expression newval)
             return true; // uninitialized value
 
         default:
-            newval.error("CTFE internal error: illegal CTFE value `%s`", newval.toChars());
+            error(newval.loc, "CTFE internal error: illegal CTFE value `%s`", newval.toChars());
             return false;
     }
 }
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index d7cb2b1f9708..9f661ea410bb 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -23,6 +23,7 @@ import dmd.declaration;
 import dmd.dscope;
 import dmd.dstruct;
 import dmd.dsymbol;
+import dmd.errors;
 import dmd.escape;
 import dmd.expression;
 import dmd.expressionsem;
@@ -135,7 +136,7 @@ Expression implicitCastTo(Expression e, Scope* sc, Type t)
         {
             if (!t.deco)
             {
-                e.error("forward reference to type `%s`", t.toChars());
+                error(e.loc, "forward reference to type `%s`", t.toChars());
             }
             else
             {
@@ -143,7 +144,7 @@ Expression implicitCastTo(Expression e, Scope* sc, Type t)
                 //type = type.typeSemantic(loc, sc);
                 //printf("type %s t %s\n", type.deco, t.deco);
                 auto ts = toAutoQualChars(e.type, t);
-                e.error("cannot implicitly convert expression `%s` of type `%s` to `%s`",
+                error(e.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`",
                     e.toChars(), ts[0], ts[1]);
             }
         }
@@ -244,7 +245,7 @@ MATCH implicitConvTo(Expression e, Type t)
             return MATCH.nomatch;
         if (!e.type)
         {
-            e.error("`%s` is not an expression", e.toChars());
+            error(e.loc, "`%s` is not an expression", e.toChars());
             e.type = Type.terror;
         }
 
@@ -715,6 +716,14 @@ MATCH implicitConvTo(Expression e, Type t)
                     if (e.postfix != 'd')
                         m = MATCH.convert;
                     return m;
+                case Tint8:
+                case Tuns8:
+                    if (e.hexString)
+                    {
+                        m = MATCH.convert;
+                        return m;
+                    }
+                    break;
                 case Tenum:
                     if (tn.isTypeEnum().sym.isSpecial())
                     {
@@ -1671,7 +1680,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
                 goto Lok;
 
             auto ts = toAutoQualChars(e.type, t);
-            e.error("cannot cast expression `%s` of type `%s` to `%s` because of different sizes",
+            error(e.loc, "cannot cast expression `%s` of type `%s` to `%s` because of different sizes",
                 e.toChars(), ts[0], ts[1]);
             return ErrorExp.get();
         }
@@ -1700,7 +1709,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
                     const dim = t1b.isTypeSArray().dim.toInteger();
                     if (tsize == 0 || (dim * fsize) % tsize != 0)
                     {
-                        e.error("cannot cast expression `%s` of type `%s` to `%s` since sizes don't line up",
+                        error(e.loc, "cannot cast expression `%s` of type `%s` to `%s` since sizes don't line up",
                                 e.toChars(), e.type.toChars(), t.toChars());
                         return ErrorExp.get();
                     }
@@ -1743,7 +1752,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
                 // void delegate() dg;
                 // cast(U*)dg; // ==> cast(U*)dg.ptr;
                 // Note that it happens even when U is a Tfunction!
-                e.deprecation("casting from %s to %s is deprecated", e.type.toChars(), t.toChars());
+                deprecation(e.loc, "casting from %s to %s is deprecated", e.type.toChars(), t.toChars());
                 goto Lok;
             }
             goto Lfail;
@@ -1761,7 +1770,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
                 if (result)
                     return result;
             }
-            e.error("cannot cast expression `%s` of type `%s` to `%s`", e.toChars(), e.type.toChars(), t.toChars());
+            error(e.loc, "cannot cast expression `%s` of type `%s` to `%s`", e.toChars(), e.type.toChars(), t.toChars());
             return ErrorExp.get();
         }
 
@@ -1830,7 +1839,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
         if (!e.committed && t.ty == Tpointer && t.nextOf().ty == Tvoid &&
             (!sc || !(sc.flags & SCOPE.Cfile)))
         {
-            e.error("cannot convert string literal to `void*`");
+            error(e.loc, "cannot convert string literal to `void*`");
             return ErrorExp.get();
         }
 
@@ -1968,7 +1977,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
                 {
                     dchar c;
                     if (const s = utf_decodeChar(se.peekString(), u, c))
-                        e.error("%.*s", cast(int)s.length, s.ptr);
+                        error(e.loc, "%.*s", cast(int)s.length, s.ptr);
                     else
                         buffer.writeUTF16(c);
                 }
@@ -1981,7 +1990,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
                 {
                     dchar c;
                     if (const s = utf_decodeChar(se.peekString(), u, c))
-                        e.error("%.*s", cast(int)s.length, s.ptr);
+                        error(e.loc, "%.*s", cast(int)s.length, s.ptr);
                     buffer.write4(c);
                     newlen++;
                 }
@@ -1993,7 +2002,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
                 {
                     dchar c;
                     if (const s = utf_decodeWchar(se.peekWstring(), u, c))
-                        e.error("%.*s", cast(int)s.length, s.ptr);
+                        error(e.loc, "%.*s", cast(int)s.length, s.ptr);
                     else
                         buffer.writeUTF8(c);
                 }
@@ -2006,7 +2015,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
                 {
                     dchar c;
                     if (const s = utf_decodeWchar(se.peekWstring(), u, c))
-                        e.error("%.*s", cast(int)s.length, s.ptr);
+                        error(e.loc, "%.*s", cast(int)s.length, s.ptr);
                     buffer.write4(c);
                     newlen++;
                 }
@@ -2018,7 +2027,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
                 {
                     uint c = se.peekDstring()[u];
                     if (!utf_isValidDchar(c))
-                        e.error("invalid UCS-32 char \\U%08x", c);
+                        error(e.loc, "invalid UCS-32 char \\U%08x", c);
                     else
                         buffer.writeUTF8(c);
                     newlen++;
@@ -2032,7 +2041,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
                 {
                     uint c = se.peekDstring()[u];
                     if (!utf_isValidDchar(c))
-                        e.error("invalid UCS-32 char \\U%08x", c);
+                        error(e.loc, "invalid UCS-32 char \\U%08x", c);
                     else
                         buffer.writeUTF16(c);
                     newlen++;
@@ -2392,7 +2401,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
                     }
                     else if (f.needThis())
                     {
-                        e.error("no `this` to create delegate for `%s`", f.toChars());
+                        error(e.loc, "no `this` to create delegate for `%s`", f.toChars());
                         return ErrorExp.get();
                     }
                     else if (f.isNested())
@@ -2402,7 +2411,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
                     }
                     else
                     {
-                        e.error("cannot cast from function pointer to delegate");
+                        error(e.loc, "cannot cast from function pointer to delegate");
                         return ErrorExp.get();
                     }
                 }
@@ -2443,7 +2452,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
             int offset;
             e.func.tookAddressOf++;
             if (e.func.tintro && e.func.tintro.nextOf().isBaseOf(e.func.type.nextOf(), &offset) && offset)
-                e.error("%s", msg.ptr);
+                error(e.loc, "%s", msg.ptr);
             auto result = e.copy();
             result.type = t;
             return result;
@@ -2459,7 +2468,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
                 {
                     int offset;
                     if (f.tintro && f.tintro.nextOf().isBaseOf(f.type.nextOf(), &offset) && offset)
-                        e.error("%s", msg.ptr);
+                        error(e.loc, "%s", msg.ptr);
                     if (f != e.func)    // if address not already marked as taken
                         f.tookAddressOf++;
                     auto result = new DelegateExp(e.loc, e.e1, f, false, e.vthis2);
@@ -2467,7 +2476,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
                     return result;
                 }
                 if (e.func.tintro)
-                    e.error("%s", msg.ptr);
+                    error(e.loc, "%s", msg.ptr);
             }
         }
 
@@ -2596,7 +2605,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
             }
         }
         auto ts = toAutoQualChars(tsa ? tsa : e.type, t);
-        e.error("cannot cast expression `%s` of type `%s` to `%s`",
+        error(e.loc, "cannot cast expression `%s` of type `%s` to `%s`",
             e.toChars(), ts[0], ts[1]);
         return ErrorExp.get();
     }
@@ -3610,7 +3619,7 @@ Expression integralPromotions(Expression e, Scope* sc)
     switch (e.type.toBasetype().ty)
     {
     case Tvoid:
-        e.error("void has no value");
+        error(e.loc, "void has no value");
         return ErrorExp.get();
 
     case Tint8:
@@ -3659,7 +3668,7 @@ void fix16997(Scope* sc, UnaExp ue)
             case Tchar:
             case Twchar:
             case Tdchar:
-                ue.deprecation("integral promotion not done for `%s`, remove '-revert=intpromote' switch or `%scast(int)(%s)`",
+                deprecation(ue.loc, "integral promotion not done for `%s`, remove '-revert=intpromote' switch or `%scast(int)(%s)`",
                     ue.toChars(), EXPtoString(ue.op).ptr, ue.e1.toChars());
                 break;
 
diff --git a/gcc/d/dmd/dclass.d b/gcc/d/dmd/dclass.d
index b446e77b8799..0fbbb1128e74 100644
--- a/gcc/d/dmd/dclass.d
+++ b/gcc/d/dmd/dclass.d
@@ -24,6 +24,7 @@ import dmd.declaration;
 import dmd.dscope;
 import dmd.dsymbol;
 import dmd.dsymbolsem;
+import dmd.errors;
 import dmd.func;
 import dmd.id;
 import dmd.identifier;
@@ -222,7 +223,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
 
         // Look for special class names
         if (id == Id.__sizeof || id == Id.__xalignof || id == Id._mangleof)
-            error("illegal class name");
+            classError("%s `%s` illegal class name", null);
 
         // BUG: What if this is the wrong TypeInfo, i.e. it is nested?
         if (id.toChars()[0] == 'T')
@@ -230,103 +231,103 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
             if (id == Id.TypeInfo)
             {
                 if (!inObject)
-                    error("%s", msg.ptr);
+                    classError("%s `%s` %s", msg.ptr);
                 Type.dtypeinfo = this;
             }
             if (id == Id.TypeInfo_Class)
             {
                 if (!inObject)
-                    error("%s", msg.ptr);
+                    classError("%s `%s` %s", msg.ptr);
                 Type.typeinfoclass = this;
             }
             if (id == Id.TypeInfo_Interface)
             {
                 if (!inObject)
-                    error("%s", msg.ptr);
+                    classError("%s `%s` %s", msg.ptr);
                 Type.typeinfointerface = this;
             }
             if (id == Id.TypeInfo_Struct)
             {
                 if (!inObject)
-                    error("%s", msg.ptr);
+                    classError("%s `%s` %s", msg.ptr);
                 Type.typeinfostruct = this;
             }
             if (id == Id.TypeInfo_Pointer)
             {
                 if (!inObject)
-                    error("%s", msg.ptr);
+                    classError("%s `%s` %s", msg.ptr);
                 Type.typeinfopointer = this;
             }
             if (id == Id.TypeInfo_Array)
             {
                 if (!inObject)
-                    error("%s", msg.ptr);
+                    classError("%s `%s` %s", msg.ptr);
                 Type.typeinfoarray = this;
             }
             if (id == Id.TypeInfo_StaticArray)
             {
                 //if (!inObject)
-                //    Type.typeinfostaticarray.error("%s", msg);
+                //    Type.typeinfostaticarray.classError("%s `%s` %s", msg);
                 Type.typeinfostaticarray = this;
             }
             if (id == Id.TypeInfo_AssociativeArray)
             {
                 if (!inObject)
-                    error("%s", msg.ptr);
+                    classError("%s `%s` %s", msg.ptr);
                 Type.typeinfoassociativearray = this;
             }
             if (id == Id.TypeInfo_Enum)
             {
                 if (!inObject)
-                    error("%s", msg.ptr);
+                    classError("%s `%s` %s", msg.ptr);
                 Type.typeinfoenum = this;
             }
             if (id == Id.TypeInfo_Function)
             {
                 if (!inObject)
-                    error("%s", msg.ptr);
+                    classError("%s `%s` %s", msg.ptr);
                 Type.typeinfofunction = this;
             }
             if (id == Id.TypeInfo_Delegate)
             {
                 if (!inObject)
-                    error("%s", msg.ptr);
+                    classError("%s `%s` %s", msg.ptr);
                 Type.typeinfodelegate = this;
             }
             if (id == Id.TypeInfo_Tuple)
             {
                 if (!inObject)
-                    error("%s", msg.ptr);
+                    classError("%s `%s` %s", msg.ptr);
                 Type.typeinfotypelist = this;
             }
             if (id == Id.TypeInfo_Const)
             {
                 if (!inObject)
-                    error("%s", msg.ptr);
+                    classError("%s `%s` %s", msg.ptr);
                 Type.typeinfoconst = this;
             }
             if (id == Id.TypeInfo_Invariant)
             {
                 if (!inObject)
-                    error("%s", msg.ptr);
+                    classError("%s `%s` %s", msg.ptr);
                 Type.typeinfoinvariant = this;
             }
             if (id == Id.TypeInfo_Shared)
             {
                 if (!inObject)
-                    error("%s", msg.ptr);
+                    classError("%s `%s` %s", msg.ptr);
                 Type.typeinfoshared = this;
             }
             if (id == Id.TypeInfo_Wild)
             {
                 if (!inObject)
-                    error("%s", msg.ptr);
+                    classError("%s `%s` %s", msg.ptr);
                 Type.typeinfowild = this;
             }
             if (id == Id.TypeInfo_Vector)
             {
                 if (!inObject)
-                    error("%s", msg.ptr);
+                    classError("%s `%s` %s", msg.ptr);
                 Type.typeinfovector = this;
             }
         }
@@ -334,38 +335,43 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
         if (id == Id.Object)
         {
             if (!inObject)
-                error("%s", msg.ptr);
+                classError("%s `%s` %s", msg.ptr);
             object = this;
         }
 
         if (id == Id.Throwable)
         {
             if (!inObject)
-                error("%s", msg.ptr);
+                classError("%s `%s` %s", msg.ptr);
             throwable = this;
         }
         if (id == Id.Exception)
         {
             if (!inObject)
-                error("%s", msg.ptr);
+                classError("%s `%s` %s", msg.ptr);
             exception = this;
         }
         if (id == Id.Error)
         {
             if (!inObject)
-                error("%s", msg.ptr);
+                classError("%s `%s` %s", msg.ptr);
             errorException = this;
         }
         if (id == Id.cpp_type_info_ptr)
         {
             if (!inObject)
-                error("%s", msg.ptr);
+                classError("%s `%s` %s", msg.ptr);
             cpp_type_info_ptr = this;
         }
 
         baseok = Baseok.none;
     }
 
+    final void classError(const(char)* fmt, const(char)* arg)
+    {
+        .error(loc, fmt, kind, toPrettyChars, arg);
+    }
+
     static ClassDeclaration create(const ref Loc loc, Identifier id, BaseClasses* baseclasses, Dsymbols* members, bool inObject)
     {
         return new ClassDeclaration(loc, id, baseclasses, members, inObject);
@@ -481,7 +487,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
         {
             // .stringof is always defined (but may be hidden by some other symbol)
             if (ident != Id.stringof && !(flags & IgnoreErrors) && semanticRun < PASS.semanticdone)
-                error("is forward referenced when looking for `%s`", ident.toChars());
+                classError("%s `%s` is forward referenced when looking for `%s`", ident.toChars());
             //*(char*)0=0;
             return null;
         }
@@ -503,7 +509,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
 
             if (!b.sym.symtab)
             {
-                error("base `%s` is forward referenced", b.sym.ident.toChars());
+                classError("%s `%s` base `%s` is forward referenced", b.sym.ident.toChars());
                 continue;
             }
 
@@ -814,7 +820,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
         }
 
         if (fdambig)
-            error("ambiguous virtual function `%s`", fdambig.toChars());
+            classError("%s `%s` ambiguous virtual function `%s`", fdambig.toChars());
 
         return fdmatch;
     }
diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d
index b21678ce508c..b65e7e833d4d 100644
--- a/gcc/d/dmd/declaration.d
+++ b/gcc/d/dmd/declaration.d
@@ -326,12 +326,12 @@ extern (C++) abstract class Declaration : Dsymbol
                             continue;
                         if (sdv.postblit.isDisabled())
                         {
-                            p.error(loc, "is not copyable because field `%s` is not copyable", structField.toChars());
+                            .error(loc, "%s `%s` is not copyable because field `%s` is not copyable", p.kind, p.toPrettyChars, structField.toChars());
                             return true;
                         }
                     }
                 }
-                p.error(loc, "is not copyable because it has a disabled postblit");
+                .error(loc, "%s `%s` is not copyable because it has a disabled postblit", p.kind, p.toPrettyChars);
                 return true;
             }
         }
@@ -357,7 +357,7 @@ extern (C++) abstract class Declaration : Dsymbol
                 return true;
             }
         }
-        error(loc, "cannot be used because it is annotated with `@disable`");
+        .error(loc, "%s `%s` cannot be used because it is annotated with `@disable`", kind, toPrettyChars);
         return true;
     }
 
@@ -388,7 +388,7 @@ extern (C++) abstract class Declaration : Dsymbol
                 {
                     const(char)* s = isParameter() && parent.ident != Id.ensure ? "parameter" : "result";
                     if (!(flag & ModifyFlags.noError))
-                        error(loc, "cannot modify %s `%s` in contract", s, toChars());
+                        error(loc, "%s `%s` cannot modify %s `%s` in contract", kind, toPrettyChars, s, toChars());
                     return Modifiable.initialization; // do not report type related errors
                 }
             }
@@ -402,7 +402,7 @@ extern (C++) abstract class Declaration : Dsymbol
                 if (scx.func == vthis.parent && (scx.flags & SCOPE.contract))
                 {
                     if (!(flag & ModifyFlags.noError))
-                        error(loc, "cannot modify parameter `this` in contract");
+                        error(loc, "%s `%s` cannot modify parameter `this` in contract", kind, toPrettyChars);
                     return Modifiable.initialization; // do not report type related errors
                 }
             }
@@ -945,7 +945,7 @@ extern (C++) final class AliasDeclaration : Declaration
         }
         if (inuse)
         {
-            error("recursive alias declaration");
+            .error(loc, "%s `%s` recursive alias declaration", kind, toPrettyChars);
 
         Lerr:
             // Avoid breaking "recursive alias" state during errors gagged
@@ -1003,7 +1003,7 @@ extern (C++) final class AliasDeclaration : Declaration
     {
         if (inuse)
         {
-            error("recursive alias declaration");
+            .error(loc, "%s `%s` recursive alias declaration", kind, toPrettyChars);
             return this;
         }
         inuse = 1;
@@ -1377,7 +1377,7 @@ extern (C++) class VarDeclaration : Declaration
             Dsymbol parent = toParent();
             if (!parent && !(storage_class & STC.static_))
             {
-                error("forward referenced");
+                .error(loc, "%s `%s` forward referenced", kind, toPrettyChars);
                 type = Type.terror;
             }
             else if (storage_class & (STC.static_ | STC.extern_ | STC.gshared) ||
diff --git a/gcc/d/dmd/denum.d b/gcc/d/dmd/denum.d
index 955a17dc6e89..98bf4dd2aad1 100644
--- a/gcc/d/dmd/denum.d
+++ b/gcc/d/dmd/denum.d
@@ -18,6 +18,7 @@ import core.stdc.stdio;
 
 import dmd.astenums;
 import dmd.attrib;
+import dmd.errors;
 import dmd.gluelayer;
 import dmd.declaration;
 import dmd.dscope;
@@ -191,7 +192,7 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
                 return defaultval = memtype.defaultInit(loc);
             }
 
-            error(loc, "is opaque and has no default initializer");
+            error(loc, "%s `%s` is opaque and has no default initializer", kind, toPrettyChars);
             return handleErrors();
         }
 
@@ -202,7 +203,7 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
             {
                 if (em.semanticRun < PASS.semanticdone)
                 {
-                    error(loc, "forward reference of `%s.init`", toChars());
+                    error(loc, "%s `%s` forward reference of `%s.init`", kind, toPrettyChars, toChars());
                     return handleErrors();
                 }
 
diff --git a/gcc/d/dmd/dimport.d b/gcc/d/dmd/dimport.d
index c4d5ddbc0798..3b8d9f6722d9 100644
--- a/gcc/d/dmd/dimport.d
+++ b/gcc/d/dmd/dimport.d
@@ -93,7 +93,7 @@ extern (C++) final class Import : Dsymbol
     extern (D) void addAlias(Identifier name, Identifier _alias)
     {
         if (isstatic)
-            error("cannot have an import bind list");
+            .error(loc, "%s `%s` cannot have an import bind list", kind, toPrettyChars);
         if (!aliasId)
             this.ident = null; // make it an anonymous import
         names.push(name);
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index 7cdafda050cd..a43be7d2308f 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -427,17 +427,23 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
     {
         printf("\n********\n%s FuncDeclaration::interpret(istate = %p) %s\n", fd.loc.toChars(), istate, fd.toChars());
     }
+
+    void fdError(const(char)* msg)
+    {
+        error(fd.loc, "%s `%s` %s", fd.kind, fd.toPrettyChars, msg);
+    }
+
     assert(pue);
     if (fd.semanticRun == PASS.semantic3)
     {
-        fd.error("circular dependency. Functions cannot be interpreted while being compiled");
+        fdError("circular dependency. Functions cannot be interpreted while being compiled");
         return CTFEExp.cantexp;
     }
     if (!fd.functionSemantic3())
         return CTFEExp.cantexp;
     if (fd.semanticRun < PASS.semantic3done)
     {
-        fd.error("circular dependency. Functions cannot be interpreted while being compiled");
+        fdError("circular dependency. Functions cannot be interpreted while being compiled");
         return CTFEExp.cantexp;
     }
 
@@ -445,7 +451,7 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
     if (tf.parameterList.varargs != VarArg.none && arguments &&
         ((fd.parameters && arguments.length != fd.parameters.length) || (!fd.parameters && arguments.length)))
     {
-        fd.error("C-style variadic functions are not yet implemented in CTFE");
+        fdError("C-style variadic functions are not yet implemented in CTFE");
         return CTFEExp.cantexp;
     }
 
@@ -460,7 +466,7 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
     {
         // error, no this. Prevent segfault.
         // Here should be unreachable by the strict 'this' check in front-end.
-        fd.error("need `this` to access member `%s`", fd.toChars());
+        error(fd.loc, "%s `%s` need `this` to access member `%s`", fd.kind, fd.toPrettyChars, fd.toChars());
         return CTFEExp.cantexp;
     }
 
@@ -483,7 +489,7 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
             if (!istate && (fparam.storageClass & STC.out_))
             {
                 // initializing an out parameter involves writing to it.
-                earg.error("global `%s` cannot be passed as an `out` parameter at compile time", earg.toChars());
+                error(earg.loc, "global `%s` cannot be passed as an `out` parameter at compile time", earg.toChars());
                 return CTFEExp.cantexp;
             }
             // Convert all reference arguments into lvalue references
@@ -577,7 +583,7 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
             VarDeclaration vx = earg.isVarExp().var.isVarDeclaration();
             if (!vx)
             {
-                fd.error("cannot interpret `%s` as a `ref` parameter", earg.toChars());
+                error(fd.loc, "%s `%s` cannot interpret `%s` as a `ref` parameter", fd.kind, fd.toPrettyChars, earg.toChars());
                 return CTFEExp.cantexp;
             }
 
@@ -634,7 +640,7 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
     {
         if (ctfeGlobals.callDepth > CTFE_RECURSION_LIMIT)
         {
-            fd.error("CTFE recursion limit exceeded");
+            fdError("CTFE recursion limit exceeded");
             e = CTFEExp.cantexp;
             break;
         }
@@ -649,7 +655,7 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
 
         if (istatex.start)
         {
-            fd.error("CTFE internal error: failed to resume at statement `%s`", istatex.start.toChars());
+            error(fd.loc, "%s `%s` CTFE internal error: failed to resume at statement `%s`", fd.kind, fd.toPrettyChars, istatex.start.toChars());
             return CTFEExp.cantexp;
         }
 
@@ -680,7 +686,7 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
             /* missing a return statement can happen with C functions
              * https://issues.dlang.org/show_bug.cgi?id=23056
              */
-            fd.error("no return value from function");
+            fdError("no return value from function");
             e = CTFEExp.cantexp;
         }
     }
@@ -1255,7 +1261,7 @@ Expression interpretStatement(UnionExp* pue, Statement s, InterState* istate)
             }
         if (!scase)
         {
-            if (s.hasNoDefault)
+            if (!s.hasDefault)
                 error(s.loc, "no `default` or `case` for `%s` in `switch` statement", econdition.toChars());
             scase = s.sdefault;
         }
@@ -1419,7 +1425,7 @@ Expression interpretStatement(UnionExp* pue, Statement s, InterState* istate)
                     setValue(ca.var, ex.thrown);
                 }
                 e = interpretStatement(ca.handler, istate);
-                if (CTFEExp.isGotoExp(e))
+                while (CTFEExp.isGotoExp(e))
                 {
                     /* This is an optimization that relies on the locality of the jump target.
                      * If the label is in the same catch handler, the following scan
@@ -1431,11 +1437,19 @@ Expression interpretStatement(UnionExp* pue, Statement s, InterState* istate)
                     istatex.start = istate.gotoTarget; // set starting statement
                     istatex.gotoTarget = null;
                     Expression eh = interpretStatement(ca.handler, &istatex);
-                    if (!istatex.start)
+                    if (istatex.start)
+                    {
+                        // The goto target is outside the current scope.
+                        break;
+                    }
+                    // The goto target was within the body.
+                    if (CTFEExp.isCantExp(eh))
                     {
-                        istate.gotoTarget = null;
                         e = eh;
+                        break;
                     }
+                    *istate = istatex;
+                    e = eh;
                 }
                 break;
             }
@@ -1562,7 +1576,7 @@ Expression interpretStatement(UnionExp* pue, Statement s, InterState* istate)
         ctfeGlobals.stack.push(s.wthis);
         setValue(s.wthis, e);
         e = interpretStatement(s._body, istate);
-        if (CTFEExp.isGotoExp(e))
+        while (CTFEExp.isGotoExp(e))
         {
             /* This is an optimization that relies on the locality of the jump target.
              * If the label is in the same WithStatement, the following scan
@@ -1574,11 +1588,19 @@ Expression interpretStatement(UnionExp* pue, Statement s, InterState* istate)
             istatex.start = istate.gotoTarget; // set starting statement
             istatex.gotoTarget = null;
             Expression ex = interpretStatement(s._body, &istatex);
-            if (!istatex.start)
+            if (istatex.start)
+            {
+                // The goto target is outside the current scope.
+                break;
+            }
+            // The goto target was within the body.
+            if (CTFEExp.isCantExp(ex))
             {
-                istate.gotoTarget = null;
                 e = ex;
+                break;
             }
+            *istate = istatex;
+            e = ex;
         }
         ctfeGlobals.stack.pop(s.wthis);
         result = e;
@@ -1673,7 +1695,7 @@ public:
             printf("type = %s\n", e.type.toChars());
             showCtfeExpr(e);
         }
-        e.error("cannot interpret `%s` at compile time", e.toChars());
+        error(e.loc, "cannot interpret `%s` at compile time", e.toChars());
         result = CTFEExp.cantexp;
     }
 
@@ -1730,7 +1752,7 @@ public:
             assert(result.op == EXP.structLiteral || result.op == EXP.classReference || result.op == EXP.type);
             return;
         }
-        e.error("value of `this` is not known at compile time");
+        error(e.loc, "value of `this` is not known at compile time");
         result = CTFEExp.cantexp;
     }
 
@@ -1819,14 +1841,14 @@ public:
         if (e.type.ty != Tpointer)
         {
             // Probably impossible
-            e.error("cannot interpret `%s` at compile time", e.toChars());
+            error(e.loc, "cannot interpret `%s` at compile time", e.toChars());
             result = CTFEExp.cantexp;
             return;
         }
         Type pointee = (cast(TypePointer)e.type).next;
         if (e.var.isThreadlocal())
         {
-            e.error("cannot take address of thread-local variable %s at compile time", e.var.toChars());
+            error(e.loc, "cannot take address of thread-local variable %s at compile time", e.var.toChars());
             result = CTFEExp.cantexp;
             return;
         }
@@ -1881,7 +1903,7 @@ public:
                     result = pue.exp();
                     return;
                 }
-                e.error("reinterpreting cast from `%s` to `%s` is not supported in CTFE", val.type.toChars(), e.type.toChars());
+                error(e.loc, "reinterpreting cast from `%s` to `%s` is not supported in CTFE", val.type.toChars(), e.type.toChars());
                 result = CTFEExp.cantexp;
                 return;
             }
@@ -1922,7 +1944,7 @@ public:
             return;
         }
 
-        e.error("cannot convert `&%s` to `%s` at compile time", e.var.type.toChars(), e.type.toChars());
+        error(e.loc, "cannot convert `&%s` to `%s` at compile time", e.var.type.toChars(), e.type.toChars());
         result = CTFEExp.cantexp;
     }
 
@@ -1938,7 +1960,7 @@ public:
 
             // We cannot take the address of an imported symbol at compile time
             if (decl.isImportedSymbol()) {
-                e.error("cannot take address of imported symbol `%s` at compile time", decl.toChars());
+                error(e.loc, "cannot take address of imported symbol `%s` at compile time", decl.toChars());
                 result = CTFEExp.cantexp;
                 return;
             }
@@ -2183,9 +2205,9 @@ public:
                     }
 
                     if (!v.isCTFE() && v.isDataseg())
-                        e.error("static variable `%s` cannot be read at compile time", v.toChars());
+                        error(e.loc, "static variable `%s` cannot be read at compile time", v.toChars());
                     else // CTFE initiated from inside a function
-                        e.error("variable `%s` cannot be read at compile time", v.toChars());
+                        error(e.loc, "variable `%s` cannot be read at compile time", v.toChars());
                     result = CTFEExp.cantexp;
                     return;
                 }
@@ -2277,7 +2299,7 @@ public:
                         }
                         else
                         {
-                            e.error("declaration `%s` is not yet implemented in CTFE", e.toChars());
+                            error(e.loc, "declaration `%s` is not yet implemented in CTFE", e.toChars());
                             result = CTFEExp.cantexp;
                             return 1;
                         }
@@ -2316,7 +2338,7 @@ public:
                     if (result !is null)
                         return;
                 }
-                e.error("declaration `%s` is not yet implemented in CTFE", e.toChars());
+                error(e.loc, "declaration `%s` is not yet implemented in CTFE", e.toChars());
                 result = CTFEExp.cantexp;
             }
             else if (v.type.size() == 0)
@@ -2326,7 +2348,7 @@ public:
             }
             else
             {
-                e.error("variable `%s` cannot be modified at compile time", v.toChars());
+                error(e.loc, "variable `%s` cannot be modified at compile time", v.toChars());
                 result = CTFEExp.cantexp;
             }
             return;
@@ -2334,7 +2356,7 @@ public:
         if (s.isTemplateMixin() || s.isTupleDeclaration())
         {
             // These can be made to work, too lazy now
-            e.error("declaration `%s` is not yet implemented in CTFE", e.toChars());
+            error(e.loc, "declaration `%s` is not yet implemented in CTFE", e.toChars());
             result = CTFEExp.cantexp;
             return;
         }
@@ -2366,13 +2388,13 @@ public:
 
             if (result.op == EXP.null_)
             {
-                e.error("null pointer dereference evaluating typeid. `%s` is `null`", ex.toChars());
+                error(e.loc, "null pointer dereference evaluating typeid. `%s` is `null`", ex.toChars());
                 result = CTFEExp.cantexp;
                 return;
             }
             if (result.op != EXP.classReference)
             {
-                e.error("CTFE internal error: determining classinfo");
+                error(e.loc, "CTFE internal error: determining classinfo");
                 result = CTFEExp.cantexp;
                 return;
             }
@@ -2409,7 +2431,7 @@ public:
                 continue;
             if (ex.op == EXP.voidExpression)
             {
-                e.error("CTFE internal error: void element `%s` in sequence", exp.toChars());
+                error(e.loc, "CTFE internal error: void element `%s` in sequence", exp.toChars());
                 assert(0);
             }
 
@@ -2496,7 +2518,7 @@ public:
             expandTuples(expsx);
             if (expsx.length != dim)
             {
-                e.error("CTFE internal error: invalid array literal");
+                error(e.loc, "CTFE internal error: invalid array literal");
                 result = CTFEExp.cantexp;
                 return;
             }
@@ -2559,7 +2581,7 @@ public:
             expandTuples(valuesx);
         if (keysx.length != valuesx.length)
         {
-            e.error("CTFE internal error: invalid AA");
+            error(e.loc, "CTFE internal error: invalid AA");
             result = CTFEExp.cantexp;
             return;
         }
@@ -2680,7 +2702,7 @@ public:
             expandTuples(expsx);
             if (expsx.length != e.sd.fields.length)
             {
-                e.error("CTFE internal error: invalid struct literal");
+                error(e.loc, "CTFE internal error: invalid struct literal");
                 result = CTFEExp.cantexp;
                 return;
             }
@@ -2810,7 +2832,7 @@ public:
                 {
                     if (v.inuse)
                     {
-                        e.error("circular reference to `%s`", v.toPrettyChars());
+                        error(e.loc, "circular reference to `%s`", v.toPrettyChars());
                         result = CTFEExp.cantexp;
                         return;
                     }
@@ -2855,7 +2877,9 @@ public:
                         result = eref;
                         return;
                     }
-                    e.member.error("`%s` cannot be constructed at compile time, because the constructor has no available source code", e.newtype.toChars());
+                    auto m = e.member;
+                    error(m.loc, "%s `%s` `%s` cannot be constructed at compile time, because the constructor has no available source code",
+                        m.kind, m.toPrettyChars, e.newtype.toChars());
                     result = CTFEExp.cantexp;
                     return;
                 }
@@ -2897,7 +2921,7 @@ public:
             result = pue.exp();
             return;
         }
-        e.error("cannot interpret `%s` at compile time", e.toChars());
+        error(e.loc, "cannot interpret `%s` at compile time", e.toChars());
         result = CTFEExp.cantexp;
     }
 
@@ -2998,7 +3022,7 @@ public:
         }
         if (e.e1.type.ty == Tpointer || e.e2.type.ty == Tpointer)
         {
-            e.error("pointer expression `%s` cannot be interpreted at compile time", e.toChars());
+            error(e.loc, "pointer expression `%s` cannot be interpreted at compile time", e.toChars());
             result = CTFEExp.cantexp;
             return;
         }
@@ -3027,7 +3051,7 @@ public:
             const uinteger_t sz = e1.type.size() * 8;
             if (i2 < 0 || i2 >= sz)
             {
-                e.error("shift by %lld is outside the range 0..%llu", i2, cast(ulong)sz - 1);
+                error(e.loc, "shift by %lld is outside the range 0..%llu", i2, cast(ulong)sz - 1);
                 result = CTFEExp.cantexp;
                 return;
             }
@@ -3078,13 +3102,13 @@ public:
             if (e1.isConst() != 1)
             {
                 // The following should really be an assert()
-                e1.error("CTFE internal error: non-constant value `%s`", e1.toChars());
+                error(e1.loc, "CTFE internal error: non-constant value `%s`", e1.toChars());
                 emplaceExp!CTFEExp(&ue, EXP.cantExpression);
                 return ue;
             }
             if (e2.isConst() != 1)
             {
-                e2.error("CTFE internal error: non-constant value `%s`", e2.toChars());
+                error(e2.loc, "CTFE internal error: non-constant value `%s`", e2.toChars());
                 emplaceExp!CTFEExp(&ue, EXP.cantExpression);
                 return ue;
             }
@@ -3095,7 +3119,7 @@ public:
         *pue = evaluate(e.loc, e.type, e1, e2);
         result = (*pue).exp();
         if (CTFEExp.isCantExp(result))
-            e.error("`%s` cannot be interpreted at compile time", e.toChars());
+            error(e.loc, "`%s` cannot be interpreted at compile time", e.toChars());
     }
 
     extern (D) private void interpretCompareCommon(BinExp e, fp2_t fp)
@@ -3123,7 +3147,7 @@ public:
             if (cmp == -1)
             {
                 char dir = (e.op == EXP.greaterThan || e.op == EXP.greaterOrEqual) ? '<' : '>';
-                e.error("the ordering of pointers to unrelated memory blocks is indeterminate in CTFE. To check if they point to the same memory block, use both `>` and `<` inside `&&` or `||`, eg `%s && %s %c= %s + 1`", e.toChars(), e.e1.toChars(), dir, e.e2.toChars());
+                error(e.loc, "the ordering of pointers to unrelated memory blocks is indeterminate in CTFE. To check if they point to the same memory block, use both `>` and `<` inside `&&` or `||`, eg `%s && %s %c= %s + 1`", e.toChars(), e.e1.toChars(), dir, e.e2.toChars());
                 result = CTFEExp.cantexp;
                 return;
             }
@@ -3141,7 +3165,7 @@ public:
             return;
         if (!isCtfeComparable(e1))
         {
-            e.error("cannot compare `%s` at compile time", e1.toChars());
+            error(e.loc, "cannot compare `%s` at compile time", e1.toChars());
             result = CTFEExp.cantexp;
             return;
         }
@@ -3150,7 +3174,7 @@ public:
             return;
         if (!isCtfeComparable(e2))
         {
-            e.error("cannot compare `%s` at compile time", e2.toChars());
+            error(e.loc, "cannot compare `%s` at compile time", e2.toChars());
             result = CTFEExp.cantexp;
             return;
         }
@@ -3277,7 +3301,7 @@ public:
         Expression e1 = e.e1;
         if (!istate)
         {
-            e.error("value of `%s` is not known at compile time", e1.toChars());
+            error(e.loc, "value of `%s` is not known at compile time", e1.toChars());
             return;
         }
 
@@ -3591,14 +3615,14 @@ public:
             }
             else
             {
-                e.error("pointer expression `%s` cannot be interpreted at compile time", e.toChars());
+                error(e.loc, "pointer expression `%s` cannot be interpreted at compile time", e.toChars());
                 result = CTFEExp.cantexp;
                 return;
             }
             if (exceptionOrCant(newval))
             {
                 if (CTFEExp.isCantExp(newval))
-                    e.error("cannot interpret `%s` at compile time", e.toChars());
+                    error(e.loc, "cannot interpret `%s` at compile time", e.toChars());
                 return;
             }
         }
@@ -3607,7 +3631,7 @@ public:
         {
             if (existingAA.ownedByCtfe != OwnedBy.ctfe)
             {
-                e.error("cannot modify read-only constant `%s`", existingAA.toChars());
+                error(e.loc, "cannot modify read-only constant `%s`", existingAA.toChars());
                 result = CTFEExp.cantexp;
                 return;
             }
@@ -3647,7 +3671,7 @@ public:
             Type t = e1.type.toBasetype();
             if (t.ty != Tarray)
             {
-                e.error("`%s` is not yet supported at compile time", e.toChars());
+                error(e.loc, "`%s` is not yet supported at compile time", e.toChars());
                 result = CTFEExp.cantexp;
                 return;
             }
@@ -3725,7 +3749,7 @@ public:
                     auto v = dve.var.isVarDeclaration();
                     if (!sle || !v)
                     {
-                        e.error("CTFE internal error: dotvar slice assignment");
+                        error(e.loc, "CTFE internal error: dotvar slice assignment");
                         result = CTFEExp.cantexp;
                         return;
                     }
@@ -3784,12 +3808,12 @@ public:
             auto v = e1.isDotVarExp().var.isVarDeclaration();
             if (!sle || !v)
             {
-                e.error("CTFE internal error: dotvar assignment");
+                error(e.loc, "CTFE internal error: dotvar assignment");
                 return CTFEExp.cantexp;
             }
             if (sle.ownedByCtfe != OwnedBy.ctfe)
             {
-                e.error("cannot modify read-only constant `%s`", sle.toChars());
+                error(e.loc, "cannot modify read-only constant `%s`", sle.toChars());
                 return CTFEExp.cantexp;
             }
 
@@ -3797,7 +3821,7 @@ public:
                        : ex.isClassReferenceExp().findFieldIndexByName(v);
             if (fieldi == -1)
             {
-                e.error("CTFE internal error: cannot find field `%s` in `%s`", v.toChars(), ex.toChars());
+                error(e.loc, "CTFE internal error: cannot find field `%s` in `%s`", v.toChars(), ex.toChars());
                 return CTFEExp.cantexp;
             }
             assert(0 <= fieldi && fieldi < sle.elements.length);
@@ -3839,7 +3863,7 @@ public:
             {
                 if (existingSE.ownedByCtfe != OwnedBy.ctfe)
                 {
-                    e.error("cannot modify read-only string literal `%s`", ie.e1.toChars());
+                    error(e.loc, "cannot modify read-only string literal `%s`", ie.e1.toChars());
                     return CTFEExp.cantexp;
                 }
                 existingSE.setCodeUnit(index, cast(dchar)newval.toInteger());
@@ -3847,14 +3871,14 @@ public:
             }
             if (aggregate.op != EXP.arrayLiteral)
             {
-                e.error("index assignment `%s` is not yet supported in CTFE ", e.toChars());
+                error(e.loc, "index assignment `%s` is not yet supported in CTFE ", e.toChars());
                 return CTFEExp.cantexp;
             }
 
             ArrayLiteralExp existingAE = aggregate.isArrayLiteralExp();
             if (existingAE.ownedByCtfe != OwnedBy.ctfe)
             {
-                e.error("cannot modify read-only constant `%s`", existingAE.toChars());
+                error(e.loc, "cannot modify read-only constant `%s`", existingAE.toChars());
                 return CTFEExp.cantexp;
             }
 
@@ -3863,7 +3887,7 @@ public:
         }
         else
         {
-            e.error("`%s` cannot be evaluated at compile time", e.toChars());
+            error(e.loc, "`%s` cannot be evaluated at compile time", e.toChars());
             return CTFEExp.cantexp;
         }
 
@@ -3899,7 +3923,7 @@ public:
                 newval = resolveSlice(newval);
                 if (CTFEExp.isCantExp(newval))
                 {
-                    e.error("CTFE internal error: assignment `%s`", e.toChars());
+                    error(e.loc, "CTFE internal error: assignment `%s`", e.toChars());
                     return CTFEExp.cantexp;
                 }
             }
@@ -4035,7 +4059,7 @@ public:
             const srclen = resolveArrayLength(newval);
             if (srclen != (upperbound - lowerbound))
             {
-                e.error("array length mismatch assigning `[0..%llu]` to `[%llu..%llu]`",
+                error(e.loc, "array length mismatch assigning `[0..%llu]` to `[%llu..%llu]`",
                     ulong(srclen), ulong(lowerbound), ulong(upperbound));
                 return CTFEExp.cantexp;
             }
@@ -4045,7 +4069,7 @@ public:
         {
             if (existingSE.ownedByCtfe != OwnedBy.ctfe)
             {
-                e.error("cannot modify read-only string literal `%s`", existingSE.toChars());
+                error(e.loc, "cannot modify read-only string literal `%s`", existingSE.toChars());
                 return CTFEExp.cantexp;
             }
 
@@ -4058,7 +4082,7 @@ public:
                 if (aggregate == aggr2 &&
                     lowerbound < srcupper && srclower < upperbound)
                 {
-                    e.error("overlapping slice assignment `[%llu..%llu] = [%llu..%llu]`",
+                    error(e.loc, "overlapping slice assignment `[%llu..%llu] = [%llu..%llu]`",
                         ulong(lowerbound), ulong(upperbound), ulong(srclower), ulong(srcupper));
                     return CTFEExp.cantexp;
                 }
@@ -4068,7 +4092,7 @@ public:
                     newval = resolveSlice(newval);
                     if (CTFEExp.isCantExp(newval))
                     {
-                        e.error("CTFE internal error: slice `%s`", orignewval.toChars());
+                        error(e.loc, "CTFE internal error: slice `%s`", orignewval.toChars());
                         return CTFEExp.cantexp;
                     }
                 }
@@ -4106,7 +4130,7 @@ public:
         {
             if (existingAE.ownedByCtfe != OwnedBy.ctfe)
             {
-                e.error("cannot modify read-only constant `%s`", existingAE.toChars());
+                error(e.loc, "cannot modify read-only constant `%s`", existingAE.toChars());
                 return CTFEExp.cantexp;
             }
 
@@ -4178,7 +4202,7 @@ public:
                 if (aggregate == aggr2 &&
                     lowerbound < srcupper && srclower < upperbound)
                 {
-                    e.error("overlapping slice assignment `[%llu..%llu] = [%llu..%llu]`",
+                    error(e.loc, "overlapping slice assignment `[%llu..%llu] = [%llu..%llu]`",
                         ulong(lowerbound), ulong(upperbound), ulong(srclower), ulong(srcupper));
                     return CTFEExp.cantexp;
                 }
@@ -4188,7 +4212,7 @@ public:
                     newval = resolveSlice(newval);
                     if (CTFEExp.isCantExp(newval))
                     {
-                        e.error("CTFE internal error: slice `%s`", orignewval.toChars());
+                        error(e.loc, "CTFE internal error: slice `%s`", orignewval.toChars());
                         return CTFEExp.cantexp;
                     }
                 }
@@ -4309,7 +4333,7 @@ public:
             return interpret(pue, retslice, istate);
         }
 
-        e.error("slice operation `%s = %s` cannot be evaluated at compile time", e1.toChars(), newval.toChars());
+        error(e.loc, "slice operation `%s = %s` cannot be evaluated at compile time", e1.toChars(), newval.toChars());
         return CTFEExp.cantexp;
     }
 
@@ -4514,7 +4538,7 @@ public:
             }
             if (except)
             {
-                e.error("comparison `%s` of pointers to unrelated memory blocks remains indeterminate at compile time because exception `%s` was thrown while evaluating `%s`", e.e1.toChars(), except.toChars(), e.e2.toChars());
+                error(e.loc, "comparison `%s` of pointers to unrelated memory blocks remains indeterminate at compile time because exception `%s` was thrown while evaluating `%s`", e.e1.toChars(), except.toChars(), e.e2.toChars());
                 result = CTFEExp.cantexp;
                 return;
             }
@@ -4537,7 +4561,7 @@ public:
             // comparison is in the same direction as the first, or else
             // more than two memory blocks are involved (either two independent
             // invalid comparisons are present, or else agg3 == agg4).
-            e.error("comparison `%s` of pointers to unrelated memory blocks is indeterminate at compile time, even when combined with `%s`.", e.e1.toChars(), e.e2.toChars());
+            error(e.loc, "comparison `%s` of pointers to unrelated memory blocks is indeterminate at compile time, even when combined with `%s`.", e.e1.toChars(), e.e2.toChars());
             result = CTFEExp.cantexp;
             return;
         }
@@ -4630,14 +4654,14 @@ public:
                 res = true;
             else
             {
-                e.error("`%s` does not evaluate to a `bool`", result.toChars());
+                error(e.loc, "`%s` does not evaluate to a `bool`", result.toChars());
                 result = CTFEExp.cantexp;
                 return;
             }
         }
         else
         {
-            e.error("`%s` cannot be interpreted as a `bool`", result.toChars());
+            error(e.loc, "`%s` cannot be interpreted as a `bool`", result.toChars());
             result = CTFEExp.cantexp;
             return;
         }
@@ -4667,7 +4691,7 @@ public:
         }
         errorSupplemental(callingExp.loc, "called from here: `%s`", callingExp.toChars());
         // Quit if it's not worth trying to compress the stack trace
-        if (ctfeGlobals.callDepth < 6 || global.params.verbose)
+        if (ctfeGlobals.callDepth < 6 || global.params.v.verbose)
             return;
         // Recursion happens if the current function already exists in the call stack.
         int numToSuppress = 0;
@@ -4851,13 +4875,13 @@ public:
         {
             // delegate.funcptr()
             // others
-            e.error("cannot call `%s` at compile time", e.toChars());
+            error(e.loc, "cannot call `%s` at compile time", e.toChars());
             result = CTFEExp.cantexp;
             return;
         }
         if (!fd)
         {
-            e.error("CTFE internal error: cannot evaluate `%s` at compile time", e.toChars());
+            error(e.loc, "CTFE internal error: cannot evaluate `%s` at compile time", e.toChars());
             result = CTFEExp.cantexp;
             return;
         }
@@ -4870,7 +4894,7 @@ public:
 
             if (pthis.op == EXP.typeid_)
             {
-                pthis.error("static variable `%s` cannot be read at compile time", pthis.toChars());
+                error(pthis.loc, "static variable `%s` cannot be read at compile time", pthis.toChars());
                 result = CTFEExp.cantexp;
                 return;
             }
@@ -4879,7 +4903,7 @@ public:
             if (pthis.op == EXP.null_)
             {
                 assert(pthis.type.toBasetype().ty == Tclass);
-                e.error("function call through null class reference `%s`", pthis.toChars());
+                error(e.loc, "function call through null class reference `%s`", pthis.toChars());
                 result = CTFEExp.cantexp;
                 return;
             }
@@ -4901,7 +4925,7 @@ public:
 
         if (fd && fd.semanticRun >= PASS.semantic3done && fd.hasSemantic3Errors())
         {
-            e.error("CTFE failed because of previous errors in `%s`", fd.toChars());
+            error(e.loc, "CTFE failed because of previous errors in `%s`", fd.toChars());
             result = CTFEExp.cantexp;
             return;
         }
@@ -4913,7 +4937,7 @@ public:
 
         if (!fd.fbody)
         {
-            e.error("`%s` cannot be interpreted at compile time, because it has no available source code", fd.toChars());
+            error(e.loc, "`%s` cannot be interpreted at compile time, because it has no available source code", fd.toChars());
             result = CTFEExp.showcontext;
             return;
         }
@@ -5092,7 +5116,7 @@ public:
         }
         else
         {
-            e.error("`%s` does not evaluate to boolean result at compile time", e.econd.toChars());
+            error(e.loc, "`%s` does not evaluate to boolean result at compile time", e.econd.toChars());
             result = CTFEExp.cantexp;
         }
     }
@@ -5110,7 +5134,7 @@ public:
             return;
         if (e1.op != EXP.string_ && e1.op != EXP.arrayLiteral && e1.op != EXP.slice && e1.op != EXP.null_)
         {
-            e.error("`%s` cannot be evaluated at compile time", e.toChars());
+            error(e.loc, "`%s` cannot be evaluated at compile time", e.toChars());
             result = CTFEExp.cantexp;
             return;
         }
@@ -5163,7 +5187,7 @@ public:
             return;
         if (e1.op != EXP.arrayLiteral && e1.op != EXP.int64 && e1.op != EXP.float64)
         {
-            e.error("`%s` cannot be evaluated at compile time", e.toChars());
+            error(e.loc, "`%s` cannot be evaluated at compile time", e.toChars());
             result = CTFEExp.cantexp;
             return;
         }
@@ -5193,7 +5217,7 @@ public:
             if (result.op != EXP.vector)
                 return;
         }
-        e.error("`%s` cannot be evaluated at compile time", e.toChars());
+        error(e.loc, "`%s` cannot be evaluated at compile time", e.toChars());
         result = CTFEExp.cantexp;
     }
 
@@ -5207,7 +5231,7 @@ public:
         assert(e1);
         if (exceptionOrCant(e1))
             return;
-        e.error("`%s` cannot be evaluated at compile time", e.toChars());
+        error(e.loc, "`%s` cannot be evaluated at compile time", e.toChars());
         result = CTFEExp.cantexp;
     }
 
@@ -5221,7 +5245,7 @@ public:
         assert(e1);
         if (exceptionOrCant(e1))
             return;
-        e.error("`%s` cannot be evaluated at compile time", e.toChars());
+        error(e.loc, "`%s` cannot be evaluated at compile time", e.toChars());
         result = CTFEExp.cantexp;
     }
 
@@ -5246,18 +5270,18 @@ public:
 
             if (agg.op == EXP.null_)
             {
-                e.error("cannot index through null pointer `%s`", e.e1.toChars());
+                error(e.loc, "cannot index through null pointer `%s`", e.e1.toChars());
                 return false;
             }
             if (agg.op == EXP.int64)
             {
-                e.error("cannot index through invalid pointer `%s` of value `%s`", e.e1.toChars(), e1.toChars());
+                error(e.loc, "cannot index through invalid pointer `%s` of value `%s`", e.e1.toChars(), e1.toChars());
                 return false;
             }
             // Pointer to a non-array variable
             if (agg.op == EXP.symbolOffset)
             {
-                e.error("mutable variable `%s` cannot be %s at compile time, even through a pointer", cast(char*)(modify ? "modified" : "read"), agg.isSymOffExp().var.toChars());
+                error(e.loc, "mutable variable `%s` cannot be %s at compile time, even through a pointer", cast(char*)(modify ? "modified" : "read"), agg.isSymOffExp().var.toChars());
                 return false;
             }
 
@@ -5266,7 +5290,7 @@ public:
                 dinteger_t len = resolveArrayLength(agg);
                 if (ofs + indx >= len)
                 {
-                    e.error("pointer index `[%lld]` exceeds allocated memory block `[0..%lld]`", ofs + indx, len);
+                    error(e.loc, "pointer index `[%lld]` exceeds allocated memory block `[0..%lld]`", ofs + indx, len);
                     return false;
                 }
             }
@@ -5274,7 +5298,7 @@ public:
             {
                 if (ofs + indx != 0)
                 {
-                    e.error("pointer index `[%lld]` lies outside memory block `[0..1]`", ofs + indx);
+                    error(e.loc, "pointer index `[%lld]` lies outside memory block `[0..1]`", ofs + indx);
                     return false;
                 }
             }
@@ -5288,7 +5312,7 @@ public:
             return false;
         if (e1.op == EXP.null_)
         {
-            e.error("cannot index null array `%s`", e.e1.toChars());
+            error(e.loc, "cannot index null array `%s`", e.e1.toChars());
             return false;
         }
         if (auto ve = e1.isVectorExp())
@@ -5306,7 +5330,7 @@ public:
         {
             if (e1.op != EXP.arrayLiteral && e1.op != EXP.string_ && e1.op != EXP.slice && e1.op != EXP.vector)
             {
-                e.error("cannot determine length of `%s` at compile time", e.e1.toChars());
+                error(e.loc, "cannot determine length of `%s` at compile time", e.e1.toChars());
                 return false;
             }
             len = resolveArrayLength(e1);
@@ -5325,7 +5349,7 @@ public:
             return false;
         if (e2.op != EXP.int64)
         {
-            e.error("CTFE internal error: non-integral index `[%s]`", e.e2.toChars());
+            error(e.loc, "CTFE internal error: non-integral index `[%s]`", e.e2.toChars());
             return false;
         }
 
@@ -5338,7 +5362,7 @@ public:
 
             if (index > iupr - ilwr)
             {
-                e.error("index %llu exceeds array length %llu", index, iupr - ilwr);
+                error(e.loc, "index %llu exceeds array length %llu", index, iupr - ilwr);
                 return false;
             }
             *pagg = e1.isSliceExp().e1;
@@ -5350,7 +5374,7 @@ public:
             *pidx = e2.toInteger();
             if (len <= *pidx)
             {
-                e.error("array index %lld is out of bounds `[0..%lld]`", *pidx, len);
+                error(e.loc, "array index %lld is out of bounds `[0..%lld]`", *pidx, len);
                 return false;
             }
         }
@@ -5408,7 +5432,7 @@ public:
                 {
                     assert(0); // does not reach here?
                 }
-                e.error("cannot index null array `%s`", e.e1.toChars());
+                error(e.loc, "cannot index null array `%s`", e.e1.toChars());
                 result = CTFEExp.cantexp;
                 return;
             }
@@ -5436,7 +5460,7 @@ public:
             result = findKeyInAA(e.loc, e1.isAssocArrayLiteralExp(), e2);
             if (!result)
             {
-                e.error("key `%s` not found in associative array `%s`", e2.toChars(), e.e1.toChars());
+                error(e.loc, "key `%s` not found in associative array `%s`", e2.toChars(), e.e1.toChars());
                 result = CTFEExp.cantexp;
             }
             return;
@@ -5464,7 +5488,7 @@ public:
             return;
         if (result.op == EXP.void_)
         {
-            e.error("`%s` is used before initialized", e.toChars());
+            error(e.loc, "`%s` is used before initialized", e.toChars());
             errorSupplemental(result.loc, "originally uninitialized here");
             result = CTFEExp.cantexp;
             return;
@@ -5487,7 +5511,7 @@ public:
                 return;
             if (e1.op == EXP.int64)
             {
-                e.error("cannot slice invalid pointer `%s` of value `%s`", e.e1.toChars(), e1.toChars());
+                error(e.loc, "cannot slice invalid pointer `%s` of value `%s`", e.e1.toChars(), e1.toChars());
                 result = CTFEExp.cantexp;
                 return;
             }
@@ -5515,19 +5539,19 @@ public:
                     result.type = e.type;
                     return;
                 }
-                e.error("cannot slice null pointer `%s`", e.e1.toChars());
+                error(e.loc, "cannot slice null pointer `%s`", e.e1.toChars());
                 result = CTFEExp.cantexp;
                 return;
             }
             if (agg.op == EXP.symbolOffset)
             {
-                e.error("slicing pointers to static variables is not supported in CTFE");
+                error(e.loc, "slicing pointers to static variables is not supported in CTFE");
                 result = CTFEExp.cantexp;
                 return;
             }
             if (agg.op != EXP.arrayLiteral && agg.op != EXP.string_)
             {
-                e.error("pointer `%s` cannot be sliced at compile time (it does not point to an array)", e.e1.toChars());
+                error(e.loc, "pointer `%s` cannot be sliced at compile time (it does not point to an array)", e.e1.toChars());
                 result = CTFEExp.cantexp;
                 return;
             }
@@ -5536,7 +5560,7 @@ public:
             //Type *pointee = ((TypePointer *)agg.type)->next;
             if (sliceBoundsCheck(0, len, ilwr, iupr))
             {
-                e.error("pointer slice `[%lld..%lld]` exceeds allocated memory block `[0..%lld]`", ilwr, iupr, len);
+                error(e.loc, "pointer slice `[%lld..%lld]` exceeds allocated memory block `[0..%lld]`", ilwr, iupr, len);
                 result = CTFEExp.cantexp;
                 return;
             }
@@ -5584,7 +5608,7 @@ public:
         {
             if (e1.op != EXP.arrayLiteral && e1.op != EXP.string_ && e1.op != EXP.null_ && e1.op != EXP.slice && e1.op != EXP.vector)
             {
-                e.error("cannot determine length of `%s` at compile time", e1.toChars());
+                error(e.loc, "cannot determine length of `%s` at compile time", e1.toChars());
                 result = CTFEExp.cantexp;
                 return;
             }
@@ -5628,7 +5652,7 @@ public:
                 result = e1;
                 return;
             }
-            e1.error("slice `[%llu..%llu]` is out of bounds", ilwr, iupr);
+            error(e1.loc, "slice `[%llu..%llu]` is out of bounds", ilwr, iupr);
             result = CTFEExp.cantexp;
             return;
         }
@@ -5640,7 +5664,7 @@ public:
             uinteger_t up1 = se.upr.toInteger();
             if (sliceBoundsCheck(0, up1 - lo1, ilwr, iupr))
             {
-                e.error("slice `[%llu..%llu]` exceeds array bounds `[0..%llu]`", ilwr, iupr, up1 - lo1);
+                error(e.loc, "slice `[%llu..%llu]` exceeds array bounds `[0..%llu]`", ilwr, iupr, up1 - lo1);
                 result = CTFEExp.cantexp;
                 return;
             }
@@ -5657,7 +5681,7 @@ public:
         {
             if (sliceBoundsCheck(0, dollar, ilwr, iupr))
             {
-                e.error("slice `[%lld..%lld]` exceeds array bounds `[0..%lld]`", ilwr, iupr, dollar);
+                error(e.loc, "slice `[%lld..%lld]` exceeds array bounds `[0..%lld]`", ilwr, iupr, dollar);
                 result = CTFEExp.cantexp;
                 return;
             }
@@ -5687,7 +5711,7 @@ public:
         }
         if (e2.op != EXP.assocArrayLiteral)
         {
-            e.error("`%s` cannot be interpreted at compile time", e.toChars());
+            error(e.loc, "`%s` cannot be interpreted at compile time", e.toChars());
             result = CTFEExp.cantexp;
             return;
         }
@@ -5769,7 +5793,7 @@ public:
 
         if (CTFEExp.isCantExp(result))
         {
-            e.error("`%s` cannot be interpreted at compile time", e.toChars());
+            error(e.loc, "`%s` cannot be interpreted at compile time", e.toChars());
             return;
         }
         // We know we still own it, because we interpreted both e1 and e2
@@ -5811,7 +5835,7 @@ public:
         case Tclass:
             if (result.op != EXP.classReference)
             {
-                e.error("`delete` on invalid class reference `%s`", result.toChars());
+                error(e.loc, "`delete` on invalid class reference `%s`", result.toChars());
                 result = CTFEExp.cantexp;
                 return;
             }
@@ -5902,7 +5926,7 @@ public:
                 }
                 else if (ultimatePointee.ty != Tvoid && ultimateSrc.ty != Tvoid && !isSafePointerCast(elemtype, pointee))
                 {
-                    e.error("reinterpreting cast from `%s*` to `%s*` is not supported in CTFE", elemtype.toChars(), pointee.toChars());
+                    error(e.loc, "reinterpreting cast from `%s*` to `%s*` is not supported in CTFE", elemtype.toChars(), pointee.toChars());
                     result = CTFEExp.cantexp;
                     return;
                 }
@@ -5961,7 +5985,7 @@ public:
                     }
                     if (!isSafePointerCast(origType, pointee))
                     {
-                        e.error("using `void*` to reinterpret cast from `%s*` to `%s*` is not supported in CTFE", origType.toChars(), pointee.toChars());
+                        error(e.loc, "using `void*` to reinterpret cast from `%s*` to `%s*` is not supported in CTFE", origType.toChars(), pointee.toChars());
                         result = CTFEExp.cantexp;
                         return;
                     }
@@ -6005,7 +6029,7 @@ public:
                 Type origType = (cast(SymbolExp)e1).var.type;
                 if (castBackFromVoid && !isSafePointerCast(origType, pointee))
                 {
-                    e.error("using `void*` to reinterpret cast from `%s*` to `%s*` is not supported in CTFE", origType.toChars(), pointee.toChars());
+                    error(e.loc, "using `void*` to reinterpret cast from `%s*` to `%s*` is not supported in CTFE", origType.toChars(), pointee.toChars());
                     result = CTFEExp.cantexp;
                     return;
                 }
@@ -6022,7 +6046,7 @@ public:
             e1 = interpretRegion(e1, istate);
             if (e1.op != EXP.null_)
             {
-                e.error("pointer cast from `%s` to `%s` is not supported at compile time", e1.type.toChars(), e.to.toChars());
+                error(e.loc, "pointer cast from `%s` to `%s` is not supported at compile time", e1.type.toChars(), e.to.toChars());
                 result = CTFEExp.cantexp;
                 return;
             }
@@ -6043,7 +6067,7 @@ public:
             SliceExp se = e1.isSliceExp();
             if (!isSafePointerCast(se.e1.type.nextOf(), e.to.nextOf()))
             {
-                e.error("array cast from `%s` to `%s` is not supported at compile time", se.e1.type.toChars(), e.to.toChars());
+                error(e.loc, "array cast from `%s` to `%s` is not supported at compile time", se.e1.type.toChars(), e.to.toChars());
                 result = CTFEExp.cantexp;
                 return;
             }
@@ -6056,7 +6080,7 @@ public:
         // types of identical size.
         if ((e.to.ty == Tsarray || e.to.ty == Tarray) && (e1.type.ty == Tsarray || e1.type.ty == Tarray) && !isSafePointerCast(e1.type.nextOf(), e.to.nextOf()))
         {
-            e.error("array cast from `%s` to `%s` is not supported at compile time", e1.type.toChars(), e.to.toChars());
+            error(e.loc, "array cast from `%s` to `%s` is not supported at compile time", e1.type.toChars(), e.to.toChars());
             result = CTFEExp.cantexp;
             return;
         }
@@ -6104,18 +6128,18 @@ public:
                     return;
                 result = scrubReturnValue(e.loc, result);
                 if (StringExp se = result.toStringExp())
-                    e.error("%s", se.toStringz().ptr);
+                    error(e.loc, "%s", se.toStringz().ptr);
                 else
-                    e.error("%s", result.toChars());
+                    error(e.loc, "%s", result.toChars());
             }
             else
-                e.error("`%s` failed", e.toChars());
+                error(e.loc, "`%s` failed", e.toChars());
             result = CTFEExp.cantexp;
             return;
         }
         else
         {
-            e.error("`%s` is not a compile time boolean expression", e1.toChars());
+            error(e.loc, "`%s` is not a compile time boolean expression", e1.toChars());
             result = CTFEExp.cantexp;
             return;
         }
@@ -6193,7 +6217,7 @@ public:
         {
             if (soe.offset == 0 && soe.var.isFuncDeclaration())
                 return;
-            e.error("cannot dereference pointer to static variable `%s` at compile time", soe.var.toChars());
+            error(e.loc, "cannot dereference pointer to static variable `%s` at compile time", soe.var.toChars());
             result = CTFEExp.cantexp;
             return;
         }
@@ -6218,9 +6242,9 @@ public:
         if (result.op != EXP.address)
         {
             if (result.op == EXP.null_)
-                e.error("dereference of null pointer `%s`", e.e1.toChars());
+                error(e.loc, "dereference of null pointer `%s`", e.e1.toChars());
             else
-                e.error("dereference of invalid pointer `%s`", result.toChars());
+                error(e.loc, "dereference of invalid pointer `%s`", result.toChars());
             result = CTFEExp.cantexp;
             return;
         }
@@ -6251,7 +6275,7 @@ public:
     {
         void notImplementedYet()
         {
-            e.error("`%s.%s` is not yet implemented at compile time", e.e1.toChars(), e.var.toChars());
+            error(e.loc, "`%s.%s` is not yet implemented at compile time", e.e1.toChars(), e.var.toChars());
             result = CTFEExp.cantexp;
             return;
         }
@@ -6280,7 +6304,7 @@ public:
         VarDeclaration v = e.var.isVarDeclaration();
         if (!v)
         {
-            e.error("CTFE internal error: `%s`", e.toChars());
+            error(e.loc, "CTFE internal error: `%s`", e.toChars());
             result = CTFEExp.cantexp;
             return;
         }
@@ -6288,9 +6312,9 @@ public:
         if (ex.op == EXP.null_)
         {
             if (ex.type.toBasetype().ty == Tclass)
-                e.error("class `%s` is `null` and cannot be dereferenced", e.e1.toChars());
+                error(e.loc, "class `%s` is `null` and cannot be dereferenced", e.e1.toChars());
             else
-                e.error("CTFE internal error: null this `%s`", e.e1.toChars());
+                error(e.loc, "CTFE internal error: null this `%s`", e.e1.toChars());
             result = CTFEExp.cantexp;
             return;
         }
@@ -6333,7 +6357,7 @@ public:
         }
         if (i == -1)
         {
-            e.error("couldn't find field `%s` of type `%s` in `%s`", v.toChars(), e.type.toChars(), se.toChars());
+            error(e.loc, "couldn't find field `%s` of type `%s` in `%s`", v.toChars(), e.type.toChars(), se.toChars());
             result = CTFEExp.cantexp;
             return;
         }
@@ -6361,7 +6385,7 @@ public:
         result = (*se.elements)[i];
         if (!result)
         {
-            e.error("internal compiler error: null field `%s`", v.toChars());
+            error(e.loc, "internal compiler error: null field `%s`", v.toChars());
             result = CTFEExp.cantexp;
             return;
         }
@@ -6370,11 +6394,11 @@ public:
             const s = vie.var.toChars();
             if (v.overlapped)
             {
-                e.error("reinterpretation through overlapped field `%s` is not allowed in CTFE", s);
+                error(e.loc, "reinterpretation through overlapped field `%s` is not allowed in CTFE", s);
                 result = CTFEExp.cantexp;
                 return;
             }
-            e.error("cannot read uninitialized variable `%s` in CTFE", s);
+            error(e.loc, "cannot read uninitialized variable `%s` in CTFE", s);
             result = CTFEExp.cantexp;
             return;
         }
@@ -6444,7 +6468,7 @@ public:
 
     override void visit(VoidInitExp e)
     {
-        e.error("CTFE internal error: trying to read uninitialized variable");
+        error(e.loc, "CTFE internal error: trying to read uninitialized variable");
         assert(0);
     }
 
@@ -6472,7 +6496,7 @@ void interpretThrow(ref Expression result, Expression exp, const ref Loc loc, In
     }
     else
     {
-        exp.error("to be thrown `%s` must be non-null", exp.toChars());
+        error(exp.loc, "to be thrown `%s` must be non-null", exp.toChars());
         result = ErrorExp.get();
     }
 }
@@ -7258,7 +7282,7 @@ private Expression foreachApplyUtf(UnionExp* pue, InterState* istate, Expression
     auto ale = str.isArrayLiteralExp();
     if (!se && !ale)
     {
-        str.error("CTFE internal error: cannot foreach `%s`", str.toChars());
+        error(str.loc, "CTFE internal error: cannot foreach `%s`", str.toChars());
         return CTFEExp.cantexp;
     }
     Expressions args = Expressions(numParams);
@@ -7410,7 +7434,7 @@ private Expression foreachApplyUtf(UnionExp* pue, InterState* istate, Expression
         }
         if (errmsg)
         {
-            deleg.error("`%.*s`", cast(int)errmsg.length, errmsg.ptr);
+            error(deleg.loc, "`%.*s`", cast(int)errmsg.length, errmsg.ptr);
             return CTFEExp.cantexp;
         }
 
@@ -7714,6 +7738,6 @@ private void removeHookTraceImpl(ref CallExp ce, ref FuncDeclaration fd)
 
     ce = ctfeEmplaceExp!CallExp(ce.loc, ctfeEmplaceExp!VarExp(ce.loc, fd, false), arguments);
 
-    if (global.params.verbose)
+    if (global.params.v.verbose)
         message("strip     %s =>\n          %s", oldCE.toChars(), ce.toChars());
 }
diff --git a/gcc/d/dmd/dmangle.d b/gcc/d/dmd/dmangle.d
index 9b7230897129..8fdb1ae835c5 100644
--- a/gcc/d/dmd/dmangle.d
+++ b/gcc/d/dmd/dmangle.d
@@ -142,6 +142,7 @@ import dmd.declaration;
 import dmd.dmodule;
 import dmd.dsymbol;
 import dmd.dtemplate;
+import dmd.errors;
 import dmd.expression;
 import dmd.func;
 import dmd.globals;
@@ -821,7 +822,7 @@ public:
             printf("\n");
         }
         if (!ti.tempdecl)
-            ti.error("is not defined");
+            error(ti.loc, "%s `%s` is not defined", ti.kind, ti.toPrettyChars);
         else
             mangleParent(ti);
 
@@ -888,7 +889,7 @@ public:
                 buf.writeByte('V');
                 if (ea.op == EXP.tuple)
                 {
-                    ea.error("sequence is not a valid template value argument");
+                    error(ea.loc, "sequence is not a valid template value argument");
                     continue;
                 }
                 // Now that we know it is not an alias, we MUST obtain a value
@@ -926,7 +927,7 @@ public:
                     }
                     if (!d.type || !d.type.deco)
                     {
-                        ti.error("forward reference of %s `%s`", d.kind(), d.toChars());
+                        error(ti.loc, "%s `%s` forward reference of %s `%s`", ti.kind, ti.toPrettyChars, d.kind(), d.toChars());
                         continue;
                     }
                 }
@@ -982,7 +983,8 @@ public:
     ////////////////////////////////////////////////////////////////////////////
     override void visit(Expression e)
     {
-        e.error("expression `%s` is not a valid template value argument", e.toChars());
+        if (!e.type.isTypeError())
+            error(e.loc, "expression `%s` is not a valid template value argument", e.toChars());
     }
 
     override void visit(IntegerExp e)
@@ -1040,7 +1042,7 @@ public:
             {
                 dchar c;
                 if (const s = utf_decodeWchar(slice, u, c))
-                    e.error("%.*s", cast(int)s.length, s.ptr);
+                    error(e.loc, "%.*s", cast(int)s.length, s.ptr);
                 else
                     tmp.writeUTF8(c);
             }
@@ -1054,7 +1056,7 @@ public:
             foreach (c; slice)
             {
                 if (!utf_isValidDchar(c))
-                    e.error("invalid UCS-32 char \\U%08x", c);
+                    error(e.loc, "invalid UCS-32 char \\U%08x", c);
                 else
                     tmp.writeUTF8(c);
             }
@@ -1300,7 +1302,7 @@ extern (D) void toBuffer(ref OutBuffer buf, const(char)[] id, Dsymbol s)
 {
     const len = id.length;
     if (buf.length + len >= 8 * 1024 * 1024) // 8 megs ought be enough for anyone
-        s.error("excessive length %llu for symbol, possible recursive expansion?", cast(ulong)(buf.length + len));
+        error(s.loc, "%s `%s` excessive length %llu for symbol, possible recursive expansion?", s.kind, s.toPrettyChars, cast(ulong)(buf.length + len));
     else
     {
         buf.print(len);
@@ -1422,7 +1424,7 @@ extern (D) const(char)[] externallyMangledIdentifier(Declaration d)
           (d.isVarDeclaration() && d.isDataseg() && d.storage_class & STC.extern_))))
     {
         if (linkage != LINK.d && d.localNum)
-            d.error("the same declaration cannot be in multiple scopes with non-D linkage");
+            error(d.loc, "%s `%s` the same declaration cannot be in multiple scopes with non-D linkage", d.kind, d.toPrettyChars);
 
         final switch (linkage)
         {
@@ -1438,7 +1440,7 @@ extern (D) const(char)[] externallyMangledIdentifier(Declaration d)
                 return p.toDString();
             }
             case LINK.default_:
-                d.error("forward declaration");
+                error(d.loc, "%s `%s` forward declaration", d.kind, d.toPrettyChars);
                 return d.ident.toString();
             case LINK.system:
                 assert(0);
diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index eb68b31edeb0..202630304be0 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/dmd/dmodule.d
@@ -468,7 +468,8 @@ extern (C++) final class Module : Package
                  !FileName.equalsExt(srcfilename, dd_ext))
         {
 
-            error("source file name '%.*s' must have .%.*s extension",
+            error(loc, "%s `%s` source file name '%.*s' must have .%.*s extension",
+                  kind, toPrettyChars,
                   cast(int)srcfilename.length, srcfilename.ptr,
                   cast(int)mars_ext.length, mars_ext.ptr);
             fatal();
@@ -528,7 +529,7 @@ extern (C++) final class Module : Package
 
         if (!m.read(loc))
             return null;
-        if (global.params.verbose)
+        if (global.params.v.verbose)
         {
             OutBuffer buf;
             foreach (pid; packages)
@@ -593,7 +594,8 @@ extern (C++) final class Module : Package
         }
         if (FileName.equals(docfilename, srcfile.toString()))
         {
-            error("source file and output file have same name '%s'", srcfile.toChars());
+            error(loc, "%s `%s` source file and output file have same name '%s'",
+                kind, toPrettyChars, srcfile.toChars());
             fatal();
         }
         return FileName(docfilename);
@@ -793,7 +795,7 @@ extern (C++) final class Module : Package
         {
             const bool doUnittests = global.params.useUnitTests || global.params.ddoc.doOutput || global.params.dihdr.doOutput;
             scope p = new Parser!AST(this, buf, cast(bool) docfile, global.errorSink, &global.compileEnv, doUnittests);
-            p.transitionIn = global.params.vin;
+            p.transitionIn = global.params.v.vin;
             p.nextToken();
             p.parseModuleDeclaration();
             md = p.md;
@@ -852,7 +854,7 @@ extern (C++) final class Module : Package
             /* Check to see if module name is a valid identifier
              */
             if (!Identifier.isValidIdentifier(this.ident.toChars()))
-                error("has non-identifier characters in filename, use module declaration instead");
+                error(loc, "%s `%s` has non-identifier characters in filename, use module declaration instead", kind, toPrettyChars);
         }
         // Insert module into the symbol table
         Dsymbol s = this;
@@ -905,11 +907,11 @@ extern (C++) final class Module : Package
             if (Module mprev = prev.isModule())
             {
                 if (!FileName.equals(srcname, mprev.srcfile.toChars()))
-                    error(loc, "from file %s conflicts with another module %s from file %s", srcname, mprev.toChars(), mprev.srcfile.toChars());
+                    error(loc, "%s `%s` from file %s conflicts with another module %s from file %s", kind, toPrettyChars, srcname, mprev.toChars(), mprev.srcfile.toChars());
                 else if (isRoot() && mprev.isRoot())
-                    error(loc, "from file %s is specified twice on the command line", srcname);
+                    error(loc, "%s `%s` from file %s is specified twice on the command line", kind, toPrettyChars, srcname);
                 else
-                    error(loc, "from file %s must be imported with 'import %s;'", srcname, toPrettyChars());
+                    error(loc, "%s `%s` from file %s must be imported with 'import %s;'", kind, toPrettyChars, srcname, toPrettyChars());
                 // https://issues.dlang.org/show_bug.cgi?id=14446
                 // Return previously parsed module to avoid AST duplication ICE.
                 return mprev;
@@ -920,7 +922,7 @@ extern (C++) final class Module : Package
                 if (isPackageFile)
                     amodules.push(this); // Add to global array of all modules
                 else
-                    error(md ? md.loc : loc, "from file %s conflicts with package name %s", srcname, pkg.toChars());
+                    error(md ? md.loc : loc, "%s `%s` from file %s conflicts with package name %s", kind, toPrettyChars, srcname, pkg.toChars());
             }
             else
                 assert(global.errors);
@@ -941,7 +943,7 @@ extern (C++) final class Module : Package
             return; // already done
         if (filetype == FileType.ddoc)
         {
-            error("is a Ddoc file, cannot import it");
+            error(loc, "%s `%s` is a Ddoc file, cannot import it", kind, toPrettyChars);
             return;
         }
 
@@ -1026,11 +1028,11 @@ extern (C++) final class Module : Package
                 const slice = se.peekString();
                 if (slice.length)
                 {
-                    deprecation(loc, "is deprecated - %.*s", cast(int)slice.length, slice.ptr);
+                    deprecation(loc, "%s `%s` is deprecated - %.*s", kind, toPrettyChars, cast(int)slice.length, slice.ptr);
                     return;
                 }
             }
-            deprecation(loc, "is deprecated");
+            deprecation(loc, "%s `%s` is deprecated", kind, toPrettyChars);
         }
     }
 
@@ -1479,7 +1481,8 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod)
 
         if (buf.length & 3)
         {
-            mod.error("odd length of UTF-32 char source %llu", cast(ulong) buf.length);
+            .error(mod.loc, "%s `%s` odd length of UTF-32 char source %llu",
+                mod.kind, mod.toPrettyChars, cast(ulong) buf.length);
             return null;
         }
 
@@ -1495,7 +1498,7 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod)
             {
                 if (u > 0x10FFFF)
                 {
-                    mod.error("UTF-32 value %08x greater than 0x10FFFF", u);
+                    .error(mod.loc, "%s `%s` UTF-32 value %08x greater than 0x10FFFF", mod.kind, mod.toPrettyChars, u);
                     return null;
                 }
                 dbuf.writeUTF8(u);
@@ -1525,7 +1528,7 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod)
 
         if (buf.length & 1)
         {
-            mod.error("odd length of UTF-16 char source %llu", cast(ulong) buf.length);
+            .error(mod.loc, "%s `%s` odd length of UTF-16 char source %llu", mod.kind, mod.toPrettyChars, cast(ulong) buf.length);
             return null;
         }
 
@@ -1545,13 +1548,13 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod)
                     i++;
                     if (i >= eBuf.length)
                     {
-                        mod.error("surrogate UTF-16 high value %04x at end of file", u);
+                        .error(mod.loc, "%s `%s` surrogate UTF-16 high value %04x at end of file", mod.kind, mod.toPrettyChars, u);
                         return null;
                     }
                     const u2 = readNext(&eBuf[i]);
                     if (u2 < 0xDC00 || 0xE000 <= u2)
                     {
-                        mod.error("surrogate UTF-16 low value %04x out of range", u2);
+                        .error(mod.loc, "%s `%s` surrogate UTF-16 low value %04x out of range", mod.kind, mod.toPrettyChars, u2);
                         return null;
                     }
                     u = (u - 0xD7C0) << 10;
@@ -1559,12 +1562,12 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod)
                 }
                 else if (u >= 0xDC00 && u <= 0xDFFF)
                 {
-                    mod.error("unpaired surrogate UTF-16 value %04x", u);
+                    .error(mod.loc, "%s `%s` unpaired surrogate UTF-16 value %04x", mod.kind, mod.toPrettyChars, u);
                     return null;
                 }
                 else if (u == 0xFFFE || u == 0xFFFF)
                 {
-                    mod.error("illegal UTF-16 value %04x", u);
+                    .error(mod.loc, "%s `%s` illegal UTF-16 value %04x", mod.kind, mod.toPrettyChars, u);
                     return null;
                 }
                 dbuf.writeUTF8(u);
@@ -1623,7 +1626,8 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod)
     // It's UTF-8
     if (buf[0] >= 0x80)
     {
-        mod.error("source file must start with BOM or ASCII character, not \\x%02X", buf[0]);
+        auto loc = mod.getLoc();
+        .error(loc, "%s `%s` source file must start with BOM or ASCII character, not \\x%02X", mod.kind, mod.toPrettyChars, buf[0]);
         return null;
     }
 
diff --git a/gcc/d/dmd/doc.d b/gcc/d/dmd/doc.d
index 5488d5a0008f..b1a4c2fe504b 100644
--- a/gcc/d/dmd/doc.d
+++ b/gcc/d/dmd/doc.d
@@ -438,7 +438,7 @@ void gendocfile(Module m, const char[] ddoctext, const char* datetime, ErrorSink
         if (!loc.filename)
             loc.filename = srcfilename.ptr;
 
-        size_t commentlen = m.comment ? strlen(cast(char*)m.comment) : 0;
+        size_t commentlen = strlen(cast(char*)m.comment);
         Dsymbols a;
         // https://issues.dlang.org/show_bug.cgi?id=9764
         // Don't push m in a, to prevent emphasize ddoc file name.
diff --git a/gcc/d/dmd/dstruct.d b/gcc/d/dmd/dstruct.d
index a131a8a721c4..56aad3eece3b 100644
--- a/gcc/d/dmd/dstruct.d
+++ b/gcc/d/dmd/dstruct.d
@@ -273,7 +273,7 @@ extern (C++) class StructDeclaration : AggregateDeclaration
         {
             // .stringof is always defined (but may be hidden by some other symbol)
             if(ident != Id.stringof && !(flags & IgnoreErrors) && semanticRun < PASS.semanticdone)
-                error("is forward referenced when looking for `%s`", ident.toChars());
+                .error(loc, "%s `%s` is forward referenced when looking for `%s`", kind, toPrettyChars, ident.toChars());
             return null;
         }
 
diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d
index c9a2c92194b8..1f4a4664c3ef 100644
--- a/gcc/d/dmd/dsymbol.d
+++ b/gcc/d/dmd/dsymbol.d
@@ -375,79 +375,6 @@ extern (C++) class Dsymbol : ASTNode
         return '`' ~ cstr.toDString() ~ "`\0";
     }
 
-    static if (__VERSION__ < 2092)
-    {
-        final void error(const ref Loc loc, const(char)* format, ...)
-        {
-            va_list ap;
-            va_start(ap, format);
-            .verrorReport(loc, format, ap, ErrorKind.error, kind(), prettyFormatHelper().ptr);
-            va_end(ap);
-        }
-
-        final void error(const(char)* format, ...)
-        {
-            va_list ap;
-            va_start(ap, format);
-            const loc = getLoc();
-            .verrorReport(loc, format, ap, ErrorKind.error, kind(), prettyFormatHelper().ptr);
-            va_end(ap);
-        }
-
-        final void deprecation(const ref Loc loc, const(char)* format, ...)
-        {
-            va_list ap;
-            va_start(ap, format);
-            .verrorReport(loc, format, ap, ErrorKind.deprecation, kind(), prettyFormatHelper().ptr);
-            va_end(ap);
-        }
-
-        final void deprecation(const(char)* format, ...)
-        {
-            va_list ap;
-            va_start(ap, format);
-            const loc = getLoc();
-            .verrorReport(loc, format, ap, ErrorKind.deprecation, kind(), prettyFormatHelper().ptr);
-            va_end(ap);
-        }
-    }
-    else
-    {
-        pragma(printf) final void error(const ref Loc loc, const(char)* format, ...)
-        {
-            va_list ap;
-            va_start(ap, format);
-            .verrorReport(loc, format, ap, ErrorKind.error, kind(), prettyFormatHelper().ptr);
-            va_end(ap);
-        }
-
-        pragma(printf) final void error(const(char)* format, ...)
-        {
-            va_list ap;
-            va_start(ap, format);
-            const loc = getLoc();
-            .verrorReport(loc, format, ap, ErrorKind.error, kind(), prettyFormatHelper().ptr);
-            va_end(ap);
-        }
-
-        pragma(printf) final void deprecation(const ref Loc loc, const(char)* format, ...)
-        {
-            va_list ap;
-            va_start(ap, format);
-            .verrorReport(loc, format, ap, ErrorKind.deprecation, kind(), prettyFormatHelper().ptr);
-            va_end(ap);
-        }
-
-        pragma(printf) final void deprecation(const(char)* format, ...)
-        {
-            va_list ap;
-            va_start(ap, format);
-            const loc = getLoc();
-            .verrorReport(loc, format, ap, ErrorKind.deprecation, kind(), prettyFormatHelper().ptr);
-            va_end(ap);
-        }
-    }
-
     final bool checkDeprecated(const ref Loc loc, Scope* sc)
     {
         if (global.params.useDeprecated == DiagnosticReporting.off)
@@ -470,9 +397,9 @@ extern (C++) class Dsymbol : ASTNode
                 break;
         }
         if (message)
-            deprecation(loc, "is deprecated - %s", message);
+            deprecation(loc, "%s `%s` is deprecated - %s", kind, toPrettyChars, message);
         else
-            deprecation(loc, "is deprecated");
+            deprecation(loc, "%s `%s` is deprecated", kind, toPrettyChars);
 
         if (auto ti = sc.parent ? sc.parent.isInstantiated() : null)
             ti.printInstantiationTrace(Classification.deprecation);
@@ -886,7 +813,7 @@ extern (C++) class Dsymbol : ASTNode
             if (ident == Id.__sizeof ||
                 !(sc && sc.flags & SCOPE.Cfile) && (ident == Id.__xalignof || ident == Id._mangleof))
             {
-                error("`.%s` property cannot be redefined", ident.toChars());
+                .error(loc, "%s `%s` `.%s` property cannot be redefined", kind, toPrettyChars, ident.toChars());
                 errors = true;
             }
         }
@@ -1026,7 +953,7 @@ extern (C++) class Dsymbol : ASTNode
      */
     uinteger_t size(const ref Loc loc)
     {
-        error("symbol `%s` has no size", toChars());
+        .error(loc, "%s `%s` symbol `%s` has no size", kind, toPrettyChars, toChars());
         return SIZE_INVALID;
     }
 
@@ -1776,7 +1703,7 @@ public:
         }
         else
         {
-            s1.error(s1.loc, "conflicts with %s `%s` at %s", s2.kind(), s2.toPrettyChars(), s2.locToChars());
+            .error(s1.loc, "%s `%s` conflicts with %s `%s` at %s", s1.kind, s1.toPrettyChars, s2.kind(), s2.toPrettyChars(), s2.locToChars());
         }
     }
 
@@ -2140,7 +2067,7 @@ extern (C++) final class ArrayScopeSymbol : ScopeDsymbol
                      */
                     if (exp.op == EXP.array && (cast(ArrayExp)exp).arguments.length != 1)
                     {
-                        exp.error("`%s` only defines opDollar for one dimension", ad.toChars());
+                        error(exp.loc, "`%s` only defines opDollar for one dimension", ad.toChars());
                         return null;
                     }
                     Declaration d = s.isDeclaration();
@@ -2149,7 +2076,7 @@ extern (C++) final class ArrayScopeSymbol : ScopeDsymbol
                 }
                 e = e.expressionSemantic(sc);
                 if (!e.type)
-                    exp.error("`%s` has no value", e.toChars());
+                    error(exp.loc, "`%s` has no value", e.toChars());
                 t = e.type.toBasetype();
                 if (t && t.ty == Tfunction)
                     e = new CallExp(e.loc, e);
diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h
index 96fa8fdd6400..027897532d1f 100644
--- a/gcc/d/dmd/dsymbol.h
+++ b/gcc/d/dmd/dsymbol.h
@@ -205,10 +205,6 @@ public:
     const char *locToChars();
     bool equals(const RootObject * const o) const override;
     bool isAnonymous() const;
-    void error(const Loc &loc, const char *format, ...);
-    void error(const char *format, ...);
-    void deprecation(const Loc &loc, const char *format, ...);
-    void deprecation(const char *format, ...);
     bool checkDeprecated(const Loc &loc, Scope *sc);
     Module *getModule();
     bool isCsymbol();
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index ebdd3a8566d9..65c07952e00a 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -205,7 +205,7 @@ const(char)* getMessage(DeprecatedDeclaration dd)
         if (auto se = dd.msg.toStringExp())
             dd.msgstr = se.toStringz().ptr;
         else
-            dd.msg.error("compile time constant expected, not `%s`", dd.msg.toChars());
+            error(dd.msg.loc, "compile time constant expected, not `%s`", dd.msg.toChars());
     }
     return dd.msgstr;
 }
@@ -289,7 +289,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
 
     override void visit(Dsymbol dsym)
     {
-        dsym.error("%p has no semantic routine", dsym);
+        .error(dsym.loc, "%s `%s` %p has no semantic routine", dsym.kind, dsym.toPrettyChars, dsym);
     }
 
     override void visit(ScopeDsymbol) { }
@@ -467,7 +467,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         }
 
         if (dsym.storage_class & STC.extern_ && dsym._init)
-            dsym.error("extern symbols cannot have initializers");
+            .error(dsym.loc, "%s `%s` extern symbols cannot have initializers", dsym.kind, dsym.toPrettyChars);
 
         AggregateDeclaration ad = dsym.isThis();
         if (ad)
@@ -553,16 +553,17 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         {
             if (inferred)
             {
-                dsym.error("- type `%s` is inferred from initializer `%s`, and variables cannot be of type `void`", dsym.type.toChars(), dsym._init.toChars());
+                .error(dsym.loc, "%s `%s` - type `%s` is inferred from initializer `%s`, and variables cannot be of type `void`",
+                    dsym.kind, dsym.toPrettyChars, dsym.type.toChars(), toChars(dsym._init));
             }
             else
-                dsym.error("- variables cannot be of type `void`");
+                .error(dsym.loc, "%s `%s` - variables cannot be of type `void`", dsym.kind, dsym.toPrettyChars);
             dsym.type = Type.terror;
             tb = dsym.type;
         }
         if (tb.ty == Tfunction)
         {
-            dsym.error("cannot be declared to be a function");
+            .error(dsym.loc, "%s `%s` cannot be declared to be a function", dsym.kind, dsym.toPrettyChars);
             dsym.type = Type.terror;
             tb = dsym.type;
         }
@@ -572,7 +573,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             // or when the variable is defined externally
             if (!ts.sym.members && !(dsym.storage_class & (STC.ref_ | STC.extern_)))
             {
-                dsym.error("- no definition of struct `%s`", ts.toChars());
+                .error(dsym.loc, "%s `%s` - no definition of struct `%s`", dsym.kind, dsym.toPrettyChars, ts.toChars());
 
                 // Explain why the definition is required when it's part of another type
                 if (!dsym.type.isTypeStruct())
@@ -590,7 +591,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             }
         }
         if ((dsym.storage_class & STC.auto_) && !inferred)
-            dsym.error("- storage class `auto` has no effect if type is not inferred, did you mean `scope`?");
+            .error(dsym.loc, "%s `%s` - storage class `auto` has no effect if type is not inferred, did you mean `scope`?", dsym.kind, dsym.toPrettyChars);
 
         if (auto tt = tb.isTypeTuple())
         {
@@ -762,12 +763,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         if (StorageClass stc = dsym.storage_class & (STC.synchronized_ | STC.override_ | STC.abstract_ | STC.final_))
         {
             if (stc == STC.final_)
-                dsym.error("cannot be `final`, perhaps you meant `const`?");
+                .error(dsym.loc, "%s `%s` cannot be `final`, perhaps you meant `const`?", dsym.kind, dsym.toPrettyChars);
             else
             {
                 OutBuffer buf;
                 stcToBuffer(buf, stc);
-                dsym.error("cannot be `%s`", buf.peekChars());
+                .error(dsym.loc, "%s `%s` cannot be `%s`", dsym.kind, dsym.toPrettyChars, buf.peekChars());
             }
             dsym.storage_class &= ~stc; // strip off
         }
@@ -784,7 +785,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             {
                 OutBuffer buf;
                 stcToBuffer(buf, stc);
-                dsym.error("cannot be `scope` and `%s`", buf.peekChars());
+                .error(dsym.loc, "%s `%s` cannot be `scope` and `%s`", dsym.kind, dsym.toPrettyChars, buf.peekChars());
             }
             else if (dsym.isMember())
             {
@@ -809,7 +810,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             AggregateDeclaration aad = parent.isAggregateDeclaration();
             if (aad)
             {
-                if (global.params.vfield && dsym.storage_class & (STC.const_ | STC.immutable_) && dsym._init && !dsym._init.isVoidInitializer())
+                if (global.params.v.field && dsym.storage_class & (STC.const_ | STC.immutable_) && dsym._init && !dsym._init.isVoidInitializer())
                 {
                     const(char)* s = (dsym.storage_class & STC.immutable_) ? "immutable" : "const";
                     message(dsym.loc, "`%s.%s` is `%s` field", ad.toPrettyChars(), dsym.toChars(), s);
@@ -850,7 +851,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 AggregateDeclaration ad2 = ti.tempdecl.isMember();
                 if (ad2 && dsym.storage_class != STC.undefined_)
                 {
-                    dsym.error("- cannot use template to add field to aggregate `%s`", ad2.toChars());
+                    .error(dsym.loc, "%s `%s` - cannot use template to add field to aggregate `%s`", dsym.kind, dsym.toPrettyChars, ad2.toChars());
                 }
             }
         }
@@ -873,14 +874,14 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
 
         if ((dsym.storage_class & (STC.ref_ | STC.parameter | STC.foreach_ | STC.temp | STC.result)) == STC.ref_ && dsym.ident != Id.This)
         {
-            dsym.error("- only parameters, functions and `foreach` declarations can be `ref`");
+            .error(dsym.loc, "%s `%s` - only parameters, functions and `foreach` declarations can be `ref`", dsym.kind, dsym.toPrettyChars);
         }
 
         if (dsym.type.hasWild())
         {
             if (dsym.storage_class & (STC.static_ | STC.extern_ | STC.gshared | STC.manifest | STC.field) || dsym.isDataseg())
             {
-                dsym.error("- only parameters or stack-based variables can be `inout`");
+                .error(dsym.loc, "%s `%s` - only parameters or stack-based variables can be `inout`", dsym.kind, dsym.toPrettyChars);
             }
             FuncDeclaration func = sc.func;
             if (func)
@@ -898,7 +899,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 }
                 if (!isWild)
                 {
-                    dsym.error("- `inout` variables can only be declared inside `inout` functions");
+                    .error(dsym.loc, "%s `%s` - `inout` variables can only be declared inside `inout` functions", dsym.kind, dsym.toPrettyChars);
                 }
             }
         }
@@ -918,7 +919,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 {
                 }
                 else
-                    dsym.error("- default construction is disabled for type `%s`", dsym.type.toChars());
+                    .error(dsym.loc, "%s `%s` - default construction is disabled for type `%s`", dsym.kind, dsym.toPrettyChars, dsym.type.toChars());
             }
         }
 
@@ -927,7 +928,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         {
             if (dsym.storage_class & (STC.field | STC.out_ | STC.ref_ | STC.static_ | STC.manifest | STC.gshared) || !fd)
             {
-                dsym.error("globals, statics, fields, manifest constants, ref and out parameters cannot be `scope`");
+                .error(dsym.loc, "%s `%s` globals, statics, fields, manifest constants, ref and out parameters cannot be `scope`", dsym.kind, dsym.toPrettyChars);
             }
 
             // @@@DEPRECATED_2.097@@@  https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
@@ -936,7 +937,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             if (!(dsym.storage_class & STC.scope_))
             {
                 if (!(dsym.storage_class & STC.parameter) && dsym.ident != Id.withSym)
-                    dsym.error("reference to `scope class` must be `scope`");
+                    .error(dsym.loc, "%s `%s` reference to `scope class` must be `scope`", dsym.kind, dsym.toPrettyChars);
             }
         }
 
@@ -973,13 +974,13 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         if (dsym._init)
         { } // remember we had an explicit initializer
         else if (dsym.storage_class & STC.manifest)
-            dsym.error("- manifest constants must have initializers");
+            .error(dsym.loc, "%s `%s` - manifest constants must have initializers", dsym.kind, dsym.toPrettyChars);
 
         // Don't allow non-extern, non-__gshared variables to be interfaced with C++
         if (dsym._linkage == LINK.cpp && !(dsym.storage_class & (STC.ctfe | STC.extern_ | STC.gshared)) && dsym.isDataseg())
         {
             const char* p = (dsym.storage_class & STC.shared_) ? "shared" : "static";
-            dsym.error("cannot have `extern(C++)` linkage because it is `%s`", p);
+            .error(dsym.loc, "%s `%s` cannot have `extern(C++)` linkage because it is `%s`", dsym.kind, dsym.toPrettyChars, p);
             errorSupplemental(dsym.loc, "perhaps declare it as `__gshared` instead");
             dsym.errors = true;
         }
@@ -1001,7 +1002,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
 
             //printf("Providing default initializer for '%s'\n", dsym.toChars());
             if (sz == SIZE_INVALID && dsym.type.ty != Terror)
-                dsym.error("- size of type `%s` is invalid", dsym.type.toChars());
+                .error(dsym.loc, "%s `%s` - size of type `%s` is invalid", dsym.kind, dsym.toPrettyChars, dsym.type.toChars());
 
             Type tv = dsym.type;
             while (tv.ty == Tsarray)    // Don't skip Tenum
@@ -1036,7 +1037,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             }
             if (dsym.type.baseElemOf().ty == Tvoid)
             {
-                dsym.error("of type `%s` does not have a default initializer", dsym.type.toChars());
+                .error(dsym.loc, "%s `%s` of type `%s` does not have a default initializer", dsym.kind, dsym.toPrettyChars, dsym.type.toChars());
             }
             else if (auto e = dsym.type.defaultInit(dsym.loc))
             {
@@ -1057,7 +1058,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 dsym._init.isVoidInitializer() &&
                 !(dsym.storage_class & STC.field))
             {
-                dsym.error("- incomplete array type must have initializer");
+                .error(dsym.loc, "%s `%s` - incomplete array type must have initializer", dsym.kind, dsym.toPrettyChars);
             }
 
             ExpInitializer ei = dsym._init.isExpInitializer();
@@ -1089,7 +1090,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                             e = dsym._init.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0);
                             if (!e)
                             {
-                                dsym.error("is not a static and cannot have static initializer");
+                                .error(dsym.loc, "%s `%s` is not a static and cannot have static initializer", dsym.kind, dsym.toPrettyChars);
                                 e = ErrorExp.get();
                             }
                         }
@@ -1249,7 +1250,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                             {
                                 // The only allowable initializer is a (non-copy) constructor
                                 if (ei.exp.isLvalue())
-                                    dsym.error("of type struct `%s` uses `this(this)`, which is not allowed in static initialization", tb2.toChars());
+                                    .error(dsym.loc, "%s `%s` of type struct `%s` uses `this(this)`, which is not allowed in static initialization", dsym.kind, dsym.toPrettyChars, tb2.toChars());
                             }
                         }
                     }
@@ -1286,7 +1287,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             {
                 // currently disabled because of std.stdio.stdin, stdout and stderr
                 if (dsym.isDataseg() && !(dsym.storage_class & STC.extern_))
-                    dsym.error("static storage variables cannot have destructors");
+                    .error(dsym.loc, "%s `%s` static storage variables cannot have destructors", dsym.kind, dsym.toPrettyChars);
             }
         }
 
@@ -1319,11 +1320,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             return;
 
         if (!(global.params.bitfields || sc.flags & SCOPE.Cfile))
-            dsym.error("use -preview=bitfields for bitfield support");
+            .error(dsym.loc, "%s `%s` use -preview=bitfields for bitfield support", dsym.kind, dsym.toPrettyChars);
 
         if (!dsym.parent.isStructDeclaration() && !dsym.parent.isClassDeclaration())
         {
-            dsym.error("- bit-field must be member of struct, union, or class");
+            .error(dsym.loc, "%s `%s` - bit-field must be member of struct, union, or class", dsym.kind, dsym.toPrettyChars);
         }
 
         sc = sc.startCTFE();
@@ -1333,18 +1334,18 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         if (!dsym.type.isintegral())
         {
             // C11 6.7.2.1-5
-            width.error("bit-field type `%s` is not an integer type", dsym.type.toChars());
+            error(width.loc, "bit-field type `%s` is not an integer type", dsym.type.toChars());
             dsym.errors = true;
         }
         if (!width.isIntegerExp())
         {
-            width.error("bit-field width `%s` is not an integer constant", dsym.width.toChars());
+            error(width.loc, "bit-field width `%s` is not an integer constant", dsym.width.toChars());
             dsym.errors = true;
         }
         const uwidth = width.toInteger(); // uwidth is unsigned
         if (uwidth == 0 && !dsym.isAnonymous())
         {
-            width.error("bit-field `%s` has zero width", dsym.toChars());
+            error(width.loc, "bit-field `%s` has zero width", dsym.toChars());
             dsym.errors = true;
         }
         const sz = dsym.type.size();
@@ -1353,7 +1354,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         const max_width = sz * 8;
         if (uwidth > max_width)
         {
-            width.error("width `%lld` of bit-field `%s` does not fit in type `%s`", cast(long)uwidth, dsym.toChars(), dsym.type.toChars());
+            error(width.loc, "width `%lld` of bit-field `%s` does not fit in type `%s`", cast(long)uwidth, dsym.toChars(), dsym.type.toChars());
             dsym.errors = true;
         }
         dsym.fieldWidth = cast(uint)uwidth;
@@ -1453,7 +1454,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                     import dmd.access : symbolIsVisible;
                     if (!symbolIsVisible(sc, sym) && !sym.errors)
                     {
-                        imp.mod.error(imp.loc, "member `%s` is not visible from module `%s`",
+                        .error(imp.loc, "%s `%s` member `%s` is not visible from module `%s`", imp.mod.kind, imp.mod.toPrettyChars,
                             imp.names[i].toChars(), sc._module.toChars());
                         sym.errors = true;
                     }
@@ -1468,9 +1469,9 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                     // https://issues.dlang.org/show_bug.cgi?id=23908
                     // Don't suggest symbols from the importer's module
                     if (s && s.parent != importer)
-                        imp.mod.error(imp.loc, "import `%s` not found, did you mean %s `%s`?", imp.names[i].toChars(), s.kind(), s.toPrettyChars());
+                        .error(imp.loc, "%s `%s` import `%s` not found, did you mean %s `%s`?", imp.mod.kind, imp.mod.toPrettyChars, imp.names[i].toChars(), s.kind(), s.toPrettyChars());
                     else
-                        imp.mod.error(imp.loc, "import `%s` not found", imp.names[i].toChars());
+                        .error(imp.loc, "%s `%s` import `%s` not found", imp.mod.kind, imp.mod.toPrettyChars, imp.names[i].toChars());
                     ad.type = Type.terror;
                 }
             }
@@ -1621,12 +1622,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             e = se;
             if (!se.len)
             {
-                pd.error("- zero-length string not allowed for mangled name");
+                .error(pd.loc, "%s `%s` - zero-length string not allowed for mangled name", pd.kind, pd.toPrettyChars);
                 return null;
             }
             if (se.sz != 1)
             {
-                pd.error("- mangled name characters can only be of type `char`");
+                .error(pd.loc, "%s `%s` - mangled name characters can only be of type `char`", pd.kind, pd.toPrettyChars);
                 return null;
             }
             version (all)
@@ -1649,18 +1650,18 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                         }
                         else
                         {
-                            pd.error("char 0x%02x not allowed in mangled name", c);
+                            .error(pd.loc, "%s `%s` char 0x%02x not allowed in mangled name", pd.kind, pd.toPrettyChars, c);
                             break;
                         }
                     }
                     if (const msg = utf_decodeChar(slice, i, c))
                     {
-                        pd.error("%.*s", cast(int)msg.length, msg.ptr);
+                        .error(pd.loc, "%s `%s` %.*s", pd.kind, pd.toPrettyChars, cast(int)msg.length, msg.ptr);
                         break;
                     }
                     if (!isUniAlpha(c))
                     {
-                        pd.error("char `0x%04x` not allowed in mangled name", c);
+                        .error(pd.loc, "%s `%s` char `0x%04x` not allowed in mangled name", pd.kind, pd.toPrettyChars, c);
                         break;
                     }
                 }
@@ -1712,7 +1713,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                             e = se;
                         }
                         else
-                            e.error("must be a string");
+                            error(e.loc, "must be a string");
                     }
                     if (agg)
                     {
@@ -1729,7 +1730,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 }
                 else if (auto td = s.isTemplateDeclaration())
                 {
-                    pd.error("cannot apply to a template declaration");
+                    .error(pd.loc, "%s `%s` cannot apply to a template declaration", pd.kind, pd.toPrettyChars);
                     errorSupplemental(pd.loc, "use `template Class(Args...){ pragma(mangle, \"other_name\") class Class {} }`");
                 }
                 else if (auto se = verifyMangleString((*pd.args)[0]))
@@ -1737,7 +1738,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                     const name = (cast(const(char)[])se.peekData()).xarraydup;
                     uint cnt = setMangleOverride(s, name);
                     if (cnt > 1)
-                        pd.error("can only apply to a single declaration");
+                        .error(pd.loc, "%s `%s` can only apply to a single declaration", pd.kind, pd.toPrettyChars);
                 }
             }
         }
@@ -1746,7 +1747,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         {
             if (pd.decl)
             {
-                pd.error("is missing a terminating `;`");
+                .error(pd.loc, "%s `%s` is missing a terminating `;`", pd.kind, pd.toPrettyChars);
                 declarations();
                 // do them anyway, to avoid segfaults.
             }
@@ -1759,14 +1760,14 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             if (pd.ident == Id.linkerDirective)
             {
                 if (!pd.args || pd.args.length != 1)
-                    pd.error("one string argument expected for pragma(linkerDirective)");
+                    .error(pd.loc, "%s `%s` one string argument expected for pragma(linkerDirective)", pd.kind, pd.toPrettyChars);
                 else
                 {
                     auto se = semanticString(sc, (*pd.args)[0], "linker directive");
                     if (!se)
                         return noDeclarations();
                     (*pd.args)[0] = se;
-                    if (global.params.verbose)
+                    if (global.params.v.verbose)
                         message("linkopt   %.*s", cast(int)se.len, se.peekString().ptr);
                 }
                 return noDeclarations();
@@ -1785,7 +1786,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         else if (pd.ident == Id.lib)
         {
             if (!pd.args || pd.args.length != 1)
-                pd.error("string expected for library name");
+                .error(pd.loc, "%s `%s` string expected for library name", pd.kind, pd.toPrettyChars);
             else
             {
                 auto se = semanticString(sc, (*pd.args)[0], "library name");
@@ -1794,7 +1795,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 (*pd.args)[0] = se;
 
                 auto name = se.peekString().xarraydup;
-                if (global.params.verbose)
+                if (global.params.v.verbose)
                     message("library   %s", name.ptr);
                 if (global.params.moduleDeps.buffer && !global.params.moduleDeps.name)
                 {
@@ -1829,8 +1830,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 pd.args = new Expressions();
             if (pd.args.length == 0 || pd.args.length > 2)
             {
-                pd.error(pd.args.length == 0 ? "- string expected for mangled name"
-                                          : "expected 1 or 2 arguments");
+                .error(pd.loc, pd.args.length == 0 ? "%s `%s` - string expected for mangled name"
+                                          : "%s `%s` expected 1 or 2 arguments", pd.kind, pd.toPrettyChars);
                 pd.args.setDim(1);
                 (*pd.args)[0] = ErrorExp.get(); // error recovery
             }
@@ -1839,7 +1840,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         else if (pd.ident == Id.crt_constructor || pd.ident == Id.crt_destructor)
         {
             if (pd.args && pd.args.length != 0)
-                pd.error("takes no argument");
+                .error(pd.loc, "%s `%s` takes no argument", pd.kind, pd.toPrettyChars);
             else
             {
                 immutable isCtor = pd.ident == Id.crt_constructor;
@@ -1872,14 +1873,14 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 }
 
                 if (recurse(pd, isCtor) > 1)
-                    pd.error("can only apply to a single declaration");
+                    .error(pd.loc, "%s `%s` can only apply to a single declaration", pd.kind, pd.toPrettyChars);
             }
             return declarations();
         }
         else if (pd.ident == Id.printf || pd.ident == Id.scanf)
         {
             if (pd.args && pd.args.length != 0)
-                pd.error("takes no argument");
+                .error(pd.loc, "%s `%s` takes no argument", pd.kind, pd.toPrettyChars);
             return declarations();
         }
         else if (!global.params.ignoreUnsupportedPragmas)
@@ -1888,7 +1889,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             return declarations();
         }
 
-        if (!global.params.verbose)
+        if (!global.params.v.verbose)
             return declarations();
 
         /* Print unrecognized pragmas
@@ -1944,7 +1945,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         const bool doUnittests = global.params.useUnitTests || global.params.ddoc.doOutput || global.params.dihdr.doOutput;
         auto loc = adjustLocForMixin(str, cd.loc, global.params.mixinOut);
         scope p = new Parser!ASTCodegen(loc, sc._module, str, false, global.errorSink, &global.compileEnv, doUnittests);
-        p.transitionIn = global.params.vin;
+        p.transitionIn = global.params.v.vin;
         p.nextToken();
 
         auto d = p.parseDeclDefs(0);
@@ -1953,7 +1954,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
 
         if (p.token.value != TOK.endOfFile)
         {
-            cd.error("incomplete mixin declaration `%s`", str.ptr);
+            .error(cd.loc, "%s `%s` incomplete mixin declaration `%s`", cd.kind, cd.toPrettyChars, str.ptr);
             return null;
         }
         return d;
@@ -1990,7 +1991,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             const sident = se.toStringz();
             if (!sident.length || !Identifier.isValidIdentifier(sident))
             {
-                ns.exp.error("expected valid identifier for C++ namespace but got `%.*s`",
+                error(ns.exp.loc, "expected valid identifier for C++ namespace but got `%.*s`",
                              cast(int)sident.length, sident.ptr);
                 return null;
             }
@@ -2028,7 +2029,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                         return; // An error happened in `identFromSE`
                 }
                 else
-                    ns.exp.error("`%s`: index %llu is not a string constant, it is a `%s`",
+                    error(ns.exp.loc, "`%s`: index %llu is not a string constant, it is a `%s`",
                                  ns.exp.toChars(), cast(ulong) d, ns.exp.type.toChars());
             }
         }
@@ -2038,8 +2039,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         else if (ns.exp.isTypeExp() && ns.exp.isTypeExp().type.toBasetype().isTypeTuple())
         {
         }
-        else
-            ns.exp.error("compile time string constant (or sequence) expected, not `%s`",
+        else if (!ns.exp.type.isTypeError())
+            error(ns.exp.loc, "compile time string constant (or sequence) expected, not `%s`",
                          ns.exp.toChars());
         attribSemantic(ns);
     }
@@ -2196,7 +2197,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             }
             if (ed.memtype.ty == Tvoid)
             {
-                ed.error("base type must not be `void`");
+                .error(ed.loc, "%s `%s` base type must not be `void`", ed.kind, ed.toPrettyChars);
                 ed.memtype = Type.terror;
             }
             if (ed.memtype.ty == Terror)
@@ -2217,7 +2218,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
 
         if (ed.members.length == 0)
         {
-            ed.error("enum `%s` must have at least one member", ed.toChars());
+            .error(ed.loc, "%s `%s enum `%s` must have at least one member", ed.kind, ed.toPrettyChars, ed.toChars());
             ed.errors = true;
             ed.semanticRun = PASS.semanticdone;
             return;
@@ -2308,13 +2309,13 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                     if (!ie)
                     {
                         // C11 6.7.2.2-2
-                        em.error("enum member must be an integral constant expression, not `%s` of type `%s`", e.toChars(), e.type.toChars());
+                        .error(em.loc, "%s `%s` enum member must be an integral constant expression, not `%s` of type `%s`", em.kind, em.toPrettyChars, e.toChars(), e.type.toChars());
                         return errorReturn(em);
                     }
                     if (ed.memtype && !ir.contains(getIntRange(ie)))
                     {
                         // C11 6.7.2.2-2
-                        em.error("enum member value `%s` does not fit in `%s`", e.toChars(), commonType.toChars());
+                        .error(em.loc, "%s `%s` enum member value `%s` does not fit in `%s`", em.kind, em.toPrettyChars, e.toChars(), commonType.toChars());
                         return errorReturn(em);
                     }
                     nextValue = ie.toInteger();
@@ -2331,7 +2332,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                         Expression max = getProperty(commonType, null, em.loc, Id.max, 0);
                         if (nextValue == max.toInteger())
                         {
-                            em.error("initialization with `%s+1` causes overflow for type `%s`", max.toChars(), commonType.toChars());
+                            .error(em.loc, "%s `%s` initialization with `%s+1` causes overflow for type `%s`", em.kind, em.toPrettyChars, max.toChars(), commonType.toChars());
                             return errorReturn(em);
                         }
                         nextValue += 1;
@@ -2391,7 +2392,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             return;
         if (em.semanticRun == PASS.semantic)
         {
-            em.error("circular reference to `enum` member");
+            .error(em.loc, "%s `%s` circular reference to `enum` member", em.kind, em.toPrettyChars);
             return errorReturn();
         }
         assert(em.ed);
@@ -2605,7 +2606,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 auto mt = em.ed.memtype;
                 if (!mt)
                     mt = eprev.type;
-                em.error("initialization with `%s.%s+1` causes overflow for type `%s`",
+                .error(em.loc, "%s `%s` initialization with `%s.%s+1` causes overflow for type `%s`", em.kind, em.toPrettyChars,
                     emprev.ed.toChars(), emprev.toChars(), mt.toChars());
                 return errorReturn();
             }
@@ -2643,7 +2644,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 etest = etest.ctfeInterpret();
                 if (etest.toInteger())
                 {
-                    em.error("has inexact value due to loss of precision");
+                    .error(em.loc, "%s `%s` has inexact value due to loss of precision", em.kind, em.toPrettyChars);
                     return errorReturn();
                 }
             }
@@ -2738,7 +2739,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             }
             if (i + 1 != tempdecl.parameters.length && tp.isTemplateTupleParameter())
             {
-                tempdecl.error("template sequence parameter must be the last one");
+                .error(tempdecl.loc, "%s `%s` template sequence parameter must be the last one", tempdecl.kind, tempdecl.toPrettyChars);
                 tempdecl.errors = true;
             }
         }
@@ -2925,7 +2926,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 else
                     assert(0);
             }
-            tm.error("recursive mixin instantiation");
+            .error(tm.loc, "%s `%s` recursive mixin instantiation", tm.kind, tm.toPrettyChars);
             return;
 
         Lcontinue:
@@ -2982,7 +2983,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         if (++nest > global.recursionLimit)
         {
             global.gag = 0; // ensure error message gets printed
-            tm.error("recursive expansion");
+            .error(tm.loc, "%s `%s` recursive expansion", tm.kind, tm.toPrettyChars);
             fatal();
         }
 
@@ -3010,7 +3011,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         // Give additional context info if error occurred during instantiation
         if (global.errors != errorsave)
         {
-            tm.error("error instantiating");
+            .error(tm.loc, "%s `%s` error instantiating", tm.kind, tm.toPrettyChars);
             tm.errors = true;
         }
 
@@ -3238,7 +3239,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
 
             if (!fd.type.isTypeError())
             {
-                fd.error("`%s` must be a function instead of `%s`", fd.toChars(), fd.type.toChars());
+                .error(fd.loc, "%s `%s` `%s` must be a function instead of `%s`", fd.kind, fd.toPrettyChars, fd.toChars(), fd.type.toChars());
                 fd.type = Type.terror;
             }
             fd.errors = true;
@@ -3376,7 +3377,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             {
                 OutBuffer buf;
                 MODtoBuffer(buf, tf.mod);
-                funcdecl.error("without `this` cannot be `%s`", buf.peekChars());
+                .error(funcdecl.loc, "%s `%s` without `this` cannot be `%s`", funcdecl.kind, funcdecl.toPrettyChars, buf.peekChars());
                 tf.mod = 0; // remove qualifiers
             }
 
@@ -3425,11 +3426,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         {
             const idStr = funcdecl.isCrtCtor ? "crt_constructor" : "crt_destructor";
             if (f.nextOf().ty != Tvoid)
-                funcdecl.error("must return `void` for `pragma(%s)`", idStr.ptr);
+                .error(funcdecl.loc, "%s `%s` must return `void` for `pragma(%s)`", funcdecl.kind, funcdecl.toPrettyChars, idStr.ptr);
             if (funcdecl._linkage != LINK.c && f.parameterList.length != 0)
-                funcdecl.error("must be `extern(C)` for `pragma(%s)` when taking parameters", idStr.ptr);
+                .error(funcdecl.loc, "%s `%s` must be `extern(C)` for `pragma(%s)` when taking parameters", funcdecl.kind, funcdecl.toPrettyChars, idStr.ptr);
             if (funcdecl.isThis())
-                funcdecl.error("cannot be a non-static member function for `pragma(%s)`", idStr.ptr);
+                .error(funcdecl.loc, "%s `%s` cannot be a non-static member function for `pragma(%s)`", funcdecl.kind, funcdecl.toPrettyChars, idStr.ptr);
         }
 
         if (funcdecl.overnext && funcdecl.isCsymbol())
@@ -3443,7 +3444,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             auto fn = fnext.type.isTypeFunction();
             if (!fn || !cFuncEquivalence(f, fn))
             {
-                funcdecl.error("redeclaration with different type");
+                .error(funcdecl.loc, "%s `%s` redeclaration with different type", funcdecl.kind, funcdecl.toPrettyChars);
                 //printf("t1: %s\n", f.toChars());
                 //printf("t2: %s\n", fn.toChars());
             }
@@ -3451,7 +3452,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         }
 
         if ((funcdecl.storage_class & STC.auto_) && !f.isref && !funcdecl.inferRetType)
-            funcdecl.error("storage class `auto` has no effect if return type is not inferred");
+            .error(funcdecl.loc, "%s `%s` storage class `auto` has no effect if return type is not inferred", funcdecl.kind, funcdecl.toPrettyChars);
 
         if (f.isreturn && !funcdecl.needThis() && !funcdecl.isNested())
         {
@@ -3459,7 +3460,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
              * the 'return' applies
              */
             if (sc.scopesym && sc.scopesym.isAggregateDeclaration())
-                funcdecl.error("`static` member has no `this` to which `return` can apply");
+                .error(funcdecl.loc, "%s `%s` `static` member has no `this` to which `return` can apply", funcdecl.kind, funcdecl.toPrettyChars);
             else
                 error(funcdecl.loc, "top-level function `%s` has no `this` to which `return` can apply", funcdecl.toChars());
         }
@@ -3473,20 +3474,20 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 sfunc = visibilityToChars(funcdecl.visibility.kind);
             else
                 sfunc = "final";
-            funcdecl.error("`%s` functions cannot be `abstract`", sfunc);
+            .error(funcdecl.loc, "%s `%s` `%s` functions cannot be `abstract`", funcdecl.kind, funcdecl.toPrettyChars, sfunc);
         }
 
         if (funcdecl.isOverride() && !funcdecl.isVirtual() && !funcdecl.isFuncLiteralDeclaration())
         {
             Visibility.Kind kind = funcdecl.visible().kind;
             if ((kind == Visibility.Kind.private_ || kind == Visibility.Kind.package_) && funcdecl.isMember())
-                funcdecl.error("`%s` method is not virtual and cannot override", visibilityToChars(kind));
+                .error(funcdecl.loc, "%s `%s` `%s` method is not virtual and cannot override", funcdecl.kind, funcdecl.toPrettyChars, visibilityToChars(kind));
             else
-                funcdecl.error("cannot override a non-virtual function");
+                .error(funcdecl.loc, "%s `%s` cannot override a non-virtual function", funcdecl.kind, funcdecl.toPrettyChars);
         }
 
         if (funcdecl.isAbstract() && funcdecl.isFinalFunc())
-            funcdecl.error("cannot be both `final` and `abstract`");
+            .error(funcdecl.loc, "%s `%s` cannot be both `final` and `abstract`", funcdecl.kind, funcdecl.toPrettyChars);
 
         if (funcdecl.printf || funcdecl.scanf)
         {
@@ -3497,15 +3498,15 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         {
             funcdecl.storage_class |= STC.abstract_;
             if (funcdecl.isCtorDeclaration() || funcdecl.isPostBlitDeclaration() || funcdecl.isDtorDeclaration() || funcdecl.isInvariantDeclaration() || funcdecl.isNewDeclaration() || funcdecl.isDelete())
-                funcdecl.error("constructors, destructors, postblits, invariants, new and delete functions are not allowed in interface `%s`", id.toChars());
+                .error(funcdecl.loc, "%s `%s` constructors, destructors, postblits, invariants, new and delete functions are not allowed in interface `%s`", funcdecl.kind, funcdecl.toPrettyChars, id.toChars());
             if (funcdecl.fbody && funcdecl.isVirtual())
-                funcdecl.error("function body only allowed in `final` functions in interface `%s`", id.toChars());
+                .error(funcdecl.loc, "%s `%s` function body only allowed in `final` functions in interface `%s`", funcdecl.kind, funcdecl.toPrettyChars, id.toChars());
         }
 
         if (UnionDeclaration ud = parent.isUnionDeclaration())
         {
             if (funcdecl.isPostBlitDeclaration() || funcdecl.isDtorDeclaration() || funcdecl.isInvariantDeclaration())
-                funcdecl.error("destructors, postblits and invariants are not allowed in union `%s`", ud.toChars());
+                .error(funcdecl.loc, "%s `%s` destructors, postblits and invariants are not allowed in union `%s`", funcdecl.kind, funcdecl.toPrettyChars, ud.toChars());
         }
 
         if (StructDeclaration sd = parent.isStructDeclaration())
@@ -3563,7 +3564,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 /* If same name function exists in base class but 'this' is auto return,
                  * cannot find index of base class's vtbl[] to override.
                  */
-                funcdecl.error("return type inference is not supported if may override base class function");
+                .error(funcdecl.loc, "%s `%s` return type inference is not supported if may override base class function", funcdecl.kind, funcdecl.toPrettyChars);
             }
 
             /* Find index of existing function in base class's vtbl[] to override
@@ -3591,7 +3592,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                         {
                             f2 = f2.overloadExactMatch(funcdecl.type);
                             if (f2 && f2.isFinalFunc() && f2.visible().kind != Visibility.Kind.private_)
-                                funcdecl.error("cannot override `final` function `%s`", f2.toPrettyChars());
+                                .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s`", funcdecl.kind, funcdecl.toPrettyChars, f2.toPrettyChars());
                         }
                     }
                 }
@@ -3681,7 +3682,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                         /* the derived class cd doesn't have its vtbl[] allocated yet.
                          * https://issues.dlang.org/show_bug.cgi?id=21008
                          */
-                        funcdecl.error("circular reference to class `%s`", cd.toChars());
+                        .error(funcdecl.loc, "%s `%s` circular reference to class `%s`", funcdecl.kind, funcdecl.toPrettyChars, cd.toChars());
                         funcdecl.errors = true;
                         return;
                     }
@@ -3697,7 +3698,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
 
                     auto vtf = getFunctionType(fdv);
                     if (vtf.trust > TRUST.system && f.trust == TRUST.system)
-                        funcdecl.error("cannot override `@safe` method `%s` with a `@system` attribute",
+                        .error(funcdecl.loc, "%s `%s` cannot override `@safe` method `%s` with a `@system` attribute", funcdecl.kind, funcdecl.toPrettyChars,
                                        fdv.toPrettyChars);
 
                     if (fdc.toParent() == parent)
@@ -3718,7 +3719,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
 
                     // This function overrides fdv
                     if (fdv.isFinalFunc())
-                        funcdecl.error("cannot override `final` function `%s`", fdv.toPrettyChars());
+                        .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s`", funcdecl.kind, funcdecl.toPrettyChars, fdv.toPrettyChars());
 
                     if (!funcdecl.isOverride())
                     {
@@ -3744,7 +3745,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                         bool fdcmixin = fdc.parent.isClassDeclaration() !is null;
                         if (thismixin == fdcmixin)
                         {
-                            funcdecl.error("multiple overrides of same function");
+                            .error(funcdecl.loc, "%s `%s` multiple overrides of same function", funcdecl.kind, funcdecl.toPrettyChars);
                         }
                         /*
                          * https://issues.dlang.org/show_bug.cgi?id=711
@@ -3878,7 +3879,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                                 {
                                     if (!funcdecl.tintro.nextOf().equals(ti.nextOf()) && !funcdecl.tintro.nextOf().isBaseOf(ti.nextOf(), null) && !ti.nextOf().isBaseOf(funcdecl.tintro.nextOf(), null))
                                     {
-                                        funcdecl.error("incompatible covariant types `%s` and `%s`", funcdecl.tintro.toChars(), ti.toChars());
+                                        .error(funcdecl.loc, "%s `%s` incompatible covariant types `%s` and `%s`", funcdecl.kind, funcdecl.toPrettyChars, funcdecl.tintro.toChars(), ti.toChars());
                                     }
                                 }
                                 else
@@ -3951,7 +3952,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                     }
                 }
                 else
-                    funcdecl.error("does not override any function");
+                    .error(funcdecl.loc, "%s `%s` does not override any function", funcdecl.kind, funcdecl.toPrettyChars);
             }
 
         L2:
@@ -3973,7 +3974,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                         {
                             f2 = f2.overloadExactMatch(funcdecl.type);
                             if (f2 && f2.isFinalFunc() && f2.visible().kind != Visibility.Kind.private_)
-                                funcdecl.error("cannot override `final` function `%s.%s`", b.sym.toChars(), f2.toPrettyChars());
+                                .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s.%s`", funcdecl.kind, funcdecl.toPrettyChars, b.sym.toChars(), f2.toPrettyChars());
                         }
                     }
                 }
@@ -3994,7 +3995,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
 
         }
         else if (funcdecl.isOverride() && !parent.isTemplateInstance())
-            funcdecl.error("`override` only applies to class member functions");
+            .error(funcdecl.loc, "%s `%s` `override` only applies to class member functions", funcdecl.kind, funcdecl.toPrettyChars);
 
         if (auto ti = parent.isTemplateInstance)
         {
@@ -4009,7 +4010,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
 
     Ldone:
         if (!funcdecl.fbody && !funcdecl.allowsContractWithoutBody())
-            funcdecl.error("`in` and `out` contracts can only appear without a body when they are virtual interface functions or abstract");
+            .error(funcdecl.loc, "%s `%s` `in` and `out` contracts can only appear without a body when they are virtual interface functions or abstract", funcdecl.kind, funcdecl.toPrettyChars);
 
         /* Do not allow template instances to add virtual functions
          * to a class.
@@ -4031,7 +4032,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 ClassDeclaration cd = ti.tempdecl.isClassMember();
                 if (cd)
                 {
-                    funcdecl.error("cannot use template to add virtual function to class `%s`", cd.toChars());
+                    .error(funcdecl.loc, "%s `%s` cannot use template to add virtual function to class `%s`", funcdecl.kind, funcdecl.toPrettyChars, cd.toChars());
                 }
             }
         }
@@ -4053,7 +4054,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         funcdecl._scope.setNoFree();
 
         __gshared bool printedMain = false; // semantic might run more than once
-        if (global.params.verbose && !printedMain)
+        if (global.params.v.verbose && !printedMain)
         {
             const(char)* type = funcdecl.isMain() ? "main" : funcdecl.isWinMain() ? "winmain" : funcdecl.isDllMain() ? "dllmain" : cast(const(char)*)null;
             Module mod = sc._module;
@@ -4171,8 +4172,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             {
                 if (ctd.fbody || !(ctd.storage_class & STC.disable))
                 {
-                    ctd.error("default constructor for structs only allowed " ~
-                        "with `@disable`, no body, and no parameters");
+                    .error(ctd.loc, "%s `%s` default constructor for structs only allowed " ~
+                        "with `@disable`, no body, and no parameters", ctd.kind, ctd.toPrettyChars);
                     ctd.storage_class |= STC.disable;
                     ctd.fbody = null;
                 }
@@ -4185,13 +4186,13 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             {
                 if (ctd.storage_class & STC.disable)
                 {
-                    ctd.error("is marked `@disable`, so it cannot have default "~
-                              "arguments for all parameters.");
+                    .error(ctd.loc, "%s `%s` is marked `@disable`, so it cannot have default "~
+                              "arguments for all parameters.", ctd.kind, ctd.toPrettyChars);
                     errorSupplemental(ctd.loc, "Use `@disable this();` if you want to disable default initialization.");
                 }
                 else
-                    ctd.error("all parameters have default arguments, "~
-                              "but structs cannot have default constructors.");
+                    .error(ctd.loc, "%s `%s` all parameters have default arguments, "~
+                              "but structs cannot have default constructors.", ctd.kind, ctd.toPrettyChars);
             }
             else if ((dim == 1 || (dim > 1 && tf.parameterList[1].defaultArg)))
             {
@@ -4369,7 +4370,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 e = doAtomicOp("+=", v.ident, IntegerExp.literal!(1));
                 if (e is null)
                 {
-                    scd.error("shared static constructor within a template require `core.atomic : atomicOp` to be present");
+                    .error(scd.loc, "%s `%s` shared static constructor within a template require `core.atomic : atomicOp` to be present", scd.kind, scd.toPrettyChars);
                     return;
                 }
             }
@@ -4465,7 +4466,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 e = doAtomicOp("-=", v.ident, IntegerExp.literal!(1));
                 if (e is null)
                 {
-                    sdd.error("shared static destructo within a template require `core.atomic : atomicOp` to be present");
+                    .error(sdd.loc, "%s `%s` shared static destructo within a template require `core.atomic : atomicOp` to be present", sdd.kind, sdd.toPrettyChars);
                     return;
                 }
             }
@@ -4666,7 +4667,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
 
             sd.storage_class |= sc.stc;
             if (sd.storage_class & STC.abstract_)
-                sd.error("structs, unions cannot be `abstract`");
+                .error(sd.loc, "%s `%s` structs, unions cannot be `abstract`", sd.kind, sd.toPrettyChars);
 
             sd.userAttribDecl = sc.userAttribDecl;
 
@@ -4712,7 +4713,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         {
             if (sd.type.ty != Terror)
             {
-                sd.error(sd.loc, "circular or forward reference");
+                .error(sd.loc, "%s `%s` circular or forward reference", sd.kind, sd.toPrettyChars);
                 sd.errors = true;
                 sd.type = Type.terror;
             }
@@ -4786,7 +4787,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
 
                 if (fcall && fcall.isStatic())
                 {
-                    sd.error(fcall.loc, "`static opCall` is hidden by constructors and can never be called");
+                    .error(fcall.loc, "%s `%s` `static opCall` is hidden by constructors and can never be called", sd.kind, sd.toPrettyChars);
                     errorSupplemental(fcall.loc, "Please use a factory method instead, or replace all constructors with `static opCall`.");
                 }
             }
@@ -4810,7 +4811,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                     printf("type = %d sym = %p, %s\n", sd.type.ty, sym, sym.toPrettyChars());
                 }
                 // https://issues.dlang.org/show_bug.cgi?id=19024
-                sd.error("already exists at %s. Perhaps in another function with the same name?", sym.loc.toChars());
+                .error(sd.loc, "%s `%s` already exists at %s. Perhaps in another function with the same name?", sd.kind, sd.toPrettyChars, sym.loc.toChars());
             }
         }
 
@@ -4901,7 +4902,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
 
             cldec.storage_class |= sc.stc;
             if (cldec.storage_class & STC.auto_)
-                cldec.error("storage class `auto` is invalid when declaring a class, did you mean to use `scope`?");
+                .error(cldec.loc, "%s `%s` storage class `auto` is invalid when declaring a class, did you mean to use `scope`?", cldec.kind, cldec.toPrettyChars);
             if (cldec.storage_class & STC.scope_)
                 cldec.stack = true;
             if (cldec.storage_class & STC.abstract_)
@@ -4998,7 +4999,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 if (!tc)
                 {
                     if (b.type != Type.terror)
-                        cldec.error("base type must be `class` or `interface`, not `%s`", b.type.toChars());
+                        .error(cldec.loc, "%s `%s` base type must be `class` or `interface`, not `%s`", cldec.kind, cldec.toPrettyChars, b.type.toChars());
                     cldec.baseclasses.remove(0);
                     goto L7;
                 }
@@ -5018,7 +5019,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 {
                     if (cdb == cldec)
                     {
-                        cldec.error("circular inheritance");
+                        .error(cldec.loc, "%s `%s` circular inheritance", cldec.kind, cldec.toPrettyChars);
                         cldec.baseclasses.remove(0);
                         goto L7;
                     }
@@ -5062,14 +5063,14 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                     {
                         if (multiClassError == 0)
                         {
-                            error(cldec.loc,"`%s`: base class must be specified first, " ~
+                            .error(cldec.loc,"`%s`: base class must be specified first, " ~
                                   "before any interfaces.", cldec.toPrettyChars());
                             multiClassError += 1;
                         }
                         else if (multiClassError >= 1)
                         {
                                 if(multiClassError == 1)
-                                    error(cldec.loc,"`%s`: multiple class inheritance is not supported." ~
+                                    .error(cldec.loc, "`%s`: multiple class inheritance is not supported." ~
                                           " Use multiple interface inheritance and/or composition.", cldec.toPrettyChars());
                                 multiClassError += 1;
 
@@ -5097,7 +5098,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                     BaseClass* b2 = (*cldec.baseclasses)[j];
                     if (b2.sym == tc.sym)
                     {
-                        cldec.error("inherits from duplicate interface `%s`", b2.sym.toChars());
+                        .error(cldec.loc, "%s `%s` inherits from duplicate interface `%s`", cldec.kind, cldec.toPrettyChars, b2.sym.toChars());
                         cldec.baseclasses.remove(i);
                         continue BCLoop;
                     }
@@ -5141,7 +5142,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             {
                 void badObjectDotD()
                 {
-                    cldec.error("missing or corrupt object.d");
+                    .error(cldec.loc, "%s `%s` missing or corrupt object.d", cldec.kind, cldec.toPrettyChars);
                     fatal();
                 }
 
@@ -5165,7 +5166,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             if (cldec.baseClass)
             {
                 if (cldec.baseClass.storage_class & STC.final_)
-                    cldec.error("cannot inherit from class `%s` because it is `final`", cldec.baseClass.toChars());
+                    .error(cldec.loc, "%s `%s` cannot inherit from class `%s` because it is `final`", cldec.kind, cldec.toPrettyChars, cldec.baseClass.toChars());
 
                 // Inherit properties from base class
                 if (cldec.baseClass.isCOMclass())
@@ -5173,7 +5174,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 if (cldec.baseClass.isCPPclass())
                     cldec.classKind = ClassKind.cpp;
                 if (cldec.classKind != cldec.baseClass.classKind)
-                    cldec.error("with %s linkage cannot inherit from class `%s` with %s linkage",
+                    .error(cldec.loc, "%s `%s` with %s linkage cannot inherit from class `%s` with %s linkage", cldec.kind, cldec.toPrettyChars,
                         cldec.classKind.toChars(), cldec.baseClass.toChars(), cldec.baseClass.classKind.toChars());
 
                 if (cldec.baseClass.stack)
@@ -5191,7 +5192,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                     cldec.com = true;
                 if (cldec.classKind == ClassKind.cpp && !b.sym.isCPPinterface())
                 {
-                    error(cldec.loc, "C++ class `%s` cannot implement D interface `%s`",
+                    .error(cldec.loc, "C++ class `%s` cannot implement D interface `%s`",
                         cldec.toPrettyChars(), b.sym.toPrettyChars());
                 }
             }
@@ -5253,7 +5254,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             {
                 if (cldec.classKind == ClassKind.cpp && cldec.baseClass.vtbl.length == 0)
                 {
-                    cldec.error("C++ base class `%s` needs at least one virtual function", cldec.baseClass.toChars());
+                    .error(cldec.loc, "%s `%s` C++ base class `%s` needs at least one virtual function", cldec.kind, cldec.toPrettyChars, cldec.baseClass.toChars());
                 }
 
                 // Copy vtbl[] from base class
@@ -5279,7 +5280,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             {
                 // Use the base class's 'this' member
                 if (cldec.storage_class & STC.static_)
-                    cldec.error("static class cannot inherit from nested class `%s`", cldec.baseClass.toChars());
+                    .error(cldec.loc, "%s `%s` static class cannot inherit from nested class `%s`", cldec.kind, cldec.toPrettyChars, cldec.baseClass.toChars());
                 if (cldec.toParentLocal() != cldec.baseClass.toParentLocal() &&
                     (!cldec.toParentLocal() ||
                      !cldec.baseClass.toParentLocal().getType() ||
@@ -5287,14 +5288,14 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 {
                     if (cldec.toParentLocal())
                     {
-                        cldec.error("is nested within `%s`, but super class `%s` is nested within `%s`",
+                        .error(cldec.loc, "%s `%s` is nested within `%s`, but super class `%s` is nested within `%s`", cldec.kind, cldec.toPrettyChars,
                             cldec.toParentLocal().toChars(),
                             cldec.baseClass.toChars(),
                             cldec.baseClass.toParentLocal().toChars());
                     }
                     else
                     {
-                        cldec.error("is not nested, but super class `%s` is nested within `%s`",
+                        .error(cldec.loc, "%s `%s` is not nested, but super class `%s` is nested within `%s`", cldec.kind, cldec.toPrettyChars,
                             cldec.baseClass.toChars(),
                             cldec.baseClass.toParentLocal().toChars());
                     }
@@ -5308,14 +5309,14 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                     {
                         if (cldec.toParent2() && cldec.toParent2() != cldec.toParentLocal())
                         {
-                            cldec.error("needs the frame pointer of `%s`, but super class `%s` needs the frame pointer of `%s`",
+                            .error(cldec.loc, "%s `%s` needs the frame pointer of `%s`, but super class `%s` needs the frame pointer of `%s`", cldec.kind, cldec.toPrettyChars,
                                 cldec.toParent2().toChars(),
                                 cldec.baseClass.toChars(),
                                 cldec.baseClass.toParent2().toChars());
                         }
                         else
                         {
-                            cldec.error("doesn't need a frame pointer, but super class `%s` needs the frame pointer of `%s`",
+                            .error(cldec.loc, "%s `%s` doesn't need a frame pointer, but super class `%s` needs the frame pointer of `%s`", cldec.kind, cldec.toPrettyChars,
                                 cldec.baseClass.toChars(),
                                 cldec.baseClass.toParent2().toChars());
                         }
@@ -5410,7 +5411,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             }
             else
             {
-                cldec.error("cannot implicitly generate a default constructor when base class `%s` is missing a default constructor",
+                .error(cldec.loc, "%s `%s` cannot implicitly generate a default constructor when base class `%s` is missing a default constructor", cldec.kind, cldec.toPrettyChars,
                     cldec.baseClass.toPrettyChars());
             }
         }
@@ -5434,7 +5435,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         if (auto f = hasIdentityOpAssign(cldec, sc2))
         {
             if (!(f.storage_class & STC.disable))
-                cldec.error(f.loc, "identity assignment operator overload is illegal");
+                .error(f.loc, "%s `%s` identity assignment operator overload is illegal", cldec.kind, cldec.toPrettyChars);
         }
 
         cldec.inv = buildInv(cldec, sc2);
@@ -5454,7 +5455,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             cldec.isAbstract();               // recalculate
             if (cldec.isabstract != isabstractsave)
             {
-                cldec.error("cannot infer `abstract` attribute due to circular dependencies");
+                .error(cldec.loc, "%s `%s` cannot infer `abstract` attribute due to circular dependencies", cldec.kind, cldec.toPrettyChars);
             }
         }
 
@@ -5467,7 +5468,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 printf("this = %p %s\n", cldec, cldec.toPrettyChars());
                 printf("type = %d sym = %p, %s\n", cldec.type.ty, cd, cd.toPrettyChars());
             }
-            cldec.error("already exists at %s. Perhaps in another function with the same name?", cd.loc.toChars());
+            .error(cldec.loc, "%s `%s` already exists at %s. Perhaps in another function with the same name?", cldec.kind, cldec.toPrettyChars, cd.loc.toChars());
         }
 
         if (global.errors != errors || (cldec.baseClass && cldec.baseClass.errors))
@@ -5488,7 +5489,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 if (!vd.isThisDeclaration() &&
                     vd.visible() >= Visibility(Visibility.Kind.public_))
                 {
-                    vd.error("Field members of a `synchronized` class cannot be `%s`",
+                    .error(vd.loc, "%s `%s` Field members of a `synchronized` class cannot be `%s`", vd.kind, vd.toPrettyChars,
                         visibilityToChars(vd.visible().kind));
                 }
             }
@@ -5650,7 +5651,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 if (!tc || !tc.sym.isInterfaceDeclaration())
                 {
                     if (b.type != Type.terror)
-                        idec.error("base type must be `interface`, not `%s`", b.type.toChars());
+                        .error(idec.loc, "%s `%s` base type must be `interface`, not `%s`", idec.kind, idec.toPrettyChars, b.type.toChars());
                     idec.baseclasses.remove(i);
                     continue;
                 }
@@ -5661,14 +5662,14 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                     BaseClass* b2 = (*idec.baseclasses)[j];
                     if (b2.sym == tc.sym)
                     {
-                        idec.error("inherits from duplicate interface `%s`", b2.sym.toChars());
+                        .error(idec.loc, "%s `%s` inherits from duplicate interface `%s`", idec.kind, idec.toPrettyChars, b2.sym.toChars());
                         idec.baseclasses.remove(i);
                         continue BCLoop;
                     }
                 }
                 if (tc.sym == idec || idec.isBaseOf2(tc.sym))
                 {
-                    idec.error("circular inheritance of interface");
+                    .error(idec.loc, "%s `%s` circular inheritance of interface", idec.kind, idec.toPrettyChars);
                     idec.baseclasses.remove(i);
                     continue;
                 }
@@ -5931,7 +5932,7 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList
         auto ungag = Ungag(global.gag);
         if (!tempinst.gagged)
             global.gag = 0;
-        tempinst.error(tempinst.loc, "recursive template expansion");
+        .error(tempinst.loc, "%s `%s` recursive template expansion", tempinst.kind, tempinst.toPrettyChars);
         if (tempinst.gagged)
             tempinst.semanticRun = PASS.initial;
         else
@@ -5989,7 +5990,7 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList
     // If tempdecl is a mixin, disallow it
     if (tempdecl.ismixin)
     {
-        tempinst.error("mixin templates are not regular templates");
+        .error(tempinst.loc, "%s `%s` mixin templates are not regular templates", tempinst.kind, tempinst.toPrettyChars);
         goto Lerror;
     }
 
@@ -6210,7 +6211,8 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList
     Scope* _scope = tempdecl._scope;
     if (tempdecl.semanticRun == PASS.initial)
     {
-        tempinst.error("template instantiation `%s` forward references template declaration `%s`", tempinst.toChars(), tempdecl.toChars());
+        .error(tempinst.loc, "%s `%s` template instantiation `%s` forward references template declaration `%s`",
+           tempinst.kind, tempinst.toPrettyChars, tempinst.toChars(), tempdecl.toChars());
         return;
     }
 
@@ -6454,7 +6456,7 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList
             if (++nest > global.recursionLimit)
             {
                 global.gag = 0; // ensure error message gets printed
-                tempinst.error("recursive expansion");
+                .error(tempinst.loc, "%s `%s` recursive expansion", tempinst.kind, tempinst.toPrettyChars);
                 fatal();
             }
         }
@@ -6502,7 +6504,7 @@ Laftersemantic:
         if (!tempinst.errors)
         {
             if (!tempdecl.literal)
-                tempinst.error(tempinst.loc, "error instantiating");
+                .error(tempinst.loc, "%s `%s` error instantiating", tempinst.kind, tempinst.toPrettyChars);
             if (tempinst.tinst)
                 tempinst.tinst.printInstantiationTrace();
         }
@@ -6712,7 +6714,7 @@ void aliasSemantic(AliasDeclaration ds, Scope* sc)
         return errorRet();
     if (s == ds)
     {
-        ds.error("cannot resolve");
+        .error(ds.loc, "%s `%s` cannot resolve", ds.kind, ds.toPrettyChars);
         return errorRet();
     }
     if (!s || !s.isEnumMember())
@@ -6743,7 +6745,7 @@ void aliasSemantic(AliasDeclaration ds, Scope* sc)
                 if (!s)
                 {
                     if (e.op != EXP.error)
-                        ds.error("cannot alias an expression `%s`", e.toChars());
+                        .error(ds.loc, "%s `%s` cannot alias an expression `%s`", ds.kind, ds.toPrettyChars, e.toChars());
                     return errorRet();
                 }
             }
@@ -6799,7 +6801,7 @@ private void aliasAssignSemantic(AliasAssign ds, Scope* sc)
         Dsymbol as = sc.search(ds.loc, ds.ident, &scopesym);
         if (!as)
         {
-            ds.error("undefined identifier `%s`", ds.ident.toChars());
+            .error(ds.loc, "%s `%s` undefined identifier `%s`", ds.kind, ds.toPrettyChars, ds.ident.toChars());
             return null;
         }
         if (as.errors)
@@ -6808,13 +6810,13 @@ private void aliasAssignSemantic(AliasAssign ds, Scope* sc)
         auto ad = as.isAliasDeclaration();
         if (!ad)
         {
-            ds.error("identifier `%s` must be an alias declaration", as.toChars());
+            .error(ds.loc, "%s `%s` identifier `%s` must be an alias declaration", ds.kind, ds.toPrettyChars, as.toChars());
             return null;
         }
 
         if (ad.overnext)
         {
-            ds.error("cannot reassign overloaded alias");
+            error(ds.loc, "%s `%s` cannot reassign overloaded alias", ds.kind, ds.toPrettyChars);
             return null;
         }
 
@@ -6824,12 +6826,12 @@ private void aliasAssignSemantic(AliasAssign ds, Scope* sc)
         {
             if (!adParent)
                 adParent = ds.toParent();
-            error(ds.loc, "`%s` must have same parent `%s` as alias `%s`", ds.ident.toChars(), adParent.toChars(), ad.toChars());
+            .error(ds.loc, "`%s` must have same parent `%s` as alias `%s`", ds.ident.toChars(), adParent.toChars(), ad.toChars());
             return null;
         }
         if (!adParent.isTemplateInstance())
         {
-            ds.error("must be a member of a template");
+            .error(ds.loc, "%s `%s` must be a member of a template", ds.kind, ds.toPrettyChars);
             return null;
         }
 
@@ -6910,7 +6912,7 @@ private void aliasAssignSemantic(AliasAssign ds, Scope* sc)
         return errorRet();
     if (s == aliassym)
     {
-        ds.error("cannot resolve");
+        .error(ds.loc, "%s `%s` cannot resolve", ds.kind, ds.toPrettyChars);
         return errorRet();
     }
 
@@ -6942,7 +6944,7 @@ private void aliasAssignSemantic(AliasAssign ds, Scope* sc)
                 if (!s)
                 {
                     if (e.op != EXP.error)
-                        ds.error("cannot alias an expression `%s`", e.toChars());
+                        .error(ds.loc, "%s `%s` cannot alias an expression `%s`", ds.kind, ds.toPrettyChars, e.toChars());
                     return errorRet();
                 }
             }
@@ -7175,7 +7177,7 @@ bool determineFields(AggregateDeclaration ad)
             if (ad == tvs.sym)
             {
                 const(char)* psz = (v.type.toBasetype().ty == Tsarray) ? "static array of " : "";
-                ad.error("cannot have field `%s` with %ssame struct type", v.toChars(), psz);
+                .error(ad.loc, "%s `%s` cannot have field `%s` with %ssame struct type", ad.kind, ad.toPrettyChars, v.toChars(), psz);
                 ad.type = Type.terror;
                 ad.errors = true;
                 return 1;
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index 67ca2ef66a4b..23d1140fe381 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -872,7 +872,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
                 if (!ti.symtab)
                     ti.symtab = new DsymbolTable();
                 if (!scx.insert(v))
-                    error("parameter `%s.%s` is already defined", toChars(), v.toChars());
+                    .error(loc, "%s `%s` parameter `%s.%s` is already defined", kind, toPrettyChars, toChars(), v.toChars());
                 else
                     v.parent = fd;
             }
@@ -916,7 +916,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
         import dmd.staticcond;
 
         // there will be a full tree view in verbose mode, and more compact list in the usual
-        const full = global.params.verbose;
+        const full = global.params.v.verbose;
         uint count;
         const msg = visualizeStaticCondition(constraint, lastConstraint, lastConstraintNegs[], full, count);
         scope (exit)
@@ -1769,7 +1769,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
                                     if (m2 < matchTiargs)
                                         matchTiargs = m2; // pick worst match
                                     if (!(*dedtypes)[i].equals(oded))
-                                        error("specialization not allowed for deduced parameter `%s`", tparam.ident.toChars());
+                                        .error(loc, "%s `%s` specialization not allowed for deduced parameter `%s`", kind, toPrettyChars, kind, toPrettyChars, tparam.ident.toChars());
                                 }
                                 else
                                 {
@@ -2147,7 +2147,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
                     if (m2 < matchTiargs)
                         matchTiargs = m2; // pick worst match
                     if (!(*dedtypes)[i].equals(oded))
-                        error("specialization not allowed for deduced parameter `%s`", tparam.ident.toChars());
+                        .error(loc, "%s `%s` specialization not allowed for deduced parameter `%s`", kind, toPrettyChars, tparam.ident.toChars());
                 }
                 else
                 {
@@ -2194,7 +2194,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
                     if (m2 < matchTiargs)
                         matchTiargs = m2; // pick worst match
                     if (!(*dedtypes)[i].equals(oded))
-                        error("specialization not allowed for deduced parameter `%s`", tparam.ident.toChars());
+                        .error(loc, "%s `%s` specialization not allowed for deduced parameter `%s`", kind, toPrettyChars, tparam.ident.toChars());
                 }
             }
             oded = declareParameter(paramscope, tparam, oded);
@@ -2346,7 +2346,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
         }
 
         if (!sc.insert(d))
-            error("declaration `%s` is already defined", tp.ident.toChars());
+            .error(loc, "%s `%s` declaration `%s` is already defined", kind, toPrettyChars, tp.ident.toChars());
         d.dsymbolSemantic(sc);
         /* So the caller's o gets updated with the result of semantic() being run on o
          */
@@ -5629,7 +5629,8 @@ extern (C++) final class TemplateValueParameter : TemplateParameter
                     // i.e: `template T(int arg = T)`
                     // Raise error now before calling resolveProperties otherwise we'll
                     // start looping on the expansion of the template instance.
-                    sc.tinst.tempdecl.error("recursive template expansion");
+                    auto td = sc.tinst.tempdecl;
+                    .error(td.loc, "%s `%s` recursive template expansion", td.kind, td.toPrettyChars);
                     return ErrorExp.get();
                 }
             }
@@ -5993,7 +5994,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
             }
             if (!inst)
             {
-                error("cannot resolve forward reference");
+                .error(loc, "%s `%s` cannot resolve forward reference", kind, toPrettyChars);
                 errors = true;
                 return this;
             }
@@ -6039,17 +6040,17 @@ extern (C++) class TemplateInstance : ScopeDsymbol
      * Given an error instantiating the TemplateInstance,
      * give the nested TemplateInstance instantiations that got
      * us here. Those are a list threaded into the nested scopes.
+     * Params:
+     *  cl = classification of this trace as printing either errors or deprecations
+     *  max_shown = maximum number of trace elements printed (controlled with -v/-verror-limit)
      */
-    extern(D) final void printInstantiationTrace(Classification cl = Classification.error)
+    extern(D) final void printInstantiationTrace(Classification cl = Classification.error,
+                                                 const(uint) max_shown = global.params.v.errorSupplementCount())
     {
         if (global.gag)
             return;
 
         // Print full trace for verbose mode, otherwise only short traces
-        const(uint) max_shown = !global.params.verbose ?
-                                    (global.params.errorSupplementLimit ? global.params.errorSupplementLimit : uint.max)
-                                    : uint.max;
-
         const(char)* format = "instantiated from here: `%s`";
 
         // This returns a function pointer
@@ -6456,9 +6457,9 @@ extern (C++) class TemplateInstance : ScopeDsymbol
             {
                 s = sc.search_correct(id);
                 if (s)
-                    error("template `%s` is not defined, did you mean %s?", id.toChars(), s.toChars());
+                    .error(loc, "%s `%s` template `%s` is not defined, did you mean %s?", kind, toPrettyChars, id.toChars(), s.toChars());
                 else
-                    error("template `%s` is not defined", id.toChars());
+                    .error(loc, "%s `%s` template `%s` is not defined", kind, toPrettyChars, id.toChars());
                 return false;
             }
             static if (LOG)
@@ -6526,7 +6527,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
                     }
                     if (td.semanticRun == PASS.initial)
                     {
-                        error("`%s` forward references template declaration `%s`",
+                        .error(loc, "%s `%s` `%s` forward references template declaration `%s`", kind, toPrettyChars,
                             toChars(), td.toChars());
                         return 1;
                     }
@@ -6581,7 +6582,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
             }
             if (!s)
             {
-                error("template `%s` is not defined", id.toChars());
+                .error(loc, "%s `%s` template `%s` is not defined", kind, toPrettyChars, id.toChars());
                 return false;
             }
         }
@@ -6652,7 +6653,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
         }
         else
         {
-            error("`%s` is not a template declaration, it is a %s", id.toChars(), s.kind());
+            .error(loc, "%s `%s` `%s` is not a template declaration, it is a %s", kind, toPrettyChars, id.toChars(), s.kind());
             return false;
         }
     }
@@ -6970,7 +6971,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
             tdtypes.setDim(tempdecl.parameters.length);
             if (!tempdecl.matchWithInstance(sc, this, &tdtypes, argumentList, 2))
             {
-                error("incompatible arguments for template instantiation");
+                .error(loc, "%s `%s` incompatible arguments for template instantiation", kind, toPrettyChars);
                 return false;
             }
             // TODO: Normalizing tiargs for https://issues.dlang.org/show_bug.cgi?id=7469 is necessary?
@@ -7130,13 +7131,13 @@ extern (C++) class TemplateInstance : ScopeDsymbol
                 const cmsg = tdecl.getConstraintEvalError(tip);
                 if (cmsg)
                 {
-                    error("%s `%s`\n%s", msg, tmsg, cmsg);
+                    .error(loc, "%s `%s` %s `%s`\n%s", kind, toPrettyChars, msg, tmsg, cmsg);
                     if (tip)
                         .tip(tip);
                 }
                 else
                 {
-                    error("%s `%s`", msg, tmsg);
+                    .error(loc, "%s `%s` %s `%s`", kind, toPrettyChars, msg, tmsg);
 
                     if (tdecl.parameters.length == tiargs.length)
                     {
@@ -7290,7 +7291,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
                         }
                         if (td.semanticRun == PASS.initial)
                         {
-                            error("`%s` forward references template declaration `%s`", toChars(), td.toChars());
+                            .error(loc, "%s `%s` `%s` forward references template declaration `%s`", kind, toPrettyChars, toChars(), td.toChars());
                             return 1;
                         }
                     }
@@ -7370,7 +7371,8 @@ extern (C++) class TemplateInstance : ScopeDsymbol
                 // Emulate Expression.toMangleBuffer call that had exist in TemplateInstance.genIdent.
                 if (ea.op != EXP.int64 && ea.op != EXP.float64 && ea.op != EXP.complex80 && ea.op != EXP.null_ && ea.op != EXP.string_ && ea.op != EXP.arrayLiteral && ea.op != EXP.assocArrayLiteral && ea.op != EXP.structLiteral)
                 {
-                    ea.error("expression `%s` is not a valid template value argument", ea.toChars());
+                    if (!ea.type.isTypeError())
+                        .error(ea.loc, "%s `%s` expression `%s` is not a valid template value argument", kind, toPrettyChars, ea.toChars());
                     errors = true;
                 }
             }
@@ -7425,7 +7427,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
                                 goto L1;
                             }
                         }
-                        error("`%s` is nested in both `%s` and `%s`", toChars(), enclosing.toChars(), dparent.toChars());
+                        .error(loc, "%s `%s` `%s` is nested in both `%s` and `%s`", kind, toPrettyChars, toChars(), enclosing.toChars(), dparent.toChars());
                         errors = true;
                     }
                 L1:
@@ -7611,7 +7613,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
         if (++nest > global.recursionLimit)
         {
             global.gag = 0; // ensure error message gets printed
-            error("recursive expansion exceeded allowed nesting limit");
+            .error(loc, "%s `%s` recursive expansion exceeded allowed nesting limit", kind, toPrettyChars);
             fatal();
         }
 
@@ -7628,7 +7630,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
         if (++nest > global.recursionLimit)
         {
             global.gag = 0; // ensure error message gets printed
-            error("recursive expansion exceeded allowed nesting limit");
+            .error(loc, "%s `%s` recursive expansion exceeded allowed nesting limit", kind, toPrettyChars);
             fatal();
         }
 
@@ -7838,7 +7840,7 @@ extern (C++) final class TemplateMixin : TemplateInstance
             tqual.resolve(loc, sc, e, t, s);
             if (!s)
             {
-                error("is not defined");
+                .error(loc, "%s `%s` is not defined", kind, toPrettyChars);
                 return false;
             }
             s = s.toAlias();
@@ -7866,7 +7868,7 @@ extern (C++) final class TemplateMixin : TemplateInstance
             }
             if (!tempdecl)
             {
-                error("- `%s` is a %s, not a template", s.toChars(), s.kind());
+                .error(loc, "%s `%s` - `%s` is a %s, not a template", kind, toPrettyChars, s.toChars(), s.kind());
                 return false;
             }
         }
@@ -8270,6 +8272,7 @@ MATCH matchArg(TemplateParameter tp, Scope* sc, RootObject oarg, size_t i, Templ
              */
             if (tap.specType)
             {
+                tap.specType = typeSemantic(tap.specType, tap.loc, sc);
                 Declaration d = (cast(Dsymbol)sa).isDeclaration();
                 if (!d)
                     return matchArgNoMatch();
@@ -8453,12 +8456,12 @@ struct TemplateStats
         {
             if (ts.allInstances is null)
                 ts.allInstances = new TemplateInstances();
-            if (global.params.vtemplatesListInstances)
+            if (global.params.v.templatesListInstances)
                 ts.allInstances.push(cast() ti);
         }
 
     // message(ti.loc, "incInstance %p %p", td, ti);
-        if (!global.params.vtemplates)
+        if (!global.params.v.templates)
             return;
         if (!td)
             return;
@@ -8482,7 +8485,7 @@ struct TemplateStats
                           const TemplateInstance ti)
     {
         // message(ti.loc, "incUnique %p %p", td, ti);
-        if (!global.params.vtemplates)
+        if (!global.params.v.templates)
             return;
         if (!td)
             return;
@@ -8511,7 +8514,7 @@ extern (C++) void printTemplateStats()
         }
     }
 
-    if (!global.params.vtemplates)
+    if (!global.params.v.templates)
         return;
 
     Array!(TemplateDeclarationStats) sortedStats;
@@ -8525,7 +8528,7 @@ extern (C++) void printTemplateStats()
 
     foreach (const ref ss; sortedStats[])
     {
-        if (global.params.vtemplatesListInstances &&
+        if (global.params.v.templatesListInstances &&
             ss.ts.allInstances)
         {
             message(ss.td.loc,
diff --git a/gcc/d/dmd/dtoh.d b/gcc/d/dmd/dtoh.d
index d5f658a8a424..f906ee127892 100644
--- a/gcc/d/dmd/dtoh.d
+++ b/gcc/d/dmd/dtoh.d
@@ -23,6 +23,7 @@ import dmd.dsymbol;
 import dmd.errors;
 import dmd.globals;
 import dmd.hdrgen;
+import dmd.id;
 import dmd.identifier;
 import dmd.location;
 import dmd.root.filename;
@@ -1046,6 +1047,10 @@ public:
     {
         debug (Debug_DtoH) mixin(traceVisit!ad);
 
+        // Declared in object.d but already included in `#include`s
+        if (ad.ident == Id._size_t || ad.ident == Id._ptrdiff_t)
+            return;
+
         if (!shouldEmitAndMarkVisited(ad))
             return;
 
@@ -3211,6 +3216,21 @@ const(char*) keywordClass(const Identifier ident)
             if (global.params.cplusplus >= CppStdRevision.cpp20)
                 return "keyword in C++20";
             return null;
+        case "restrict":
+        case "_Alignas":
+        case "_Alignof":
+        case "_Atomic":
+        case "_Bool":
+        //case "_Complex": // handled above in C++
+        case "_Generic":
+        case "_Imaginary":
+        case "_Noreturn":
+        case "_Static_assert":
+        case "_Thread_local":
+        case "_assert":
+        case "_import":
+        //case "__...": handled in default case below
+            return "Keyword in C";
 
         default:
             // Identifiers starting with __ are reserved
diff --git a/gcc/d/dmd/dversion.d b/gcc/d/dmd/dversion.d
index 0945b5424b58..aa22532061ef 100644
--- a/gcc/d/dmd/dversion.d
+++ b/gcc/d/dmd/dversion.d
@@ -20,6 +20,7 @@ import dmd.dmodule;
 import dmd.dscope;
 import dmd.dsymbol;
 import dmd.dsymbolsem;
+import dmd.errors;
 import dmd.globals;
 import dmd.identifier;
 import dmd.location;
@@ -77,14 +78,14 @@ extern (C++) final class DebugSymbol : Dsymbol
         {
             if (!m)
             {
-                error("declaration must be at module level");
+                .error(loc, "%s `%s` declaration must be at module level", kind, toPrettyChars);
                 errors = true;
             }
             else
             {
                 if (findCondition(m.debugidsNot, ident))
                 {
-                    error("defined after use");
+                    .error(loc, "%s `%s` defined after use", kind, toPrettyChars);
                     errors = true;
                 }
                 if (!m.debugids)
@@ -96,7 +97,7 @@ extern (C++) final class DebugSymbol : Dsymbol
         {
             if (!m)
             {
-                error("level declaration must be at module level");
+                .error(loc, "%s `%s` level declaration must be at module level", kind, toPrettyChars);
                 errors = true;
             }
             else
@@ -172,14 +173,14 @@ extern (C++) final class VersionSymbol : Dsymbol
             VersionCondition.checkReserved(loc, ident.toString());
             if (!m)
             {
-                error("declaration must be at module level");
+                .error(loc, "%s `%s` declaration must be at module level", kind, toPrettyChars);
                 errors = true;
             }
             else
             {
                 if (findCondition(m.versionidsNot, ident))
                 {
-                    error("defined after use");
+                    .error(loc, "%s `%s` defined after use", kind, toPrettyChars);
                     errors = true;
                 }
                 if (!m.versionids)
@@ -191,7 +192,7 @@ extern (C++) final class VersionSymbol : Dsymbol
         {
             if (!m)
             {
-                error("level declaration must be at module level");
+                .error(loc, "%s `%s` level declaration must be at module level", kind, toPrettyChars);
                 errors = true;
             }
             else
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index 99f65879046f..720523174b77 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -238,17 +238,6 @@ bool isNeedThisScope(Scope* sc, Declaration d)
     return true;
 }
 
-/******************************
- * check e is exp.opDispatch!(tiargs) or not
- * It's used to switch to UFCS the semantic analysis path
- */
-bool isDotOpDispatch(Expression e)
-{
-    if (auto dtie = e.isDotTemplateInstanceExp())
-        return dtie.ti.name == Id.opDispatch;
-    return false;
-}
-
 /****************************************
  * Expand tuples in-place.
  *
@@ -379,41 +368,6 @@ TupleDeclaration isAliasThisTuple(Expression e)
     }
 }
 
-int expandAliasThisTuples(Expressions* exps, size_t starti = 0)
-{
-    if (!exps || exps.length == 0)
-        return -1;
-
-    for (size_t u = starti; u < exps.length; u++)
-    {
-        Expression exp = (*exps)[u];
-        if (TupleDeclaration td = exp.isAliasThisTuple)
-        {
-            exps.remove(u);
-            size_t i;
-            td.foreachVar((s)
-            {
-                auto d = s.isDeclaration();
-                auto e = new DotVarExp(exp.loc, exp, d);
-                assert(d.type);
-                e.type = d.type;
-                exps.insert(u + i, e);
-                ++i;
-            });
-            version (none)
-            {
-                printf("expansion ->\n");
-                foreach (e; exps)
-                {
-                    printf("\texps[%d] e = %s %s\n", i, EXPtoString(e.op), e.toChars());
-                }
-            }
-            return cast(int)u;
-        }
-    }
-    return -1;
-}
-
 /****************************************
  * If `s` is a function template, i.e. the only member of a template
  * and that member is a function, return that template.
@@ -602,7 +556,7 @@ extern (C++) struct UnionExp
 
 private:
     // Ensure that the union is suitably aligned.
-    align(8) union __AnonStruct__u
+    align(8) union _AnonStruct_u
     {
         char[__traits(classInstanceSize, Expression)] exp;
         char[__traits(classInstanceSize, IntegerExp)] integerexp;
@@ -623,23 +577,7 @@ private:
         char[__traits(classInstanceSize, VectorExp)] vectorexp;
     }
 
-    __AnonStruct__u u;
-}
-
-/********************************
- * Test to see if two reals are the same.
- * Regard NaN's as equivalent.
- * Regard +0 and -0 as different.
- * Params:
- *      x1 = first operand
- *      x2 = second operand
- * Returns:
- *      true if x1 is x2
- *      else false
- */
-bool RealIdentical(real_t x1, real_t x2) @safe
-{
-    return (CTFloat.isNaN(x1) && CTFloat.isNaN(x2)) || CTFloat.isIdentical(x1, x2);
+    _AnonStruct_u u;
 }
 
 /************************ TypeDotIdExp ************************************/
@@ -818,99 +756,6 @@ extern (C++) abstract class Expression : ASTNode
         return buf.extractChars();
     }
 
-    static if (__VERSION__ < 2092)
-    {
-        final void error(const(char)* format, ...) const
-        {
-            if (type != Type.terror)
-            {
-                va_list ap;
-                va_start(ap, format);
-                .verrorReport(loc, format, ap, ErrorKind.error);
-                va_end(ap);
-            }
-        }
-
-        final void errorSupplemental(const(char)* format, ...)
-        {
-            if (type == Type.terror)
-                return;
-
-            va_list ap;
-            va_start(ap, format);
-            .verrorReportSupplemental(loc, format, ap, ErrorKind.error);
-            va_end(ap);
-        }
-
-        final void warning(const(char)* format, ...) const
-        {
-            if (type != Type.terror)
-            {
-                va_list ap;
-                va_start(ap, format);
-                .verrorReport(loc, format, ap, ErrorKind.warning);
-                va_end(ap);
-            }
-        }
-
-        final void deprecation(const(char)* format, ...) const
-        {
-            if (type != Type.terror)
-            {
-                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, ...) const
-        {
-            if (type != Type.terror)
-            {
-                va_list ap;
-                va_start(ap, format);
-                .verrorReport(loc, format, ap, ErrorKind.error);
-                va_end(ap);
-            }
-        }
-
-        pragma(printf) final void errorSupplemental(const(char)* format, ...)
-        {
-            if (type == Type.terror)
-                return;
-
-            va_list ap;
-            va_start(ap, format);
-            .verrorReportSupplemental(loc, format, ap, ErrorKind.error);
-            va_end(ap);
-        }
-
-        pragma(printf) final void warning(const(char)* format, ...) const
-        {
-            if (type != Type.terror)
-            {
-                va_list ap;
-                va_start(ap, format);
-                .verrorReport(loc, format, ap, ErrorKind.warning);
-                va_end(ap);
-            }
-        }
-
-        pragma(printf) final void deprecation(const(char)* format, ...) const
-        {
-            if (type != Type.terror)
-            {
-                va_list ap;
-                va_start(ap, format);
-                .verrorReport(loc, format, ap, ErrorKind.deprecation);
-                va_end(ap);
-            }
-        }
-    }
-
     /**********************************
      * Combine e1 and e2 by CommaExp if both are not NULL.
      */
@@ -992,7 +837,8 @@ extern (C++) abstract class Expression : ASTNode
     dinteger_t toInteger()
     {
         //printf("Expression %s\n", EXPtoString(op).ptr);
-        error("integer constant expression expected instead of `%s`", toChars());
+        if (!type.isTypeError())
+            error(loc, "integer constant expression expected instead of `%s`", toChars());
         return 0;
     }
 
@@ -1004,19 +850,19 @@ extern (C++) abstract class Expression : ASTNode
 
     real_t toReal()
     {
-        error("floating point constant expression expected instead of `%s`", toChars());
+        error(loc, "floating point constant expression expected instead of `%s`", toChars());
         return CTFloat.zero;
     }
 
     real_t toImaginary()
     {
-        error("floating point constant expression expected instead of `%s`", toChars());
+        error(loc, "floating point constant expression expected instead of `%s`", toChars());
         return CTFloat.zero;
     }
 
     complex_t toComplex()
     {
-        error("floating point constant expression expected instead of `%s`", toChars());
+        error(loc, "floating point constant expression expected instead of `%s`", toChars());
         return complex_t(CTFloat.zero);
     }
 
@@ -1045,9 +891,9 @@ extern (C++) abstract class Expression : ASTNode
             loc = e.loc;
 
         if (e.op == EXP.type)
-            error("`%s` is a `%s` definition and cannot be modified", e.type.toChars(), e.type.kind());
+            error(loc, "`%s` is a `%s` definition and cannot be modified", e.type.toChars(), e.type.kind());
         else
-            error("`%s` is not an lvalue and cannot be modified", e.toChars());
+            error(loc, "`%s` is not an lvalue and cannot be modified", e.toChars());
 
         return ErrorExp.get();
     }
@@ -1071,17 +917,17 @@ extern (C++) abstract class Expression : ASTNode
                             break;
                         if (!ff.type.isMutable)
                         {
-                            error("cannot modify `%s` in `%s` function", toChars(), MODtoChars(type.mod));
+                            error(loc, "cannot modify `%s` in `%s` function", toChars(), MODtoChars(type.mod));
                             return ErrorExp.get();
                         }
                     }
                 }
-                error("cannot modify `%s` expression `%s`", MODtoChars(type.mod), toChars());
+                error(loc, "cannot modify `%s` expression `%s`", MODtoChars(type.mod), toChars());
                 return ErrorExp.get();
             }
             else if (!type.isAssignable())
             {
-                error("cannot modify struct instance `%s` of type `%s` because it contains `const` or `immutable` members",
+                error(loc, "cannot modify struct instance `%s` of type `%s` because it contains `const` or `immutable` members",
                     toChars(), type.toChars());
                 return ErrorExp.get();
             }
@@ -1136,7 +982,7 @@ extern (C++) abstract class Expression : ASTNode
     {
         if (type && type.toBasetype().ty == Tvoid)
         {
-            error("expression `%s` is `void` and has no value", toChars());
+            error(loc, "expression `%s` is `void` and has no value", toChars());
             //print(); assert(0);
             if (!global.gag)
                 type = Type.terror;
@@ -1153,7 +999,7 @@ extern (C++) abstract class Expression : ASTNode
             return true;
         if (!type.isscalar())
         {
-            error("`%s` is not a scalar, it is a `%s`", toChars(), type.toChars());
+            error(loc, "`%s` is not a scalar, it is a `%s`", toChars(), type.toChars());
             return true;
         }
         return checkValue();
@@ -1167,7 +1013,7 @@ extern (C++) abstract class Expression : ASTNode
             return true;
         if (type.toBasetype().ty == Tbool)
         {
-            error("operation not allowed on `bool` `%s`", toChars());
+            error(loc, "operation not allowed on `bool` `%s`", toChars());
             return true;
         }
         return false;
@@ -1181,7 +1027,7 @@ extern (C++) abstract class Expression : ASTNode
             return true;
         if (!type.isintegral())
         {
-            error("`%s` is not of integral type, it is a `%s`", toChars(), type.toChars());
+            error(loc, "`%s` is not of integral type, it is a `%s`", toChars(), type.toChars());
             return true;
         }
         return checkValue();
@@ -1199,7 +1045,7 @@ extern (C++) abstract class Expression : ASTNode
             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());
+            error(loc, msg, EXPtoString(op).ptr, toChars(), type.toChars());
             return true;
         }
         return checkValue();
@@ -1240,7 +1086,7 @@ extern (C++) abstract class Expression : ASTNode
         // If the call has a pure parent, then the called func must be pure.
         if (!f.isPure() && checkImpure(sc, loc, null, f))
         {
-            error("`pure` %s `%s` cannot call impure %s `%s`",
+            error(loc, "`pure` %s `%s` cannot call impure %s `%s`",
                 sc.func.kind(), sc.func.toPrettyChars(), f.kind(),
                 f.toPrettyChars());
 
@@ -1379,7 +1225,7 @@ extern (C++) abstract class Expression : ASTNode
 
             if (checkImpure(sc, loc, "`pure` %s `%s` cannot access mutable static data `%s`", v))
             {
-                error("`pure` %s `%s` cannot access mutable static data `%s`",
+                error(loc, "`pure` %s `%s` cannot access mutable static data `%s`",
                     sc.func.kind(), sc.func.toPrettyChars(), v.toChars());
                 err = true;
             }
@@ -1424,7 +1270,7 @@ extern (C++) abstract class Expression : ASTNode
                         OutBuffer vbuf;
                         MODMatchToBuffer(&ffbuf, ff.type.mod, v.type.mod);
                         MODMatchToBuffer(&vbuf, v.type.mod, ff.type.mod);
-                        error("%s%s `%s` cannot access %sdata `%s`",
+                        error(loc, "%s%s `%s` cannot access %sdata `%s`",
                             ffbuf.peekChars(), ff.kind(), ff.toPrettyChars(), vbuf.peekChars(), v.toChars());
                         err = true;
                         break;
@@ -1483,7 +1329,7 @@ extern (C++) abstract class Expression : ASTNode
             {
                 if (sc.varDecl.storage_class & STC.safe)
                 {
-                    error("`@safe` variable `%s` cannot be initialized by calling `@system` function `%s`",
+                    error(loc, "`@safe` variable `%s` cannot be initialized by calling `@system` function `%s`",
                         sc.varDecl.toChars(), f.toChars());
                     return true;
                 }
@@ -1504,7 +1350,7 @@ extern (C++) abstract class Expression : ASTNode
                     loc = sc.func.loc;
 
                 const prettyChars = f.toPrettyChars();
-                error("`@safe` %s `%s` cannot call `@system` %s `%s`",
+                error(loc, "`@safe` %s `%s` cannot call `@system` %s `%s`",
                     sc.func.kind(), sc.func.toPrettyChars(), f.kind(),
                     prettyChars);
                 if (!f.isDtorDeclaration)
@@ -1568,7 +1414,7 @@ extern (C++) abstract class Expression : ASTNode
                     || f.ident == Id._d_arrayappendT || f.ident == Id._d_arrayappendcTX
                     || f.ident == Id._d_arraycatnTX || f.ident == Id._d_newclassT))
                 {
-                    error("`@nogc` %s `%s` cannot call non-@nogc %s `%s`",
+                    error(loc, "`@nogc` %s `%s` cannot call non-@nogc %s `%s`",
                         sc.func.kind(), sc.func.toPrettyChars(), f.kind(), f.toPrettyChars());
 
                     if (!f.isDtorDeclaration)
@@ -1628,7 +1474,7 @@ extern (C++) abstract class Expression : ASTNode
                 //        sc.intypeof, sc.getStructClassScope(), func, fdthis);
                 auto t = ve.var.isThis();
                 assert(t);
-                error("accessing non-static variable `%s` requires an instance of `%s`", ve.var.toChars(), t.toChars());
+                error(loc, "accessing non-static variable `%s` requires an instance of `%s`", ve.var.toChars(), t.toChars());
                 return true;
             }
         }
@@ -1661,8 +1507,8 @@ extern (C++) abstract class Expression : ASTNode
             break;
         }
 
-        error("read-modify-write operations are not allowed for `shared` variables");
-        errorSupplemental("Use `core.atomic.atomicOp!\"%s\"(%s, %s)` instead",
+        error(loc, "read-modify-write operations are not allowed for `shared` variables");
+        errorSupplemental(loc, "Use `core.atomic.atomicOp!\"%s\"(%s, %s)` instead",
                           EXPtoString(rmwOp).ptr, toChars(), ex ? ex.toChars() : "1");
         return true;
     }
@@ -1862,7 +1708,10 @@ extern (C++) abstract class Expression : ASTNode
         inout(IdentityExp) isIdentityExp() { return (op == EXP.identity || op == EXP.notIdentity) ? cast(typeof(return))this : null; }
         inout(CondExp)     isCondExp() { return op == EXP.question ? cast(typeof(return))this : null; }
         inout(GenericExp)  isGenericExp() { return op == EXP._Generic ? cast(typeof(return))this : null; }
-        inout(DefaultInitExp)    isDefaultInitExp() { return isDefaultInitOp(op) ? cast(typeof(return))this: null; }
+        inout(DefaultInitExp)    isDefaultInitExp() { return
+            (op == EXP.prettyFunction    || op == EXP.functionString ||
+             op == EXP.line              || op == EXP.moduleString   ||
+             op == EXP.file              || op == EXP.fileFullPath   ) ? cast(typeof(return))this : null; }
         inout(FileInitExp)       isFileInitExp() { return (op == EXP.file || op == EXP.fileFullPath) ? cast(typeof(return))this : null; }
         inout(LineInitExp)       isLineInitExp() { return op == EXP.line ? cast(typeof(return))this : null; }
         inout(ModuleInitExp)     isModuleInitExp() { return op == EXP.moduleString ? cast(typeof(return))this : null; }
@@ -1910,7 +1759,7 @@ extern (C++) final class IntegerExp : Expression
         {
             //printf("%s, loc = %d\n", toChars(), loc.linnum);
             if (type.ty != Terror)
-                error("integral constant must be scalar type, not `%s`", type.toChars());
+                error(loc, "integral constant must be scalar type, not `%s`", type.toChars());
             type = Type.terror;
         }
         this.type = type;
@@ -1988,7 +1837,7 @@ extern (C++) final class IntegerExp : Expression
             e = this;
         else if (!loc.isValid())
             loc = e.loc;
-        e.error("cannot modify constant `%s`", e.toChars());
+        error(e.loc, "cannot modify constant `%s`", e.toChars());
         return ErrorExp.get();
     }
 
@@ -2172,11 +2021,6 @@ extern (C++) final class VoidInitExp : Expression
         this.type = var.type;
     }
 
-    override const(char)* toChars() const
-    {
-        return "void";
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -2210,6 +2054,21 @@ extern (C++) final class RealExp : Expression
         emplaceExp!(RealExp)(pue, loc, value, type);
     }
 
+    /********************************
+     * Test to see if two reals are the same.
+     * Regard NaN's as equivalent.
+     * Regard +0 and -0 as different.
+     * Params:
+     *      x1 = first operand
+     *      x2 = second operand
+     * Returns:
+     *      true if x1 is x2
+     *      else false
+     */
+    private static bool RealIdentical(real_t x1, real_t x2) @safe
+    {
+        return (CTFloat.isNaN(x1) && CTFloat.isNaN(x2)) || CTFloat.isIdentical(x1, x2);
+    }
     override bool equals(const RootObject o) const
     {
         if (this == o)
@@ -2299,7 +2158,9 @@ extern (C++) final class ComplexExp : Expression
             return true;
         if (auto ne = (cast(Expression)o).isComplexExp())
         {
-            if (type.toHeadMutable().equals(ne.type.toHeadMutable()) && RealIdentical(creall(value), creall(ne.value)) && RealIdentical(cimagl(value), cimagl(ne.value)))
+            if (type.toHeadMutable().equals(ne.type.toHeadMutable()) &&
+                RealExp.RealIdentical(creall(value), creall(ne.value)) &&
+                RealExp.RealIdentical(cimagl(value), cimagl(ne.value)))
             {
                 return true;
             }
@@ -2594,6 +2455,9 @@ extern (C++) final class StringExp : Expression
      */
     bool committed;
 
+    /// If the string is parsed from a hex string literal
+    bool hexString = false;
+
     enum char NoPostfix = 0;
 
     extern (D) this(const ref Loc loc, const(void)[] string) scope
@@ -2685,7 +2549,7 @@ extern (C++) final class StringExp : Expression
             {
                 if (const s = utf_decodeChar(string[0 .. len], u, c))
                 {
-                    error("%.*s", cast(int)s.length, s.ptr);
+                    error(loc, "%.*s", cast(int)s.length, s.ptr);
                     return 0;
                 }
                 result += utf_codeLength(encSize, c);
@@ -2697,7 +2561,7 @@ extern (C++) final class StringExp : Expression
             {
                 if (const s = utf_decodeWchar(wstring[0 .. len], u, c))
                 {
-                    error("%.*s", cast(int)s.length, s.ptr);
+                    error(loc, "%.*s", cast(int)s.length, s.ptr);
                     return 0;
                 }
                 result += utf_codeLength(encSize, c);
@@ -2902,7 +2766,7 @@ extern (C++) final class StringExp : Expression
 
     override Expression modifiableLvalue(Scope* sc, Expression e)
     {
-        error("cannot modify string literal `%s`", toChars());
+        error(loc, "cannot modify string literal `%s`", toChars());
         return ErrorExp.get();
     }
 
@@ -3035,7 +2899,7 @@ extern (C++) final class TupleExp : Expression
             }
             else
             {
-                error("`%s` is not an expression", o.toChars());
+                error(loc, "`%s` is not an expression", o.toChars());
             }
         }
     }
@@ -3571,13 +3435,13 @@ extern (C++) final class TypeExp : Expression
 
     override bool checkType()
     {
-        error("type `%s` is not an expression", toChars());
+        error(loc, "type `%s` is not an expression", toChars());
         return true;
     }
 
     override bool checkValue()
     {
-        error("type `%s` has no value", toChars());
+        error(loc, "type `%s` has no value", toChars());
         return true;
     }
 
@@ -3617,7 +3481,7 @@ extern (C++) final class ScopeExp : Expression
     {
         if (sds.isPackage())
         {
-            error("%s `%s` has no type", sds.kind(), sds.toChars());
+            error(loc, "%s `%s` has no type", sds.kind(), sds.toChars());
             return true;
         }
         if (auto ti = sds.isTemplateInstance())
@@ -3627,7 +3491,7 @@ extern (C++) final class ScopeExp : Expression
                 ti.semantictiargsdone &&
                 ti.semanticRun == PASS.initial)
             {
-                error("partial %s `%s` has no type", sds.kind(), toChars());
+                error(loc, "partial %s `%s` has no type", sds.kind(), toChars());
                 return true;
             }
         }
@@ -3636,7 +3500,7 @@ extern (C++) final class ScopeExp : Expression
 
     override bool checkValue()
     {
-        error("%s `%s` has no value", sds.kind(), sds.toChars());
+        error(loc, "%s `%s` has no value", sds.kind(), sds.toChars());
         return true;
     }
 
@@ -3678,13 +3542,13 @@ extern (C++) final class TemplateExp : Expression
 
     override bool checkType()
     {
-        error("%s `%s` has no type", td.kind(), toChars());
+        error(loc, "%s `%s` has no type", td.kind(), toChars());
         return true;
     }
 
     override bool checkValue()
     {
-        error("%s `%s` has no value", td.kind(), toChars());
+        error(loc, "%s `%s` has no value", td.kind(), toChars());
         return true;
     }
 
@@ -3877,22 +3741,22 @@ extern (C++) final class VarExp : SymbolExp
     {
         if (var.storage_class & STC.manifest)
         {
-            error("manifest constant `%s` cannot be modified", var.toChars());
+            error(loc, "manifest constant `%s` cannot be modified", var.toChars());
             return ErrorExp.get();
         }
         if (var.storage_class & STC.lazy_ && !delegateWasExtracted)
         {
-            error("lazy variable `%s` cannot be modified", var.toChars());
+            error(loc, "lazy variable `%s` cannot be modified", var.toChars());
             return ErrorExp.get();
         }
         if (var.ident == Id.ctfe)
         {
-            error("cannot modify compiler-generated variable `__ctfe`");
+            error(loc, "cannot modify compiler-generated variable `__ctfe`");
             return ErrorExp.get();
         }
         if (var.ident == Id.dollar) // https://issues.dlang.org/show_bug.cgi?id=13574
         {
-            error("cannot modify operator `$`");
+            error(loc, "cannot modify operator `$`");
             return ErrorExp.get();
         }
         return this;
@@ -3903,7 +3767,7 @@ extern (C++) final class VarExp : SymbolExp
         //printf("VarExp::modifiableLvalue('%s')\n", var.toChars());
         if (var.storage_class & STC.manifest)
         {
-            error("cannot modify manifest constant `%s`", toChars());
+            error(loc, "cannot modify manifest constant `%s`", toChars());
             return ErrorExp.get();
         }
         // See if this expression is a modifiable lvalue (i.e. not const)
@@ -4219,7 +4083,7 @@ extern (C++) final class FuncExp : Expression
     {
         if (td)
         {
-            error("template lambda has no type");
+            error(loc, "template lambda has no type");
             return true;
         }
         return false;
@@ -4229,7 +4093,7 @@ extern (C++) final class FuncExp : Expression
     {
         if (td)
         {
-            error("template lambda has no value");
+            error(loc, "template lambda has no value");
             return true;
         }
         return false;
@@ -4425,11 +4289,11 @@ extern (C++) abstract class UnaExp : Expression
 
         if (e1.op == EXP.type)
         {
-            error("incompatible type for `%s(%s)`: cannot use `%s` with types", EXPtoString(op).ptr, e1.toChars(), EXPtoString(op).ptr);
+            error(loc, "incompatible type for `%s(%s)`: cannot use `%s` with types", EXPtoString(op).ptr, e1.toChars(), EXPtoString(op).ptr);
         }
         else
         {
-            error("incompatible type for `%s(%s)`: `%s`", EXPtoString(op).ptr, e1.toChars(), e1.type.toChars());
+            error(loc, "incompatible type for `%s(%s)`: `%s`", EXPtoString(op).ptr, e1.toChars(), e1.type.toChars());
         }
         return ErrorExp.get();
     }
@@ -4504,18 +4368,18 @@ extern (C++) abstract class BinExp : Expression
         const(char)* thisOp = (op == EXP.question) ? ":" : EXPtoString(op).ptr;
         if (e1.op == EXP.type || e2.op == EXP.type)
         {
-            error("incompatible types for `(%s) %s (%s)`: cannot use `%s` with types",
+            error(loc, "incompatible types for `(%s) %s (%s)`: cannot use `%s` with types",
                 e1.toChars(), thisOp, e2.toChars(), EXPtoString(op).ptr);
         }
         else if (e1.type.equals(e2.type))
         {
-            error("incompatible types for `(%s) %s (%s)`: both operands are of type `%s`",
+            error(loc, "incompatible types for `(%s) %s (%s)`: both operands are of type `%s`",
                 e1.toChars(), thisOp, e2.toChars(), e1.type.toChars());
         }
         else
         {
             auto ts = toAutoQualChars(e1.type, e2.type);
-            error("incompatible types for `(%s) %s (%s)`: `%s` and `%s`",
+            error(loc, "incompatible types for `(%s) %s (%s)`: `%s` and `%s`",
                 e1.toChars(), thisOp, e2.toChars(), ts[0], ts[1]);
         }
         return ErrorExp.get();
@@ -4536,7 +4400,7 @@ extern (C++) abstract class BinExp : Expression
         {
             if ((type.isintegral() && t2.isfloating()))
             {
-                warning("`%s %s %s` is performing truncating conversion", type.toChars(), EXPtoString(op).ptr, t2.toChars());
+                warning(loc, "`%s %s %s` is performing truncating conversion", type.toChars(), EXPtoString(op).ptr, t2.toChars());
             }
         }
 
@@ -4548,17 +4412,17 @@ extern (C++) abstract class BinExp : Expression
             const(char)* opstr = EXPtoString(op).ptr;
             if (t1.isreal() && t2.iscomplex())
             {
-                error("`%s %s %s` is undefined. Did you mean `%s %s %s.re`?", t1.toChars(), opstr, t2.toChars(), t1.toChars(), opstr, t2.toChars());
+                error(loc, "`%s %s %s` is undefined. Did you mean `%s %s %s.re`?", t1.toChars(), opstr, t2.toChars(), t1.toChars(), opstr, t2.toChars());
                 return ErrorExp.get();
             }
             else if (t1.isimaginary() && t2.iscomplex())
             {
-                error("`%s %s %s` is undefined. Did you mean `%s %s %s.im`?", t1.toChars(), opstr, t2.toChars(), t1.toChars(), opstr, t2.toChars());
+                error(loc, "`%s %s %s` is undefined. Did you mean `%s %s %s.im`?", t1.toChars(), opstr, t2.toChars(), t1.toChars(), opstr, t2.toChars());
                 return ErrorExp.get();
             }
             else if ((t1.isreal() || t1.isimaginary()) && t2.isimaginary())
             {
-                error("`%s %s %s` is an undefined operation", t1.toChars(), opstr, t2.toChars());
+                error(loc, "`%s %s %s` is an undefined operation", t1.toChars(), opstr, t2.toChars());
                 return ErrorExp.get();
             }
         }
@@ -4570,7 +4434,7 @@ extern (C++) abstract class BinExp : Expression
             // Thus, r+=i, r+=c, i+=r, i+=c are all forbidden operations.
             if ((t1.isreal() && (t2.isimaginary() || t2.iscomplex())) || (t1.isimaginary() && (t2.isreal() || t2.iscomplex())))
             {
-                error("`%s %s %s` is undefined (result is complex)", t1.toChars(), EXPtoString(op).ptr, t2.toChars());
+                error(loc, "`%s %s %s` is undefined (result is complex)", t1.toChars(), EXPtoString(op).ptr, t2.toChars());
                 return ErrorExp.get();
             }
             if (type.isreal() || type.isimaginary())
@@ -4661,7 +4525,7 @@ extern (C++) abstract class BinExp : Expression
         {
             if (t2.iscomplex())
             {
-                error("cannot perform modulo complex arithmetic");
+                error(loc, "cannot perform modulo complex arithmetic");
                 return ErrorExp.get();
             }
         }
@@ -4950,13 +4814,13 @@ extern (C++) final class DotTemplateExp : UnaExp
 
     override bool checkType()
     {
-        error("%s `%s` has no type", td.kind(), toChars());
+        error(loc, "%s `%s` has no type", td.kind(), toChars());
         return true;
     }
 
     override bool checkValue()
     {
-        error("%s `%s` has no value", td.kind(), toChars());
+        error(loc, "%s `%s` has no value", td.kind(), toChars());
         return true;
     }
 
@@ -5125,7 +4989,7 @@ extern (C++) final class DotTemplateInstanceExp : UnaExp
             ti.semantictiargsdone &&
             ti.semanticRun == PASS.initial)
         {
-            error("partial %s `%s` has no type", ti.kind(), toChars());
+            error(loc, "partial %s `%s` has no type", ti.kind(), toChars());
             return true;
         }
         return false;
@@ -5137,9 +5001,9 @@ extern (C++) final class DotTemplateInstanceExp : UnaExp
             ti.semantictiargsdone &&
             ti.semanticRun == PASS.initial)
 
-            error("partial %s `%s` has no value", ti.kind(), toChars());
+            error(loc, "partial %s `%s` has no value", ti.kind(), toChars());
         else
-            error("%s `%s` has no value", ti.kind(), ti.toChars());
+            error(loc, "%s `%s` has no value", ti.kind(), ti.toChars());
         return true;
     }
 
@@ -5484,9 +5348,9 @@ extern (C++) final class PtrExp : UnaExp
         if (var && var.type.isFunction_Delegate_PtrToFunction())
         {
             if (var.type.isTypeFunction())
-                error("function `%s` is not an lvalue and cannot be modified", var.toChars());
+                error(loc, "function `%s` is not an lvalue and cannot be modified", var.toChars());
             else
-                error("function pointed to by `%s` is not an lvalue and cannot be modified", var.toChars());
+                error(loc, "function pointed to by `%s` is not an lvalue and cannot be modified", var.toChars());
             return ErrorExp.get();
         }
         return Expression.modifiableLvalue(sc, e);
@@ -5774,7 +5638,7 @@ extern (C++) final class SliceExp : UnaExp
 
     override Expression modifiableLvalue(Scope* sc, Expression e)
     {
-        error("slice expression `%s` is not a modifiable lvalue", toChars());
+        error(loc, "slice expression `%s` is not a modifiable lvalue", toChars());
         return this;
     }
 
@@ -5848,7 +5712,7 @@ extern (C++) final class ArrayExp : UnaExp
     override Expression toLvalue(Scope* sc, Expression e)
     {
         if (type && type.toBasetype().ty == Tvoid)
-            error("`void`s have no value");
+            error(loc, "`void`s have no value");
         return this;
     }
 
@@ -6116,7 +5980,7 @@ extern (C++) final class IndexExp : BinExp
             Type t2b = e2.type.toBasetype();
             if (t2b.ty == Tarray && t2b.nextOf().isMutable())
             {
-                error("associative arrays can only be assigned values with immutable keys, not `%s`", e2.type.toChars());
+                error(loc, "associative arrays can only be assigned values with immutable keys, not `%s`", e2.type.toChars());
                 return ErrorExp.get();
             }
             modifiable = true;
@@ -6975,7 +6839,7 @@ extern (C++) final class CondExp : BinExp
     {
         if (!e1.isLvalue() && !e2.isLvalue())
         {
-            error("conditional expression `%s` is not a modifiable lvalue", toChars());
+            error(loc, "conditional expression `%s` is not a modifiable lvalue", toChars());
             return ErrorExp.get();
         }
         e1 = e1.modifiableLvalue(sc, e1);
@@ -7061,14 +6925,6 @@ extern (C++) final class CondExp : BinExp
     }
 }
 
-/// Returns: if this token is the `op` for a derived `DefaultInitExp` class.
-bool isDefaultInitOp(EXP op) pure nothrow @safe @nogc
-{
-    return  op == EXP.prettyFunction    || op == EXP.functionString ||
-            op == EXP.line              || op == EXP.moduleString   ||
-            op == EXP.file              || op == EXP.fileFullPath   ;
-}
-
 /***********************************************************
  * A special keyword when used as a function's default argument
  *
@@ -7085,6 +6941,12 @@ bool isDefaultInitOp(EXP op) pure nothrow @safe @nogc
  */
 extern (C++) class DefaultInitExp : Expression
 {
+    /*************************
+     * Params:
+     *  loc = location
+     *  op = EXP.prettyFunction, EXP.functionString, EXP.moduleString,
+     *       EXP.line, EXP.file, EXP.fileFullPath
+     */
     extern (D) this(const ref Loc loc, EXP op) @safe
     {
         super(loc, op);
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index 2189757e61f3..5c656ee9353c 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -51,7 +51,7 @@ bool isTrivialExp(Expression *e);
 bool hasSideEffect(Expression *e, bool assumeImpureCalls = false);
 
 enum BE : int32_t;
-BE canThrow(Expression *e, FuncDeclaration *func, bool mustNotThrow);
+BE canThrow(Expression *e, FuncDeclaration *func, ErrorSink *eSink);
 
 typedef unsigned char OwnedBy;
 enum
@@ -93,9 +93,6 @@ public:
     DYNCAST dyncast() const override final { return DYNCAST_EXPRESSION; }
 
     const char *toChars() const override;
-    void error(const char *format, ...) const;
-    void warning(unsigned flag, const char *format, ...) const;
-    void deprecation(const char *format, ...) const;
 
     virtual dinteger_t toInteger();
     virtual uinteger_t toUInteger();
@@ -380,6 +377,7 @@ public:
     size_t len;         // number of chars, wchars, or dchars
     unsigned char sz;   // 1: char, 2: wchar, 4: dchar
     bool committed;     // if type is committed
+    bool hexString;     // if string is parsed from a hex string literal
 
     static StringExp *create(const Loc &loc, const char *s);
     static StringExp *create(const Loc &loc, const void *s, d_size_t len);
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index 30382bbc6bb5..0bdcda9fe6ea 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -171,7 +171,7 @@ StringExp semanticString(Scope *sc, Expression exp, const char* s)
     auto se = e.toStringExp();
     if (!se)
     {
-        exp.error("`string` expected for %s, not `(%s)` of type `%s`",
+        error(exp.loc, "`string` expected for %s, not `(%s)` of type `%s`",
             s, exp.toChars(), exp.type.toChars());
         return null;
     }
@@ -224,7 +224,7 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
         Lfallback:
             if (ae.arguments.length == 1)
                 return null;
-            ae.error("multi-dimensional slicing requires template `opSlice`");
+            error(ae.loc, "multi-dimensional slicing requires template `opSlice`");
             return ErrorExp.get();
         }
         //printf("[%d] e = %s\n", i, e.toChars());
@@ -274,7 +274,7 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
 
         if (!e.type)
         {
-            ae.error("`%s` has no value", e.toChars());
+            error(ae.loc, "`%s` has no value", e.toChars());
             e = ErrorExp.get();
         }
         if (e.op == EXP.error)
@@ -311,7 +311,7 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, IntervalExp ie, Expression* p
         e = resolveProperties(sc, e);
         if (!e.type)
         {
-            ae.error("`%s` has no value", e.toChars());
+            error(ae.loc, "`%s` has no value", e.toChars());
             errors = true;
         }
         return e;
@@ -482,6 +482,18 @@ private Expression searchUFCS(Scope* sc, UnaExp ue, Identifier ident)
     }
 }
 
+/******************************
+ * check e is exp.opDispatch!(tiargs) or not
+ * It's used to switch to UFCS the semantic analysis path
+ */
+private bool isDotOpDispatch(Expression e)
+{
+    if (auto dtie = e.isDotTemplateInstanceExp())
+        return dtie.ti.name == Id.opDispatch;
+    return false;
+}
+
+
 /******************************
  * Pull out callable entity with UFCS.
  */
@@ -519,12 +531,12 @@ private Expression resolveUFCS(Scope* sc, CallExp ce)
                  */
                 if (!ce.arguments || ce.arguments.length != 1)
                 {
-                    ce.error("expected key as argument to `aa.remove()`");
+                    error(ce.loc, "expected key as argument to `aa.remove()`");
                     return ErrorExp.get();
                 }
                 if (!eleft.type.isMutable())
                 {
-                    ce.error("cannot remove key from `%s` associative array `%s`", MODtoChars(t.mod), eleft.toChars());
+                    error(ce.loc, "cannot remove key from `%s` associative array `%s`", MODtoChars(t.mod), eleft.toChars());
                     return ErrorExp.get();
                 }
                 Expression key = (*ce.arguments)[0];
@@ -638,6 +650,41 @@ private Expression resolveUFCS(Scope* sc, CallExp ce)
     return null;
 }
 
+int expandAliasThisTuples(Expressions* exps, size_t starti = 0)
+{
+    if (!exps || exps.length == 0)
+        return -1;
+
+    for (size_t u = starti; u < exps.length; u++)
+    {
+        Expression exp = (*exps)[u];
+        if (TupleDeclaration td = exp.isAliasThisTuple)
+        {
+            exps.remove(u);
+            size_t i;
+            td.foreachVar((s)
+            {
+                auto d = s.isDeclaration();
+                auto e = new DotVarExp(exp.loc, exp, d);
+                assert(d.type);
+                e.type = d.type;
+                exps.insert(u + i, e);
+                ++i;
+            });
+            version (none)
+            {
+                printf("expansion ->\n");
+                foreach (e; exps)
+                {
+                    printf("\texps[%d] e = %s %s\n", i, EXPtoString(e.op), e.toChars());
+                }
+            }
+            return cast(int)u;
+        }
+    }
+    return -1;
+}
+
 /******************************
  * Pull out property with UFCS.
  */
@@ -1137,7 +1184,7 @@ L1:
              */
             if (flag)
                 return null;
-            e1.error("`this` for `%s` needs to be type `%s` not type `%s`", var.toChars(), ad.toChars(), t.toChars());
+            error(e1.loc, "`this` for `%s` needs to be type `%s` not type `%s`", var.toChars(), ad.toChars(), t.toChars());
             return ErrorExp.get();
         }
     }
@@ -1510,7 +1557,7 @@ private Type arrayExpressionToCommonType(Scope* sc, ref Expressions exps)
         e = resolveProperties(sc, e);
         if (!e.type)
         {
-            e.error("`%s` has no value", e.toChars());
+            error(e.loc, "`%s` has no value", e.toChars());
             t0 = Type.terror;
             continue;
         }
@@ -1706,7 +1753,7 @@ private bool preFunctionParameters(Scope* sc, ArgumentList argumentList, const b
                 {
                     if (reportErrors)
                     {
-                        arg.error("cannot pass type `%s` as a function argument", arg.toChars());
+                        error(arg.loc, "cannot pass type `%s` as a function argument", arg.toChars());
                         arg = ErrorExp.get();
                     }
                     err = true;
@@ -1716,7 +1763,7 @@ private bool preFunctionParameters(Scope* sc, ArgumentList argumentList, const b
             {
                 if (reportErrors)
                 {
-                    arg.error("cannot pass function `%s` as a function argument", arg.toChars());
+                    error(arg.loc, "cannot pass function `%s` as a function argument", arg.toChars());
                     arg = ErrorExp.get();
                 }
                 err = true;
@@ -1745,7 +1792,7 @@ private bool checkDefCtor(Loc loc, Type t)
         StructDeclaration sd = ts.sym;
         if (sd.noDefaultCtor)
         {
-            sd.error(loc, "default construction is disabled");
+            .error(loc, "%s `%s` default construction is disabled", sd.kind, sd.toPrettyChars);
             return true;
         }
     }
@@ -1887,7 +1934,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
             }
             else
             {
-                if (isDefaultInitOp(arg.op))
+                if (arg.isDefaultInitExp())
                 {
                     arg = arg.resolveLoc(loc, sc);
                     (*arguments)[i] = arg;
@@ -2138,7 +2185,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
                 Type t = arg.type;
                 if (!t.isMutable() || !t.isAssignable()) // check blit assignable
                 {
-                    arg.error("cannot modify struct `%s` with immutable members", arg.toChars());
+                    error(arg.loc, "cannot modify struct `%s` with immutable members", arg.toChars());
                     err = true;
                 }
                 else
@@ -2270,12 +2317,12 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
                     const(char)* p = tf.linkage == LINK.c ? "extern(C)" : "extern(C++)";
                     if (arg.type.ty == Tarray)
                     {
-                        arg.error("cannot pass dynamic arrays to `%s` vararg functions", p);
+                        error(arg.loc, "cannot pass dynamic arrays to `%s` vararg functions", p);
                         err = true;
                     }
                     if (arg.type.ty == Tsarray)
                     {
-                        arg.error("cannot pass static arrays to `%s` vararg functions", p);
+                        error(arg.loc, "cannot pass static arrays to `%s` vararg functions", p);
                         err = true;
                     }
                 }
@@ -2284,12 +2331,12 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
             // Do not allow types that need destructors or copy constructors.
             if (arg.type.needsDestruction())
             {
-                arg.error("cannot pass types that need destruction as variadic arguments");
+                error(arg.loc, "cannot pass types that need destruction as variadic arguments");
                 err = true;
             }
             if (arg.type.needsCopyOrPostblit())
             {
-                arg.error("cannot pass types with postblits or copy constructors as variadic arguments");
+                error(arg.loc, "cannot pass types with postblits or copy constructors as variadic arguments");
                 err = true;
             }
 
@@ -2313,7 +2360,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
             {
                 if (se.hasOverloads && !se.var.isFuncDeclaration().isUnique())
                 {
-                    arg.error("function `%s` is overloaded", arg.toChars());
+                    error(arg.loc, "function `%s` is overloaded", arg.toChars());
                     err = true;
                 }
             }
@@ -2370,7 +2417,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
         for (ptrdiff_t i = 0; i != nargs; i++)
         {
             Expression arg = (*arguments)[i];
-            if (canThrow(arg, sc.func, false))
+            if (canThrow(arg, sc.func, null))
                 lastthrow = i;
             if (arg.type.needsDestruction())
             {
@@ -2752,7 +2799,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     Dsymbol s2;
                     if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s != s2)
                     {
-                        exp.error("with symbol `%s` is shadowing local symbol `%s`", s.toPrettyChars(), s2.toPrettyChars());
+                        error(exp.loc, "with symbol `%s` is shadowing local symbol `%s`", s.toPrettyChars(), s2.toPrettyChars());
                         return setError();
                     }
                 }
@@ -2852,7 +2899,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         {
             if (sc.flags & SCOPE.ctfe)
             {
-                exp.error("variable `__ctfe` cannot be read at compile time");
+                error(exp.loc, "variable `__ctfe` cannot be read at compile time");
                 return setError();
             }
 
@@ -2914,15 +2961,15 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         /* Look for what user might have meant
          */
         if (const n = importHint(exp.ident.toString()))
-            exp.error("`%s` is not defined, perhaps `import %.*s;` is needed?", exp.ident.toChars(), cast(int)n.length, n.ptr);
+            error(exp.loc, "`%s` is not defined, perhaps `import %.*s;` is needed?", exp.ident.toChars(), cast(int)n.length, n.ptr);
         else if (auto s2 = sc.search_correct(exp.ident))
-            exp.error("undefined identifier `%s`, did you mean %s `%s`?", exp.ident.toChars(), s2.kind(), s2.toChars());
+            error(exp.loc, "undefined identifier `%s`, did you mean %s `%s`?", exp.ident.toChars(), s2.kind(), s2.toChars());
         else if (const p = Scope.search_correct_C(exp.ident))
-            exp.error("undefined identifier `%s`, did you mean `%s`?", exp.ident.toChars(), p);
+            error(exp.loc, "undefined identifier `%s`, did you mean `%s`?", exp.ident.toChars(), p);
         else if (exp.ident == Id.dollar)
-            exp.error("undefined identifier `$`");
+            error(exp.loc, "undefined identifier `$`");
         else
-            exp.error("undefined identifier `%s`", exp.ident.toChars());
+            error(exp.loc, "undefined identifier `%s`", exp.ident.toChars());
 
         result = ErrorExp.get();
     }
@@ -2957,7 +3004,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             {
                 if (!s)
                 {
-                    e.error("`%s` is not in a class or struct scope", e.toChars());
+                    error(e.loc, "`%s` is not in a class or struct scope", e.toChars());
                     return setError();
                 }
                 ClassDeclaration cd = s.isClassDeclaration();
@@ -2978,7 +3025,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         }
         if (!fd)
         {
-            e.error("`this` is only defined in non-static member functions, not `%s`", sc.parent.toChars());
+            error(e.loc, "`this` is only defined in non-static member functions, not `%s`", sc.parent.toChars());
             return setError();
         }
 
@@ -3023,7 +3070,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             {
                 if (!s)
                 {
-                    e.error("`%s` is not in a class scope", e.toChars());
+                    error(e.loc, "`%s` is not in a class scope", e.toChars());
                     return setError();
                 }
                 cd = s.isClassDeclaration();
@@ -3032,7 +3079,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     cd = cd.baseClass;
                     if (!cd)
                     {
-                        e.error("class `%s` has no `super`", s.toChars());
+                        error(e.loc, "class `%s` has no `super`", s.toChars());
                         return setError();
                     }
                     e.type = cd.type;
@@ -3057,7 +3104,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             goto Lerr;
         if (!cd.baseClass)
         {
-            e.error("no base class for `%s`", cd.toChars());
+            error(e.loc, "no base class for `%s`", cd.toChars());
             e.type = cd.type.addMod(e.var.type.mod);
         }
         else
@@ -3073,7 +3120,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         return;
 
     Lerr:
-        e.error("`super` is only allowed in non-static class member functions");
+        error(e.loc, "`super` is only allowed in non-static class member functions");
         result = ErrorExp.get();
     }
 
@@ -3117,7 +3164,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             {
                 if (const p = utf_decodeChar(e.peekString(), u, c))
                 {
-                    e.error("%.*s", cast(int)p.length, p.ptr);
+                    error(e.loc, "%.*s", cast(int)p.length, p.ptr);
                     return setError();
                 }
                 else
@@ -3140,7 +3187,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             {
                 if (const p = utf_decodeChar(e.peekString(), u, c))
                 {
-                    e.error("%.*s", cast(int)p.length, p.ptr);
+                    error(e.loc, "%.*s", cast(int)p.length, p.ptr);
                     return setError();
                 }
                 else
@@ -3201,7 +3248,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             e = e.expressionSemantic(sc);
             if (!e.type)
             {
-                exp.error("`%s` has no value", e.toChars());
+                error(exp.loc, "`%s` has no value", e.toChars());
                 err = true;
             }
             else if (e.op == EXP.error)
@@ -3257,7 +3304,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
          */
         if (e.elements.length > 0 && t0.ty == Tvoid)
         {
-            e.error("`%s` of type `%s` has no value", e.toChars(), e.type.toChars());
+            error(e.loc, "`%s` of type `%s` has no value", e.toChars(), e.type.toChars());
             return setError();
         }
 
@@ -3289,7 +3336,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         expandTuples(e.values);
         if (e.keys.length != e.values.length)
         {
-            e.error("number of keys is %llu, must match number of values %llu",
+            error(e.loc, "number of keys is %llu, must match number of values %llu",
                         cast(ulong) e.keys.length, cast(ulong) e.values.length);
             return setError();
         }
@@ -3500,7 +3547,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             {
                 if (!v.type)
                 {
-                    exp.error("forward reference of %s `%s`", v.kind(), v.toChars());
+                    error(exp.loc, "forward reference of %s `%s`", v.kind(), v.toChars());
                     return setError();
                 }
                 if ((v.storage_class & STC.manifest) && v._init)
@@ -3521,7 +3568,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                      */
                     if (ti.inuse)
                     {
-                        exp.error("recursive expansion of %s `%s`", ti.kind(), ti.toPrettyChars());
+                        error(exp.loc, "recursive expansion of %s `%s`", ti.kind(), ti.toPrettyChars());
                         return setError();
                     }
                     v.checkDeprecated(exp.loc, sc);
@@ -3658,7 +3705,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             cdthis = exp.thisexp.type.isClassHandle();
             if (!cdthis)
             {
-                exp.error("`this` for nested class must be a class type, not `%s`", exp.thisexp.type.toChars());
+                error(exp.loc, "`this` for nested class must be a class type, not `%s`", exp.thisexp.type.toChars());
                 return setError();
             }
 
@@ -3706,7 +3753,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
         if (exp.thisexp && tb.ty != Tclass)
         {
-            exp.error("`.new` is only for allocating nested classes, not `%s`", tb.toChars());
+            error(exp.loc, "`.new` is only for allocating nested classes, not `%s`", tb.toChars());
             return setError();
         }
 
@@ -3725,19 +3772,19 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 cd.ctor = cd.searchCtor();
             if (cd.noDefaultCtor && !nargs && !cd.defaultCtor)
             {
-                exp.error("default construction is disabled for type `%s`", cd.type.toChars());
+                error(exp.loc, "default construction is disabled for type `%s`", cd.type.toChars());
                 return setError();
             }
 
             if (cd.isInterfaceDeclaration())
             {
-                exp.error("cannot create instance of interface `%s`", cd.toChars());
+                error(exp.loc, "cannot create instance of interface `%s`", cd.toChars());
                 return setError();
             }
 
             if (cd.isAbstract())
             {
-                exp.error("cannot create instance of abstract class `%s`", cd.toChars());
+                error(exp.loc, "cannot create instance of abstract class `%s`", cd.toChars());
                 errorSupplemental(cd.loc, "class `%s` is declared here", cd.toChars());
                 for (size_t i = 0; i < cd.vtbl.length; i++)
                 {
@@ -3767,9 +3814,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                         void noReferenceToOuterClass()
                         {
                             if (cd.isAnonymous)
-                                exp.error("cannot construct anonymous nested class because no implicit `this` reference to outer class is available");
+                                error(exp.loc, "cannot construct anonymous nested class because no implicit `this` reference to outer class is available");
                             else
-                                exp.error("cannot construct nested class `%s` because no implicit `this` reference to outer class `%s` is available",
+                                error(exp.loc, "cannot construct nested class `%s` because no implicit `this` reference to outer class `%s` is available",
                                     cd.toChars(), cdn.toChars());
                             return setError();
                         }
@@ -3800,20 +3847,20 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     if (cdthis != cdn && !cdn.isBaseOf(cdthis, null))
                     {
                         //printf("cdthis = %s\n", cdthis.toChars());
-                        exp.error("`this` for nested class must be of type `%s`, not `%s`",
+                        error(exp.loc, "`this` for nested class must be of type `%s`, not `%s`",
                             cdn.toChars(), exp.thisexp.type.toChars());
                         return setError();
                     }
                     if (!MODimplicitConv(exp.thisexp.type.mod, exp.newtype.mod))
                     {
-                        exp.error("nested type `%s` should have the same or weaker constancy as enclosing type `%s`",
+                        error(exp.loc, "nested type `%s` should have the same or weaker constancy as enclosing type `%s`",
                             exp.newtype.toChars(), exp.thisexp.type.toChars());
                         return setError();
                     }
                 }
                 else if (exp.thisexp)
                 {
-                    exp.error("`.new` is only for allocating nested classes");
+                    error(exp.loc, "`.new` is only for allocating nested classes");
                     return setError();
                 }
                 else if (auto fdn = s.isFuncDeclaration())
@@ -3821,7 +3868,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     // make sure the parent context fdn of cd is reachable from sc
                     if (!ensureStaticLinkTo(sc.parent, fdn))
                     {
-                        exp.error("outer function context of `%s` is needed to `new` nested class `%s`",
+                        error(exp.loc, "outer function context of `%s` is needed to `new` nested class `%s`",
                             fdn.toPrettyChars(), cd.toPrettyChars());
                         return setError();
                     }
@@ -3831,7 +3878,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             }
             else if (exp.thisexp)
             {
-                exp.error("`.new` is only for allocating nested classes");
+                error(exp.loc, "`.new` is only for allocating nested classes");
                 return setError();
             }
 
@@ -3844,7 +3891,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                         te = getRightThis(exp.loc, sc, ad2, te, cd);
                     if (te.op == EXP.error)
                     {
-                        exp.error("need `this` of type `%s` needed to `new` nested class `%s`", ad2.toChars(), cd.toChars());
+                        error(exp.loc, "need `this` of type `%s` needed to `new` nested class `%s`", ad2.toChars(), cd.toChars());
                         return setError();
                     }
                 }
@@ -3852,7 +3899,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
             if (cd.disableNew && !exp.onstack)
             {
-                exp.error("cannot allocate `class %s` with `new` because it is annotated with `@disable new()`",
+                error(exp.loc, "cannot allocate `class %s` with `new` because it is annotated with `@disable new()`",
                           originalNewtype.toChars());
                 return setError();
             }
@@ -3879,7 +3926,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             {
                 if (nargs)
                 {
-                    exp.error("no constructor for `%s`", cd.toChars());
+                    error(exp.loc, "no constructor for `%s`", cd.toChars());
                     return setError();
                 }
 
@@ -3972,14 +4019,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 sd.ctor = sd.searchCtor();
             if (sd.noDefaultCtor && !nargs)
             {
-                exp.error("default construction is disabled for type `%s`", sd.type.toChars());
+                error(exp.loc, "default construction is disabled for type `%s`", sd.type.toChars());
                 return setError();
             }
             // checkDeprecated() is already done in newtype.typeSemantic().
 
             if (sd.disableNew)
             {
-                exp.error("cannot allocate `struct %s` with `new` because it is annotated with `@disable new()`",
+                error(exp.loc, "cannot allocate `struct %s` with `new` because it is annotated with `@disable new()`",
                           originalNewtype.toChars());
                 return setError();
             }
@@ -4053,7 +4100,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             {
                 // https://issues.dlang.org/show_bug.cgi?id=20422
                 // Without this check the compiler would give a misleading error
-                exp.error("missing length argument for array");
+                error(exp.loc, "missing length argument for array");
                 return setError();
             }
 
@@ -4062,21 +4109,21 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             AggregateDeclaration ad = s ? s.isAggregateDeclaration() : null;
             if (ad && ad.noDefaultCtor)
             {
-                exp.error("default construction is disabled for type `%s`", tb.nextOf().toChars());
+                error(exp.loc, "default construction is disabled for type `%s`", tb.nextOf().toChars());
                 return setError();
             }
             for (size_t i = 0; i < nargs; i++)
             {
                 if (tb.ty != Tarray)
                 {
-                    exp.error("too many arguments for array");
+                    error(exp.loc, "too many arguments for array");
                     return setError();
                 }
 
                 Expression arg = (*exp.arguments)[i];
                 if (exp.names && (*exp.names)[i])
                 {
-                    exp.error("no named argument `%s` allowed for array dimension", (*exp.names)[i].toChars());
+                    error(exp.loc, "no named argument `%s` allowed for array dimension", (*exp.names)[i].toChars());
                     return setError();
                 }
 
@@ -4088,7 +4135,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 if (arg.op == EXP.int64 && (target.isLP64 ?
                     cast(sinteger_t)arg.toInteger() : cast(int)arg.toInteger()) < 0)
                 {
-                    exp.error("negative array dimension `%s`", (*exp.arguments)[i].toChars());
+                    error(exp.loc, "negative array dimension `%s`", (*exp.arguments)[i].toChars());
                     return setError();
                 }
                 (*exp.arguments)[i] = arg;
@@ -4104,7 +4151,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             {
                 if (exp.names && (*exp.names)[0])
                 {
-                    exp.error("no named argument `%s` allowed for scalar", (*exp.names)[0].toChars());
+                    error(exp.loc, "no named argument `%s` allowed for scalar", (*exp.names)[0].toChars());
                     return setError();
                 }
                 Expression e = (*exp.arguments)[0];
@@ -4113,7 +4160,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             }
             else
             {
-                exp.error("more than one argument for construction of `%s`", exp.type.toChars());
+                error(exp.loc, "more than one argument for construction of `%s`", exp.type.toChars());
                 return setError();
             }
 
@@ -4125,13 +4172,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             // e.g. `new Alias(args)`
             if (nargs)
             {
-                exp.error("`new` cannot take arguments for an associative array");
+                error(exp.loc, "`new` cannot take arguments for an associative array");
                 return setError();
             }
         }
         else
         {
-            exp.error("cannot create a `%s` with `new`", exp.type.toChars());
+            error(exp.loc, "cannot create a `%s` with `new`", exp.type.toChars());
             return setError();
         }
 
@@ -4425,10 +4472,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 OutBuffer buf;
                 foreach (idx, ref arg; *arguments)
                     buf.printf("%s%s", (idx ? ", ".ptr : "".ptr), arg.type.toChars());
-                exp.error("function literal `%s%s` is not callable using argument types `(%s)`",
+                error(exp.loc, "function literal `%s%s` is not callable using argument types `(%s)`",
                           exp.fd.toChars(), parametersTypeToChars(tfl.parameterList),
                           buf.peekChars());
-                exp.errorSupplemental("too %s arguments, expected %d, got %d",
+                errorSupplemental(exp.loc, "too %s arguments, expected %d, got %d",
                                       arguments.length < dim ? "few".ptr : "many".ptr,
                                       cast(int)dim, cast(int)arguments.length);
                 return ErrorExp.get();
@@ -4638,7 +4685,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 __gshared int nest;
                 if (++nest > global.recursionLimit)
                 {
-                    exp.error("recursive evaluation of `%s`", exp.toChars());
+                    error(exp.loc, "recursive evaluation of `%s`", exp.toChars());
                     --nest;
                     return setError();
                 }
@@ -4717,12 +4764,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     }
                     else
                     {
-                        arg.error("identifier or `(` expected");
+                        error(arg.loc, "identifier or `(` expected");
                         result = ErrorExp.get();
                     }
                     return;
                 }
-                exp.error("identifier or `(` expected before `)`");
+                error(exp.loc, "identifier or `(` expected before `)`");
                 result = ErrorExp.get();
                 return;
             }
@@ -4827,7 +4874,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                         exp.e1 = resolveAliasThis(sc, exp.e1);
                         goto Lagain;
                     }
-                    exp.error("%s `%s` does not overload ()", sd.kind(), sd.toChars());
+                    error(exp.loc, "%s `%s` does not overload ()", sd.kind(), sd.toChars());
                     return setError();
                 }
 
@@ -4888,7 +4935,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 }
                 else
                 {
-                    exp.error("more than one argument for construction of `%s`", t1.toChars());
+                    error(exp.loc, "more than one argument for construction of `%s`", t1.toChars());
                     return setError();
                 }
                 e = e.expressionSemantic(sc);
@@ -5012,7 +5059,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
              */
             if (sc.func && sc.func.isInvariantDeclaration() && ue.e1.op == EXP.this_ && exp.f.addPostInvariant())
             {
-                exp.error("cannot call `public`/`export` function `%s` from invariant", exp.f.toChars());
+                error(exp.loc, "cannot call `public`/`export` function `%s` from invariant", exp.f.toChars());
                 return setError();
             }
 
@@ -5028,7 +5075,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             }
             else if (!checkSymbolAccess(sc, exp.f))
             {
-                exp.error("%s `%s` of type `%s` is not accessible from module `%s`",
+                error(exp.loc, "%s `%s` of type `%s` is not accessible from module `%s`",
                     exp.f.kind(), exp.f.toPrettyChars(), exp.f.type.toChars(), sc._module.toChars);
                 return setError();
             }
@@ -5106,12 +5153,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 // Base class constructor call
                 if (!cd || !cd.baseClass || !sc.func.isCtorDeclaration())
                 {
-                    exp.error("super class constructor call must be in a constructor");
+                    error(exp.loc, "super class constructor call must be in a constructor");
                     return setError();
                 }
                 if (!cd.baseClass.ctor)
                 {
-                    exp.error("no super class constructor for `%s`", cd.baseClass.toChars());
+                    error(exp.loc, "no super class constructor for `%s`", cd.baseClass.toChars());
                     return setError();
                 }
             }
@@ -5121,7 +5168,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 // constructor
                 if (!ad || !sc.func.isCtorDeclaration())
                 {
-                    exp.error("constructor call must be in a constructor");
+                    error(exp.loc, "constructor call must be in a constructor");
                     return setError();
                 }
 
@@ -5138,11 +5185,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             if (!sc.intypeof && !(sc.ctorflow.callSuper & CSX.halt))
             {
                 if (sc.inLoop || sc.ctorflow.callSuper & CSX.label)
-                    exp.error("constructor calls not allowed in loops or after labels");
+                    error(exp.loc, "constructor calls not allowed in loops or after labels");
                 if (sc.ctorflow.callSuper & (CSX.super_ctor | CSX.this_ctor))
-                    exp.error("multiple constructor calls");
+                    error(exp.loc, "multiple constructor calls");
                 if ((sc.ctorflow.callSuper & CSX.return_) && !(sc.ctorflow.callSuper & CSX.any_ctor))
-                    exp.error("an earlier `return` statement skips constructor");
+                    error(exp.loc, "an earlier `return` statement skips constructor");
                 sc.ctorflow.callSuper |= CSX.any_ctor | (isSuper ? CSX.super_ctor : CSX.this_ctor);
             }
 
@@ -5170,7 +5217,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             // call graph
             if (exp.f == sc.func)
             {
-                exp.error("cyclic constructor call");
+                error(exp.loc, "cyclic constructor call");
                 return setError();
             }
         }
@@ -5187,7 +5234,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         }
         else if (!t1)
         {
-            exp.error("function expected before `()`, not `%s`", exp.e1.toChars());
+            error(exp.loc, "function expected before `()`, not `%s`", exp.e1.toChars());
             return setError();
         }
         else if (t1.ty == Terror)
@@ -5270,7 +5317,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             }
             else
             {
-                exp.error("function expected before `()`, not `%s` of type `%s`", exp.e1.toChars(), exp.e1.type.toChars());
+                error(exp.loc, "function expected before `()`, not `%s` of type `%s`", exp.e1.toChars(), exp.e1.type.toChars());
                 return setError();
             }
 
@@ -5305,20 +5352,20 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 bool err = false;
                 if (!tf.purity && sc.func.setImpure(exp.loc, "`pure` %s `%s` cannot call impure `%s`", exp.e1))
                 {
-                    exp.error("`pure` %s `%s` cannot call impure %s `%s`",
+                    error(exp.loc, "`pure` %s `%s` cannot call impure %s `%s`",
                         sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
                     err = true;
                 }
                 if (!tf.isnogc && sc.func.setGC(exp.loc, "`@nogc` %s `%s` cannot call non-@nogc `%s`", exp.e1))
                 {
-                    exp.error("`@nogc` %s `%s` cannot call non-@nogc %s `%s`",
+                    error(exp.loc, "`@nogc` %s `%s` cannot call non-@nogc %s `%s`",
                         sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
                     err = true;
                 }
                 if (tf.trust <= TRUST.system && sc.setUnsafe(true, exp.loc,
                     "`@safe` function `%s` cannot call `@system` `%s`", sc.func, exp.e1))
                 {
-                    exp.error("`@safe` %s `%s` cannot call `@system` %s `%s`",
+                    error(exp.loc, "`@safe` %s `%s` cannot call `@system` %s `%s`",
                         sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
                     err = true;
                 }
@@ -5436,7 +5483,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         {
             exp.e1 = e1org; // https://issues.dlang.org/show_bug.cgi?id=10922
                         // avoid recursive expression printing
-            exp.error("forward reference to inferred return type of function call `%s`", exp.toChars());
+            error(exp.loc, "forward reference to inferred return type of function call `%s`", exp.toChars());
             return setError();
         }
 
@@ -5488,6 +5535,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             }
         }
 
+        // `super.fun()` with fun being abstract and unimplemented
+        auto supDotFun = exp.e1.isDotVarExp();
+        if (supDotFun && supDotFun.e1.isSuperExp() && exp.f && exp.f.isAbstract() && !exp.f.fbody)
+        {
+            error(exp.loc, "call to unimplemented abstract function `%s`", exp.f.toFullSignature());
+            errorSupplemental(exp.loc, "declared here: %s", exp.f.loc.toChars());
+        }
+
         // declare dual-context container
         if (exp.f && exp.f.hasDualContext() && !sc.intypeof && sc.func)
         {
@@ -5499,7 +5554,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     te = getRightThis(exp.loc, sc, ad2, te, exp.f);
                 if (te.op == EXP.error)
                 {
-                    exp.error("need `this` of type `%s` to call function `%s`", ad2.toChars(), exp.f.toChars());
+                    error(exp.loc, "need `this` of type `%s` to call function `%s`", ad2.toChars(), exp.f.toChars());
                     return setError();
                 }
             }
@@ -5579,7 +5634,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             if (!sc.insert(s))
             {
                 auto conflict = sc.search(Loc.initial, s.ident, null);
-                e.error("declaration `%s` is already defined", s.toPrettyChars());
+                error(e.loc, "declaration `%s` is already defined", s.toPrettyChars());
                 errorSupplemental(conflict.loc, "`%s` `%s` is defined here",
                                   conflict.kind(), conflict.toChars());
                 return setError();
@@ -5613,7 +5668,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     // 65535 should be enough for anyone
                     if (!s.localNum)
                     {
-                        e.error("more than 65535 symbols with name `%s` generated", s.ident.toChars());
+                        error(e.loc, "more than 65535 symbols with name `%s` generated", s.ident.toChars());
                         return setError();
                     }
 
@@ -5646,11 +5701,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                             {
                                 if (sc.func.fes)
                                 {
-                                    e.deprecation("%s `%s` is shadowing %s `%s`. Rename the `foreach` variable.", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars());
+                                    deprecation(e.loc, "%s `%s` is shadowing %s `%s`. Rename the `foreach` variable.", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars());
                                 }
                                 else
                                 {
-                                    e.error("%s `%s` is shadowing %s `%s`", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars());
+                                    error(e.loc, "%s `%s` is shadowing %s `%s`", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars());
                                     return setError();
                                 }
                             }
@@ -5715,7 +5770,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         if (!ta)
         {
             //printf("ta %p ea %p sa %p\n", ta, ea, sa);
-            exp.error("no type for `typeid(%s)`", ea ? ea.toChars() : (sa ? sa.toChars() : ""));
+            error(exp.loc, "no type for `typeid(%s)`", ea ? ea.toChars() : (sa ? sa.toChars() : ""));
             return setError();
         }
 
@@ -5821,7 +5876,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             if (!tup && !sc.insert(s))
             {
                 auto conflict = sc.search(Loc.initial, s.ident, null);
-                e.error("declaration `%s` is already defined", s.toPrettyChars());
+                error(e.loc, "declaration `%s` is already defined", s.toPrettyChars());
                 errorSupplemental(conflict.loc, "`%s` `%s` is defined here",
                                   conflict.kind(), conflict.toChars());
             }
@@ -5842,7 +5897,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         }
         if (e.id && !(sc.flags & SCOPE.condition))
         {
-            e.error("can only declare type aliases within `static if` conditionals or `static assert`s");
+            error(e.loc, "can only declare type aliases within `static if` conditionals or `static assert`s");
             return setError();
         }
 
@@ -6128,7 +6183,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     if (!sc.insert(s))
                     {
                         auto conflict = sc.search(Loc.initial, s.ident, null);
-                        e.error("declaration `%s` is already defined", s.toPrettyChars());
+                        error(e.loc, "declaration `%s` is already defined", s.toPrettyChars());
                         errorSupplemental(conflict.loc, "`%s` `%s` is defined here",
                                           conflict.kind(), conflict.toChars());
                     }
@@ -6277,7 +6332,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         const bool doUnittests = global.params.useUnitTests || global.params.ddoc.doOutput || global.params.dihdr.doOutput;
         auto loc = adjustLocForMixin(str, exp.loc, global.params.mixinOut);
         scope p = new Parser!ASTCodegen(loc, sc._module, str, false, global.errorSink, &global.compileEnv, doUnittests);
-        p.transitionIn = global.params.vin;
+        p.transitionIn = global.params.v.vin;
         p.nextToken();
         //printf("p.loc.linnum = %d\n", p.loc.linnum);
 
@@ -6287,9 +6342,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
         if (p.token.value != TOK.endOfFile)
         {
-            e.error("unexpected token `%s` after %s expression",
+            error(e.loc, "unexpected token `%s` after %s expression",
                 p.token.toChars(), EXPtoString(e.op).ptr);
-            e.errorSupplemental("while parsing string mixin expression `%s`",
+            errorSupplemental(e.loc, "while parsing string mixin expression `%s`",
                 str.ptr);
             return null;
         }
@@ -6327,7 +6382,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         auto namez = se.toStringz();
         if (!global.filePath)
         {
-            e.error("need `-J` switch to import text file `%s`", namez.ptr);
+            error(e.loc, "need `-J` switch to import text file `%s`", namez.ptr);
             return setError();
         }
 
@@ -6338,41 +6393,41 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
         if (FileName.absolute(namez))
         {
-            e.error("absolute path is not allowed in import expression: `%s`", se.toChars());
+            error(e.loc, "absolute path is not allowed in import expression: `%s`", se.toChars());
             return setError();
         }
 
         auto idxReserved = FileName.findReservedChar(namez);
         if (idxReserved != size_t.max)
         {
-            e.error("`%s` is not a valid filename on this platform", se.toChars());
-            e.errorSupplemental("Character `'%c'` is reserved and cannot be used", namez[idxReserved]);
+            error(e.loc, "`%s` is not a valid filename on this platform", se.toChars());
+            errorSupplemental(e.loc, "Character `'%c'` is reserved and cannot be used", namez[idxReserved]);
             return setError();
         }
 
         if (FileName.refersToParentDir(namez))
         {
-            e.error("path refers to parent (`..`) directory: `%s`", se.toChars());
+            error(e.loc, "path refers to parent (`..`) directory: `%s`", se.toChars());
             return setError();
         }
 
         auto resolvedNamez = FileName.searchPath(global.filePath, namez, false);
         if (!resolvedNamez)
         {
-            e.error("file `%s` cannot be found or not in a path specified with `-J`", se.toChars());
-            e.errorSupplemental("Path(s) searched (as provided by `-J`):");
+            error(e.loc, "file `%s` cannot be found or not in a path specified with `-J`", se.toChars());
+            errorSupplemental(e.loc, "Path(s) searched (as provided by `-J`):");
             foreach (idx, path; *global.filePath)
             {
                 const attr = FileName.exists(path);
                 const(char)* err = attr == 2 ? "" :
                     (attr == 1 ? " (not a directory)" : " (path not found)");
-                e.errorSupplemental("[%llu]: `%s`%s", cast(ulong)idx, path, err);
+                errorSupplemental(e.loc, "[%llu]: `%s`%s", cast(ulong)idx, path, err);
             }
             return setError();
         }
 
         sc._module.contentImportedFiles.push(resolvedNamez.ptr);
-        if (global.params.verbose)
+        if (global.params.v.verbose)
         {
             const slice = se.peekString();
             message("file      %.*s\t(%s)", cast(int)slice.length, slice.ptr, resolvedNamez.ptr);
@@ -6409,7 +6464,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             }
             else
             {
-                e.error("cannot read file `%s`", resolvedNamez.ptr);
+                error(e.loc, "cannot read file `%s`", resolvedNamez.ptr);
                 return setError();
             }
         }
@@ -6427,7 +6482,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         const generateMsg = !exp.msg &&
                             sc.needsCodegen() && // let ctfe interpreter handle the error message
                             global.params.checkAction == CHECKACTION.context &&
-                            global.params.useAssert == CHECKENABLE.on;
+                            global.params.useAssert == CHECKENABLE.on &&
+                            !((exp.e1.isIntegerExp() && (exp.e1.toInteger() == 0)) ||
+                               exp.e1.isNullExp());
         Expression temporariesPrefix;
 
         if (generateMsg)
@@ -6776,7 +6833,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 dmd.typesem.resolve(exp.e1.type, exp.e1.loc, sc, e, t, s, true);
                 if (e)
                 {
-                    exp.e1.error("argument to `_Alignof` must be a type");
+                    error(exp.e1.loc, "argument to `_Alignof` must be a type");
                     return setError();
                 }
                 else if (t)
@@ -6789,7 +6846,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 }
                 else if (s)
                 {
-                    exp.e1.error("argument to `_Alignof` must be a type");
+                    error(exp.e1.loc, "argument to `_Alignof` must be a type");
                     return setError();
                 }
                 else
@@ -6908,7 +6965,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     e = new TypeExp(exp.loc, cast(Type)o);
                     break;
                 default:
-                    exp.error("`%s` is not an expression", o.toChars());
+                    error(exp.loc, "`%s` is not an expression", o.toChars());
                     return setError();
                 }
                 if (var)
@@ -7071,7 +7128,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 OutBuffer thisBuf, funcBuf;
                 MODMatchToBuffer(&thisBuf, e.e1.type.mod, tf.mod);
                 MODMatchToBuffer(&funcBuf, tf.mod, e.e1.type.mod);
-                e.error("%smethod `%s` is not callable using a %s`%s`",
+                error(e.loc, "%smethod `%s` is not callable using a %s`%s`",
                     funcBuf.peekChars(), f.toPrettyChars(), thisBuf.peekChars(), e.e1.toChars());
                 return setError();
             }
@@ -7095,7 +7152,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     te = getRightThis(e.loc, sc, ad2, te, f);
                 if (te.op == EXP.error)
                 {
-                    e.error("need `this` of type `%s` to make delegate from function `%s`", ad2.toChars(), f.toChars());
+                    error(e.loc, "need `this` of type `%s` to make delegate from function `%s`", ad2.toChars(), f.toChars());
                     return setError();
                 }
             }
@@ -7267,7 +7324,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
         if (!exp.e1.type)
         {
-            exp.error("cannot take address of `%s`", exp.e1.toChars());
+            error(exp.loc, "cannot take address of `%s`", exp.e1.toChars());
             return setError();
         }
         if (!checkAddressable(exp, sc))
@@ -7288,10 +7345,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 if (auto ve = exp.e1.isVarExp())
                 {
                     Declaration d = ve.var;
-                    exp.error("forward reference to %s `%s`", d.kind(), d.toChars());
+                    error(exp.loc, "forward reference to %s `%s`", d.kind(), d.toChars());
                 }
                 else
-                    exp.error("forward reference to type `%s` of expression `%s`", exp.e1.type.toChars(), exp.e1.toChars());
+                    error(exp.loc, "forward reference to type `%s` of expression `%s`", exp.e1.type.toChars(), exp.e1.toChars());
                 return setError();
             }
         }
@@ -7461,7 +7518,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         case Tarray:
             if (isNonAssignmentArrayOp(exp.e1))
                 goto default;
-            exp.error("using `*` on an array is no longer supported; use `*(%s).ptr` instead", exp.e1.toChars());
+            error(exp.loc, "using `*` on an array is no longer supported; use `*(%s).ptr` instead", exp.e1.toChars());
             exp.type = (cast(TypeArray)tb).next;
             exp.e1 = exp.e1.castTo(sc, exp.type.pointerTo());
             break;
@@ -7474,7 +7531,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             break;
 
         default:
-            exp.error("can only `*` a pointer, not a `%s`", exp.e1.type.toChars());
+            error(exp.loc, "can only `*` a pointer, not a `%s`", exp.e1.type.toChars());
             goto case Terror;
         }
 
@@ -7688,7 +7745,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
          * `isRAII` has been set to true for the deletion of a `scope class`.  */
         if (tb.ty != Tclass)
         {
-            exp.error("cannot delete type `%s`", exp.e1.type.toChars());
+            error(exp.loc, "cannot delete type `%s`", exp.e1.type.toChars());
             return setError();
         }
 
@@ -7697,7 +7754,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         {
             /* Because COM classes are deleted by IUnknown.Release()
              */
-            exp.error("cannot `delete` instance of COM interface `%s`", cd.toChars());
+            error(exp.loc, "cannot `delete` instance of COM interface `%s`", cd.toChars());
             return setError();
         }
 
@@ -7801,7 +7858,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
         if (!exp.e1.type)
         {
-            exp.error("cannot cast `%s`", exp.e1.toChars());
+            error(exp.loc, "cannot cast `%s`", exp.e1.toChars());
             return setError();
         }
 
@@ -7839,7 +7896,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
         if (exp.to.ty == Ttuple)
         {
-            exp.error("cannot cast `%s` of type `%s` to type sequence `%s`", exp.e1.toChars(), exp.e1.type.toChars(), exp.to.toChars());
+            error(exp.loc, "cannot cast `%s` of type `%s` to type sequence `%s`", exp.e1.toChars(), exp.e1.type.toChars(), exp.to.toChars());
             return setError();
         }
 
@@ -8022,7 +8079,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             if (elem.isConst() == 1)
                 return false;
 
-             exp.error("constant expression expected, not `%s`", elem.toChars());
+             error(exp.loc, "constant expression expected, not `%s`", elem.toChars());
              return true;
         }
 
@@ -8087,7 +8144,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         {
             if (exp.lwr || exp.upr)
             {
-                exp.error("cannot slice type `%s`", exp.e1.toChars());
+                error(exp.loc, "cannot slice type `%s`", exp.e1.toChars());
                 return setError();
             }
             Expression e = new TypeExp(exp.loc, exp.e1.type.arrayOf());
@@ -8139,12 +8196,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         {
             if (t1b.isPtrToFunction())
             {
-                exp.error("cannot slice function pointer `%s`", exp.e1.toChars());
+                error(exp.loc, "cannot slice function pointer `%s`", exp.e1.toChars());
                 return setError();
             }
             if (!exp.lwr || !exp.upr)
             {
-                exp.error("upper and lower bounds are needed to slice a pointer");
+                error(exp.loc, "upper and lower bounds are needed to slice a pointer");
                 if (auto ad = isAggregate(tp.next.toBasetype()))
                 {
                     auto s = search_function(ad, Id.index);
@@ -8154,7 +8211,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                         auto fd = s.isFuncDeclaration();
                         if ((fd && !fd.getParameterList().length) || s.isTemplateDeclaration())
                         {
-                            exp.errorSupplemental(
+                            errorSupplemental(exp.loc,
                                 "pointer `%s` points to an aggregate that defines an `%s`, perhaps you meant `(*%s)[]`",
                                 exp.e1.toChars(),
                                 s.ident.toChars(),
@@ -8185,7 +8242,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             }
             if (!exp.lwr || !exp.upr)
             {
-                exp.error("need upper and lower bound to slice a sequence");
+                error(exp.loc, "need upper and lower bound to slice a sequence");
                 return setError();
             }
         }
@@ -8199,7 +8256,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         }
         else
         {
-            exp.error("`%s` cannot be sliced with `[]`", t1b.ty == Tvoid ? exp.e1.toChars() : t1b.toChars());
+            error(exp.loc, "`%s` cannot be sliced with `[]`", t1b.ty == Tvoid ? exp.e1.toChars() : t1b.toChars());
             return setError();
         }
 
@@ -8265,7 +8322,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
             if (i2 < i1 || length < i2)
             {
-                exp.error("string slice `[%llu .. %llu]` is out of bounds", i1, i2);
+                error(exp.loc, "string slice `[%llu .. %llu]` is out of bounds", i1, i2);
                 return setError();
             }
 
@@ -8405,13 +8462,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         }
 
         if (isAggregate(exp.e1.type))
-            exp.error("no `[]` operator overload for type `%s`", exp.e1.type.toChars());
+            error(exp.loc, "no `[]` operator overload for type `%s`", exp.e1.type.toChars());
         else if (exp.e1.op == EXP.type && exp.e1.type.ty != Ttuple)
-            exp.error("static array of `%s` with multiple lengths not allowed", exp.e1.type.toChars());
+            error(exp.loc, "static array of `%s` with multiple lengths not allowed", exp.e1.type.toChars());
         else if (isIndexableNonAggregate(exp.e1.type))
-            exp.error("only one index allowed to index `%s`", exp.e1.type.toChars());
+            error(exp.loc, "only one index allowed to index `%s`", exp.e1.type.toChars());
         else
-            exp.error("cannot use `[]` operator on expression of type `%s`", exp.e1.type.toChars());
+            error(exp.loc, "cannot use `[]` operator on expression of type `%s`", exp.e1.type.toChars());
 
         result = ErrorExp.get();
     }
@@ -8489,7 +8546,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             discardValue(e.e1);
         }
         else if (!e.allowCommaExp && !e.isGenerated)
-            e.error("using the result of a comma expression is not allowed");
+            error(e.loc, "using the result of a comma expression is not allowed");
     }
 
     override void visit(IntervalExp e)
@@ -8660,7 +8717,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         case Tpointer:
             if (t1b.isPtrToFunction())
             {
-                exp.error("cannot index function pointer `%s`", exp.e1.toChars());
+                error(exp.loc, "cannot index function pointer `%s`", exp.e1.toChars());
                 return setError();
             }
             exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
@@ -8742,7 +8799,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
                 if (length <= index)
                 {
-                    exp.error("array index `[%llu]` is outside array bounds `[0 .. %llu]`", index, cast(ulong)length);
+                    error(exp.loc, "array index `[%llu]` is outside array bounds `[0 .. %llu]`", index, cast(ulong)length);
                     return setError();
                 }
                 Expression e;
@@ -8757,7 +8814,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 return;
             }
         default:
-            exp.error("`%s` must be an array or pointer type, not `%s`", exp.e1.toChars(), exp.e1.type.toChars());
+            error(exp.loc, "`%s` must be an array or pointer type, not `%s`", exp.e1.toChars(), exp.e1.type.toChars());
             return setError();
         }
 
@@ -8847,7 +8904,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         if (exp.e1.op == EXP.slice)
         {
             const(char)* s = exp.op == EXP.plusPlus ? "increment" : "decrement";
-            exp.error("cannot post-%s array slice `%s`, use pre-%s instead", s, exp.e1.toChars(), s);
+            error(exp.loc, "cannot post-%s array slice `%s`, use pre-%s instead", s, exp.e1.toChars(), s);
             return setError();
         }
 
@@ -8987,7 +9044,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         if (auto e2comma = exp.e2.isCommaExp())
         {
             if (!e2comma.isGenerated && !(sc.flags & SCOPE.Cfile))
-                exp.error("using the result of a comma expression is not allowed");
+                error(exp.loc, "using the result of a comma expression is not allowed");
 
             /* Rewrite to get rid of the comma from rvalue
              *   e1=(e0,e2) => e0,(e1=e2)
@@ -9230,7 +9287,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 Expression e = null;
                 if (dim != tup2.exps.length)
                 {
-                    exp.error("mismatched sequence lengths, %d and %d", cast(int)dim, cast(int)tup2.exps.length);
+                    error(exp.loc, "mismatched sequence lengths, %d and %d", cast(int)dim, cast(int)tup2.exps.length);
                     return setError();
                 }
                 if (dim == 0)
@@ -9462,7 +9519,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                             {
                                 if (!e2x.type.implicitConvTo(e1x.type))
                                 {
-                                    exp.error("conversion error from `%s` to `%s`",
+                                    error(exp.loc, "conversion error from `%s` to `%s`",
                                         e2x.type.toChars(), e1x.type.toChars());
                                     return setError();
                                 }
@@ -9780,7 +9837,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     }
                     if (dim1 != dim2)
                     {
-                        exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
+                        error(exp.loc, "mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
                         return setError();
                     }
                 }
@@ -9810,7 +9867,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                         if (overflow || dim >= uint.max)
                         {
                             // dym exceeds maximum array size
-                            exp.error("static array `%s` size overflowed to %llu",
+                            error(exp.loc, "static array `%s` size overflowed to %llu",
                                         e1x.type.toChars(), cast(ulong) dim);
                             return setError();
                         }
@@ -9914,13 +9971,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 // https://issues.dlang.org/show_bug.cgi?id=9884
                 (!fun || (fun && !fun.isStaticCtorDeclaration())))
             {
-                exp.error("slice `%s` is not mutable", se.toChars());
+                error(exp.loc, "slice `%s` is not mutable", se.toChars());
                 return setError();
             }
 
             if (exp.op == EXP.assign && !tn.baseElemOf().isAssignable())
             {
-                exp.error("slice `%s` is not mutable, struct `%s` has immutable members",
+                error(exp.loc, "slice `%s` is not mutable, struct `%s` has immutable members",
                     exp.e1.toChars(), tn.baseElemOf().toChars());
                 result = ErrorExp.get();
                 return;
@@ -9943,7 +10000,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 Type tn = exp.e1.type.nextOf();
                 if (tn && !tn.baseElemOf().isAssignable())
                 {
-                    exp.error("array `%s` is not mutable, struct `%s` has immutable members",
+                    error(exp.loc, "array `%s` is not mutable, struct `%s` has immutable members",
                         exp.e1.toChars(), tn.baseElemOf().toChars());
                     result = ErrorExp.get();
                     return;
@@ -10014,7 +10071,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 uinteger_t dim2 = tsa2.dim.toInteger();
                 if (dim1 != dim2)
                 {
-                    exp.error("mismatched array lengths %d and %d for assignment `%s`", cast(int)dim1, cast(int)dim2, exp.toChars());
+                    error(exp.loc, "mismatched array lengths %d and %d for assignment `%s`", cast(int)dim1, cast(int)dim2, exp.toChars());
                     return setError();
                 }
             }
@@ -10179,13 +10236,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             if (vd && vd.onstack)
             {
                 assert(t1.ty == Tclass);
-                exp.error("cannot rebind scope variables");
+                error(exp.loc, "cannot rebind scope variables");
             }
         }
 
         if (exp.e1.op == EXP.variable && (cast(VarExp)exp.e1).var.ident == Id.ctfe)
         {
-            exp.error("cannot modify compiler-generated variable `__ctfe`");
+            error(exp.loc, "cannot modify compiler-generated variable `__ctfe`");
         }
 
         exp.type = exp.e1.type;
@@ -10287,7 +10344,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     res = Expression.combine(e0, ce).expressionSemantic(sc);
                 }
 
-                if (global.params.verbose)
+                if (global.params.v.verbose)
                     message("lowered   %s =>\n          %s", exp.toChars(), res.toChars());
             }
         }
@@ -10377,7 +10434,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         if (isArrayAssign)
             res = Expression.combine(res, ae.e1).expressionSemantic(sc);
 
-        if (global.params.verbose)
+        if (global.params.v.verbose)
             message("lowered   %s =>\n          %s", ae.toChars(), res.toChars());
 
         res = new LoweredAssignExp(ae, res);
@@ -10490,7 +10547,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         {
             if (se.e1.type.toBasetype().ty == Tsarray)
             {
-                exp.error("cannot append to static array `%s`", se.e1.type.toChars());
+                error(exp.loc, "cannot append to static array `%s`", se.e1.type.toChars());
                 return setError();
             }
         }
@@ -10614,7 +10671,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             if (result)
                 return;
 
-            exp.error("cannot append type `%s` to type `%s`", tb2.toChars(), tb1.toChars());
+            error(exp.loc, "cannot append type `%s` to type `%s`", tb2.toChars(), tb1.toChars());
             return setError();
         }
 
@@ -10960,7 +11017,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 e = scaleFactor(exp, sc);
             else
             {
-                exp.error("can't subtract `%s` from pointer", t2.toChars());
+                error(exp.loc, "can't subtract `%s` from pointer", t2.toChars());
                 e = ErrorExp.get();
             }
             result = e;
@@ -10969,7 +11026,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         if (t2.ty == Tpointer)
         {
             exp.type = exp.e2.type;
-            exp.error("can't subtract pointer from `%s`", exp.e1.type.toChars());
+            error(exp.loc, "can't subtract pointer from `%s`", exp.e1.type.toChars());
             return setError();
         }
 
@@ -11546,7 +11603,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             exp.type = exp.e1.type;
             if (exp.e2.type.iscomplex())
             {
-                exp.error("cannot perform modulo complex arithmetic");
+                error(exp.loc, "cannot perform modulo complex arithmetic");
                 return setError();
             }
         }
@@ -11613,7 +11670,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         Module mmath = Module.loadStdMath();
         if (!mmath)
         {
-            e.error("`%s` requires `std.math` for `^^` operators", e.toChars());
+            error(e.loc, "`%s` requires `std.math` for `^^` operators", e.toChars());
             return setError();
         }
         e = new ScopeExp(exp.loc, mmath);
@@ -11968,7 +12025,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
         if (e2x.op == EXP.type || e2x.op == EXP.scope_)
         {
-            exp.error("`%s` is not an expression", exp.e2.toChars());
+            error(exp.loc, "`%s` is not an expression", exp.e2.toChars());
             return setError();
         }
         if (e1x.op == EXP.error || e1x.type.ty == Tnoreturn)
@@ -12017,7 +12074,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         Type t2 = exp.e2.type.toBasetype();
         if (t1.ty == Tclass && exp.e2.op == EXP.null_ || t2.ty == Tclass && exp.e1.op == EXP.null_)
         {
-            exp.error("do not use `null` when comparing class types");
+            error(exp.loc, "do not use `null` when comparing class types");
             return setError();
         }
 
@@ -12027,7 +12084,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         {
             if (!e.type.isscalar() && e.type.equals(exp.e1.type))
             {
-                exp.error("recursive `opCmp` expansion");
+                error(exp.loc, "recursive `opCmp` expansion");
                 return setError();
             }
             if (e.op == EXP.call)
@@ -12095,7 +12152,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             Type t2next = t2.nextOf();
             if (t1next.implicitConvTo(t2next) < MATCH.constant && t2next.implicitConvTo(t1next) < MATCH.constant && (t1next.ty != Tvoid && t2next.ty != Tvoid))
             {
-                exp.error("array comparison type mismatch, `%s` vs `%s`", t1next.toChars(), t2next.toChars());
+                error(exp.loc, "array comparison type mismatch, `%s` vs `%s`", t1next.toChars(), t2next.toChars());
                 return setError();
             }
 
@@ -12124,19 +12181,19 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         else if (t1.ty == Tstruct || t2.ty == Tstruct || (t1.ty == Tclass && t2.ty == Tclass))
         {
             if (t2.ty == Tstruct)
-                exp.error("need member function `opCmp()` for %s `%s` to compare", t2.toDsymbol(sc).kind(), t2.toChars());
+                error(exp.loc, "need member function `opCmp()` for %s `%s` to compare", t2.toDsymbol(sc).kind(), t2.toChars());
             else
-                exp.error("need member function `opCmp()` for %s `%s` to compare", t1.toDsymbol(sc).kind(), t1.toChars());
+                error(exp.loc, "need member function `opCmp()` for %s `%s` to compare", t1.toDsymbol(sc).kind(), t1.toChars());
             return setError();
         }
         else if (t1.iscomplex() || t2.iscomplex())
         {
-            exp.error("compare not defined for complex operands");
+            error(exp.loc, "compare not defined for complex operands");
             return setError();
         }
         else if (t1.ty == Taarray || t2.ty == Taarray)
         {
-            exp.error("`%s` is not defined for associative arrays", EXPtoString(exp.op).ptr);
+            error(exp.loc, "`%s` is not defined for associative arrays", EXPtoString(exp.op).ptr);
             return setError();
         }
         else if (!target.isVectorOpSupported(t1, exp.op, t2))
@@ -12213,9 +12270,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
         case Tarray, Tsarray:
             result = exp.incompatibleTypes();
-            exp.errorSupplemental("`in` is only allowed on associative arrays");
+            errorSupplemental(exp.loc, "`in` is only allowed on associative arrays");
             const(char)* slice = (t2b.ty == Tsarray) ? "[]" : "";
-            exp.errorSupplemental("perhaps use `std.algorithm.find(%s, %s%s)` instead",
+            errorSupplemental(exp.loc, "perhaps use `std.algorithm.find(%s, %s%s)` instead",
                 exp.e1.toChars(), exp.e2.toChars(), slice);
             return;
 
@@ -12293,7 +12350,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             auto t1 = exp.e1.type;
             auto t2 = exp.e2.type;
             if (t1.ty == Tenum && t2.ty == Tenum && !t1.equivalent(t2))
-                exp.error("comparison between different enumeration types `%s` and `%s`; If this behavior is intended consider using `std.conv.asOriginalType`",
+                error(exp.loc, "comparison between different enumeration types `%s` and `%s`; If this behavior is intended consider using `std.conv.asOriginalType`",
                     t1.toChars(), t2.toChars());
         }
 
@@ -12435,7 +12492,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             __equals = __equals.trySemantic(sc); // for better error message
             if (!__equals)
             {
-                exp.error("incompatible types for array comparison: `%s` and `%s`",
+                error(exp.loc, "incompatible types for array comparison: `%s` and `%s`",
                           exp.e1.type.toChars(), exp.e2.type.toChars());
                 __equals = ErrorExp.get();
             }
@@ -12517,7 +12574,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
         if (exp.e1.type.toBasetype().ty == Tsarray ||
             exp.e2.type.toBasetype().ty == Tsarray)
-            exp.deprecation("identity comparison of static arrays "
+            deprecation(exp.loc, "identity comparison of static arrays "
                 ~ "implicitly coerces them to slices, "
                 ~ "which are compared by reference");
 
@@ -12936,7 +12993,7 @@ private Expression dotIdSemanticPropX(DotIdExp exp, Scope* sc)
 
                 if (f.purityInprocess || f.safetyInprocess || f.nothrowInprocess || f.nogcInprocess)
                 {
-                    f.error(loc, "cannot retrieve its `.mangleof` while inferring attributes");
+                    error(loc, "%s `%s` cannot retrieve its `.mangleof` while inferring attributes", f.kind, f.toPrettyChars);
                     return ErrorExp.get();
                 }
             }
@@ -13002,12 +13059,12 @@ private Expression dotIdSemanticPropX(DotIdExp exp, Scope* sc)
     // Template has no built-in properties except for 'stringof'.
     if ((exp.e1.isDotTemplateExp() || exp.e1.isTemplateExp()) && exp.ident != Id.stringof)
     {
-        exp.error("template `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars());
+        error(exp.loc, "template `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars());
         return ErrorExp.get();
     }
     if (!exp.e1.type)
     {
-        exp.error("expression `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars());
+        error(exp.loc, "expression `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars());
         return ErrorExp.get();
     }
 
@@ -13121,9 +13178,9 @@ Expression dotIdSemanticProp(DotIdExp exp, Scope* sc, bool gag)
                     !v.type.deco && v.inuse)
                 {
                     if (v.inuse)
-                        exp.error("circular reference to %s `%s`", v.kind(), v.toPrettyChars());
+                        error(exp.loc, "circular reference to %s `%s`", v.kind(), v.toPrettyChars());
                     else
-                        exp.error("forward reference to %s `%s`", v.kind(), v.toPrettyChars());
+                        error(exp.loc, "forward reference to %s `%s`", v.kind(), v.toPrettyChars());
                     return ErrorExp.get();
                 }
                 if (v.type.isTypeError())
@@ -13284,12 +13341,12 @@ Expression dotIdSemanticProp(DotIdExp exp, Scope* sc, bool gag)
         if (s && symbolIsVisible(sc, s))
         {
             if (s.isPackage())
-                exp.error("undefined identifier `%s` in %s `%s`, perhaps add `static import %s;`", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars(), s.toPrettyChars());
+                error(exp.loc, "undefined identifier `%s` in %s `%s`, perhaps add `static import %s;`", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars(), s.toPrettyChars());
             else
-                exp.error("undefined identifier `%s` in %s `%s`, did you mean %s `%s`?", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars(), s.kind(), s.toChars());
+                error(exp.loc, "undefined identifier `%s` in %s `%s`, did you mean %s `%s`?", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars(), s.kind(), s.toChars());
         }
         else
-            exp.error("undefined identifier `%s` in %s `%s`", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars());
+            error(exp.loc, "undefined identifier `%s` in %s `%s`", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars());
         return ErrorExp.get();
     }
     else if (t1b.ty == Tpointer && exp.e1.type.ty != Tenum &&
@@ -13544,7 +13601,7 @@ Expression dotTemplateSemanticProp(DotTemplateInstanceExp exp, Scope* sc, bool g
     }
 
 Lerr:
-    exp.error("`%s` isn't a template", e.toChars());
+    error(exp.loc, "`%s` isn't a template", e.toChars());
     return errorExp();
 }
 
@@ -13578,7 +13635,7 @@ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)
         bool sharedError(Expression e)
         {
             // https://dlang.org/phobos/core_atomic.html
-            e.error("direct access to shared `%s` is not allowed, see `core.atomic`", e.toChars());
+            error(e.loc, "direct access to shared `%s` is not allowed, see `core.atomic`", e.toChars());
             return true;
         }
 
@@ -13737,7 +13794,7 @@ bool checkAddressVar(Scope* sc, Expression exp, VarDeclaration v)
 
     if (!v.canTakeAddressOf())
     {
-        exp.error("cannot take address of `%s`", exp.toChars());
+        error(exp.loc, "cannot take address of `%s`", exp.toChars());
         return false;
     }
     if (sc.func && !sc.intypeof && !v.isDataseg())
@@ -13774,7 +13831,7 @@ bool checkAddressable(Expression e, Scope* sc)
                 // whether SCOPE.Cfile is set.
                 if (auto bf = ex.isDotVarExp().var.isBitFieldDeclaration())
                 {
-                    e.error("cannot take address of bit-field `%s`", bf.toChars());
+                    error(e.loc, "cannot take address of bit-field `%s`", bf.toChars());
                     return false;
                 }
                 goto case EXP.cast_;
@@ -13799,9 +13856,9 @@ bool checkAddressable(Expression e, Scope* sc)
                     if (ex.isVarExp().var.storage_class & STC.register)
                     {
                         if (e.isIndexExp())
-                            e.error("cannot index through register variable `%s`", ex.toChars());
+                            error(e.loc, "cannot index through register variable `%s`", ex.toChars());
                         else
-                            e.error("cannot take address of register variable `%s`", ex.toChars());
+                            error(e.loc, "cannot take address of register variable `%s`", ex.toChars());
                         return false;
                     }
                 }
@@ -13881,7 +13938,7 @@ Expression getThisSkipNestedFuncs(const ref Loc loc, Scope* sc, Dsymbol s, Aggre
         {
             if (flag)
                 return null;
-            e1.error("need `this` of type `%s` to access member `%s` from static function `%s`", ad.toChars(), var.toChars(), f.toChars());
+            error(e1.loc, "need `this` of type `%s` to access member `%s` from static function `%s`", ad.toChars(), var.toChars(), f.toChars());
             e1 = ErrorExp.get();
             return e1;
         }
@@ -14116,7 +14173,7 @@ Expression toBoolean(Expression exp, Scope* sc)
     switch(exp.op)
     {
         case EXP.delete_:
-            exp.error("`delete` does not give a boolean result");
+            error(exp.loc, "`delete` does not give a boolean result");
             return ErrorExp.get();
 
         case EXP.comma:
@@ -14137,7 +14194,7 @@ Expression toBoolean(Expression exp, Scope* sc)
             // Things like:
             //  if (a = b) ...
             // are usually mistakes.
-            exp.error("assignment cannot be used as a condition, perhaps `==` was meant?");
+            error(exp.loc, "assignment cannot be used as a condition, perhaps `==` was meant?");
             return ErrorExp.get();
 
         //LogicalExp
@@ -14201,7 +14258,7 @@ Expression toBoolean(Expression exp, Scope* sc)
             if (!t.isBoolean())
             {
                 if (tb != Type.terror)
-                    exp.error("expression `%s` of type `%s` does not have a boolean value",
+                    error(exp.loc, "expression `%s` of type `%s` does not have a boolean value",
                               exp.toChars(), t.toChars());
                 return ErrorExp.get();
             }
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index bf7ad7ee8d5d..81bb028964fb 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -744,7 +744,7 @@ extern (C++) class FuncDeclaration : Declaration
 
                     if (exactvi >= 0)
                     {
-                        error("cannot determine overridden function");
+                        .error(loc, "%s `%s` cannot determine overridden function", kind, toPrettyChars);
                         return exactvi;
                     }
                     exactvi = vi;
@@ -1057,7 +1057,7 @@ extern (C++) class FuncDeclaration : Declaration
                 OutBuffer thisBuf, funcBuf;
                 MODMatchToBuffer(&thisBuf, tthis.mod, tf.mod);
                 MODMatchToBuffer(&funcBuf, tf.mod, tthis.mod);
-                .error(loc, "%smethod %s is not callable using a %sobject",
+                .error(loc, "%smethod %s is not callable using a %sobject", kind, toPrettyChars,
                     funcBuf.peekChars(), this.toPrettyChars(), thisBuf.peekChars());
             }
         }
@@ -1696,7 +1696,7 @@ extern (C++) class FuncDeclaration : Declaration
 
     extern (D) final void printGCUsage(const ref Loc loc, const(char)* warn)
     {
-        if (!global.params.vgc)
+        if (!global.params.v.gc)
             return;
 
         Module m = getModule();
@@ -2240,13 +2240,13 @@ extern (C++) class FuncDeclaration : Declaration
 
         if (setGC(loc, "%s `%s` is `@nogc` yet allocates closure for `%s()` with the GC", this))
         {
-            error("is `@nogc` yet allocates closure for `%s()` with the GC", toChars());
+            .error(loc, "%s `%s` is `@nogc` yet allocates closure for `%s()` with the GC", kind, toPrettyChars, toChars());
             if (global.gag)     // need not report supplemental errors
                 return true;
         }
         else if (!global.params.useGC)
         {
-            error("is `-betterC` yet allocates closure for `%s()` with the GC", toChars());
+            .error(loc, "%s `%s` is `-betterC` yet allocates closure for `%s()` with the GC", kind, toPrettyChars, toChars());
             if (global.gag)     // need not report supplemental errors
                 return true;
         }
@@ -2370,7 +2370,7 @@ extern (C++) class FuncDeclaration : Declaration
             vresult.dsymbolSemantic(sc);
 
             if (!sc.insert(vresult))
-                error("out result %s is already defined", vresult.toChars());
+                .error(loc, "%s `%s` out result %s is already defined", kind, toPrettyChars, vresult.toChars());
             assert(vresult.parent == this);
         }
     }
@@ -2877,7 +2877,7 @@ extern (C++) class FuncDeclaration : Declaration
             }
 
             if (tf.parameterList.varargs || nparams >= 2 || argerr)
-                error("parameter list must be empty or accept one parameter of type `string[]`");
+                .error(loc, "%s `%s` parameter list must be empty or accept one parameter of type `string[]`", kind, toPrettyChars);
         }
 
         else if (linkage == LINK.c)
@@ -2912,7 +2912,7 @@ extern (C++) class FuncDeclaration : Declaration
 
             if (argerr)
             {
-                error("parameters must match one of the following signatures");
+                .error(loc, "%s `%s` parameters must match one of the following signatures", kind, toPrettyChars);
                 loc.errorSupplemental("`main()`");
                 loc.errorSupplemental("`main(int argc, char** argv)`");
                 loc.errorSupplemental("`main(int argc, char** argv, char** environ)` [POSIX extension]");
@@ -2925,7 +2925,7 @@ extern (C++) class FuncDeclaration : Declaration
         retType = retType.toBasetype();
 
         if (retType.ty != Tint32 && retType.ty != Tvoid && retType.ty != Tnoreturn)
-            error("must return `int`, `void` or `noreturn`, not `%s`", tf.nextOf().toChars());
+            .error(loc, "%s `%s` must return `int`, `void` or `noreturn`, not `%s`", kind, toPrettyChars, tf.nextOf().toChars());
     }
 
     /***********************************************
@@ -3110,7 +3110,7 @@ extern (D) int overloadApply(Dsymbol fstart, scope int delegate(Dsymbol) dg, Sco
                 }
                 else
                 {
-                    d.error("is aliased to a function");
+                    .error(d.loc, "%s `%s` is aliased to a function", d.kind, d.toPrettyChars);
                     break;
                 }
                 next = fa.overnext;
@@ -3149,7 +3149,7 @@ extern (D) int overloadApply(Dsymbol fstart, scope int delegate(Dsymbol) dg, Sco
             }
             else
             {
-                d.error("is aliased to a function");
+                .error(d.loc, "%s `%s` is aliased to a function", d.kind, d.toPrettyChars);
                 break;
                 // BUG: should print error message?
             }
@@ -3391,7 +3391,7 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
                    td.kind(), td.parent.toPrettyChars(), td.ident.toChars(),
                    tiargsBuf.peekChars(), fargsBuf.peekChars());
 
-            if (!global.gag || global.params.showGaggedErrors)
+            if (!global.gag || global.params.v.showGaggedErrors)
                 printCandidates(loc, td, sc.isDeprecated());
             return null;
         }
@@ -3430,7 +3430,7 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
         {
             .error(loc, "none of the overloads of `%s` are callable using a %sobject",
                    fd.ident.toChars(), thisBuf.peekChars());
-            if (!global.gag || global.params.showGaggedErrors)
+            if (!global.gag || global.params.v.showGaggedErrors)
                 printCandidates(loc, fd, sc.isDeprecated());
             return null;
         }
@@ -3461,7 +3461,7 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
     {
         .error(loc, "none of the overloads of `%s` are callable using argument types `%s`",
                fd.toChars(), fargsBuf.peekChars());
-        if (!global.gag || global.params.showGaggedErrors)
+        if (!global.gag || global.params.v.showGaggedErrors)
             printCandidates(loc, fd, sc.isDeprecated());
         return null;
     }
@@ -3471,7 +3471,7 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
            tf.modToChars(), fargsBuf.peekChars());
 
     // re-resolve to check for supplemental message
-    if (!global.gag || global.params.showGaggedErrors)
+    if (!global.gag || global.params.v.showGaggedErrors)
     {
         if (tthis)
         {
@@ -3514,9 +3514,7 @@ private void printCandidates(Decl)(const ref Loc loc, Decl declaration, bool sho
 if (is(Decl == TemplateDeclaration) || is(Decl == FuncDeclaration))
 {
     // max num of overloads to print (-v or -verror-supplements overrides this).
-    const int DisplayLimit = !global.params.verbose ?
-                                (global.params.errorSupplementLimit ? global.params.errorSupplementLimit : int.max)
-                                : int.max;
+    const uint DisplayLimit = global.params.v.errorSupplementCount();
     const(char)* constraintsTip;
     // determine if the first candidate was printed
     int printed;
@@ -3580,7 +3578,7 @@ if (is(Decl == TemplateDeclaration) || is(Decl == FuncDeclaration))
     });
     int skipped = 0;
     overloadApply(declaration, (s) {
-        if (global.params.verbose || printed < DisplayLimit)
+        if (global.params.v.verbose || printed < DisplayLimit)
         {
             if (matchSymbol(s, true, count == 1))
                 printed++;
diff --git a/gcc/d/dmd/globals.d b/gcc/d/dmd/globals.d
index 840074e5d8f3..2f6fae3a1ab0 100644
--- a/gcc/d/dmd/globals.d
+++ b/gcc/d/dmd/globals.d
@@ -118,6 +118,38 @@ extern(C++) struct Help
     bool hc;           // -HC
 }
 
+extern(C++) struct Verbose
+{
+    bool verbose;           // verbose compile
+    bool showColumns;       // print character (column) numbers in diagnostics
+    bool tls;               // identify thread local variables
+    bool templates;         // collect and list statistics on template instantiations
+    // collect and list statistics on template instantiations origins.
+    // TODO: make this an enum when we want to list other kinds of instances
+    bool templatesListInstances;
+    bool gc;                // identify gc usage
+    bool field;             // identify non-mutable field variables
+    bool complex = true;    // identify complex/imaginary type usage
+    bool vin;               // identify 'in' parameters
+    bool showGaggedErrors;  // print gagged errors anyway
+    bool printErrorContext; // print errors with the error context (the error line in the source file)
+    bool logo;              // print compiler logo
+    bool color;             // use ANSI colors in console output
+    bool cov;               // generate code coverage data
+    MessageStyle messageStyle = MessageStyle.digitalmars; // style of file/line annotations on messages
+    uint errorLimit = 20;
+    uint errorSupplementLimit = 6;      // Limit the number of supplemental messages for each error (0 means unlimited)
+
+    uint errorSupplementCount()
+    {
+        if (verbose)
+            return uint.max;
+        if (errorSupplementLimit == 0)
+            return uint.max;
+        return errorSupplementLimit;
+    }
+}
+
 /// Put command line switches in here
 extern (C++) struct Param
 {
@@ -125,23 +157,13 @@ extern (C++) struct Param
     bool multiobj;          // break one object file into multiple ones
     bool trace;             // insert profiling hooks
     bool tracegc;           // instrument calls to 'new'
-    bool verbose;           // verbose compile
     bool vcg_ast;           // write-out codegen-ast
-    bool showColumns;       // print character (column) numbers in diagnostics
-    bool vtls;              // identify thread local variables
-    bool vtemplates;        // collect and list statistics on template instantiations
-    bool vtemplatesListInstances; // collect and list statistics on template instantiations origins. TODO: make this an enum when we want to list other kinds of instances
-    bool vgc;               // identify gc usage
-    bool vfield;            // identify non-mutable field variables
-    bool vcomplex = true;   // identify complex/imaginary type usage
-    bool vin;               // identify 'in' parameters
     DiagnosticReporting useDeprecated = DiagnosticReporting.inform;  // how use of deprecated features are handled
     bool useUnitTests;          // generate unittest code
     bool useInline = false;     // inline expand functions
     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 color;             // use ANSI colors in console output
     bool cov;               // generate code coverage data
     ubyte covPercent;       // 0..100 code coverage percentage required
     bool ctfe_cov = false;  // generate coverage data for ctfe
@@ -157,10 +179,8 @@ extern (C++) struct Param
 
     CppStdRevision cplusplus = CppStdRevision.cpp11;    // version of C++ standard to support
 
-    bool showGaggedErrors;  // print gagged errors anyway
-    bool printErrorContext;  // print errors with the error context (the error line in the source file)
     Help help;
-    bool logo;              // print compiler logo
+    Verbose v;
 
     // Options for `-preview=/-revert=`
     FeatureState useDIP25 = FeatureState.enabled; // implement https://wiki.dlang.org/DIP25
@@ -195,9 +215,6 @@ extern (C++) struct Param
 
     CHECKACTION checkAction = CHECKACTION.D; // action to take when bounds, asserts or switch defaults are violated
 
-    uint errorLimit = 20;
-    uint errorSupplementLimit = 6;      // Limit the number of supplemental messages for each error (0 means unlimited)
-
     const(char)[] argv0;                // program name
     Array!(const(char)*) modFileAliasStrings; // array of char*'s of -I module filename alias strings
     Array!(const(char)*)* imppath;      // array of char*'s of where to look for import modules
@@ -216,13 +233,7 @@ extern (C++) struct Param
     Output moduleDeps;                  // Generate `.deps` module dependencies
 
     uint debuglevel;                    // debug level
-    Array!(const(char)*)* debugids;     // debug identifiers
-
     uint versionlevel;                  // version level
-    Array!(const(char)*)* versionids;   // version identifiers
-
-
-    MessageStyle messageStyle = MessageStyle.digitalmars; // style of file/line annotations on messages
 
     bool run; // run resulting executable
     Strings runargs; // arguments for executable
@@ -355,7 +366,7 @@ extern (C++) struct Global
 
             // -color=auto is the default value
             import dmd.console : detectTerminal, detectColorPreference;
-            params.color = detectTerminal() && detectColorPreference();
+            params.v.color = detectTerminal() && detectColorPreference();
         }
         else version (IN_GCC)
         {
diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h
index e24042a4f21d..4048286ce715 100644
--- a/gcc/d/dmd/globals.h
+++ b/gcc/d/dmd/globals.h
@@ -112,6 +112,30 @@ struct Help
     d_bool hc;           // -HC
 };
 
+struct Verbose
+{
+    d_bool verbose;           // verbose compile
+    d_bool showColumns;       // print character (column) numbers in diagnostics
+    d_bool tls;               // identify thread local variables
+    d_bool templates;         // collect and list statistics on template instantiations
+    // collect and list statistics on template instantiations origins.
+    // TODO: make this an enum when we want to list other kinds of instances
+    d_bool templatesListInstances;
+    d_bool gc;                 // identify gc usage
+    d_bool field;              // identify non-mutable field variables
+    d_bool complex = true;     // identify complex/imaginary type usage
+    d_bool vin;                // identify 'in' parameters
+    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 logo;               // print compiler logo
+    d_bool color;              // use ANSI colors in console output
+    d_bool cov;                // generate code coverage data
+    MessageStyle messageStyle; // style of file/line annotations on messages
+    unsigned errorLimit;
+    unsigned errorSupplementLimit; // Limit the number of supplemental messages for each error (0 means unlimited)
+    unsigned errorSupplementCount();
+};
+
 // Put command line switches in here
 struct Param
 {
@@ -119,23 +143,13 @@ struct Param
     d_bool multiobj;      // break one object file into multiple ones
     d_bool trace;         // insert profiling hooks
     d_bool tracegc;       // instrument calls to 'new'
-    d_bool verbose;       // verbose compile
     d_bool vcg_ast;       // write-out codegen-ast
-    d_bool showColumns;   // print character (column) numbers in diagnostics
-    d_bool vtls;          // identify thread local variables
-    d_bool vtemplates;    // collect and list statistics on template instantiations
-    d_bool vtemplatesListInstances; // collect and list statistics on template instantiations origins
-    d_bool vgc;           // identify gc usage
-    d_bool vfield;        // identify non-mutable field variables
-    d_bool vcomplex;      // identify complex/imaginary type usage
-    d_bool vin;           // identify 'in' parameters
     Diagnostic useDeprecated;
     d_bool useUnitTests;  // generate unittest code
     d_bool useInline;     // inline expand functions
     d_bool release;       // build release version
     d_bool preservePaths; // true means don't strip path from source file
     Diagnostic warnings;
-    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
     d_bool ctfe_cov;      // generate coverage data for ctfe
@@ -149,10 +163,9 @@ struct Param
     d_bool allInst;       // generate code for all template instantiations
     d_bool bitfields;         // support C style bit fields
     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)
+
     Help help;
-    d_bool logo;              // print logo;
+    Verbose v;
 
     // Options for `-preview=/-revert=`
     FeatureState useDIP25;       // implement https://wiki.dlang.org/DIP25
@@ -187,9 +200,6 @@ struct Param
 
     CHECKACTION checkAction;       // action to take when bounds, asserts or switch defaults are violated
 
-    unsigned errorLimit;
-    unsigned errorSupplementLimit; // Limit the number of supplemental messages for each error (0 means unlimited)
-
     DString  argv0;    // program name
     Array<const char *> modFileAliasStrings; // array of char*'s of -I module filename alias strings
     Array<const char *> *imppath;     // array of char*'s of where to look for import modules
@@ -208,13 +218,7 @@ struct Param
     Output moduleDeps;        // Generate `.deps` module dependencies
 
     unsigned debuglevel;   // debug level
-    Array<const char *> *debugids;     // debug identifiers
-
     unsigned versionlevel; // version level
-    Array<const char *> *versionids;   // version identifiers
-
-
-    MessageStyle messageStyle;  // style of file/line annotations on messages
 
     d_bool run;           // run resulting executable
     Strings runargs;    // arguments for executable
diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d
index b4c8e8b899b5..056e486e927a 100644
--- a/gcc/d/dmd/hdrgen.d
+++ b/gcc/d/dmd/hdrgen.d
@@ -88,6 +88,39 @@ extern (C++) void genhdrfile(Module m, ref OutBuffer buf)
     toCBuffer(m, buf, hgs);
 }
 
+/***************************************
+ * Turn a Statement into a string suitable for printf.
+ * Leaks memory.
+ * Params:
+ *      s = Statement to convert
+ * Returns:
+ *      0-terminated string
+ */
+public extern (C++) const(char)* toChars(const Statement s)
+{
+    HdrGenState hgs;
+    OutBuffer buf;
+    toCBuffer(s, buf, hgs);
+    buf.writeByte(0);
+    return buf.extractSlice().ptr;
+}
+
+public extern (C++) const(char)* toChars(const Initializer i)
+{
+    OutBuffer buf;
+    HdrGenState hgs;
+    toCBuffer(i, buf, hgs);
+    return buf.extractChars();
+}
+
+public const(char)[] toString(const Initializer i)
+{
+    OutBuffer buf;
+    HdrGenState hgs;
+    toCBuffer(i, buf, hgs);
+    return buf.extractSlice();
+}
+
 /**
  * Dumps the full contents of module `m` to `buf`.
  * Params:
@@ -510,6 +543,20 @@ private void statementToBuffer(Statement s, ref OutBuffer buf, HdrGenState* hgs)
     void visitSwitch(SwitchStatement s)
     {
         buf.writestring(s.isFinal ? "final switch (" : "switch (");
+        if (auto p = s.param)
+        {
+            // Print condition assignment
+            StorageClass stc = p.storageClass;
+            if (!p.type && !stc)
+                stc = STC.auto_;
+            if (stcToBuffer(buf, stc))
+                buf.writeByte(' ');
+            if (p.type)
+                typeToBuffer(p.type, p.ident, buf, hgs);
+            else
+                buf.writestring(p.ident.toString());
+            buf.writestring(" = ");
+        }
         s.condition.expressionToBuffer(buf, hgs);
         buf.writeByte(')');
         buf.writenl();
@@ -796,48 +843,34 @@ private void statementToBuffer(Statement s, ref OutBuffer buf, HdrGenState* hgs)
 
 private void dsymbolToBuffer(Dsymbol s, ref OutBuffer buf, HdrGenState* hgs)
 {
-    scope v = new DsymbolPrettyPrintVisitor(&buf, hgs);
-    s.accept(v);
+    toCBuffer(s, buf, *hgs);
 }
 
-private extern (C++) final class DsymbolPrettyPrintVisitor : Visitor
+void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs)
 {
-    alias visit = Visitor.visit;
-public:
-    OutBuffer* buf;
-    HdrGenState* hgs;
-
-    extern (D) this(OutBuffer* buf, HdrGenState* hgs) scope @safe
-    {
-        this.buf = buf;
-        this.hgs = hgs;
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-
-    override void visit(Dsymbol s)
+    void visitDsymbol(Dsymbol s)
     {
         buf.writestring(s.toChars());
     }
 
-    override void visit(StaticAssert s)
+    void visitStaticAssert(StaticAssert s)
     {
         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(");");
         buf.writenl();
     }
 
-    override void visit(DebugSymbol s)
+    void visitDebugSymbol(DebugSymbol s)
     {
         buf.writestring("debug = ");
         if (s.ident)
@@ -848,7 +881,7 @@ public:
         buf.writenl();
     }
 
-    override void visit(VersionSymbol s)
+    void visitVersionSymbol(VersionSymbol s)
     {
         buf.writestring("version = ");
         if (s.ident)
@@ -859,20 +892,20 @@ public:
         buf.writenl();
     }
 
-    override void visit(EnumMember em)
+    void visitEnumMember(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);
         }
     }
 
-    override void visit(Import imp)
+    void visitImport(Import imp)
     {
         if (hgs.hdrgen && imp.id == Id.object)
             return; // object is imported by default
@@ -906,19 +939,19 @@ public:
         buf.writenl();
     }
 
-    override void visit(AliasThis d)
+    void visitAliasThis(AliasThis d)
     {
         buf.writestring("alias ");
         buf.writestring(d.ident.toString());
         buf.writestring(" this;\n");
     }
 
-    override void visit(AttribDeclaration d)
+    void visitAttribDeclaration(AttribDeclaration d)
     {
         bool hasSTC;
         if (auto stcd = d.isStorageClassDeclaration)
         {
-            hasSTC = stcToBuffer(*buf, stcd.stc);
+            hasSTC = stcToBuffer(buf, stcd.stc);
         }
 
         if (!d.decl)
@@ -936,7 +969,7 @@ public:
         else if (d.decl.length == 1)
         {
             if (hasSTC) buf.writeByte(' ');
-            (*d.decl)[0].accept(this);
+            toCBuffer((*d.decl)[0], buf, hgs);
             return;
         }
         else
@@ -946,35 +979,35 @@ public:
             buf.writenl();
             buf.level++;
             foreach (de; *d.decl)
-                de.accept(this);
+                toCBuffer(de, buf, hgs);
             buf.level--;
             buf.writeByte('}');
         }
         buf.writenl();
     }
 
-    override void visit(StorageClassDeclaration d)
+    void visitStorageClassDeclaration(StorageClassDeclaration d)
     {
-        visit(cast(AttribDeclaration)d);
+        visitAttribDeclaration(d);
     }
 
-    override void visit(DeprecatedDeclaration d)
+    void visitDeprecatedDeclaration(DeprecatedDeclaration d)
     {
         buf.writestring("deprecated(");
-        d.msg.expressionToBuffer(*buf, hgs);
+        d.msg.expressionToBuffer(buf, &hgs);
         buf.writestring(") ");
-        visit(cast(AttribDeclaration)d);
+        visitAttribDeclaration(d);
     }
 
-    override void visit(LinkDeclaration d)
+    void visitLinkDeclaration(LinkDeclaration d)
     {
         buf.writestring("extern (");
         buf.writestring(linkageToString(d.linkage));
         buf.writestring(") ");
-        visit(cast(AttribDeclaration)d);
+        visitAttribDeclaration(d);
     }
 
-    override void visit(CPPMangleDeclaration d)
+    void visitCPPMangleDeclaration(CPPMangleDeclaration d)
     {
         string s;
         final switch (d.cppmangle)
@@ -991,22 +1024,22 @@ public:
         buf.writestring("extern (C++, ");
         buf.writestring(s);
         buf.writestring(") ");
-        visit(cast(AttribDeclaration)d);
+        visitAttribDeclaration(d);
     }
 
-    override void visit(VisibilityDeclaration d)
+    void visitVisibilityDeclaration(VisibilityDeclaration d)
     {
-        visibilityToBuffer(*buf, d.visibility);
+        visibilityToBuffer(buf, d.visibility);
         AttribDeclaration ad = cast(AttribDeclaration)d;
         if (ad.decl.length <= 1)
             buf.writeByte(' ');
         if (ad.decl.length == 1 && (*ad.decl)[0].isVisibilityDeclaration)
-            visit(cast(AttribDeclaration)(*ad.decl)[0]);
+            visitAttribDeclaration((*ad.decl)[0].isVisibilityDeclaration);
         else
-            visit(cast(AttribDeclaration)d);
+            visitAttribDeclaration(d);
     }
 
-    override void visit(AlignDeclaration d)
+    void visitAlignDeclaration(AlignDeclaration d)
     {
         if (d.exps)
         {
@@ -1022,10 +1055,10 @@ public:
         else
             buf.writestring("align ");
 
-        visit(d.isAttribDeclaration());
+        visitAttribDeclaration(d.isAttribDeclaration());
     }
 
-    override void visit(AnonDeclaration d)
+    void visitAnonDeclaration(AnonDeclaration d)
     {
         buf.writestring(d.isunion ? "union" : "struct");
         buf.writenl();
@@ -1035,21 +1068,21 @@ public:
         if (d.decl)
         {
             foreach (de; *d.decl)
-                de.accept(this);
+                toCBuffer(de, buf, hgs);
         }
         buf.level--;
         buf.writestring("}");
         buf.writenl();
     }
 
-    override void visit(PragmaDeclaration d)
+    void visitPragmaDeclaration(PragmaDeclaration d)
     {
         buf.writestring("pragma (");
         buf.writestring(d.ident.toString());
         if (d.args && d.args.length)
         {
             buf.writestring(", ");
-            argsToBuffer(d.args, *buf, hgs);
+            argsToBuffer(d.args, buf, &hgs);
         }
 
         buf.writeByte(')');
@@ -1061,13 +1094,13 @@ public:
         if (d.ident == Id.Pinline)
             global.params.dihdr.fullOutput = true;
 
-        visit(cast(AttribDeclaration)d);
+        visitAttribDeclaration(d);
         global.params.dihdr.fullOutput = savedFullDump;
     }
 
-    override void visit(ConditionalDeclaration d)
+    void visitConditionalDeclaration(ConditionalDeclaration d)
     {
-        d.condition.conditionToBuffer(*buf, hgs);
+        d.condition.conditionToBuffer(buf, &hgs);
         if (d.decl || d.elsedecl)
         {
             buf.writenl();
@@ -1077,7 +1110,7 @@ public:
             if (d.decl)
             {
                 foreach (de; *d.decl)
-                    de.accept(this);
+                    toCBuffer(de, buf, hgs);
             }
             buf.level--;
             buf.writeByte('}');
@@ -1090,7 +1123,7 @@ public:
                 buf.writenl();
                 buf.level++;
                 foreach (de; *d.elsedecl)
-                    de.accept(this);
+                    toCBuffer(de, buf, hgs);
                 buf.level--;
                 buf.writeByte('}');
             }
@@ -1100,7 +1133,7 @@ public:
         buf.writenl();
     }
 
-    override void visit(StaticForeachDeclaration s)
+    void visitStaticForeachDeclaration(StaticForeachDeclaration s)
     {
         void foreachWithoutBody(ForeachStatement s)
         {
@@ -1110,15 +1143,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();
         }
@@ -1130,13 +1163,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();
         }
@@ -1154,62 +1187,161 @@ public:
         buf.writeByte('{');
         buf.writenl();
         buf.level++;
-        visit(cast(AttribDeclaration)s);
+        visitAttribDeclaration(s);
         buf.level--;
         buf.writeByte('}');
         buf.writenl();
 
     }
 
-    override void visit(MixinDeclaration d)
+    void visitMixinDeclaration(MixinDeclaration d)
     {
         buf.writestring("mixin(");
-        argsToBuffer(d.exps, *buf, hgs, null);
+        argsToBuffer(d.exps, buf, &hgs, null);
         buf.writestring(");");
         buf.writenl();
     }
 
-    override void visit(UserAttributeDeclaration d)
+    void visitUserAttributeDeclaration(UserAttributeDeclaration d)
     {
         buf.writestring("@(");
-        argsToBuffer(d.atts, *buf, hgs);
+        argsToBuffer(d.atts, buf, &hgs);
         buf.writeByte(')');
-        visit(cast(AttribDeclaration)d);
+        visitAttribDeclaration(d);
     }
 
-    override void visit(TemplateDeclaration d)
+    void visitTemplateConstraint(Expression constraint)
     {
-        version (none)
-        {
-            // Should handle template functions for doc generation
-            if (onemember && onemember.isFuncDeclaration())
-                buf.writestring("foo ");
-        }
-        if ((hgs.hdrgen || hgs.fullDump) && visitEponymousMember(d))
+        if (!constraint)
             return;
-        if (hgs.ddoc)
-            buf.writestring(d.kind());
-        else
-            buf.writestring("template");
-        buf.writeByte(' ');
-        buf.writestring(d.ident.toString());
-        buf.writeByte('(');
-        visitTemplateParameters(hgs.ddoc ? d.origParameters : d.parameters);
+        buf.writestring(" if (");
+        constraint.expressionToBuffer(buf, &hgs);
         buf.writeByte(')');
-        visitTemplateConstraint(d.constraint);
-        if (hgs.hdrgen || hgs.fullDump)
+    }
+
+    /// Returns: whether `do` is needed to write the function body
+    bool contractsToBuffer(FuncDeclaration f)
+    {
+        bool requireDo = false;
+        // in{}
+        if (f.frequires)
         {
-            hgs.tpltMember++;
-            buf.writenl();
-            buf.writeByte('{');
+            foreach (frequire; *f.frequires)
+            {
+                buf.writestring("in");
+                if (auto es = frequire.isExpStatement())
+                {
+                    assert(es.exp && es.exp.op == EXP.assert_);
+                    buf.writestring(" (");
+                    (cast(AssertExp)es.exp).e1.expressionToBuffer(buf, &hgs);
+                    buf.writeByte(')');
+                    buf.writenl();
+                    requireDo = false;
+                }
+                else
+                {
+                    buf.writenl();
+                    frequire.statementToBuffer(buf, &hgs);
+                    requireDo = true;
+                }
+            }
+        }
+        // out{}
+        if (f.fensures)
+        {
+            foreach (fensure; *f.fensures)
+            {
+                buf.writestring("out");
+                if (auto es = fensure.ensure.isExpStatement())
+                {
+                    assert(es.exp && es.exp.op == EXP.assert_);
+                    buf.writestring(" (");
+                    if (fensure.id)
+                    {
+                        buf.writestring(fensure.id.toString());
+                    }
+                    buf.writestring("; ");
+                    (cast(AssertExp)es.exp).e1.expressionToBuffer(buf, &hgs);
+                    buf.writeByte(')');
+                    buf.writenl();
+                    requireDo = false;
+                }
+                else
+                {
+                    if (fensure.id)
+                    {
+                        buf.writeByte('(');
+                        buf.writestring(fensure.id.toString());
+                        buf.writeByte(')');
+                    }
+                    buf.writenl();
+                    fensure.ensure.statementToBuffer(buf, &hgs);
+                    requireDo = true;
+                }
+            }
+        }
+        return requireDo;
+    }
+
+    void bodyToBuffer(FuncDeclaration f)
+    {
+        if (!f.fbody || (hgs.hdrgen && global.params.dihdr.fullOutput == false && !hgs.autoMember && !hgs.tpltMember && !hgs.insideFuncBody))
+        {
+            if (!f.fbody && (f.fensures || f.frequires))
+            {
+                buf.writenl();
+                contractsToBuffer(f);
+            }
+            buf.writeByte(';');
             buf.writenl();
-            buf.level++;
-            foreach (s; *d.members)
-                s.accept(this);
-            buf.level--;
-            buf.writeByte('}');
+            return;
+        }
+
+        // there is no way to know if a function is nested
+        // or not after parsing. We need scope information
+        // for that, which is avaible during semantic
+        // analysis. To overcome that, a simple mechanism
+        // is implemented: everytime we print a function
+        // body (templated or not) we increment a counter.
+        // We decredement the counter when we stop
+        // printing the function body.
+        ++hgs.insideFuncBody;
+        scope(exit) { --hgs.insideFuncBody; }
+
+        const savetlpt = hgs.tpltMember;
+        const saveauto = hgs.autoMember;
+        hgs.tpltMember = 0;
+        hgs.autoMember = 0;
+        buf.writenl();
+        bool requireDo = contractsToBuffer(f);
+
+        if (requireDo)
+        {
+            buf.writestring("do");
             buf.writenl();
-            hgs.tpltMember--;
+        }
+        buf.writeByte('{');
+        buf.writenl();
+        buf.level++;
+        f.fbody.statementToBuffer(buf, &hgs);
+        buf.level--;
+        buf.writeByte('}');
+        buf.writenl();
+        hgs.tpltMember = savetlpt;
+        hgs.autoMember = saveauto;
+    }
+
+    void visitBaseClasses(ClassDeclaration d)
+    {
+        if (!d || !d.baseclasses.length)
+            return;
+        if (!d.isAnonymous())
+            buf.writestring(" : ");
+        foreach (i, b; *d.baseclasses)
+        {
+            if (i)
+                buf.writestring(", ");
+            typeToBuffer(b.type, null, buf, &hgs);
         }
     }
 
@@ -1223,9 +1355,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);
@@ -1238,7 +1370,7 @@ public:
             buf.writeByte(' ');
             buf.writestring(ad.ident.toString());
             buf.writeByte('(');
-            visitTemplateParameters(hgs.ddoc ? d.origParameters : d.parameters);
+            visitTemplateParameters(hgs.ddoc ? d.origParameters : d.parameters, buf, hgs);
             buf.writeByte(')');
             visitTemplateConstraint(d.constraint);
             visitBaseClasses(ad.isClassDeclaration());
@@ -1250,7 +1382,7 @@ public:
                 buf.writenl();
                 buf.level++;
                 foreach (s; *ad.members)
-                    s.accept(this);
+                    toCBuffer(s, buf, hgs);
                 buf.level--;
                 buf.writeByte('}');
             }
@@ -1264,23 +1396,23 @@ 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('(');
-            visitTemplateParameters(hgs.ddoc ? d.origParameters : d.parameters);
+            visitTemplateParameters(hgs.ddoc ? d.origParameters : d.parameters, buf, hgs);
             buf.writeByte(')');
             if (vd._init)
             {
                 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();
@@ -1289,44 +1421,59 @@ public:
         return false;
     }
 
-    void visitTemplateParameters(TemplateParameters* parameters)
+    void visitTemplateDeclaration(TemplateDeclaration d)
     {
-        if (!parameters || !parameters.length)
-            return;
-        foreach (i, p; *parameters)
+        version (none)
         {
-            if (i)
-                buf.writestring(", ");
-            p.templateParameterToBuffer(*buf, hgs);
+            // Should handle template functions for doc generation
+            if (onemember && onemember.isFuncDeclaration())
+                buf.writestring("foo ");
         }
-    }
-
-    void visitTemplateConstraint(Expression constraint)
-    {
-        if (!constraint)
+        if ((hgs.hdrgen || hgs.fullDump) && visitEponymousMember(d))
             return;
-        buf.writestring(" if (");
-        constraint.expressionToBuffer(*buf, hgs);
+        if (hgs.ddoc)
+            buf.writestring(d.kind());
+        else
+            buf.writestring("template");
+        buf.writeByte(' ');
+        buf.writestring(d.ident.toString());
+        buf.writeByte('(');
+        visitTemplateParameters(hgs.ddoc ? d.origParameters : d.parameters, buf, hgs);
         buf.writeByte(')');
+        visitTemplateConstraint(d.constraint);
+        if (hgs.hdrgen || hgs.fullDump)
+        {
+            hgs.tpltMember++;
+            buf.writenl();
+            buf.writeByte('{');
+            buf.writenl();
+            buf.level++;
+            foreach (s; *d.members)
+                toCBuffer(s, buf, hgs);
+            buf.level--;
+            buf.writeByte('}');
+            buf.writenl();
+            hgs.tpltMember--;
+        }
     }
 
-    override void visit(TemplateInstance ti)
+    void visitTemplateInstance(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)
+    void visitTemplateMixin(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(' ');
@@ -1335,10 +1482,10 @@ public:
         buf.writeByte(';');
         buf.writenl();
         if (hgs.fullDump)
-            dumpTemplateInstance(tm, *buf, hgs);
+            dumpTemplateInstance(tm, buf, &hgs);
     }
 
-    override void visit(EnumDeclaration d)
+    void visitEnumDeclaration(EnumDeclaration d)
     {
         auto oldInEnumDecl = hgs.inEnumDecl;
         scope(exit) hgs.inEnumDecl = oldInEnumDecl;
@@ -1351,7 +1498,7 @@ public:
         if (d.memtype)
         {
             buf.writestring(" : ");
-            typeToBuffer(d.memtype, null, *buf, hgs);
+            typeToBuffer(d.memtype, null, buf, &hgs);
         }
         if (!d.members)
         {
@@ -1367,7 +1514,7 @@ public:
         {
             if (!em)
                 continue;
-            em.accept(this);
+            toCBuffer(em, buf, hgs);
             buf.writeByte(',');
             buf.writenl();
         }
@@ -1376,7 +1523,7 @@ public:
         buf.writenl();
     }
 
-    override void visit(Nspace d)
+    void visitNspace(Nspace d)
     {
         buf.writestring("extern (C++, ");
         buf.writestring(d.ident.toString());
@@ -1386,13 +1533,13 @@ public:
         buf.writenl();
         buf.level++;
         foreach (s; *d.members)
-            s.accept(this);
+            toCBuffer(s, buf, hgs);
         buf.level--;
         buf.writeByte('}');
         buf.writenl();
     }
 
-    override void visit(StructDeclaration d)
+    void visitStructDeclaration(StructDeclaration d)
     {
         buf.writestring(d.kind());
         buf.writeByte(' ');
@@ -1410,14 +1557,14 @@ public:
         buf.level++;
         hgs.insideAggregate++;
         foreach (s; *d.members)
-            s.accept(this);
+            toCBuffer(s, buf, hgs);
         hgs.insideAggregate--;
         buf.level--;
         buf.writeByte('}');
         buf.writenl();
     }
 
-    override void visit(ClassDeclaration d)
+    void visitClassDeclaration(ClassDeclaration d)
     {
         if (!d.isAnonymous())
         {
@@ -1434,7 +1581,7 @@ public:
             buf.level++;
             hgs.insideAggregate++;
             foreach (s; *d.members)
-                s.accept(this);
+                toCBuffer(s, buf, hgs);
             hgs.insideAggregate--;
             buf.level--;
             buf.writeByte('}');
@@ -1444,21 +1591,7 @@ public:
         buf.writenl();
     }
 
-    void visitBaseClasses(ClassDeclaration d)
-    {
-        if (!d || !d.baseclasses.length)
-            return;
-        if (!d.isAnonymous())
-            buf.writestring(" : ");
-        foreach (i, b; *d.baseclasses)
-        {
-            if (i)
-                buf.writestring(", ");
-            typeToBuffer(b.type, null, *buf, hgs);
-        }
-    }
-
-    override void visit(AliasDeclaration d)
+    void visitAliasDeclaration(AliasDeclaration d)
     {
         if (d.storage_class & STC.local)
             return;
@@ -1467,7 +1600,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
@@ -1481,57 +1614,57 @@ public:
             }
             else
             {
-                d.aliassym.accept(this);
+                toCBuffer(d.aliassym, buf, hgs);
             }
         }
         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(';');
         buf.writenl();
     }
 
-    override void visit(AliasAssign d)
+    void visitAliasAssign(AliasAssign d)
     {
         buf.writestring(d.ident.toString());
         buf.writestring(" = ");
         if (d.aliassym)
-            d.aliassym.accept(this);
+            toCBuffer(d.aliassym, buf, hgs);
         else // d.type
-            typeToBuffer(d.type, null, *buf, hgs);
+            typeToBuffer(d.type, null, buf, &hgs);
         buf.writeByte(';');
         buf.writenl();
     }
 
-    override void visit(VarDeclaration d)
+    void visitVarDeclaration(VarDeclaration d)
     {
         if (d.storage_class & STC.local)
             return;
-        visitVarDecl(d, false, *buf, *hgs);
+        visitVarDecl(d, false, buf, hgs);
         buf.writeByte(';');
         buf.writenl();
     }
 
-    override void visit(FuncDeclaration f)
+    void visitFuncDeclaration(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)
         {
@@ -1564,119 +1697,7 @@ public:
             bodyToBuffer(f);
     }
 
-    /// Returns: whether `do` is needed to write the function body
-    bool contractsToBuffer(FuncDeclaration f)
-    {
-        bool requireDo = false;
-        // in{}
-        if (f.frequires)
-        {
-            foreach (frequire; *f.frequires)
-            {
-                buf.writestring("in");
-                if (auto es = frequire.isExpStatement())
-                {
-                    assert(es.exp && es.exp.op == EXP.assert_);
-                    buf.writestring(" (");
-                    (cast(AssertExp)es.exp).e1.expressionToBuffer(*buf, hgs);
-                    buf.writeByte(')');
-                    buf.writenl();
-                    requireDo = false;
-                }
-                else
-                {
-                    buf.writenl();
-                    frequire.statementToBuffer(*buf, hgs);
-                    requireDo = true;
-                }
-            }
-        }
-        // out{}
-        if (f.fensures)
-        {
-            foreach (fensure; *f.fensures)
-            {
-                buf.writestring("out");
-                if (auto es = fensure.ensure.isExpStatement())
-                {
-                    assert(es.exp && es.exp.op == EXP.assert_);
-                    buf.writestring(" (");
-                    if (fensure.id)
-                    {
-                        buf.writestring(fensure.id.toString());
-                    }
-                    buf.writestring("; ");
-                    (cast(AssertExp)es.exp).e1.expressionToBuffer(*buf, hgs);
-                    buf.writeByte(')');
-                    buf.writenl();
-                    requireDo = false;
-                }
-                else
-                {
-                    if (fensure.id)
-                    {
-                        buf.writeByte('(');
-                        buf.writestring(fensure.id.toString());
-                        buf.writeByte(')');
-                    }
-                    buf.writenl();
-                    fensure.ensure.statementToBuffer(*buf, hgs);
-                    requireDo = true;
-                }
-            }
-        }
-        return requireDo;
-    }
-
-    void bodyToBuffer(FuncDeclaration f)
-    {
-        if (!f.fbody || (hgs.hdrgen && global.params.dihdr.fullOutput == false && !hgs.autoMember && !hgs.tpltMember && !hgs.insideFuncBody))
-        {
-            if (!f.fbody && (f.fensures || f.frequires))
-            {
-                buf.writenl();
-                contractsToBuffer(f);
-            }
-            buf.writeByte(';');
-            buf.writenl();
-            return;
-        }
-
-        // there is no way to know if a function is nested
-        // or not after parsing. We need scope information
-        // for that, which is avaible during semantic
-        // analysis. To overcome that, a simple mechanism
-        // is implemented: everytime we print a function
-        // body (templated or not) we increment a counter.
-        // We decredement the counter when we stop
-        // printing the function body.
-        ++hgs.insideFuncBody;
-        scope(exit) { --hgs.insideFuncBody; }
-
-        const savetlpt = hgs.tpltMember;
-        const saveauto = hgs.autoMember;
-        hgs.tpltMember = 0;
-        hgs.autoMember = 0;
-        buf.writenl();
-        bool requireDo = contractsToBuffer(f);
-
-        if (requireDo)
-        {
-            buf.writestring("do");
-            buf.writenl();
-        }
-        buf.writeByte('{');
-        buf.writenl();
-        buf.level++;
-        f.fbody.statementToBuffer(*buf, hgs);
-        buf.level--;
-        buf.writeByte('}');
-        buf.writenl();
-        hgs.tpltMember = savetlpt;
-        hgs.autoMember = saveauto;
-    }
-
-    override void visit(FuncLiteralDeclaration f)
+    void visitFuncLiteralDeclaration(FuncLiteralDeclaration f)
     {
         if (f.type.ty == Terror)
         {
@@ -1691,8 +1712,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)
@@ -1715,7 +1736,7 @@ public:
         if (rs && rs.exp)
         {
             buf.writestring(" => ");
-            rs.exp.expressionToBuffer(*buf, hgs);
+            rs.exp.expressionToBuffer(buf, &hgs);
         }
         else
         {
@@ -1725,25 +1746,25 @@ public:
         }
     }
 
-    override void visit(PostBlitDeclaration d)
+    void visitPostBlitDeclaration(PostBlitDeclaration d)
     {
-        if (stcToBuffer(*buf, d.storage_class))
+        if (stcToBuffer(buf, d.storage_class))
             buf.writeByte(' ');
         buf.writestring("this(this)");
         bodyToBuffer(d);
     }
 
-    override void visit(DtorDeclaration d)
+    void visitDtorDeclaration(DtorDeclaration d)
     {
-        if (stcToBuffer(*buf, d.storage_class))
+        if (stcToBuffer(buf, d.storage_class))
             buf.writeByte(' ');
         buf.writestring("~this()");
         bodyToBuffer(d);
     }
 
-    override void visit(StaticCtorDeclaration d)
+    void visitStaticCtorDeclaration(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 ");
@@ -1757,9 +1778,9 @@ public:
             bodyToBuffer(d);
     }
 
-    override void visit(StaticDtorDeclaration d)
+    void visitStaticDtorDeclaration(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 ");
@@ -1773,18 +1794,18 @@ public:
             bodyToBuffer(d);
     }
 
-    override void visit(InvariantDeclaration d)
+    void visitInvariantDeclaration(InvariantDeclaration d)
     {
         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();
         }
@@ -1794,41 +1815,111 @@ public:
         }
     }
 
-    override void visit(UnitTestDeclaration d)
+    void visitUnitTestDeclaration(UnitTestDeclaration d)
     {
         if (hgs.hdrgen)
             return;
-        if (stcToBuffer(*buf, d.storage_class))
+        if (stcToBuffer(buf, d.storage_class))
             buf.writeByte(' ');
         buf.writestring("unittest");
         bodyToBuffer(d);
     }
 
-    override void visit(BitFieldDeclaration d)
+    void visitBitFieldDeclaration(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)
+    void visitNewDeclaration(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)
+    void visitModule(Module m)
+    {
+        moduleToBuffer2(m, buf, &hgs);
+    }
+
+    extern (C++)
+    final class DsymbolPrettyPrintVisitor : Visitor
+    {
+        alias visit = Visitor.visit;
+
+      public:
+      override:
+        void visit(Dsymbol s)                  { visitDsymbol(s); }
+        void visit(StaticAssert s)             { visitStaticAssert(s); }
+        void visit(DebugSymbol s)              { visitDebugSymbol(s); }
+        void visit(VersionSymbol s)            { visitVersionSymbol(s); }
+        void visit(EnumMember em)              { visitEnumMember(em); }
+        void visit(Import imp)                 { visitImport(imp); }
+        void visit(AliasThis d)                { visitAliasThis(d); }
+        void visit(AttribDeclaration d)        { visitAttribDeclaration(d); }
+        void visit(StorageClassDeclaration d)  { visitStorageClassDeclaration(d); }
+        void visit(DeprecatedDeclaration d)    { visitDeprecatedDeclaration(d); }
+        void visit(LinkDeclaration d)          { visitLinkDeclaration(d); }
+        void visit(CPPMangleDeclaration d)     { visitCPPMangleDeclaration(d); }
+        void visit(VisibilityDeclaration d)    { visitVisibilityDeclaration(d); }
+        void visit(AlignDeclaration d)         { visitAlignDeclaration(d); }
+        void visit(AnonDeclaration d)          { visitAnonDeclaration(d); }
+        void visit(PragmaDeclaration d)        { visitPragmaDeclaration(d); }
+        void visit(ConditionalDeclaration d)   { visitConditionalDeclaration(d); }
+        void visit(StaticForeachDeclaration s) { visitStaticForeachDeclaration(s); }
+        void visit(MixinDeclaration d)         { visitMixinDeclaration(d); }
+        void visit(UserAttributeDeclaration d) { visitUserAttributeDeclaration(d); }
+        void visit(TemplateDeclaration d)      { visitTemplateDeclaration(d); }
+        void visit(TemplateInstance ti)        { visitTemplateInstance(ti); }
+        void visit(TemplateMixin tm)           { visitTemplateMixin(tm); }
+        void visit(EnumDeclaration d)          { visitEnumDeclaration(d); }
+        void visit(Nspace d)                   { visitNspace(d); }
+        void visit(StructDeclaration d)        { visitStructDeclaration(d); }
+        void visit(ClassDeclaration d)         { visitClassDeclaration(d); }
+        void visit(AliasDeclaration d)         { visitAliasDeclaration(d); }
+        void visit(AliasAssign d)              { visitAliasAssign(d); }
+        void visit(VarDeclaration d)           { visitVarDeclaration(d); }
+        void visit(FuncDeclaration f)          { visitFuncDeclaration(f); }
+        void visit(FuncLiteralDeclaration f)   { visitFuncLiteralDeclaration(f); }
+        void visit(PostBlitDeclaration d)      { visitPostBlitDeclaration(d); }
+        void visit(DtorDeclaration d)          { visitDtorDeclaration(d); }
+        void visit(StaticCtorDeclaration d)    { visitStaticCtorDeclaration(d); }
+        void visit(StaticDtorDeclaration d)    { visitStaticDtorDeclaration(d); }
+        void visit(InvariantDeclaration d)     { visitInvariantDeclaration(d); }
+        void visit(UnitTestDeclaration d)      { visitUnitTestDeclaration(d); }
+        void visit(BitFieldDeclaration d)      { visitBitFieldDeclaration(d); }
+        void visit(NewDeclaration d)           { visitNewDeclaration(d); }
+        void visit(Module m)                   { visitModule(m); }
+    }
+
+    scope v = new DsymbolPrettyPrintVisitor();
+    s.accept(v);
+}
+
+
+/*****************************************
+ * Pretty-print a template parameter list to a buffer.
+ */
+private void visitTemplateParameters(TemplateParameters* parameters, ref OutBuffer buf, ref HdrGenState hgs)
+{
+    if (!parameters)
+        return;
+    foreach (i, p; *parameters)
     {
-        moduleToBuffer2(m, *buf, hgs);
+        if (i)
+            buf.writestring(", ");
+        p.templateParameterToBuffer(buf, &hgs);
     }
 }
 
+
 /*******************************************
  * Pretty-print a VarDeclaration to buf.
  */
@@ -2011,7 +2102,7 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, HdrGenState*
 
     void visitVoidInit(VoidInitExp e)
     {
-        buf.writestring("__void");
+        buf.writestring("void");
     }
 
     void floatToBuffer(Type type, real_t value)
@@ -2313,8 +2404,7 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, HdrGenState*
         if (e.parameters && e.parameters.length)
         {
             buf.writestring(", ");
-            scope v = new DsymbolPrettyPrintVisitor(&buf, hgs);
-            v.visitTemplateParameters(e.parameters);
+            visitTemplateParameters(e.parameters, buf, *hgs);
         }
         buf.writeByte(')');
     }
@@ -2905,19 +2995,14 @@ void toCBuffer(const Type t, ref OutBuffer buf, const Identifier ident, ref HdrG
     typeToBuffer(cast() t, ident, buf, &hgs);
 }
 
-void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs)
-{
-    scope v = new DsymbolPrettyPrintVisitor(&buf, &hgs);
-    s.accept(v);
-}
-
 // used from TemplateInstance::toChars() and TemplateMixin::toChars()
 void toCBufferInstance(const TemplateInstance ti, ref OutBuffer buf, bool qualifyTypes = false)
 {
     HdrGenState hgs;
     hgs.fullQual = qualifyTypes;
-    scope v = new DsymbolPrettyPrintVisitor(&buf, &hgs);
-    v.visit(cast() ti);
+
+    buf.writestring(ti.name.toChars());
+    tiargsToBuffer(cast() ti, buf, &hgs);
 }
 
 void toCBuffer(const Initializer iz, ref OutBuffer buf, ref HdrGenState hgs)
@@ -3063,22 +3148,17 @@ const(char)* linkageToChars(LINK linkage)
 
 string linkageToString(LINK linkage) pure nothrow @safe
 {
-    final switch (linkage)
-    {
-    case LINK.default_:
-        return null;
-    case LINK.d:
-        return "D";
-    case LINK.c:
-        return "C";
-    case LINK.cpp:
-        return "C++";
-    case LINK.windows:
-        return "Windows";
-    case LINK.objc:
-        return "Objective-C";
-    case LINK.system:
-        return "System";
+    with (LINK)
+    {
+        immutable string[7] a = [
+                default_ : null,
+                d        : "D",
+                c        : "C",
+                cpp      : "C++",
+                windows  : "Windows",
+                objc     : "Objective-C",
+                system   : "System" ];
+        return a[linkage];
     }
 }
 
@@ -3106,22 +3186,16 @@ const(char)* visibilityToChars(Visibility.Kind kind)
 /// Ditto
 extern (D) string visibilityToString(Visibility.Kind kind) nothrow pure @safe
 {
-    final switch (kind)
-    {
-    case Visibility.Kind.undefined:
-        return null;
-    case Visibility.Kind.none:
-        return "none";
-    case Visibility.Kind.private_:
-        return "private";
-    case Visibility.Kind.package_:
-        return "package";
-    case Visibility.Kind.protected_:
-        return "protected";
-    case Visibility.Kind.public_:
-        return "public";
-    case Visibility.Kind.export_:
-        return "export";
+    with (Visibility.Kind)
+    {
+        immutable string[7] a = [
+                none       : "none",
+                private_   : "private",
+                package_   : "package",
+                protected_ : "protected",
+                public_    : "public",
+                export_    : "export" ];
+        return a[kind];
     }
 }
 
diff --git a/gcc/d/dmd/iasm.d b/gcc/d/dmd/iasm.d
index 1fdfe40765b8..c58224f7debd 100644
--- a/gcc/d/dmd/iasm.d
+++ b/gcc/d/dmd/iasm.d
@@ -64,6 +64,7 @@ extern(C++) Statement asmSemantic(AsmStatement s, Scope *sc)
             return statementSemantic(se, sc);
         }
         auto ias = new InlineAsmStatement(s.loc, s.tokens);
+        ias.caseSensitive = s.caseSensitive;
         return inlineAsmSemantic(ias, sc);
     }
     else version (IN_GCC)
diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d
index 62fb51f752e9..b506e6feb665 100644
--- a/gcc/d/dmd/id.d
+++ b/gcc/d/dmd/id.d
@@ -61,6 +61,8 @@ immutable Msgtable[] msgtable =
     { "IUnknown" },
     { "Object" },
     { "object" },
+    { "_size_t", "size_t" },
+    { "_ptrdiff_t", "ptrdiff_t" },
     { "string" },
     { "wstring" },
     { "dstring" },
diff --git a/gcc/d/dmd/importc.d b/gcc/d/dmd/importc.d
index fe0aa171d98c..98ac9038a0aa 100644
--- a/gcc/d/dmd/importc.d
+++ b/gcc/d/dmd/importc.d
@@ -20,6 +20,7 @@ import dmd.dcast;
 import dmd.declaration;
 import dmd.dscope;
 import dmd.dsymbol;
+import dmd.errors;
 import dmd.expression;
 import dmd.expressionsem;
 import dmd.identifier;
@@ -126,14 +127,14 @@ Expression fieldLookup(Expression e, Scope* sc, Identifier id, bool arrow)
         t = t.isTypePointer().next;
         auto pe = e.toChars();
         if (!arrow)
-            e.error("since `%s` is a pointer, use `%s->%s` instead of `%s.%s`", pe, pe, id.toChars(), pe, id.toChars());
+            error(e.loc, "since `%s` is a pointer, use `%s->%s` instead of `%s.%s`", pe, pe, id.toChars(), pe, id.toChars());
         e = new PtrExp(e.loc, e);
     }
     if (auto ts = t.isTypeStruct())
         s = ts.sym.search(e.loc, id, 0);
     if (!s)
     {
-        e.error("`%s` is not a member of `%s`", id.toChars(), t.toChars());
+        error(e.loc, "`%s` is not a member of `%s`", id.toChars(), t.toChars());
         return ErrorExp.get();
     }
     Expression ef = new DotVarExp(e.loc, e, s.isDeclaration());
diff --git a/gcc/d/dmd/init.d b/gcc/d/dmd/init.d
index 4501185b393a..ecca55283524 100644
--- a/gcc/d/dmd/init.d
+++ b/gcc/d/dmd/init.d
@@ -57,14 +57,6 @@ extern (C++) class Initializer : ASTNode
         this.kind = kind;
     }
 
-    override final const(char)* toChars() const
-    {
-        OutBuffer buf;
-        HdrGenState hgs;
-        toCBuffer(this, buf, hgs);
-        return buf.extractChars();
-    }
-
     final inout(ErrorInitializer) isErrorInitializer() inout @nogc nothrow pure
     {
         // Use void* cast to skip dynamic casting call
diff --git a/gcc/d/dmd/init.h b/gcc/d/dmd/init.h
index 9a6a56b68bbf..4ab5848454e0 100644
--- a/gcc/d/dmd/init.h
+++ b/gcc/d/dmd/init.h
@@ -35,8 +35,6 @@ public:
 
     DYNCAST dyncast() const override { return DYNCAST_INITIALIZER; }
 
-    const char *toChars() const override final;
-
     ErrorInitializer   *isErrorInitializer();
     VoidInitializer    *isVoidInitializer();
     StructInitializer  *isStructInitializer();
diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d
index 45f09af8733b..28c7c2bb52e9 100644
--- a/gcc/d/dmd/initsem.d
+++ b/gcc/d/dmd/initsem.d
@@ -29,6 +29,7 @@ import dmd.expression;
 import dmd.expressionsem;
 import dmd.func;
 import dmd.globals;
+import dmd.hdrgen;
 import dmd.id;
 import dmd.identifier;
 import dmd.importc;
@@ -59,12 +60,12 @@ Expression toAssocArrayLiteral(ArrayInitializer ai)
     if (!dim)
     {
         error(ai.loc, "invalid associative array initializer `%s`, use `null` instead",
-            ai.toChars());
+            toChars(ai));
         return ErrorExp.get();
     }
     auto no(const char* format, Initializer i)
     {
-        error(i.loc, format, i.toChars());
+        error(i.loc, format, toChars(i));
         return ErrorExp.get();
     }
     Expression e;
@@ -399,13 +400,13 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
         }
         if (i.exp.op == EXP.type)
         {
-            i.exp.error("initializer must be an expression, not `%s`", i.exp.toChars());
+            error(i.exp.loc, "initializer must be an expression, not `%s`", i.exp.toChars());
             return err();
         }
         // Make sure all pointers are constants
         if (needInterpret && hasNonConstPointers(i.exp))
         {
-            i.exp.error("cannot use non-constant CTFE pointer in an initializer `%s`", currExp.toChars());
+            error(i.exp.loc, "cannot use non-constant CTFE pointer in an initializer `%s`", currExp.toChars());
             return err();
         }
         Type ti = i.exp.type.toBasetype();
@@ -563,7 +564,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
                 }
                 if (dim1 != dim2)
                 {
-                    i.exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
+                    error(i.exp.loc, "mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
                     i.exp = ErrorExp.get();
                 }
             }
@@ -571,7 +572,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
             const errors = global.startGagging();
             i.exp = i.exp.implicitCastTo(sc, t);
             if (global.endGagging(errors))
-                currExp.error("cannot implicitly convert expression `%s` of type `%s` to `%s`", currExp.toChars(), et.toChars(), t.toChars());
+                error(currExp.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`", currExp.toChars(), et.toChars(), t.toChars());
         }
         }
     L1:
@@ -791,12 +792,12 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
                     const length = (*dlist).length;
                     if (length == 0 || !(*dlist)[0].ident)
                     {
-                        error(ci.loc, "`.identifier` expected for C struct field initializer `%s`", ci.toChars());
+                        error(ci.loc, "`.identifier` expected for C struct field initializer `%s`", toChars(ci));
                         return err();
                     }
                     if (length > 1)
                     {
-                        error(ci.loc, "only 1 designator currently allowed for C struct field initializer `%s`", ci.toChars());
+                        error(ci.loc, "only 1 designator currently allowed for C struct field initializer `%s`", toChars(ci));
                         return err();
                     }
                     auto id = (*dlist)[0].ident;
@@ -912,12 +913,12 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
                     const length = (*dlist).length;
                     if (length == 0 || !(*dlist)[0].exp)
                     {
-                        error(ci.loc, "`[ constant-expression ]` expected for C array element initializer `%s`", ci.toChars());
+                        error(ci.loc, "`[ constant-expression ]` expected for C array element initializer `%s`", toChars(ci));
                         return err();
                     }
                     if (length > 1)
                     {
-                        error(ci.loc, "only 1 designator currently allowed for C array element initializer `%s`", ci.toChars());
+                        error(ci.loc, "only 1 designator currently allowed for C array element initializer `%s`", toChars(ci));
                         return err();
                     }
                     //printf("tn: %s, di.initializer: %s\n", tn.toChars(), di.initializer.toChars());
@@ -988,7 +989,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
         }
         else
         {
-            error(ci.loc, "unrecognized C initializer `%s`", ci.toChars());
+            error(ci.loc, "unrecognized C initializer `%s`", toChars(ci));
             return err();
         }
     }
@@ -1103,9 +1104,9 @@ Initializer inferType(Initializer init, Scope* sc)
         {
             TemplateInstance ti = se.sds.isTemplateInstance();
             if (ti && ti.semanticRun == PASS.semantic && !ti.aliasdecl)
-                se.error("cannot infer type from %s `%s`, possible circular dependency", se.sds.kind(), se.toChars());
+                error(se.loc, "cannot infer type from %s `%s`, possible circular dependency", se.sds.kind(), se.toChars());
             else
-                se.error("cannot infer type from %s `%s`", se.sds.kind(), se.toChars());
+                error(se.loc, "cannot infer type from %s `%s`", se.sds.kind(), se.toChars());
             return new ErrorInitializer();
         }
 
@@ -1119,7 +1120,7 @@ Initializer inferType(Initializer init, Scope* sc)
             }
             if (hasOverloads && !f.isUnique())
             {
-                init.exp.error("cannot infer type from overloaded function symbol `%s`", init.exp.toChars());
+                error(init.exp.loc, "cannot infer type from overloaded function symbol `%s`", init.exp.toChars());
                 return new ErrorInitializer();
             }
         }
@@ -1127,7 +1128,7 @@ Initializer inferType(Initializer init, Scope* sc)
         {
             if (ae.e1.op == EXP.overloadSet)
             {
-                init.exp.error("cannot infer type from overloaded function symbol `%s`", init.exp.toChars());
+                error(init.exp.loc, "cannot infer type from overloaded function symbol `%s`", init.exp.toChars());
                 return new ErrorInitializer();
             }
         }
diff --git a/gcc/d/dmd/json.d b/gcc/d/dmd/json.d
index c803bf80cc0d..f1999fd458d3 100644
--- a/gcc/d/dmd/json.d
+++ b/gcc/d/dmd/json.d
@@ -788,7 +788,7 @@ public:
         objectStart();
         jsonProperties(d);
         if (d._init)
-            property("init", d._init.toString());
+            property("init", toString(d._init));
         if (d.isField())
             property("offset", d.offset);
         if (!d.alignment.isUnknown() && !d.alignment.isDefault())
@@ -815,7 +815,7 @@ public:
         arrayStart();
         foreach (m; modules)
         {
-            if (global.params.verbose)
+            if (global.params.v.verbose)
                 message("json gen %s", m.toChars());
             m.accept(this);
         }
diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d
index 28ffbf8ed6d6..882f2eac06c7 100644
--- a/gcc/d/dmd/lexer.d
+++ b/gcc/d/dmd/lexer.d
@@ -1525,6 +1525,7 @@ class Lexer
                     stringbuffer.writeByte(v);
                 }
                 t.setString(stringbuffer);
+                t.postfix = 'h';
                 stringPostfix(t);
                 return TOK.hexadecimalString;
             default:
@@ -2206,9 +2207,14 @@ class Lexer
                 if (base == 2)
                     goto Ldone; // if ".identifier" or ".unicode"
                 goto Lreal; // otherwise as part of a floating point literal
+
+            case 'i':
+                if (Ccompile)
+                    goto Ldone;
+                goto Lreal;
+
             case 'p':
             case 'P':
-            case 'i':
             Lreal:
                 p = start;
                 return inreal(t);
@@ -2401,7 +2407,13 @@ class Lexer
             decimal  = 2, // decimal
             unsigned = 4, // u or U suffix
             long_    = 8, // l or L suffix
-            llong    = 0x10 // ll or LL
+            llong    = 0x10, // ll or LL
+
+            // Microsoft extensions
+            i8       = 0x20,
+            i16      = 0x40,
+            i32      = 0x80,
+            i64      = 0x100,
         }
         FLAGS flags = (base == 10) ? FLAGS.decimal : FLAGS.octalhex;
         bool err;
@@ -2427,6 +2439,37 @@ class Lexer
                     }
                     break;
 
+                case 'i':
+                case 'I':
+                    if (p[1] == '8')
+                    {
+                        f = FLAGS.i8;
+                        ++p;
+                    }
+                    else if (p[1] == '1' && p[2] == '6')
+                    {
+                        f = FLAGS.i16;
+                        p += 2;
+                    }
+                    else if (p[1] == '3' && p[2] == '2')
+                    {
+                        f = FLAGS.i32;
+                        p += 2;
+                    }
+                    else if (p[1] == '6' && p[2] == '4')
+                    {
+                        f = FLAGS.i64;
+                        p += 2;
+                    }
+                    else
+                        break Lsuffixes;
+                    if (p[1] >= '0' && p[1] <= '9' && !err)
+                    {
+                        error("invalid integer suffix");
+                        err = true;
+                    }
+                    break;
+
                 default:
                     break Lsuffixes;
             }
@@ -2559,6 +2602,34 @@ class Lexer
                 result = TOK.uns64Literal;
                 break;
 
+            case FLAGS.octalhex | FLAGS.i8:
+            case FLAGS.octalhex | FLAGS.i16:
+            case FLAGS.octalhex | FLAGS.i32:
+            case FLAGS.octalhex | FLAGS.unsigned | FLAGS.i8:
+            case FLAGS.octalhex | FLAGS.unsigned | FLAGS.i16:
+            case FLAGS.octalhex | FLAGS.unsigned | FLAGS.i32:
+            case FLAGS.decimal  | FLAGS.unsigned | FLAGS.i8:
+            case FLAGS.decimal  | FLAGS.unsigned | FLAGS.i16:
+            case FLAGS.decimal  | FLAGS.unsigned | FLAGS.i32:
+                result = TOK.uns32Literal;
+                break;
+
+            case FLAGS.decimal | FLAGS.i8:
+            case FLAGS.decimal | FLAGS.i16:
+            case FLAGS.decimal | FLAGS.i32:
+                result = TOK.int32Literal;
+                break;
+
+            case FLAGS.octalhex | FLAGS.i64:
+            case FLAGS.octalhex | FLAGS.unsigned | FLAGS.i64:
+            case FLAGS.decimal  | FLAGS.unsigned | FLAGS.i64:
+                result = TOK.uns64Literal;
+                break;
+
+            case FLAGS.decimal | FLAGS.i64:
+                result = TOK.int64Literal;
+                break;
+
             default:
                 debug printf("%x\n",flags);
                 assert(0);
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index 63e20ed89d0d..01f94a7b04d3 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -4592,7 +4592,7 @@ extern (C++) final class TypeFunction : TypeNext
     // arguments get specially formatted
     private const(char)* getParamError(Expression arg, Parameter par)
     {
-        if (global.gag && !global.params.showGaggedErrors)
+        if (global.gag && !global.params.v.showGaggedErrors)
             return null;
         // show qualification when toChars() is the same but types are different
         // https://issues.dlang.org/show_bug.cgi?id=19948
@@ -4611,7 +4611,7 @@ extern (C++) final class TypeFunction : TypeNext
 
     private extern(D) const(char)* getMatchError(A...)(const(char)* format, A args)
     {
-        if (global.gag && !global.params.showGaggedErrors)
+        if (global.gag && !global.params.v.showGaggedErrors)
             return null;
         OutBuffer buf;
         buf.printf(format, args);
@@ -6217,7 +6217,7 @@ extern (C++) final class TypeTuple : Type
             {
                 Expression e = (*exps)[i];
                 if (e.type.ty == Ttuple)
-                    e.error("cannot form sequence of sequences");
+                    error(e.loc, "cannot form sequence of sequences");
                 auto arg = new Parameter(e.loc, STC.undefined_, e.type, null, null, null);
                 (*arguments)[i] = arg;
             }
diff --git a/gcc/d/dmd/mustuse.d b/gcc/d/dmd/mustuse.d
index 844f719e0b81..1d831bbed6b3 100644
--- a/gcc/d/dmd/mustuse.d
+++ b/gcc/d/dmd/mustuse.d
@@ -12,6 +12,7 @@ module dmd.mustuse;
 
 import dmd.dscope;
 import dmd.dsymbol;
+import dmd.errors;
 import dmd.expression;
 import dmd.globals;
 import dmd.identifier;
@@ -49,7 +50,7 @@ bool checkMustUse(Expression e, Scope* sc)
         // isStructDeclaration returns non-null for both structs and unions
         if (sd && hasMustUseAttribute(sd, sc) && !isAssignment(e) && !isIncrementOrDecrement(e))
         {
-            e.error("ignored value of `@%s` type `%s`; prepend a `cast(void)` if intentional",
+            error(e.loc, "ignored value of `@%s` type `%s`; prepend a `cast(void)` if intentional",
                 Id.udaMustUse.toChars(), e.type.toPrettyChars(true));
             return true;
         }
diff --git a/gcc/d/dmd/nogc.d b/gcc/d/dmd/nogc.d
index 01a6832a97be..560606190e06 100644
--- a/gcc/d/dmd/nogc.d
+++ b/gcc/d/dmd/nogc.d
@@ -86,7 +86,7 @@ public:
         }
         if (f.setGC(e.loc, format))
         {
-            e.error(format, f.kind(), f.toPrettyChars());
+            error(e.loc, format, f.kind(), f.toPrettyChars());
             err = true;
             return true;
         }
@@ -225,7 +225,7 @@ Expression checkGC(Scope* sc, Expression e)
     if (e && e.op != EXP.error && f && sc.intypeof != 1 &&
            (!(sc.flags & SCOPE.ctfe) || betterC) &&
            (f.type.ty == Tfunction &&
-            (cast(TypeFunction)f.type).isnogc || f.nogcInprocess || global.params.vgc) &&
+            (cast(TypeFunction)f.type).isnogc || f.nogcInprocess || global.params.v.gc) &&
            !(sc.flags & SCOPE.debug_))
     {
         scope NOGCVisitor gcv = new NOGCVisitor(f);
diff --git a/gcc/d/dmd/nspace.d b/gcc/d/dmd/nspace.d
index 551db5b74754..2d3367af804b 100644
--- a/gcc/d/dmd/nspace.d
+++ b/gcc/d/dmd/nspace.d
@@ -52,6 +52,7 @@ import dmd.astenums;
 import dmd.dscope;
 import dmd.dsymbol;
 import dmd.dsymbolsem;
+import dmd.errors;
 import dmd.expression;
 import dmd.globals;
 import dmd.identifier;
@@ -134,7 +135,7 @@ extern (C++) final class Nspace : ScopeDsymbol
         if (!members || !symtab) // opaque or semantic() is not yet called
         {
             if (!(flags & IgnoreErrors))
-                error("is forward referenced when looking for `%s`", ident.toChars());
+                .error(loc, "%s `%s` is forward referenced when looking for `%s`", kind, toPrettyChars, ident.toChars());
             return null;
         }
 
diff --git a/gcc/d/dmd/ob.d b/gcc/d/dmd/ob.d
index 4774d1f5243c..8b30681afc08 100644
--- a/gcc/d/dmd/ob.d
+++ b/gcc/d/dmd/ob.d
@@ -1970,7 +1970,7 @@ void checkObErrors(ref ObState obstate)
             else
             {
                 if (pvs.state == PtrState.Owner && v.type.hasPointersToMutableFields())
-                    v.error(e.loc, "assigning to Owner without disposing of owned value");
+                    .error(e.loc, "%s `%s` assigning to Owner without disposing of owned value", v.kind, v.toPrettyChars);
 
                 pvs.state = PtrState.Owner;
             }
@@ -1993,12 +1993,12 @@ void checkObErrors(ref ObState obstate)
 
                     if (pvsr.state == Undefined)
                     {
-                        v.error(e.loc, "is reading from `%s` which is Undefined", r.toChars());
+                        .error(e.loc, "%s `%s` is reading from `%s` which is Undefined", v.kind, v.toPrettyChars, r.toChars());
                     }
                     else if (isBorrowedPtr(v))  // v is going to borrow from r
                     {
                         if (pvsr.state == Readonly)
-                            v.error(e.loc, "is borrowing from `%s` which is Readonly", r.toChars());
+                            .error(e.loc, "%s `%s` is borrowing from `%s` which is Readonly", v.kind, v.toPrettyChars, r.toChars());
 
                         pvs.state = Borrowed;
                     }
@@ -2039,7 +2039,7 @@ void checkObErrors(ref ObState obstate)
         assert(vi != size_t.max);
         auto pvs = &gen[vi];
         if (pvs.state == PtrState.Undefined)
-            v.error(loc, "has undefined state and cannot be read");
+            .error(loc, "%s `%s` has undefined state and cannot be read", v.kind, v.toPrettyChars);
 
         readVar(ob, vi, mutable, gen);
     }
@@ -2187,7 +2187,7 @@ void checkObErrors(ref ObState obstate)
                             {
                                 // move (i.e. consume arg)
                                 if (pvs.state != PtrState.Owner)
-                                    v.error(arg.loc, "is not Owner, cannot consume its value");
+                                    .error(arg.loc, "%s `%s` is not Owner, cannot consume its value", v.kind, v.toPrettyChars);
                                 makeUndefined(vi, cpvs);
                             }
                         }
@@ -2226,7 +2226,7 @@ void checkObErrors(ref ObState obstate)
                             {
                                 // move (i.e. consume arg)
                                 if (pvs.state != PtrState.Owner)
-                                    v.error(arg.loc, "is not Owner, cannot consume its value");
+                                    .error(arg.loc, "%s `%s` is not Owner, cannot consume its value", v.kind, v.toPrettyChars);
                                 makeUndefined(vi, cpvs);
                             }
                         }
@@ -2261,7 +2261,7 @@ void checkObErrors(ref ObState obstate)
                             {
                                 if (obstate.mutableStack[vi] || obstate.mutableStack[vk])
                                 {
-                                    v.error(ce.loc, "is passed as Owner more than once");
+                                    .error(ce.loc, "%s `%s` is passed as Owner more than once", v.kind, v.toPrettyChars);
                                     break;  // no need to continue
                                 }
                             }
@@ -2490,7 +2490,7 @@ void checkObErrors(ref ObState obstate)
                     if (s1 != s2 && (s1 == PtrState.Owner || s2 == PtrState.Owner))
                     {
                         auto v = obstate.vars[i];
-                        v.error(ob.exp ? ob.exp.loc : v.loc, "is both %s and %s", s1.toChars(), s2.toChars());
+                        .error(ob.exp ? ob.exp.loc : v.loc, "%s `%s` is both %s and %s", v.kind, v.toPrettyChars, s1.toChars(), s2.toChars());
                     }
                     pvs1.combine(*pvs2, i, ob.gen);
                 }
@@ -2536,7 +2536,7 @@ void checkObErrors(ref ObState obstate)
                     switch (pvsr.state)
                     {
                         case Undefined:
-                            r.error(ob.exp.loc, "is returned but is Undefined");
+                            .error(ob.exp.loc, "%s `%s` is returned but is Undefined", r.kind, r.toPrettyChars);
                             break;
 
                         case Owner:
@@ -2568,7 +2568,7 @@ void checkObErrors(ref ObState obstate)
                 {
                     auto v = obstate.vars[i];
                     if (v.type.hasPointers())
-                        v.error(v.loc, "is not disposed of before return");
+                        .error(v.loc, "%s `%s` is not disposed of before return", v.kind, v.toPrettyChars);
                 }
             }
         }
diff --git a/gcc/d/dmd/objc.d b/gcc/d/dmd/objc.d
index 623a362907eb..359474c588ad 100644
--- a/gcc/d/dmd/objc.d
+++ b/gcc/d/dmd/objc.d
@@ -410,12 +410,12 @@ extern(C++) private final class Unsupported : Objc
 
     override void setObjc(ClassDeclaration cd)
     {
-        cd.error("Objective-C classes not supported");
+        .error(cd.loc, "%s `%s` Objective-C classes not supported", cd.kind, cd.toPrettyChars);
     }
 
     override void setObjc(InterfaceDeclaration id)
     {
-        id.error("Objective-C interfaces not supported");
+        .error(id.loc, "%s `%s` Objective-C interfaces not supported", id.kind, id.toPrettyChars);
     }
 
     override const(char)* toPrettyChars(ClassDeclaration, bool qualifyTypes) const
@@ -552,7 +552,7 @@ extern(C++) private final class Supported : Objc
 
             if (fd.objc.selector)
             {
-                fd.error("can only have one Objective-C selector per method");
+                .error(fd.loc, "%s `%s` can only have one Objective-C selector per method", fd.kind, fd.toPrettyChars);
                 return 1;
             }
 
@@ -572,15 +572,15 @@ extern(C++) private final class Supported : Objc
             return;
         TypeFunction tf = cast(TypeFunction)fd.type;
         if (fd.objc.selector.paramCount != tf.parameterList.parameters.length)
-            fd.error("number of colons in Objective-C selector must match number of parameters");
+            .error(fd.loc, "%s `%s` number of colons in Objective-C selector must match number of parameters", fd.kind, fd.toPrettyChars);
         if (fd.parent && fd.parent.isTemplateInstance())
-            fd.error("template cannot have an Objective-C selector attached");
+            .error(fd.loc, "%s `%s` template cannot have an Objective-C selector attached", fd.kind, fd.toPrettyChars);
     }
 
     override void checkLinkage(FuncDeclaration fd)
     {
         if (fd._linkage != LINK.objc && fd.objc.selector)
-            fd.error("must have Objective-C linkage to attach a selector");
+            .error(fd.loc, "%s `%s` must have Objective-C linkage to attach a selector", fd.kind, fd.toPrettyChars);
     }
 
     override bool isVirtual(const FuncDeclaration fd) const
@@ -608,7 +608,7 @@ extern(C++) private final class Supported : Objc
         fd.objc.isOptional = count > 0;
 
         if (count > 1)
-            fd.error("can only declare a function as optional once");
+            .error(fd.loc, "%s `%s` can only declare a function as optional once", fd.kind, fd.toPrettyChars);
     }
 
     /// Returns: the number of times `fd` has been declared as optional.
@@ -643,7 +643,7 @@ extern(C++) private final class Supported : Objc
 
         if (fd._linkage != LINK.objc)
         {
-            fd.error("only functions with Objective-C linkage can be declared as optional");
+            .error(fd.loc, "%s `%s` only functions with Objective-C linkage can be declared as optional", fd.kind, fd.toPrettyChars);
 
             const linkage = linkageToString(fd._linkage);
 
@@ -655,14 +655,14 @@ extern(C++) private final class Supported : Objc
 
         if (parent && parent.isTemplateInstance())
         {
-            fd.error("template cannot be optional");
+            .error(fd.loc, "%s `%s` template cannot be optional", fd.kind, fd.toPrettyChars);
             parent = parent.parent;
             assert(parent);
         }
 
         if (parent && !parent.isInterfaceDeclaration())
         {
-            fd.error("only functions declared inside interfaces can be optional");
+            .error(fd.loc, "%s `%s` only functions declared inside interfaces can be optional", fd.kind, fd.toPrettyChars);
             errorSupplemental(fd.loc, "function is declared inside %s", fd.parent.kind);
         }
     }
@@ -805,9 +805,9 @@ extern(C++) private final class Supported : Objc
         enum supplementalMessage = "`offsetof` is not available for members " ~
             "of Objective-C classes. Please use the Objective-C runtime instead";
 
-        expression.error(errorMessage, expression.toChars(),
+        error(expression.loc, errorMessage, expression.toChars(),
             expression.type.toChars());
-        expression.errorSupplemental(supplementalMessage);
+        errorSupplemental(expression.loc, supplementalMessage);
     }
 
     override void checkTupleof(Expression expression, TypeClass type) const
@@ -815,8 +815,8 @@ extern(C++) private final class Supported : Objc
         if (type.sym.classKind != ClassKind.objc)
             return;
 
-        expression.error("no property `tupleof` for type `%s`", type.toChars());
-        expression.errorSupplemental("`tupleof` is not available for members " ~
+        error(expression.loc, "no property `tupleof` for type `%s`", type.toChars());
+        errorSupplemental(expression.loc, "`tupleof` is not available for members " ~
             "of Objective-C classes. Please use the Objective-C runtime instead");
     }
 }
@@ -866,8 +866,8 @@ if (is(T == ClassDeclaration) || is(T == InterfaceDeclaration))
             }
             else
             {
-                error("base " ~ errorType ~ " for an Objective-C " ~
-                      errorType ~ " must be `extern (Objective-C)`");
+                .error(classDeclaration.loc, "%s `%s` base " ~ errorType ~ " for an Objective-C " ~
+                      errorType ~ " must be `extern (Objective-C)`", classDeclaration.kind, classDeclaration.toPrettyChars);
             }
         }
 
diff --git a/gcc/d/dmd/opover.d b/gcc/d/dmd/opover.d
index f9de1ee5a119..addcd0103d05 100644
--- a/gcc/d/dmd/opover.d
+++ b/gcc/d/dmd/opover.d
@@ -405,7 +405,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
                     {
                         // @@@DEPRECATED_2.110@@@.
                         // Deprecated in 2.088, made an error in 2.100
-                        e.error("`%s` is obsolete.  Use `opUnary(string op)() if (op == \"%s\")` instead.", id.toChars(), EXPtoString(e.op).ptr);
+                        error(e.loc, "`%s` is obsolete.  Use `opUnary(string op)() if (op == \"%s\")` instead.", id.toChars(), EXPtoString(e.op).ptr);
                         return ErrorExp.get();
                     }
                 }
@@ -644,7 +644,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
                     s = search_function(ad1, Id.opBinary);
                     if (s && !s.isTemplateDeclaration())
                     {
-                        e.e1.error("`%s.opBinary` isn't a template", e.e1.toChars());
+                        error(e.e1.loc, "`%s.opBinary` isn't a template", e.e1.toChars());
                         return ErrorExp.get();
                     }
                 }
@@ -653,7 +653,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
                     s_r = search_function(ad2, Id.opBinaryRight);
                     if (s_r && !s_r.isTemplateDeclaration())
                     {
-                        e.e2.error("`%s.opBinaryRight` isn't a template", e.e2.toChars());
+                        error(e.e2.loc, "`%s.opBinaryRight` isn't a template", e.e2.toChars());
                         return ErrorExp.get();
                     }
                     if (s_r && s_r == s) // https://issues.dlang.org/show_bug.cgi?id=12778
@@ -678,9 +678,9 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
                         // @@@DEPRECATED_2.110@@@.
                         // Deprecated in 2.088, made an error in 2.100
                         if (id == Id.postinc || id == Id.postdec)
-                            e.error("`%s` is obsolete.  Use `opUnary(string op)() if (op == \"%s\")` instead.", id.toChars(), EXPtoString(e.op).ptr);
+                            error(e.loc, "`%s` is obsolete.  Use `opUnary(string op)() if (op == \"%s\")` instead.", id.toChars(), EXPtoString(e.op).ptr);
                         else
-                            e.error("`%s` is obsolete.  Use `opBinary(string op)(...) if (op == \"%s\")` instead.", id.toChars(), EXPtoString(e.op).ptr);
+                            error(e.loc, "`%s` is obsolete.  Use `opBinary(string op)(...) if (op == \"%s\")` instead.", id.toChars(), EXPtoString(e.op).ptr);
                         return ErrorExp.get();
                     }
                 }
@@ -696,7 +696,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
                     {
                         // @@@DEPRECATED_2.110@@@.
                         // Deprecated in 2.088, made an error in 2.100
-                        e.error("`%s` is obsolete.  Use `opBinaryRight(string op)(...) if (op == \"%s\")` instead.", id_r.toChars(), EXPtoString(e.op).ptr);
+                        error(e.loc, "`%s` is obsolete.  Use `opBinaryRight(string op)(...) if (op == \"%s\")` instead.", id_r.toChars(), EXPtoString(e.op).ptr);
                         return ErrorExp.get();
                     }
                 }
@@ -738,7 +738,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
                 if (m.count > 1)
                 {
                     // Error, ambiguous
-                    e.error("overloads `%s` and `%s` both match argument list for `%s`", m.lastf.type.toChars(), m.nextf.type.toChars(), m.lastf.toChars());
+                    error(e.loc, "overloads `%s` and `%s` both match argument list for `%s`", m.lastf.type.toChars(), m.nextf.type.toChars(), m.lastf.toChars());
                 }
                 else if (m.last == MATCH.nomatch)
                 {
@@ -820,7 +820,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
                         if (m.count > 1)
                         {
                             // Error, ambiguous
-                            e.error("overloads `%s` and `%s` both match argument list for `%s`", m.lastf.type.toChars(), m.nextf.type.toChars(), m.lastf.toChars());
+                            error(e.loc, "overloads `%s` and `%s` both match argument list for `%s`", m.lastf.type.toChars(), m.nextf.type.toChars(), m.lastf.toChars());
                         }
                         else if (m.last == MATCH.nomatch)
                         {
@@ -890,7 +890,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
             }
             if (rewrittenLhs)
             {
-                e.error("cannot use `alias this` to partially initialize variable `%s` of type `%s`. Use `%s`",
+                error(e.loc, "cannot use `alias this` to partially initialize variable `%s` of type `%s`. Use `%s`",
                         e.e1.toChars(), ad1.toChars(), rewrittenLhs.toChars());
                 return ErrorExp.get();
             }
@@ -918,7 +918,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
             if (t1.ty == Tclass && e.e2.op == EXP.null_ ||
                 t2.ty == Tclass && e.e1.op == EXP.null_)
             {
-                e.error("use `%s` instead of `%s` when comparing with `null`",
+                error(e.loc, "use `%s` instead of `%s` when comparing with `null`",
                     EXPtoString(e.op == EXP.equal ? EXP.identity : EXP.notIdentity).ptr,
                     EXPtoString(e.op).ptr);
                 return ErrorExp.get();
@@ -943,7 +943,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
                      */
                     if (!ClassDeclaration.object)
                     {
-                        e.error("cannot compare classes for equality because `object.Object` was not declared");
+                        error(e.loc, "cannot compare classes for equality because `object.Object` was not declared");
                         return null;
                     }
 
@@ -1045,7 +1045,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
                 size_t dim = tup1.exps.length;
                 if (dim != tup2.exps.length)
                 {
-                    e.error("mismatched sequence lengths, `%d` and `%d`",
+                    error(e.loc, "mismatched sequence lengths, `%d` and `%d`",
                         cast(int)dim, cast(int)tup2.exps.length);
                     return ErrorExp.get();
                 }
@@ -1210,7 +1210,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
                 s = search_function(ad1, Id.opOpAssign);
                 if (s && !s.isTemplateDeclaration())
                 {
-                    e.error("`%s.opOpAssign` isn't a template", e.e1.toChars());
+                    error(e.loc, "`%s.opOpAssign` isn't a template", e.e1.toChars());
                     return ErrorExp.get();
                 }
             }
@@ -1231,7 +1231,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
                     // Deprecated in 2.088, made an error in 2.100
                     scope char[] op = EXPtoString(e.op).dup;
                     op[$-1] = '\0'; // remove trailing `=`
-                    e.error("`%s` is obsolete.  Use `opOpAssign(string op)(...) if (op == \"%s\")` instead.", id.toChars(), op.ptr);
+                    error(e.loc, "`%s` is obsolete.  Use `opOpAssign(string op)(...) if (op == \"%s\")` instead.", id.toChars(), op.ptr);
                     return ErrorExp.get();
                 }
             }
@@ -1253,7 +1253,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
                 if (m.count > 1)
                 {
                     // Error, ambiguous
-                    e.error("overloads `%s` and `%s` both match argument list for `%s`", m.lastf.type.toChars(), m.nextf.type.toChars(), m.lastf.toChars());
+                    error(e.loc, "overloads `%s` and `%s` both match argument list for `%s`", m.lastf.type.toChars(), m.nextf.type.toChars(), m.lastf.toChars());
                 }
                 else if (m.last == MATCH.nomatch)
                 {
@@ -1366,7 +1366,7 @@ private Expression compare_overload(BinExp e, Scope* sc, Identifier id, EXP* pop
             if (!(m.lastf == lastf && m.count == 2 && count == 1))
             {
                 // Error, ambiguous
-                e.error("overloads `%s` and `%s` both match argument list for `%s`", m.lastf.type.toChars(), m.nextf.type.toChars(), m.lastf.toChars());
+                error(e.loc, "overloads `%s` and `%s` both match argument list for `%s`", m.lastf.type.toChars(), m.nextf.type.toChars(), m.lastf.toChars());
             }
         }
         else if (m.last == MATCH.nomatch)
diff --git a/gcc/d/dmd/optimize.d b/gcc/d/dmd/optimize.d
index 37563826a2d2..d108cffd392d 100644
--- a/gcc/d/dmd/optimize.d
+++ b/gcc/d/dmd/optimize.d
@@ -24,6 +24,7 @@ import dmd.errors;
 import dmd.expression;
 import dmd.expressionsem;
 import dmd.globals;
+import dmd.hdrgen;
 import dmd.init;
 import dmd.location;
 import dmd.mtype;
@@ -90,7 +91,7 @@ Expression expandVar(int result, VarDeclaration v)
                 {
                     if (v.storage_class & STC.manifest)
                     {
-                        v.error("recursive initialization of constant");
+                        .error(v.loc, "%s `%s` recursive initialization of constant", v.kind, v.toPrettyChars);
                         return errorReturn();
                     }
                     return nullReturn();
@@ -100,7 +101,7 @@ Expression expandVar(int result, VarDeclaration v)
                 {
                     if (v.storage_class & STC.manifest)
                     {
-                        v.error("enum cannot be initialized with `%s`", v._init.toChars());
+                        .error(v.loc, "%s `%s` enum cannot be initialized with `%s`", v.kind, v.toPrettyChars, dmd.hdrgen.toChars(v._init));
                         return errorReturn();
                     }
                     return nullReturn();
@@ -275,7 +276,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
     //printf("Expression_optimize() e: %s result: %d keepLvalue %d\n", e.toChars(), result, keepLvalue);
     Expression ret = e;
 
-    void error()
+    void errorReturn()
     {
         ret = ErrorExp.get();
     }
@@ -571,8 +572,8 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
 
                     if (index < 0 || index > dim)
                     {
-                        e.error("array index %lld is out of bounds `[0..%lld]`", index, dim);
-                        return error();
+                        error(e.loc, "array index %lld is out of bounds `[0..%lld]`", index, dim);
+                        return errorReturn();
                     }
 
                     import core.checkedint : mulu;
@@ -580,8 +581,8 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
                     const offset = mulu(index, ts.nextOf().size(e.loc), overflow); // offset = index*size
                     if (overflow)
                     {
-                        e.error("array offset overflow");
-                        return error();
+                        error(e.loc, "array offset overflow");
+                        return errorReturn();
                     }
 
                     Expression ex = new AddrExp(ae1.loc, ae1);  // &a[i]
@@ -610,8 +611,8 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
                          */
                         if (!((dim == 0 || dim == index) && ve.var.isCsymbol()))
                         {
-                            e.error("array index %lld is out of bounds `[0..%lld]`", index, dim);
-                            return error();
+                            error(e.loc, "array index %lld is out of bounds `[0..%lld]`", index, dim);
+                            return errorReturn();
                         }
                     }
 
@@ -620,8 +621,8 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
                     const offset = mulu(index, ts.nextOf().size(e.loc), overflow);
                     if (overflow)
                     {
-                        e.error("array offset overflow");
-                        return error();
+                        error(e.loc, "array offset overflow");
+                        return errorReturn();
                     }
 
                     ret = new SymOffExp(e.loc, ve.var, offset);
@@ -645,8 +646,8 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
                          */
                         if (!((dim == 0 || dim == index) && ve.var.isCsymbol()))
                         {
-                            e.error("array index %lld is out of bounds `[0..%lld]`", index, dim);
-                            return error();
+                            error(e.loc, "array index %lld is out of bounds `[0..%lld]`", index, dim);
+                            return errorReturn();
                         }
                     }
 
@@ -655,8 +656,8 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
                     const offset = mulu(index, ts.nextOf().size(e.loc), overflow); // index*elementsize
                     if (overflow)
                     {
-                        e.error("array offset overflow");
-                        return error();
+                        error(e.loc, "array offset overflow");
+                        return errorReturn();
                     }
 
                     auto pe = new AddrExp(e.loc, ve);
@@ -808,7 +809,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
             const esz  = e.type.nextOf().size(e.loc);
             const e1sz = e.e1.type.toBasetype().nextOf().size(e.e1.loc);
             if (esz == SIZE_INVALID || e1sz == SIZE_INVALID)
-                return error();
+                return errorReturn();
 
             if (e1sz == esz)
             {
@@ -855,13 +856,13 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
             ClassDeclaration cdfrom = e.e1.type.isClassHandle();
             ClassDeclaration cdto = e.type.isClassHandle();
             if (cdfrom.errors || cdto.errors)
-                return error();
+                return errorReturn();
             if (cdto == ClassDeclaration.object && !cdfrom.isInterfaceDeclaration())
                 return returnE_e1();    // can always convert a class to Object
             // Need to determine correct offset before optimizing away the cast.
             // https://issues.dlang.org/show_bug.cgi?id=16980
             if (cdfrom.size(e.loc) == SIZE_INVALID)
-                return error();
+                return errorReturn();
             assert(cdfrom.sizeok == Sizeok.done);
             assert(cdto.sizeok == Sizeok.done || !cdto.isBaseOf(cdfrom, null));
             int offset;
@@ -886,7 +887,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
                     const e1sz = e.e1.type.size(e.e1.loc);
                     if (esz == SIZE_INVALID ||
                         e1sz == SIZE_INVALID)
-                        return error();
+                        return errorReturn();
 
                     if (esz == e1sz)
                         return returnE_e1();
@@ -919,8 +920,8 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
                 sz *= 8;
                 if (i2 < 0 || i2 >= sz)
                 {
-                    e.error("shift assign by %lld is outside the range `0..%llu`", i2, cast(ulong)sz - 1);
-                    return error();
+                    error(e.loc, "shift assign by %lld is outside the range `0..%llu`", i2, cast(ulong)sz - 1);
+                    return errorReturn();
                 }
             }
         }
@@ -1005,8 +1006,8 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
             sz *= 8;
             if (i2 < 0 || i2 >= sz)
             {
-                e.error("shift by %lld is outside the range `0..%llu`", i2, cast(ulong)sz - 1);
-                return error();
+                error(e.loc, "shift by %lld is outside the range `0..%llu`", i2, cast(ulong)sz - 1);
+                return errorReturn();
             }
             if (e.e1.isConst() == 1)
                 ret = (*shift)(e.loc, e.type, e.e1, e.e2).copy();
@@ -1062,8 +1063,8 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
         // All negative integral powers are illegal.
         if (e.e1.type.isintegral() && (e.e2.op == EXP.int64) && cast(sinteger_t)e.e2.toInteger() < 0)
         {
-            e.error("cannot raise `%s` to a negative integer power. Did you mean `(cast(real)%s)^^%s` ?", e.e1.type.toBasetype().toChars(), e.e1.toChars(), e.e2.toChars());
-            return error();
+            error(e.loc, "cannot raise `%s` to a negative integer power. Did you mean `(cast(real)%s)^^%s` ?", e.e1.type.toBasetype().toChars(), e.e1.toChars(), e.e2.toChars());
+            return errorReturn();
         }
         // If e2 *could* have been an integer, make it one.
         if (e.e2.op == EXP.float64 && e.e2.toReal() == real_t(cast(sinteger_t)e.e2.toReal()))
@@ -1337,7 +1338,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
     {
         if (b++ == global.recursionLimit)
         {
-            e.error("infinite loop while optimizing expression");
+            error(e.loc, "infinite loop while optimizing expression");
             fatal();
         }
 
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index 2a964151be50..3821f947a97e 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -6247,9 +6247,9 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                 if (auto ds = parseDebugSpecification())
                 {
                     if (ds.ident)
-                        ds.error("declaration must be at module level");
+                        eSink.error(ds.loc, "%s `%s` declaration must be at module level", ds.kind, ds.toPrettyChars);
                     else
-                        ds.error("level declaration must be at module level");
+                        eSink.error(ds.loc, "%s `%s` level declaration must be at module level", ds.kind, ds.toPrettyChars);
                 }
                 break;
             }
@@ -6263,9 +6263,9 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                 if (auto vs = parseVersionSpecification())
                 {
                     if (vs.ident)
-                        vs.error("declaration must be at module level");
+                        eSink.error(vs.loc, "%s `%s` declaration must be at module level", vs.kind, vs.toPrettyChars);
                     else
-                        vs.error("level declaration must be at module level");
+                        eSink.error(vs.loc, "%s `%s` level declaration must be at module level", vs.kind, vs.toPrettyChars);
                 }
                 break;
             }
@@ -6329,10 +6329,11 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             {
                 nextToken();
                 check(TOK.leftParenthesis);
+                auto param = parseAssignCondition();
                 AST.Expression condition = parseExpression();
                 closeCondition("switch", null, condition);
                 AST.Statement _body = parseStatement(ParseStatementFlags.scope_);
-                s = new AST.SwitchStatement(loc, condition, _body, isfinal);
+                s = new AST.SwitchStatement(loc, param, condition, _body, isfinal, token.loc);
                 break;
             }
         case TOK.case_:
@@ -8200,6 +8201,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
 
         case TOK.string_:
         case TOK.hexadecimalString:
+            const bool hexString = token.value == TOK.hexadecimalString;
             {
                 // cat adjacent strings
                 auto s = token.ustring;
@@ -8235,6 +8237,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                         break;
                 }
                 e = new AST.StringExp(loc, s[0 .. len], len, 1, postfix);
+                e.isStringExp().hexString = hexString;
                 break;
             }
         case TOK.void_:
@@ -8899,7 +8902,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                                 {
                                     e = parseUnaryExp();
                                     e = new AST.CastExp(loc, e, t);
-                                    error("C style cast illegal, use `%s`", e.toChars());
+                                    error(loc, "C style cast illegal, use `%s`", e.toChars());
                                 }
                                 return e;
                             }
diff --git a/gcc/d/dmd/root/filename.d b/gcc/d/dmd/root/filename.d
index 987c79391ccd..631c08c44d27 100644
--- a/gcc/d/dmd/root/filename.d
+++ b/gcc/d/dmd/root/filename.d
@@ -14,13 +14,14 @@ module dmd.root.filename;
 import core.stdc.ctype;
 import core.stdc.errno;
 import core.stdc.string;
+
+import dmd.common.file;
+import dmd.common.outbuffer;
+
 import dmd.root.array;
 import dmd.root.file;
-import dmd.common.outbuffer;
-import dmd.common.file;
 import dmd.root.port;
 import dmd.root.rmem;
-import dmd.root.rootobject;
 import dmd.root.string;
 
 version (Posix)
diff --git a/gcc/d/dmd/root/rootobject.d b/gcc/d/dmd/root/rootobject.d
index 7138841caa02..65c499ddf4ea 100644
--- a/gcc/d/dmd/root/rootobject.d
+++ b/gcc/d/dmd/root/rootobject.d
@@ -1,5 +1,5 @@
 /**
- * Provide the root object that classes in dmd inherit from.
+ * Provide the root object that AST classes in dmd inherit from.
  *
  * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved
  * Authors:   Walter Bright, https://www.digitalmars.com
@@ -11,10 +11,6 @@
 
 module dmd.root.rootobject;
 
-import core.stdc.stdio;
-
-import dmd.common.outbuffer;
-
 /***********************************************************
  */
 
diff --git a/gcc/d/dmd/semantic2.d b/gcc/d/dmd/semantic2.d
index e2d2e0411621..6a3795178d30 100644
--- a/gcc/d/dmd/semantic2.d
+++ b/gcc/d/dmd/semantic2.d
@@ -195,7 +195,7 @@ private extern(C++) final class Semantic2Visitor : Visitor
             if (!tempinst.errors)
             {
                 if (!tempdecl.literal)
-                    tempinst.error(tempinst.loc, "error instantiating");
+                    .error(tempinst.loc, "%s `%s` error instantiating", tempinst.kind, tempinst.toPrettyChars);
                 if (tempinst.tinst)
                     tempinst.tinst.printInstantiationTrace();
             }
@@ -315,7 +315,7 @@ private extern(C++) final class Semantic2Visitor : Visitor
                 }
 
                 if (hasInvalidEnumInitializer(ei.exp))
-                    vd.error(": Unable to initialize enum with class or pointer to struct. Use static const variable instead.");
+                    .error(vd.loc, "%s `%s` : Unable to initialize enum with class or pointer to struct. Use static const variable instead.", vd.kind, vd.toPrettyChars);
             }
         }
         else if (vd._init && vd.isThreadlocal())
@@ -326,13 +326,13 @@ private extern(C++) final class Semantic2Visitor : Visitor
             {
                 ExpInitializer ei = vd._init.isExpInitializer();
                 if (ei && ei.exp.op == EXP.classReference)
-                    vd.error("is a thread-local class and cannot have a static initializer. Use `static this()` to initialize instead.");
+                    .error(vd.loc, "%s `%s` is a thread-local class and cannot have a static initializer. Use `static this()` to initialize instead.", vd.kind, vd.toPrettyChars);
             }
             else if (vd.type.ty == Tpointer && vd.type.nextOf().ty == Tstruct && vd.type.nextOf().isMutable() && !vd.type.nextOf().isShared())
             {
                 ExpInitializer ei = vd._init.isExpInitializer();
                 if (ei && ei.exp.op == EXP.address && (cast(AddrExp)ei.exp).e1.op == EXP.structLiteral)
-                    vd.error("is a thread-local pointer to struct and cannot have a static initializer. Use `static this()` to initialize instead.");
+                    .error(vd.loc, "%s `%s` is a thread-local pointer to struct and cannot have a static initializer. Use `static this()` to initialize instead.", vd.kind, vd.toPrettyChars);
             }
         }
         vd.semanticRun = PASS.semantic2done;
@@ -454,7 +454,7 @@ private extern(C++) final class Semantic2Visitor : Visitor
                     (!sameAttr || !sameParams)
                 )
                 {
-                    f2.error("cannot overload `extern(%s)` function at %s",
+                    .error(f2.loc, "%s `%s` cannot overload `extern(%s)` function at %s", f2.kind, f2.toPrettyChars,
                             linkageToChars(f1._linkage),
                             f1.loc.toChars());
                     return 0;
@@ -473,14 +473,14 @@ private extern(C++) final class Semantic2Visitor : Visitor
                     // this condition, as well as the error for extern(C) functions above.
                     if (sameAttr != tf1.attributesEqual(tf2))
                     {
-                        f2.deprecation("cannot overload `extern(%s)` function at %s",
+                        .deprecation(f2.loc, "%s `%s` cannot overload `extern(%s)` function at %s", f2.kind, f2.toPrettyChars,
                                 linkageToChars(f1._linkage),
                                 f1.loc.toChars());
                     }
                     return 0;
                 }
 
-                error(f2.loc, "%s `%s%s` conflicts with previous declaration at %s",
+                .error(f2.loc, "%s `%s%s` conflicts with previous declaration at %s",
                         f2.kind(),
                         f2.toPrettyChars(),
                         parametersTypeToChars(tf2.parameterList),
@@ -631,7 +631,7 @@ private extern(C++) final class Semantic2Visitor : Visitor
 
         if (ad._scope)
         {
-            ad.error("has forward references");
+            .error(ad.loc, "%s `%s` has forward references", ad.kind, ad.toPrettyChars);
             return;
         }
 
@@ -685,20 +685,20 @@ private extern(C++) final class Semantic2Visitor : Visitor
                         //printf("            found\n");
                         // Check that calling conventions match
                         if (fd._linkage != ifd._linkage)
-                            fd.error("linkage doesn't match interface function");
+                            .error(fd.loc, "%s `%s` linkage doesn't match interface function", fd.kind, fd.toPrettyChars);
 
                         // Check that it is current
                         //printf("newinstance = %d fd.toParent() = %s ifd.toParent() = %s\n",
                             //newinstance, fd.toParent().toChars(), ifd.toParent().toChars());
                         if (fd.toParent() != cd && ifd.toParent() == base.sym)
-                            cd.error("interface function `%s` is not implemented", ifd.toFullSignature());
+                            .error(cd.loc, "%s `%s` interface function `%s` is not implemented", cd.kind, cd.toPrettyChars, ifd.toFullSignature());
                     }
                     else
                     {
                         //printf("            not found %p\n", fd);
                         // BUG: should mark this class as abstract?
                         if (!cd.isAbstract())
-                            cd.error("interface function `%s` is not implemented", ifd.toFullSignature());
+                            .error(cd.loc, "%s `%s` interface function `%s` is not implemented", cd.kind, cd.toPrettyChars, ifd.toFullSignature());
                     }
                 }
             }
@@ -748,7 +748,7 @@ private void doGNUABITagSemantic(ref Expression e, ref Expression* lastTag)
     // When `@gnuAbiTag` is used, the type will be the UDA, not the struct literal
     if (e.op == EXP.type)
     {
-        e.error("`@%s` at least one argument expected", Id.udaGNUAbiTag.toChars());
+        error(e.loc, "`@%s` at least one argument expected", Id.udaGNUAbiTag.toChars());
         return;
     }
 
@@ -766,7 +766,7 @@ private void doGNUABITagSemantic(ref Expression e, ref Expression* lastTag)
     auto ale = (*sle.elements)[0].isArrayLiteralExp();
     if (ale is null)
     {
-        e.error("`@%s` at least one argument expected", Id.udaGNUAbiTag.toChars());
+        error(e.loc, "`@%s` at least one argument expected", Id.udaGNUAbiTag.toChars());
         return;
     }
 
@@ -775,8 +775,8 @@ private void doGNUABITagSemantic(ref Expression e, ref Expression* lastTag)
     {
         const str1 = (*lastTag.isStructLiteralExp().elements)[0].toString();
         const str2 = ale.toString();
-        e.error("only one `@%s` allowed per symbol", Id.udaGNUAbiTag.toChars());
-        e.errorSupplemental("instead of `@%s @%s`, use `@%s(%.*s, %.*s)`",
+        error(e.loc, "only one `@%s` allowed per symbol", Id.udaGNUAbiTag.toChars());
+        errorSupplemental(e.loc, "instead of `@%s @%s`, use `@%s(%.*s, %.*s)`",
             lastTag.toChars(), e.toChars(), Id.udaGNUAbiTag.toChars(),
             // Avoid [ ... ]
             cast(int)str1.length - 2, str1.ptr + 1,
@@ -792,7 +792,7 @@ private void doGNUABITagSemantic(ref Expression e, ref Expression* lastTag)
         const str = elem.toStringExp().peekString();
         if (!str.length)
         {
-            e.error("argument `%d` to `@%s` cannot be %s", cast(int)(idx + 1),
+            error(e.loc, "argument `%d` to `@%s` cannot be %s", cast(int)(idx + 1),
                     Id.udaGNUAbiTag.toChars(),
                     elem.isNullExp() ? "`null`".ptr : "empty".ptr);
             continue;
@@ -802,7 +802,7 @@ private void doGNUABITagSemantic(ref Expression e, ref Expression* lastTag)
         {
             if (!c.isValidMangling())
             {
-                e.error("`@%s` char `0x%02x` not allowed in mangling",
+                error(e.loc, "`@%s` char `0x%02x` not allowed in mangling",
                         Id.udaGNUAbiTag.toChars(), c);
                 break;
             }
diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d
index 04f57a4c0213..e0931409df89 100644
--- a/gcc/d/dmd/semantic3.d
+++ b/gcc/d/dmd/semantic3.d
@@ -141,7 +141,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
             if (!tempinst.errors)
             {
                 if (!tempdecl.literal)
-                    tempinst.error(tempinst.loc, "error instantiating");
+                    .error(tempinst.loc, "%s `%s` error instantiating", tempinst.kind, tempinst.toPrettyChars);
                 if (tempinst.tinst)
                     tempinst.tinst.printInstantiationTrace();
             }
@@ -303,7 +303,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
 
         if (!funcdecl.fbody && funcdecl.inferRetType && !f.next)
         {
-            funcdecl.error("has no function body with return type inference");
+            .error(funcdecl.loc, "%s `%s` has no function body with return type inference", funcdecl.kind, funcdecl.toPrettyChars);
             return;
         }
 
@@ -371,7 +371,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
                     if (!sc.intypeof)
                     {
                         if (fld.tok == TOK.delegate_)
-                            funcdecl.error("cannot be %s members", ad.kind());
+                            .error(funcdecl.loc, "%s `%s` cannot be %s members", funcdecl.kind, funcdecl.toPrettyChars, ad.kind());
                         else
                             fld.tok = TOK.function_;
                     }
@@ -395,7 +395,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
             // functions to be reworked as a frontend-only feature.
             if (funcdecl.hasDualContext())
             {
-                funcdecl.deprecation("function requires a dual-context, which is deprecated");
+                .deprecation(funcdecl.loc, "%s `%s` function requires a dual-context, which is deprecated", funcdecl.kind, funcdecl.toPrettyChars);
                 if (auto ti = sc2.parent ? sc2.parent.isInstantiated() : null)
                     ti.printInstantiationTrace(Classification.deprecation);
             }
@@ -412,11 +412,11 @@ private extern(C++) final class Semantic3Visitor : Visitor
                     if (!global.params.useTypeInfo || !Type.dtypeinfo || !Type.typeinfotypelist)
                     {
                         if (!global.params.useTypeInfo)
-                            funcdecl.error("D-style variadic functions cannot be used with -betterC");
+                            .error(funcdecl.loc, "%s `%s` D-style variadic functions cannot be used with -betterC", funcdecl.kind, funcdecl.toPrettyChars);
                         else if (!Type.typeinfotypelist)
-                            funcdecl.error("`object.TypeInfo_Tuple` could not be found, but is implicitly used in D-style variadic functions");
+                            .error(funcdecl.loc, "%s `%s` `object.TypeInfo_Tuple` could not be found, but is implicitly used in D-style variadic functions", funcdecl.kind, funcdecl.toPrettyChars);
                         else
-                            funcdecl.error("`object.TypeInfo` could not be found, but is implicitly used in D-style variadic functions");
+                            .error(funcdecl.loc, "%s `%s` `object.TypeInfo` could not be found, but is implicitly used in D-style variadic functions", funcdecl.kind, funcdecl.toPrettyChars);
                         fatal();
                     }
 
@@ -484,7 +484,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
                     v.dsymbolSemantic(sc2);
                     if (!sc2.insert(v))
                     {
-                        funcdecl.error("parameter `%s.%s` is already defined", funcdecl.toChars(), v.toChars());
+                        .error(funcdecl.loc, "%s `%s` parameter `%s.%s` is already defined", funcdecl.kind, funcdecl.toPrettyChars, funcdecl.toChars(), v.toChars());
                         funcdecl.errors = true;
                     }
                     else
@@ -523,7 +523,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
                 //printf("declaring tuple %s\n", v.toChars());
                 v.isexp = true;
                 if (!sc2.insert(v))
-                    funcdecl.error("parameter `%s.%s` is already defined", funcdecl.toChars(), v.toChars());
+                    .error(funcdecl.loc, "%s `%s` parameter `%s.%s` is already defined", funcdecl.kind, funcdecl.toPrettyChars, funcdecl.toChars(), v.toChars());
                 funcdecl.localsymtab.insert(v);
                 v.parent = funcdecl;
             }
@@ -687,7 +687,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
                                  *    as delegating calls to other constructors
                                  */
                                 if (v.isCtorinit() && !v.type.isMutable() && cd)
-                                    funcdecl.error("missing initializer for %s field `%s`", MODtoChars(v.type.mod), v.toChars());
+                                    .error(funcdecl.loc, "%s `%s` missing initializer for %s field `%s`", funcdecl.kind, funcdecl.toPrettyChars, MODtoChars(v.type.mod), v.toChars());
                                 else if (v.storage_class & STC.nodefaultctor)
                                     error(funcdecl.loc, "field `%s` must be initialized in constructor", v.toChars());
                                 else if (v.type.needsNested())
@@ -698,7 +698,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
                                 bool mustInit = (v.storage_class & STC.nodefaultctor || v.type.needsNested());
                                 if (mustInit && !(sc2.ctorflow.fieldinit[i].csx & CSX.this_ctor))
                                 {
-                                    funcdecl.error("field `%s` must be initialized but skipped", v.toChars());
+                                    .error(funcdecl.loc, "%s `%s` field `%s` must be initialized but skipped", funcdecl.kind, funcdecl.toPrettyChars, v.toChars());
                                 }
                             }
                         }
@@ -714,11 +714,11 @@ private extern(C++) final class Semantic3Visitor : Visitor
                         FuncDeclaration fd = resolveFuncCall(Loc.initial, sc2, cd.baseClass.ctor, null, tthis, ArgumentList(), FuncResolveFlag.quiet);
                         if (!fd)
                         {
-                            funcdecl.error("no match for implicit `super()` call in constructor");
+                            .error(funcdecl.loc, "%s `%s` no match for implicit `super()` call in constructor", funcdecl.kind, funcdecl.toPrettyChars);
                         }
                         else if (fd.storage_class & STC.disable)
                         {
-                            funcdecl.error("cannot call `super()` implicitly because it is annotated with `@disable`");
+                            .error(funcdecl.loc, "%s `%s` cannot call `super()` implicitly because it is annotated with `@disable`", funcdecl.kind, funcdecl.toPrettyChars);
                         }
                         else
                         {
@@ -802,7 +802,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
                     // Fallthrough despite being declared as noreturn? return is already rejected when evaluating the ReturnStatement
                     if (blockexit & BE.fallthru)
                     {
-                        funcdecl.error("is typed as `%s` but does return", f.next.toChars());
+                        .error(funcdecl.loc, "%s `%s` is typed as `%s` but does return", funcdecl.kind, funcdecl.toPrettyChars, f.next.toChars());
                         funcdecl.loc.errorSupplemental("`noreturn` functions must either throw, abort or loop indefinitely");
                     }
                 }
@@ -812,9 +812,9 @@ private extern(C++) final class Semantic3Visitor : Visitor
                     if ((blockexit & BE.fallthru) && f.next.ty != Tvoid && !inlineAsm && !(sc.flags & SCOPE.Cfile))
                     {
                         if (!funcdecl.hasReturnExp)
-                            funcdecl.error("has no `return` statement, but is expected to return a value of type `%s`", f.next.toChars());
+                            .error(funcdecl.loc, "%s `%s` has no `return` statement, but is expected to return a value of type `%s`", funcdecl.kind, funcdecl.toPrettyChars, f.next.toChars());
                         else
-                            funcdecl.error("no `return exp;` or `assert(0);` at end of function");
+                            .error(funcdecl.loc, "%s `%s` no `return exp;` or `assert(0);` at end of function", funcdecl.kind, funcdecl.toPrettyChars);
                     }
                 }
 
@@ -1023,7 +1023,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
                     {
                         if (e.id)
                         {
-                            funcdecl.error(e.ensure.loc, "`void` functions have no result");
+                            .error(e.ensure.loc, "%s `%s` `void` functions have no result", funcdecl.kind, funcdecl.toPrettyChars);
                             //fens = null;
                         }
                     }
@@ -1075,7 +1075,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
                         {
                             if (!v._init)
                             {
-                                v.error("zero-length `out` parameters are not allowed.");
+                                .error(v.loc, "%s `%s` zero-length `out` parameters are not allowed.", v.kind, v.toPrettyChars);
                                 return;
                             }
                             ExpInitializer ie = v._init.isExpInitializer();
@@ -1229,7 +1229,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
                     }
                     else
                     {
-                        funcdecl.error("synchronized function `%s` must be a member of a class", funcdecl.toChars());
+                        .error(funcdecl.loc, "%s `%s` synchronized function `%s` must be a member of a class", funcdecl.kind, funcdecl.toPrettyChars, funcdecl.toChars());
                     }
                 }
 
@@ -1246,7 +1246,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
                     LabelDsymbol label = cast(LabelDsymbol)keyValue.value;
                     if (!label.statement && (!label.deleted || label.iasm))
                     {
-                        funcdecl.error(label.loc, "label `%s` is undefined", label.toChars());
+                        .error(label.loc, "%s `%s` label `%s` is undefined", funcdecl.kind, funcdecl.toPrettyChars, label.toChars());
                     }
                 }
 
@@ -1260,7 +1260,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
             }
 
             if (funcdecl.isNaked() && (funcdecl.fensures || funcdecl.frequires))
-                funcdecl.error("naked assembly functions with contracts are not supported");
+                .error(funcdecl.loc, "%s `%s` naked assembly functions with contracts are not supported", funcdecl.kind, funcdecl.toPrettyChars);
 
             sc2.ctorflow.callSuper = CSX.none;
             sc2.pop();
@@ -1366,7 +1366,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
             }
             if (isCppNonMappableType(f.next.toBasetype()))
             {
-                funcdecl.error("cannot return type `%s` because its linkage is `extern(C++)`", f.next.toChars());
+                .error(funcdecl.loc, "%s `%s` cannot return type `%s` because its linkage is `extern(C++)`", funcdecl.kind, funcdecl.toPrettyChars, f.next.toChars());
                 if (f.next.isTypeDArray())
                     errorSupplemental(funcdecl.loc, "slices are specific to D and do not have a counterpart representation in C++", f.next.toChars());
                 funcdecl.errors = true;
@@ -1375,7 +1375,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
             {
                 if (isCppNonMappableType(param.type.toBasetype(), param))
                 {
-                    funcdecl.error("cannot have parameter of type `%s` because its linkage is `extern(C++)`", param.type.toChars());
+                    .error(funcdecl.loc, "%s `%s` cannot have parameter of type `%s` because its linkage is `extern(C++)`", funcdecl.kind, funcdecl.toPrettyChars, param.type.toChars());
                     if (param.type.toBasetype().isTypeSArray())
                         errorSupplemental(funcdecl.loc, "perhaps use a `%s*` type instead",
                                           param.type.nextOf().mutableOf().unSharedOf().toChars());
@@ -1620,7 +1620,7 @@ private struct FuncDeclSem3
                 FuncDeclaration fdv = funcdecl.foverrides[i];
                 if (fdv.fbody && !fdv.frequires)
                 {
-                    funcdecl.error("cannot have an in contract when overridden function `%s` does not have an in contract", fdv.toPrettyChars());
+                    .error(funcdecl.loc, "%s `%s` cannot have an in contract when overridden function `%s` does not have an in contract", funcdecl.kind, funcdecl.toPrettyChars, fdv.toPrettyChars());
                     break;
                 }
             }
diff --git a/gcc/d/dmd/sideeffect.d b/gcc/d/dmd/sideeffect.d
index 30921c6b92ce..de92b294c140 100644
--- a/gcc/d/dmd/sideeffect.d
+++ b/gcc/d/dmd/sideeffect.d
@@ -14,6 +14,7 @@ module dmd.sideeffect;
 import dmd.astenums;
 import dmd.declaration;
 import dmd.dscope;
+import dmd.errors;
 import dmd.expression;
 import dmd.expressionsem;
 import dmd.func;
@@ -299,7 +300,7 @@ bool discardValue(Expression e)
                     }
                     else
                         s = ce.e1.toChars();
-                    e.warning("calling `%s` without side effects discards return value of type `%s`; prepend a `cast(void)` if intentional", s, e.type.toChars());
+                    warning(e.loc, "calling `%s` without side effects discards return value of type `%s`; prepend a `cast(void)` if intentional", s, e.type.toChars());
                 }
             }
         }
@@ -368,12 +369,12 @@ bool discardValue(Expression e)
         BinExp tmp = e.isBinExp();
         assert(tmp);
 
-        e.error("the result of the equality expression `%s` is discarded", e.toChars());
+        error(e.loc, "the result of the equality expression `%s` is discarded", e.toChars());
         bool seenSideEffect = false;
         foreach(expr; [tmp.e1, tmp.e2])
         {
             if (hasSideEffect(expr)) {
-                expr.errorSupplemental("note that `%s` may have a side effect", expr.toChars());
+                errorSupplemental(expr.loc, "note that `%s` may have a side effect", expr.toChars());
                 seenSideEffect |= true;
             }
         }
@@ -381,7 +382,7 @@ bool discardValue(Expression e)
     default:
         break;
     }
-    e.error("`%s` has no effect", e.toChars());
+    error(e.loc, "`%s` has no effect", e.toChars());
     return true;
 }
 
diff --git a/gcc/d/dmd/statement.d b/gcc/d/dmd/statement.d
index 58550fe6ca4b..da26bc980e87 100644
--- a/gcc/d/dmd/statement.d
+++ b/gcc/d/dmd/statement.d
@@ -82,15 +82,6 @@ extern (C++) abstract class Statement : ASTNode
         return b;
     }
 
-    override final const(char)* toChars() const
-    {
-        HdrGenState hgs;
-        OutBuffer buf;
-        toCBuffer(this, buf, hgs);
-        buf.writeByte(0);
-        return buf.extractSlice().ptr;
-    }
-
     Statement getRelatedLabeled()
     {
         return this;
@@ -571,12 +562,7 @@ extern (C++) final class CompoundDeclarationStatement : CompoundStatement
 
     override CompoundDeclarationStatement syntaxCopy()
     {
-        auto a = new Statements(statements.length);
-        foreach (i, s; *statements)
-        {
-            (*a)[i] = s ? s.syntaxCopy() : null;
-        }
-        return new CompoundDeclarationStatement(loc, a);
+        return new CompoundDeclarationStatement(loc, Statement.arraySyntaxCopy(statements));
     }
 
     override void accept(Visitor v)
@@ -601,12 +587,7 @@ extern (C++) final class UnrolledLoopStatement : Statement
 
     override UnrolledLoopStatement syntaxCopy()
     {
-        auto a = new Statements(statements.length);
-        foreach (i, s; *statements)
-        {
-            (*a)[i] = s ? s.syntaxCopy() : null;
-        }
-        return new UnrolledLoopStatement(loc, a);
+        return new UnrolledLoopStatement(loc, Statement.arraySyntaxCopy(statements));
     }
 
     override bool hasBreak() const pure nothrow
@@ -1117,30 +1098,39 @@ extern (C++) final class StaticAssertStatement : Statement
  */
 extern (C++) final class SwitchStatement : Statement
 {
+    Parameter param;
     Expression condition;           /// switch(condition)
     Statement _body;                ///
     bool isFinal;                   /// https://dlang.org/spec/statement.html#final-switch-statement
+    Loc endloc;
 
+    bool hasDefault;                /// true if has default statement
+    bool hasVars;                   /// true if has variable case values
     DefaultStatement sdefault;      /// default:
     Statement tryBody;              /// set to TryCatchStatement or TryFinallyStatement if in _body portion
     TryFinallyStatement tf;         /// set if in the 'finally' block of a TryFinallyStatement
     GotoCaseStatements gotoCases;   /// array of unresolved GotoCaseStatement's
     CaseStatements* cases;          /// array of CaseStatement's
-    int hasNoDefault;               /// !=0 if no default statement
-    int hasVars;                    /// !=0 if has variable case values
     VarDeclaration lastVar;         /// last observed variable declaration in this statement
 
-    extern (D) this(const ref Loc loc, Expression condition, Statement _body, bool isFinal)
+    extern (D) this(const ref Loc loc, Parameter param, Expression condition, Statement _body, bool isFinal, Loc endloc)
     {
         super(loc, STMT.Switch);
+        this.param = param;
         this.condition = condition;
         this._body = _body;
         this.isFinal = isFinal;
+        this.endloc = endloc;
     }
 
     override SwitchStatement syntaxCopy()
     {
-        return new SwitchStatement(loc, condition.syntaxCopy(), _body.syntaxCopy(), isFinal);
+        return new SwitchStatement(loc,
+            param ? param.syntaxCopy() : null,
+            condition.syntaxCopy(),
+            _body.syntaxCopy(),
+            isFinal,
+            endloc);
     }
 
     override bool hasBreak() const pure nothrow
@@ -1148,47 +1138,6 @@ extern (C++) final class SwitchStatement : Statement
         return true;
     }
 
-    /************************************
-     * Returns:
-     *  true if error
-     */
-    extern (D) bool checkLabel()
-    {
-        /*
-         * Checks the scope of a label for existing variable declaration.
-         * Params:
-         *   vd = last variable declared before this case/default label
-         * Returns: `true` if the variables declared in this label would be skipped.
-         */
-        bool checkVar(VarDeclaration vd)
-        {
-            for (auto v = vd; v && v != lastVar; v = v.lastVar)
-            {
-                if (v.isDataseg() || (v.storage_class & (STC.manifest | STC.temp) && vd.ident != Id.withSym) || v._init.isVoidInitializer())
-                    continue;
-                if (vd.ident == Id.withSym)
-                    error(loc, "`switch` skips declaration of `with` temporary");
-                else
-                    error(loc, "`switch` skips declaration of variable `%s`", v.toPrettyChars());
-                errorSupplemental(v.loc, "declared here");
-                return true;
-            }
-            return false;
-        }
-
-        enum error = true;
-
-        if (sdefault && checkVar(sdefault.lastVar))
-            return !error; // return error once fully deprecated
-
-        foreach (scase; *cases)
-        {
-            if (scase && checkVar(scase.lastVar))
-                return !error; // return error once fully deprecated
-        }
-        return !error;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -1712,85 +1661,6 @@ extern (C++) final class GotoStatement : Statement
         return new GotoStatement(loc, ident);
     }
 
-    /**************
-     * Returns: true for error
-     */
-    extern (D) bool checkLabel()
-    {
-        if (!label.statement)
-            return true;        // error should have been issued for this already
-
-        if (label.statement.os != os)
-        {
-            if (os && os.tok == TOK.onScopeFailure && !label.statement.os)
-            {
-                // Jump out from scope(failure) block is allowed.
-            }
-            else
-            {
-                if (label.statement.os)
-                    error(loc, "cannot `goto` in to `%s` block", Token.toChars(label.statement.os.tok));
-                else
-                    error(loc, "cannot `goto` out of `%s` block", Token.toChars(os.tok));
-                return true;
-            }
-        }
-
-        if (label.statement.tf != tf)
-        {
-            error(loc, "cannot `goto` in or out of `finally` block");
-            return true;
-        }
-
-        if (label.statement.inCtfeBlock && !inCtfeBlock)
-        {
-            error(loc, "cannot `goto` into `if (__ctfe)` block");
-            return true;
-        }
-
-        Statement stbnext;
-        for (auto stb = tryBody; stb != label.statement.tryBody; stb = stbnext)
-        {
-            if (!stb)
-            {
-                error(loc, "cannot `goto` into `try` block");
-                return true;
-            }
-            if (auto stf = stb.isTryFinallyStatement())
-                stbnext = stf.tryBody;
-            else if (auto stc = stb.isTryCatchStatement())
-                stbnext = stc.tryBody;
-            else
-                assert(0);
-        }
-
-        VarDeclaration vd = label.statement.lastVar;
-        if (!vd || vd.isDataseg() || (vd.storage_class & STC.manifest))
-            return false;
-
-        VarDeclaration last = lastVar;
-        while (last && last != vd)
-            last = last.lastVar;
-        if (last == vd)
-        {
-            // All good, the label's scope has no variables
-        }
-        else if (vd.storage_class & STC.exptemp)
-        {
-            // Lifetime ends at end of expression, so no issue with skipping the statement
-        }
-        else
-        {
-            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;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -1972,12 +1842,7 @@ extern (C++) final class CompoundAsmStatement : CompoundStatement
 
     override CompoundAsmStatement syntaxCopy()
     {
-        auto a = new Statements(statements.length);
-        foreach (i, s; *statements)
-        {
-            (*a)[i] = s ? s.syntaxCopy() : null;
-        }
-        return new CompoundAsmStatement(loc, a, stc);
+        return new CompoundAsmStatement(loc, Statement.arraySyntaxCopy(statements), stc);
     }
 
     override void accept(Visitor v)
diff --git a/gcc/d/dmd/statement.h b/gcc/d/dmd/statement.h
index dd8b9f21c056..fe899c6a4963 100644
--- a/gcc/d/dmd/statement.h
+++ b/gcc/d/dmd/statement.h
@@ -113,8 +113,6 @@ public:
 
     virtual Statement *syntaxCopy();
 
-    const char *toChars() const override final;
-
     void error(const char *format, ...);
     void warning(unsigned flag, const char *format, ...);
     void deprecation(const char *format, ...);
@@ -431,17 +429,19 @@ public:
 class SwitchStatement final : public Statement
 {
 public:
+    Parameter *param;
     Expression *condition;
     Statement *_body;
     d_bool isFinal;
+    Loc endloc;
 
+    d_bool hasDefault;             // true if default statement
+    d_bool hasVars;                // true if has variable case values
     DefaultStatement *sdefault;
     Statement *tryBody;            // set to TryCatchStatement or TryFinallyStatement if in _body portion
     TryFinallyStatement *tf;
     GotoCaseStatements gotoCases;  // array of unresolved GotoCaseStatement's
     CaseStatements *cases;         // array of CaseStatement's
-    int hasNoDefault;           // !=0 if no default statement
-    int hasVars;                // !=0 if has variable case values
     VarDeclaration *lastVar;
 
     SwitchStatement *syntaxCopy() override;
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index 304cb862f327..962ef625f5be 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -45,6 +45,7 @@ import dmd.expressionsem;
 import dmd.func;
 import dmd.globals;
 import dmd.gluelayer;
+import dmd.hdrgen;
 import dmd.id;
 import dmd.identifier;
 import dmd.importc;
@@ -130,7 +131,7 @@ private Expression checkAssignmentAsCondition(Expression e, Scope* sc)
     auto ec = lastComma(e);
     if (ec.op == EXP.assign)
     {
-        ec.error("assignment cannot be used as a condition, perhaps `==` was meant?");
+        error(ec.loc, "assignment cannot be used as a condition, perhaps `==` was meant?");
         return ErrorExp.get();
     }
     return e;
@@ -665,7 +666,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
             const olderrors = global.startGagging();
             discardValue(fs.increment);
             if (global.endGagging(olderrors))
-                fs.increment.deprecation("`%s` has no effect", fs.increment.toChars());
+                deprecation(fs.increment.loc, "`%s` has no effect", fs.increment.toChars());
             if (checkNonAssignmentArrayOp(fs.increment))
                 fs.increment = ErrorExp.get();
             fs.increment = fs.increment.optimize(WANTvalue);
@@ -1391,7 +1392,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
 
                 version (none)
                 {
-                    printf("init: %s\n", _init.toChars());
+                    printf("init: %s\n", toChars(_init));
                     printf("condition: %s\n", condition.toChars());
                     printf("increment: %s\n", increment.toChars());
                     printf("body: %s\n", forbody.toChars());
@@ -1779,7 +1780,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                     if (!se)
                         return setError();
 
-                    if (global.params.verbose)
+                    if (global.params.v.verbose)
                     {
                         message("library   %.*s", cast(int)se.len, se.string);
                     }
@@ -1868,6 +1869,37 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
             return;
         }
 
+        if (ss.param)
+        {
+            /**
+             * If the switch statement is of form `switch(auto a = exp) { body }`,
+             * rewrite to the following inside it's own scope:
+             *
+             * auto a = exp
+             * switch(a)
+             *     { body }
+             */
+            auto statements = new Statements();
+            auto vardecl = new VarDeclaration(ss.param.loc,
+                ss.param.type,
+                ss.param.ident,
+                new ExpInitializer(ss.condition.loc, ss.condition),
+                ss.param.storageClass);
+
+            statements.push(new ExpStatement(ss.param.loc, vardecl));
+
+            ss.condition = new VarExp(ss.param.loc, vardecl, false);
+            ss.param = null;
+
+            statements.push(ss);
+
+            Statement s = new CompoundStatement(ss.loc, statements);
+            s = new ScopeStatement(ss.loc, s, ss.endloc);
+            s = s.statementSemantic(sc);
+            result = s;
+            return;
+        }
+
         bool conditionError = false;
         ss.condition = ss.condition.expressionSemantic(sc);
         ss.condition = resolveProperties(sc, ss.condition);
@@ -1979,9 +2011,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
             if (ed && ss.cases.length < ed.members.length)
             {
                 int missingMembers = 0;
-                const maxShown = !global.params.verbose ?
-                                    (global.params.errorSupplementLimit ? global.params.errorSupplementLimit : int.max)
-                                    : int.max;
+                const maxShown = global.params.v.errorSupplementCount();
             Lmembers:
                 foreach (es; *ed.members)
                 {
@@ -2014,11 +2044,10 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                 needswitcherror = true;
         }
 
-        if (!sc.sw.sdefault &&
-            (!ss.isFinal || needswitcherror || global.params.useAssert == CHECKENABLE.on || sc.func.isSafe))
+        ss.hasDefault = sc.sw.sdefault ||
+            !(!ss.isFinal || needswitcherror || global.params.useAssert == CHECKENABLE.on || sc.func.isSafe);
+        if (!ss.hasDefault)
         {
-            ss.hasNoDefault = 1;
-
             if (!ss.isFinal && (!ss._body || !ss._body.isErrorStatement()) && !(sc.flags & SCOPE.Cfile))
                 error(ss.loc, "`switch` statement without a `default`; use `final switch` or add `default: assert(0);` or add `default: break;`");
 
@@ -2207,7 +2236,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                     /* Flag that we need to do special code generation
                     * for this, i.e. generate a sequence of if-then-else
                     */
-                    sw.hasVars = 1;
+                    sw.hasVars = true;
 
                     /* TODO check if v can be uninitialized at that point.
                     */
@@ -2633,7 +2662,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                     //errors = true;
                 }
                 if (global.endGagging(olderrors))
-                    rs.exp.deprecation("`%s` has no effect", rs.exp.toChars());
+                    deprecation(rs.exp.loc, "`%s` has no effect", rs.exp.toChars());
 
                 /* Replace:
                  *      return exp;
@@ -2708,7 +2737,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                     // checking for `shared`, make sure we were right
                     if (global.params.noSharedAccess == FeatureState.enabled && rs.exp.type.isShared())
                     {
-                        fd.error("function returns `shared` but cannot be inferred `ref`");
+                        .error(fd.loc, "%s `%s` function returns `shared` but cannot be inferred `ref`", fd.kind, fd.toPrettyChars);
                         supplemental();
                     }
                 }
@@ -3992,7 +4021,7 @@ private extern(D) Statement loopReturn(Expression e, Statements* cases, const re
     }
 
     s = new CompoundStatement(loc, a);
-    return new SwitchStatement(loc, e, s, false);
+    return new SwitchStatement(loc, null, e, s, false, loc);
 }
 
 /*************************************
@@ -4547,13 +4576,13 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState
                         {
                             if (!isStatic)
                             {
-                                error(fs.loc, "constant value `%s` cannot be `ref`", ie.toChars());
+                                error(fs.loc, "constant value `%s` cannot be `ref`", toChars(ie));
                             }
                             else
                             {
                                 if (!needExpansion)
                                 {
-                                    error(fs.loc, "constant value `%s` cannot be `ref`", ie.toChars());
+                                    error(fs.loc, "constant value `%s` cannot be `ref`", toChars(ie));
                                 }
                                 else
                                 {
@@ -4858,7 +4887,7 @@ private Statements* flatten(Statement statement, Scope* sc)
             const bool doUnittests = global.params.useUnitTests || global.params.ddoc.doOutput || global.params.dihdr.doOutput;
             auto loc = adjustLocForMixin(str, cs.loc, global.params.mixinOut);
             scope p = new Parser!ASTCodegen(loc, sc._module, str, false, global.errorSink, &global.compileEnv, doUnittests);
-            p.transitionIn = global.params.vin;
+            p.transitionIn = global.params.v.vin;
             p.nextToken();
 
             auto a = new Statements();
@@ -5053,3 +5082,130 @@ bool pragmaStartAddressSemantic(Loc loc, Scope* sc, Expressions* args)
     }
     return true;
 }
+
+/************************************
+ * Check for skipped variable declarations.
+ * Params:
+ *      ss = statement to check
+ * Returns:
+ *  true if error
+ */
+private bool checkLabel(SwitchStatement ss)
+{
+    /*
+     * Checks the scope of a label for existing variable declaration.
+     * Params:
+     *   vd = last variable declared before this case/default label
+     * Returns: `true` if the variables declared in this label would be skipped.
+     */
+    bool checkVar(VarDeclaration vd)
+    {
+        for (auto v = vd; v && v != ss.lastVar; v = v.lastVar)
+        {
+            if (v.isDataseg() || (v.storage_class & (STC.manifest | STC.temp) && vd.ident != Id.withSym) || v._init.isVoidInitializer())
+                continue;
+            if (vd.ident == Id.withSym)
+                error(ss.loc, "`switch` skips declaration of `with` temporary");
+            else
+                error(ss.loc, "`switch` skips declaration of variable `%s`", v.toPrettyChars());
+            errorSupplemental(v.loc, "declared here");
+            return true;
+        }
+        return false;
+    }
+
+    enum error = true;
+
+    if (ss.sdefault && checkVar(ss.sdefault.lastVar))
+        return !error; // return error once fully deprecated
+
+    foreach (scase; *ss.cases)
+    {
+        if (scase && checkVar(scase.lastVar))
+            return !error; // return error once fully deprecated
+    }
+    return !error;
+}
+
+
+/**************
+ * Check for skipped variable declarations.
+ * Params:
+ *      gs = statement to check
+ * Returns: true for error
+ */
+bool checkLabel(GotoStatement gs)
+{
+    if (!gs.label.statement)
+        return true;        // error should have been issued for this already
+
+    if (gs.label.statement.os != gs.os)
+    {
+        if (gs.os && gs.os.tok == TOK.onScopeFailure && !gs.label.statement.os)
+        {
+            // Jump out from scope(failure) block is allowed.
+        }
+        else
+        {
+            if (gs.label.statement.os)
+                error(gs.loc, "cannot `goto` in to `%s` block", Token.toChars(gs.label.statement.os.tok));
+            else
+                error(gs.loc, "cannot `goto` out of `%s` block", Token.toChars(gs.os.tok));
+            return true;
+        }
+    }
+
+    if (gs.label.statement.tf != gs.tf)
+    {
+        error(gs.loc, "cannot `goto` in or out of `finally` block");
+        return true;
+    }
+
+    if (gs.label.statement.inCtfeBlock && !gs.inCtfeBlock)
+    {
+        error(gs.loc, "cannot `goto` into `if (__ctfe)` block");
+        return true;
+    }
+
+    Statement stbnext;
+    for (auto stb = gs.tryBody; stb != gs.label.statement.tryBody; stb = stbnext)
+    {
+        if (!stb)
+        {
+            error(gs.loc, "cannot `goto` into `try` block");
+            return true;
+        }
+        if (auto stf = stb.isTryFinallyStatement())
+            stbnext = stf.tryBody;
+        else if (auto stc = stb.isTryCatchStatement())
+            stbnext = stc.tryBody;
+        else
+            assert(0);
+    }
+
+    VarDeclaration vd = gs.label.statement.lastVar;
+    if (!vd || vd.isDataseg() || (vd.storage_class & STC.manifest))
+        return false;
+
+    VarDeclaration last = gs.lastVar;
+    while (last && last != vd)
+        last = last.lastVar;
+    if (last == vd)
+    {
+        // All good, the label's scope has no variables
+    }
+    else if (vd.storage_class & STC.exptemp)
+    {
+        // Lifetime ends at end of expression, so no issue with skipping the statement
+    }
+    else
+    {
+        if (vd.ident == Id.withSym)
+            error(gs.loc, "`goto` skips declaration of `with` temporary");
+        else
+            error(gs.loc, "`goto` skips declaration of variable `%s`", vd.toPrettyChars());
+        errorSupplemental(vd.loc, "declared here");
+        return true;
+    }
+    return false;
+}
diff --git a/gcc/d/dmd/staticcond.d b/gcc/d/dmd/staticcond.d
index aa6f37ca67b4..45e777375a04 100644
--- a/gcc/d/dmd/staticcond.d
+++ b/gcc/d/dmd/staticcond.d
@@ -111,7 +111,8 @@ bool evalStaticCondition(Scope* sc, Expression original, Expression e, out bool
         const opt = e.toBool();
         if (opt.isEmpty())
         {
-            e.error("expression `%s` is not constant", e.toChars());
+            if (!e.type.isTypeError())
+                error(e.loc, "expression `%s` is not constant", e.toChars());
             errors = true;
             return false;
         }
diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d
index 2bde9f2aee9b..bdc569c87259 100644
--- a/gcc/d/dmd/traits.d
+++ b/gcc/d/dmd/traits.d
@@ -337,7 +337,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
 
     Expression dimError(int expected)
     {
-        e.error("expected %d arguments for `%s` but had %d", expected, e.ident.toChars(), cast(int)dim);
+        error(e.loc, "expected %d arguments for `%s` but had %d", expected, e.ident.toChars(), cast(int)dim);
         return ErrorExp.get();
     }
 
@@ -500,7 +500,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         auto t = isType(o);
         if (!t)
         {
-            e.error("type expected as second argument of __traits `%s` instead of `%s`",
+            error(e.loc, "type expected as second argument of __traits `%s` instead of `%s`",
                 e.ident.toChars(), o.toChars());
             return ErrorExp.get();
         }
@@ -521,7 +521,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         auto t = isType(o);
         if (!t)
         {
-            e.error("type expected as second argument of __traits `%s` instead of `%s`",
+            error(e.loc, "type expected as second argument of __traits `%s` instead of `%s`",
                 e.ident.toChars(), o.toChars());
             return ErrorExp.get();
         }
@@ -543,7 +543,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         auto t = isType(o);
         if (!t)
         {
-            e.error("type expected as second argument of __traits `%s` instead of `%s`",
+            error(e.loc, "type expected as second argument of __traits `%s` instead of `%s`",
                     e.ident.toChars(), o.toChars());
             return ErrorExp.get();
         }
@@ -577,7 +577,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
             return fd.isNested() ? True() : False();
         }
 
-        e.error("aggregate or function expected instead of `%s`", o.toChars());
+        error(e.loc, "aggregate or function expected instead of `%s`", o.toChars());
         return ErrorExp.get();
     }
     if (e.ident == Id.isDisabled)
@@ -598,7 +598,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
     {
         // @@@DEPRECATED2.121@@@
         // Deprecated in 2.101 - Can be removed from 2.121
-        e.deprecation("`traits(isVirtualFunction)` is deprecated. Use `traits(isVirtualMethod)` instead");
+        deprecation(e.loc, "`traits(isVirtualFunction)` is deprecated. Use `traits(isVirtualMethod)` instead");
 
         if (dim != 1)
             return dimError(1);
@@ -686,7 +686,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         {
             if (!po.ident)
             {
-                e.error("argument `%s` has no identifier", po.type.toChars());
+                error(e.loc, "argument `%s` has no identifier", po.type.toChars());
                 return ErrorExp.get();
             }
             id = po.ident;
@@ -696,7 +696,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
             Dsymbol s = getDsymbolWithoutExpCtx(o);
             if (!s || !s.ident)
             {
-                e.error("argument `%s` has no identifier", o.toChars());
+                error(e.loc, "argument `%s` has no identifier", o.toChars());
                 return ErrorExp.get();
             }
             id = s.ident;
@@ -733,7 +733,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         else
         {
             if (!isError(o))
-                e.error("argument `%s` has no identifier", o.toChars());
+                error(e.loc, "argument `%s` has no identifier", o.toChars());
             return ErrorExp.get();
         }
         assert(fqn);
@@ -758,7 +758,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         if (!s)
         {
             if (!isError(o))
-                e.error("argument `%s` has no visibility", o.toChars());
+                error(e.loc, "argument `%s` has no visibility", o.toChars());
             return ErrorExp.get();
         }
         if (s.semanticRun == PASS.initial)
@@ -809,7 +809,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         }
         if (!s || s.isImport())
         {
-            e.error("argument `%s` has no parent", o.toChars());
+            error(e.loc, "argument `%s` has no parent", o.toChars());
             return ErrorExp.get();
         }
 
@@ -845,7 +845,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
             ex = exp;
         else
         {
-            e.error("symbol or expression expected as first argument of __traits `child` instead of `%s`", op.toChars());
+            error(e.loc, "symbol or expression expected as first argument of __traits `child` instead of `%s`", op.toChars());
             return ErrorExp.get();
         }
 
@@ -854,7 +854,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         auto symc = getDsymbol(oc);
         if (!symc)
         {
-            e.error("symbol expected as second argument of __traits `child` instead of `%s`", oc.toChars());
+            error(e.loc, "symbol expected as second argument of __traits `child` instead of `%s`", oc.toChars());
             return ErrorExp.get();
         }
 
@@ -878,7 +878,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         auto ex = isExpression((*e.args)[0]);
         if (!ex)
         {
-            e.error("expression expected as second argument of __traits `%s`", e.ident.toChars());
+            error(e.loc, "expression expected as second argument of __traits `%s`", e.ident.toChars());
             return ErrorExp.get();
         }
         ex = ex.ctfeInterpret();
@@ -891,7 +891,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         Type t = decoToType(se.toUTF8(sc).peekString());
         if (!t)
         {
-            e.error("cannot determine `%s`", e.toChars());
+            error(e.loc, "cannot determine `%s`", e.toChars());
             return ErrorExp.get();
         }
         return (new TypeExp(e.loc, t)).expressionSemantic(sc);
@@ -909,7 +909,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         auto ex = isExpression((*e.args)[1]);
         if (!ex)
         {
-            e.error("expression expected as second argument of __traits `%s`", e.ident.toChars());
+            error(e.loc, "expression expected as second argument of __traits `%s`", e.ident.toChars());
             return ErrorExp.get();
         }
         ex = ex.ctfeInterpret();
@@ -921,7 +921,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
             b = b.ctfeInterpret();
             if (!b.type.equals(Type.tbool))
             {
-                e.error("`bool` expected as third argument of `__traits(getOverloads)`, not `%s` of type `%s`", b.toChars(), b.type.toChars());
+                error(e.loc, "`bool` expected as third argument of `__traits(getOverloads)`, not `%s` of type `%s`", b.toChars(), b.type.toChars());
                 return ErrorExp.get();
             }
             includeTemplates = b.toBool().get();
@@ -930,14 +930,14 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         StringExp se = ex.toStringExp();
         if (!se || se.len == 0)
         {
-            e.error("string expected as second argument of __traits `%s` instead of `%s`", e.ident.toChars(), ex.toChars());
+            error(e.loc, "string expected as second argument of __traits `%s` instead of `%s`", e.ident.toChars(), ex.toChars());
             return ErrorExp.get();
         }
         se = se.toUTF8(sc);
 
         if (se.sz != 1)
         {
-            e.error("string must be chars");
+            error(e.loc, "string must be chars");
             return ErrorExp.get();
         }
         auto id = Identifier.idPool(se.peekString());
@@ -972,7 +972,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
             ex = new DotIdExp(e.loc, ex2, id);
         else
         {
-            e.error("invalid first argument");
+            error(e.loc, "invalid first argument");
             return ErrorExp.get();
         }
     doSemantic:
@@ -1004,13 +1004,13 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
             Expression eorig = ex;
             ex = ex.expressionSemantic(scx);
             if (errors < global.errors)
-                e.error("`%s` cannot be resolved", eorig.toChars());
+                error(e.loc, "`%s` cannot be resolved", eorig.toChars());
 
             if (e.ident == Id.getVirtualFunctions)
             {
                 // @@@DEPRECATED2.121@@@
                 // Deprecated in 2.101 - Can be removed from 2.121
-                e.deprecation("`traits(getVirtualFunctions)` is deprecated. Use `traits(getVirtualMethods)` instead");
+                deprecation(e.loc, "`traits(getVirtualFunctions)` is deprecated. Use `traits(getVirtualMethods)` instead");
             }
 
             /* Create tuple of functions of ex
@@ -1165,7 +1165,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         auto cd = s ? s.isClassDeclaration() : null;
         if (!cd)
         {
-            e.error("first argument is not a class");
+            error(e.loc, "first argument is not a class");
             return ErrorExp.get();
         }
         if (cd.sizeok != Sizeok.done)
@@ -1174,7 +1174,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         }
         if (cd.sizeok != Sizeok.done)
         {
-            e.error("%s `%s` is forward referenced", cd.kind(), cd.toChars());
+            error(e.loc, "%s `%s` is forward referenced", cd.kind(), cd.toChars());
             return ErrorExp.get();
         }
 
@@ -1260,7 +1260,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
                 if (t)
                     printf("t = %d %s\n", t.ty, t.toChars());
             }
-            e.error("first argument is not a symbol");
+            error(e.loc, "first argument is not a symbol");
             return ErrorExp.get();
         }
 
@@ -1281,7 +1281,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
 
         if (!tf)
         {
-            e.error("first argument is not a function");
+            error(e.loc, "first argument is not a function");
             return ErrorExp.get();
         }
 
@@ -1324,7 +1324,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
 
         if (!tf)
         {
-            e.error("argument to `__traits(isReturnOnStack, %s)` is not a function", o.toChars());
+            error(e.loc, "argument to `__traits(isReturnOnStack, %s)` is not a function", o.toChars());
             return ErrorExp.get();
         }
 
@@ -1360,7 +1360,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         {
             if (!fd)
             {
-                e.error("argument to `__traits(getFunctionVariadicStyle, %s)` is not a function", o.toChars());
+                error(e.loc, "argument to `__traits(getFunctionVariadicStyle, %s)` is not a function", o.toChars());
                 return ErrorExp.get();
             }
             link = fd._linkage;
@@ -1411,7 +1411,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
                 fparams = fd.getParameterList();
             else
             {
-                e.error("first argument to `__traits(getParameterStorageClasses, %s, %s)` is not a function or a function call",
+                error(e.loc, "first argument to `__traits(getParameterStorageClasses, %s, %s)` is not a function or a function call",
                     o.toChars(), o1.toChars());
                 return ErrorExp.get();
             }
@@ -1427,7 +1427,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         auto ex = isExpression((*e.args)[1]);
         if (!ex)
         {
-            e.error("expression expected as second argument of `__traits(getParameterStorageClasses, %s, %s)`",
+            error(e.loc, "expression expected as second argument of `__traits(getParameterStorageClasses, %s, %s)`",
                 o.toChars(), o1.toChars());
             return ErrorExp.get();
         }
@@ -1435,7 +1435,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         auto ii = ex.toUInteger();
         if (ii >= fparams.length)
         {
-            e.error("parameter index must be in range 0..%u not %s", cast(uint)fparams.length, ex.toChars());
+            error(e.loc, "parameter index must be in range 0..%u not %s", cast(uint)fparams.length, ex.toChars());
             return ErrorExp.get();
         }
 
@@ -1507,7 +1507,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
             AggregateDeclaration agg;
             if (!s || ((d = s.isDeclaration()) is null && (agg = s.isAggregateDeclaration()) is null))
             {
-                e.error("argument to `__traits(getLinkage, %s)` is not a declaration", o.toChars());
+                error(e.loc, "argument to `__traits(getLinkage, %s)` is not a declaration", o.toChars());
                 return ErrorExp.get();
             }
 
@@ -1521,7 +1521,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
                     agg.size(e.loc);
                     if (agg.sizeok != Sizeok.done)
                     {
-                        e.error("%s `%s` is forward referenced", agg.kind(), agg.toChars());
+                        error(e.loc, "%s `%s` is forward referenced", agg.kind(), agg.toChars());
                         return ErrorExp.get();
                     }
                 }
@@ -1557,8 +1557,8 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         auto s = getDsymbol(o);
         if (!s)
         {
-            e.error("in expression `%s` `%s` can't have members", e.toChars(), o.toChars());
-            e.errorSupplemental("`%s` must evaluate to either a module, a struct, an union, a class, an interface or a template instantiation", o.toChars());
+            error(e.loc, "in expression `%s` `%s` can't have members", e.toChars(), o.toChars());
+            errorSupplemental(e.loc, "`%s` must evaluate to either a module, a struct, an union, a class, an interface or a template instantiation", o.toChars());
 
             return ErrorExp.get();
         }
@@ -1580,8 +1580,8 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         auto sds = s.isScopeDsymbol();
         if (!sds || sds.isTemplateDeclaration())
         {
-            e.error("in expression `%s` %s `%s` has no members", e.toChars(), s.kind(), s.toChars());
-            e.errorSupplemental("`%s` must evaluate to either a module, a struct, an union, a class, an interface or a template instantiation", s.toChars());
+            error(e.loc, "in expression `%s` %s `%s` has no members", e.toChars(), s.kind(), s.toChars());
+            errorSupplemental(e.loc, "`%s` must evaluate to either a module, a struct, an union, a class, an interface or a template instan[...]

[diff truncated at 524288 bytes]

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

only message in thread, other threads:[~2023-10-16 17:49 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-10-16 17:49 [gcc r14-4663] d: Merge upstream dmd, druntime 4c18eed967, phobos d945686a4 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).