diff mbox series

[committed] d: Merge upstream dmd d7772a2369, phobos 5748ca43f.

Message ID 20220803110451.2375766-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] d: Merge upstream dmd d7772a2369, phobos 5748ca43f. | expand

Commit Message

Iain Buclaw Aug. 3, 2022, 11:04 a.m. UTC
Hi,

This patch merges the D front-end with upstream dmd d7772a2369, and
standard library with phobos 5748ca43f, bumping the version to 2.100.1.

In upstream dmd, the D compiler and D runtime library have been merged
together into one repository.  Both dmd and libdruntime now track that.

D front-end changes:

    - Deprecated `scope(failure)' blocks that contain `return' statements.
    - Deprecated using integers for `version' or `debug' conditions.
    - Deprecated returning a discarded void value from a function.
    - `new' can now allocate an associative array.

D runtime changes:

    - Added avx512f detection to core.cpuid module.

Phobos changes:

    - Changed std.experimental.logger.core.sharedLog to return
      shared(Logger).

Bootstrapped and regression tested on x86_64-linux-gnu/-m32/-mx32, and
committed to mainline.

Regards,
Iain.

---
gcc/d/ChangeLog:

	* dmd/MERGE: Merge upstream dmd d7772a2369.
	* dmd/VERSION: Bump version to v2.100.1.
	* d-codegen.cc (get_frameinfo): Check whether decision to generate
	closure changed since semantic finished.
	* d-lang.cc (d_handle_option): Remove handling of -fdebug=level and
	-fversion=level.
	* decl.cc (DeclVisitor::visit (VarDeclaration *)): Generate evaluation
	of noreturn variable initializers before throw.
	* expr.cc (ExprVisitor::visit (AssignExp *)): Don't generate
	assignment for noreturn types, only evaluate for side effects.
	* lang.opt (fdebug=): Undocument -fdebug=level.
	(fversion=): Undocument -fversion=level.

libphobos/ChangeLog:

	* configure: Regenerate.
	* configure.ac (libtool_VERSION): Update to 4:0:0.
	* libdruntime/MERGE: Merge upstream druntime d7772a2369.
	* libdruntime/Makefile.am (DRUNTIME_DSOURCES): Add
	core/internal/array/duplication.d.
	* libdruntime/Makefile.in: Regenerate.
	* src/MERGE: Merge upstream phobos 5748ca43f.
	* testsuite/libphobos.gc/nocollect.d:
---
 gcc/d/d-codegen.cc                            |   7 +
 gcc/d/d-lang.cc                               |  20 -
 gcc/d/decl.cc                                 |   7 +-
 gcc/d/dmd/MERGE                               |   2 +-
 gcc/d/dmd/VERSION                             |   2 +-
 gcc/d/dmd/arrayop.d                           |   4 +-
 gcc/d/dmd/chkformat.d                         | 494 +++++++++++++-----
 gcc/d/dmd/clone.d                             |   4 +
 gcc/d/dmd/constfold.d                         | 123 +----
 gcc/d/dmd/cparse.d                            |   2 +-
 gcc/d/dmd/dcast.d                             |  14 +-
 gcc/d/dmd/declaration.h                       |   1 +
 gcc/d/dmd/dinterpret.d                        |  11 +-
 gcc/d/dmd/dmodule.d                           |   8 +-
 gcc/d/dmd/dsymbol.d                           |  26 +
 gcc/d/dmd/dsymbolsem.d                        |   7 +-
 gcc/d/dmd/dtemplate.d                         |   2 +-
 gcc/d/dmd/entity.d                            |  21 +-
 gcc/d/dmd/escape.d                            |  33 +-
 gcc/d/dmd/expressionsem.d                     | 113 ++--
 gcc/d/dmd/file_manager.d                      |   6 +
 gcc/d/dmd/func.d                              |  62 ++-
 gcc/d/dmd/impcnvtab.d                         |  55 ++
 gcc/d/dmd/initsem.d                           |  39 +-
 gcc/d/dmd/lexer.d                             |   2 +-
 gcc/d/dmd/mustuse.d                           |   2 +-
 gcc/d/dmd/optimize.d                          |   2 +-
 gcc/d/dmd/parse.d                             |  32 +-
 gcc/d/dmd/semantic3.d                         |  10 +-
 gcc/d/dmd/statementsem.d                      |  50 +-
 gcc/d/dmd/transitivevisitor.d                 |   6 +
 gcc/d/dmd/typesem.d                           |  13 +-
 gcc/d/expr.cc                                 |  11 +
 gcc/d/lang.opt                                |   4 +-
 .../gdc.test/compilable/backendfloatoptim.d   |  10 +
 .../gdc.test/compilable/cppmangle3.d          |   4 -
 .../gdc.test/compilable/must_use_initialize.d |  16 +
 gcc/testsuite/gdc.test/compilable/noreturn1.d |  28 +
 gcc/testsuite/gdc.test/compilable/test20832.d |  12 +
 gcc/testsuite/gdc.test/compilable/test21177.d |  65 ++-
 gcc/testsuite/gdc.test/compilable/test21432.d |  25 +
 gcc/testsuite/gdc.test/compilable/test22390.d |   8 +
 gcc/testsuite/gdc.test/compilable/test23082.d |  17 +
 gcc/testsuite/gdc.test/compilable/test23166.d |  22 +
 gcc/testsuite/gdc.test/compilable/test23172.d |  33 ++
 gcc/testsuite/gdc.test/compilable/test23235.d |  20 +
 gcc/testsuite/gdc.test/compilable/test23256.d |   6 +
 gcc/testsuite/gdc.test/compilable/test23262.d |  17 +
 .../gdc.test/compilable/testgotoskips.d       |  17 +
 .../fail_compilation/attributediagnostic.d    |  39 +-
 .../gdc.test/fail_compilation/chkformat.d     |  18 +
 .../gdc.test/fail_compilation/diag10319.d     |  20 +-
 .../gdc.test/fail_compilation/diag11198.d     |  14 +-
 .../gdc.test/fail_compilation/diag12829.d     |  10 +-
 .../gdc.test/fail_compilation/fail118.d       |  20 +-
 .../gdc.test/fail_compilation/fail20547.d     |  15 -
 .../gdc.test/fail_compilation/fail22134.d     |  17 +
 .../gdc.test/fail_compilation/fail23181.d     |  16 +
 .../gdc.test/fail_compilation/fail261.d       |   5 +-
 .../gdc.test/fail_compilation/fail58.d        |   8 +-
 .../gdc.test/fail_compilation/fail6889.d      |   2 +-
 .../gdc.test/fail_compilation/fail7848.d      |   8 +-
 .../gdc.test/fail_compilation/ice11856_1.d    |   7 +-
 .../fail_compilation/misc_parser_err_cov1.d   |   3 +-
 .../gdc.test/fail_compilation/newaa.d         |  19 +
 .../gdc.test/fail_compilation/nogc3.d         |   8 +-
 .../gdc.test/fail_compilation/retscope.d      |   4 +-
 .../gdc.test/fail_compilation/test13786.d     |  12 +-
 .../gdc.test/fail_compilation/test16193.d     |   4 +-
 .../gdc.test/fail_compilation/test21443.d     |  21 +
 .../gdc.test/fail_compilation/test21912.d     |  16 +-
 .../gdc.test/fail_compilation/test21939.d     |   5 +-
 .../gdc.test/fail_compilation/test23022.d     |  15 +
 .../gdc.test/fail_compilation/test23112.d     |  30 ++
 .../gdc.test/fail_compilation/test23170.d     |  12 +
 .../gdc.test/fail_compilation/test23216.d     |  24 +
 gcc/testsuite/gdc.test/runnable/closure.d     |   8 +-
 gcc/testsuite/gdc.test/runnable/evalorder.d   |  26 +
 gcc/testsuite/gdc.test/runnable/lexer.d       |   8 +-
 gcc/testsuite/gdc.test/runnable/noreturn1.d   |  32 ++
 gcc/testsuite/gdc.test/runnable/test11.d      |  37 --
 gcc/testsuite/gdc.test/runnable/test18973.d   |  25 +
 gcc/testsuite/gdc.test/runnable/test19.d      |  15 -
 gcc/testsuite/gdc.test/runnable/test20734.d   |   7 +
 gcc/testsuite/gdc.test/runnable/test23181.d   |  27 +
 gcc/testsuite/gdc.test/runnable/test8.d       |  39 ++
 gcc/testsuite/gdc.test/runnable/version.d     |  23 +-
 gcc/testsuite/gdc.test/runnable/warning1.d    |   9 -
 libphobos/configure                           |   2 +-
 libphobos/configure.ac                        |   2 +-
 libphobos/libdruntime/MERGE                   |   4 +-
 libphobos/libdruntime/Makefile.am             |  16 +-
 libphobos/libdruntime/Makefile.in             |  19 +-
 libphobos/libdruntime/core/cpuid.d            |  16 +
 libphobos/libdruntime/core/int128.d           |   2 -
 .../core/internal/array/appending.d           |  28 +-
 .../core/internal/array/duplication.d         | 346 ++++++++++++
 libphobos/libdruntime/core/internal/dassert.d |   2 +-
 libphobos/libdruntime/core/runtime.d          |   2 +-
 libphobos/libdruntime/core/stdc/errno.d       |   2 +-
 libphobos/libdruntime/core/stdc/stdio.d       |  53 +-
 libphobos/libdruntime/core/stdc/wchar_.d      |  90 +++-
 .../core/sys/darwin/mach/getsect.d            |   1 -
 .../core/sys/dragonflybsd/string.d            |   1 -
 .../libdruntime/core/sys/linux/sys/time.d     |   1 -
 .../libdruntime/core/sys/linux/sys/xattr.d    |   1 -
 libphobos/libdruntime/core/sys/linux/tipc.d   |   1 -
 libphobos/libdruntime/core/sys/posix/signal.d |  79 +--
 libphobos/libdruntime/core/sys/posix/spawn.d  |   2 +-
 libphobos/libdruntime/core/sys/posix/stdio.d  |   2 +-
 .../libdruntime/core/sys/posix/sys/select.d   |   1 -
 libphobos/libdruntime/core/sys/posix/time.d   |  66 ++-
 .../libdruntime/core/sys/posix/ucontext.d     |   1 -
 .../core/sys/solaris/sys/priocntl.d           |   1 -
 .../core/sys/solaris/sys/procset.d            |   1 -
 .../libdruntime/core/sys/windows/cguid.d      |   1 -
 .../libdruntime/core/sys/windows/ntsecpkg.d   |   1 -
 .../libdruntime/core/sys/windows/olectlid.d   |   1 -
 .../libdruntime/core/sys/windows/shlguid.d    |   1 -
 libphobos/libdruntime/core/sys/windows/sspi.d |   1 -
 libphobos/libdruntime/object.d                | 340 +-----------
 libphobos/libdruntime/rt/dylib_fixes.c        |   1 -
 libphobos/src/MERGE                           |   2 +-
 libphobos/src/etc/c/curl.d                    |  18 +-
 libphobos/src/std/algorithm/comparison.d      |   2 +-
 libphobos/src/std/algorithm/iteration.d       |  15 +-
 libphobos/src/std/algorithm/searching.d       |  12 +
 libphobos/src/std/conv.d                      |  19 +-
 libphobos/src/std/experimental/checkedint.d   |   2 +-
 libphobos/src/std/experimental/logger/core.d  | 176 +++++--
 .../src/std/experimental/logger/filelogger.d  |   2 +-
 .../src/std/experimental/logger/multilogger.d |   2 +-
 libphobos/src/std/file.d                      |   2 +-
 libphobos/src/std/format/internal/write.d     |   6 +-
 libphobos/src/std/format/package.d            |  24 +
 libphobos/src/std/math/package.d              |   1 +
 libphobos/src/std/math/rounding.d             |  28 +-
 libphobos/src/std/random.d                    |  67 ++-
 libphobos/src/std/stdio.d                     |  17 +-
 libphobos/src/std/sumtype.d                   | 148 +++---
 libphobos/src/std/typecons.d                  |  20 +-
 libphobos/src/std/uni/package.d               |   8 +-
 libphobos/testsuite/libphobos.gc/nocollect.d  |   2 +-
 143 files changed, 2497 insertions(+), 1287 deletions(-)
 create mode 100644 gcc/testsuite/gdc.test/compilable/backendfloatoptim.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/must_use_initialize.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test20832.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test21432.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test22390.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test23082.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test23166.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test23172.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test23235.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test23256.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test23262.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/testgotoskips.d
 delete mode 100644 gcc/testsuite/gdc.test/fail_compilation/fail20547.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/fail22134.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/fail23181.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/newaa.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test21443.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test23022.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test23112.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test23170.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test23216.d
 create mode 100644 gcc/testsuite/gdc.test/runnable/test18973.d
 create mode 100644 gcc/testsuite/gdc.test/runnable/test23181.d
 create mode 100644 libphobos/libdruntime/core/internal/array/duplication.d
diff mbox series

Patch

diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 2d90899b37f..3fd4bee58f6 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -2826,8 +2826,15 @@  get_frameinfo (FuncDeclaration *fd)
 
   DECL_LANG_FRAMEINFO (fds) = ffi;
 
+  const bool requiresClosure = fd->requiresClosure;
   if (fd->needsClosure ())
     {
+      /* This can shift due to templates being expanded that access alias
+         symbols, give it a decent error for now.  */
+      if (requiresClosure != fd->requiresClosure
+	  && (fd->nrvo_var || global.params.betterC))
+	fd->checkClosure ();
+
       /* Set-up a closure frame, this will be allocated on the heap.  */
       FRAMEINFO_CREATES_FRAME (ffi) = 1;
       FRAMEINFO_IS_CLOSURE (ffi) = 1;
diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc
index 6e4350f54cc..04147edee32 100644
--- a/gcc/d/d-lang.cc
+++ b/gcc/d/d-lang.cc
@@ -456,16 +456,6 @@  d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
       break;
 
     case OPT_fdebug_:
-      if (ISDIGIT (arg[0]))
-	{
-	  int level = integral_argument (arg);
-	  if (level != -1)
-	    {
-	      global.params.debuglevel = level;
-	      break;
-	    }
-	}
-
       if (Identifier::isValidIdentifier (CONST_CAST (char *, arg)))
 	{
 	  if (!global.params.debugids)
@@ -713,16 +703,6 @@  d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
       break;
 
     case OPT_fversion_:
-      if (ISDIGIT (arg[0]))
-	{
-	  int level = integral_argument (arg);
-	  if (level != -1)
-	    {
-	      global.params.versionlevel = level;
-	      break;
-	    }
-	}
-
       if (Identifier::isValidIdentifier (CONST_CAST (char *, arg)))
 	{
 	  if (!global.params.versionids)
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index 3caa465dd1e..58cea4dec3f 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -646,9 +646,12 @@  public:
 	if (!d->isDataseg () && !d->isMember ()
 	    && d->_init && !d->_init->isVoidInitializer ())
 	  {
+	    /* Evaluate RHS for side effects first.  */
+	    Expression *ie = initializerToExpression (d->_init);
+	    add_stmt (build_expr (ie));
+
 	    Expression *e = d->type->defaultInitLiteral (d->loc);
-	    tree exp = build_expr (e);
-	    add_stmt (exp);
+	    add_stmt (build_expr (e));
 	  }
 
 	return;
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 8324c1cc88c..c358b69e3fc 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@ 
-56589f0f4d724c1c8022c57509a243f16a04228a
+d7772a236983ec37b92d21b28bad3cd2de57b945
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/VERSION b/gcc/d/dmd/VERSION
index 5ea2ba0d8ec..83a14f57e16 100644
--- a/gcc/d/dmd/VERSION
+++ b/gcc/d/dmd/VERSION
@@ -1 +1 @@ 
-v2.100.0
+v2.100.1
diff --git a/gcc/d/dmd/arrayop.d b/gcc/d/dmd/arrayop.d
index 16cbe620bc5..272e751cb51 100644
--- a/gcc/d/dmd/arrayop.d
+++ b/gcc/d/dmd/arrayop.d
@@ -111,8 +111,8 @@  bool checkNonAssignmentArrayOp(Expression e, bool suggestion = false)
  * evaluation order as the actual array operations have no
  * side-effect.
  * References:
- * https://github.com/dlang/druntime/blob/master/src/object.d#L3944
- * https://github.com/dlang/druntime/blob/master/src/core/internal/array/operations.d
+ * https://github.com/dlang/dmd/blob/cdfadf8a18f474e6a1b8352af2541efe3e3467cc/druntime/src/object.d#L4694
+ * https://github.com/dlang/dmd/blob/master/druntime/src/core/internal/array/operations.d
  */
 Expression arrayOp(BinExp e, Scope* sc)
 {
diff --git a/gcc/d/dmd/chkformat.d b/gcc/d/dmd/chkformat.d
index a3f3bc4f141..e118d7014f9 100644
--- a/gcc/d/dmd/chkformat.d
+++ b/gcc/d/dmd/chkformat.d
@@ -62,7 +62,7 @@  import dmd.target;
 bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expression[] args, bool isVa_list)
 {
     //printf("checkPrintFormat('%.*s')\n", cast(int)format.length, format.ptr);
-    size_t n, gnu_m_count;    // index in args / number of Format.GNU_m
+    size_t n;    // index in args
     for (size_t i = 0; i < format.length;)
     {
         if (format[i] != '%')
@@ -79,6 +79,8 @@  bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
 
         if (fmt == Format.percent)
             continue;                   // "%%", no arguments
+        if (fmt == Format.GNU_m)
+            continue;                   // "%m", no arguments
 
         if (isVa_list)
         {
@@ -88,14 +90,11 @@  bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
             continue;
         }
 
-        if (fmt == Format.GNU_m)
-            ++gnu_m_count;
-
         Expression getNextArg(ref bool skip)
         {
             if (n == args.length)
             {
-                if (args.length < (n + 1) - gnu_m_count)
+                if (args.length < (n + 1))
                     deprecation(loc, "more format specifiers than %d arguments", cast(int)n);
                 else
                     skip = true;
@@ -207,7 +206,6 @@  bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
                     errorMsg(null, e, "ptrdiff_t", t);
                 break;
 
-            case Format.GNU_a:  // Format.GNU_a is only for scanf
             case Format.lg:
             case Format.g:      // double
                 if (t.ty != Tfloat64 && t.ty != Timaginary64)
@@ -289,8 +287,8 @@  bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
                 break;
 
             case Format.GNU_m:
-                break;  // not assert(0) because it may go through it if there are extra arguments
-
+            case Format.POSIX_ms:
+            case Format.POSIX_mls:
             case Format.percent:
                 assert(0);
         }
@@ -481,8 +479,6 @@  bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expres
                     errorMsg(null, e, "real*", t);
                 break;
 
-            case Format.GNU_a:
-            case Format.GNU_m:
             case Format.c:
             case Format.s:      // pointer to char string
                 if (!(t.ty == Tpointer && (tnext.ty == Tchar || tnext.ty == Tint8 || tnext.ty == Tuns8)))
@@ -500,10 +496,23 @@  bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expres
                     errorMsg(null, e, "void**", t);
                 break;
 
+            case Format.POSIX_ms: // pointer to pointer to char string
+                Type tnext2 = tnext ? tnext.nextOf() : null;
+                if (!(t.ty == Tpointer && tnext.ty == Tpointer && (tnext2.ty == Tchar || tnext2.ty == Tint8 || tnext2.ty == Tuns8)))
+                    errorMsg(null, e, "char**", t);
+                break;
+
+            case Format.POSIX_mls: // pointer to pointer to wchar_t string
+                Type tnext2 = tnext ? tnext.nextOf() : null;
+                if (!(t.ty == Tpointer && tnext.ty == Tpointer && tnext2.ty.isSomeChar && tnext2.size() == target.c.wchar_tsize))
+                    errorMsg(null, e, "wchar_t**", t);
+                break;
+
             case Format.error:
                 deprecation(loc, "format specifier `\"%.*s\"` is invalid", cast(int)slice.length, slice.ptr);
                 break;
 
+            case Format.GNU_m:
             case Format.percent:
                 assert(0);
         }
@@ -567,35 +576,97 @@  Format parseScanfFormatSpecifier(scope const char[] format, ref size_t idx,
             return error();
     }
 
-    /* Read the scanset
-     * A scanset can be anything, so we just check that it is paired
+    /* Read the specifier
      */
-    if (format[i] == '[')
+    Format specifier;
+    Modifier flags = Modifier.none;
+    switch (format[i])
     {
-        while (i < length)
-        {
-            if (format[i] == ']')
-                break;
+        case 'm':
+            // https://pubs.opengroup.org/onlinepubs/9699919799/functions/scanf.html
+            // POSIX.1-2017 C Extension (CX)
+            flags = Modifier.m;
             ++i;
-        }
+            if (i == length)
+                return error();
+            if (format[i] == 'l')
+            {
+                ++i;
+                if (i == length)
+                    return error();
+                flags = Modifier.ml;
+            }
 
-        // no `]` found
-        if (i == length)
-            return error();
+            // Check valid conversion types for %m.
+            if (format[i] == 'c' || format[i] == 's')
+                specifier = flags == Modifier.ml ? Format.POSIX_mls :
+                                                   Format.POSIX_ms;
+            else if (format[i] == 'C' || format[i] == 'S')
+                specifier = flags == Modifier.m ? Format.POSIX_mls :
+                                                  Format.error;
+            else if (format[i] == '[')
+                goto case '[';
+            else
+                specifier = Format.error;
+            ++i;
+            break;
 
-        ++i;
-        // no specifier after `]`
-        // it could be mixed with the one above, but then idx won't have the right index
-        if (i == length)
-            return error();
-    }
+        case 'l':
+            // Look for wchar_t scanset %l[..]
+            immutable j = i + 1;
+            if (j < length && format[j] == '[')
+            {
+                i = j;
+                flags = Modifier.l;
+                goto case '[';
+            }
+            goto default;
 
-    /* Read the specifier
-     */
-    char genSpec;
-    Format specifier = parseGenericFormatSpecifier(format, i, genSpec);
-    if (specifier == Format.error)
-        return error();
+        case '[':
+            // Read the scanset
+            i++;
+            if (i == length)
+                return error();
+            // If the conversion specifier begins with `[]` or `[^]`, the right
+            // bracket character is not the terminator, but in the scanlist.
+            if (format[i] == '^')
+            {
+                i++;
+                if (i == length)
+                    return error();
+            }
+            if (format[i] == ']')
+            {
+                i++;
+                if (i == length)
+                    return error();
+            }
+            // A scanset can be anything, so we just check that it is paired
+            while (i < length)
+            {
+                if (format[i] == ']')
+                    break;
+                ++i;
+            }
+            // no `]` found
+            if (i == length)
+                return error();
+
+            specifier = flags == Modifier.none ? Format.s         :
+                        flags == Modifier.l    ? Format.ls        :
+                        flags == Modifier.m    ? Format.POSIX_ms  :
+                        flags == Modifier.ml   ? Format.POSIX_mls :
+                                                 Format.error;
+            ++i;
+            break;
+
+        default:
+            char genSpec;
+            specifier = parseGenericFormatSpecifier(format, i, genSpec);
+            if (specifier == Format.error)
+                return error();
+            break;
+    }
 
     idx = i;
     return specifier;  // success
@@ -613,11 +684,13 @@  Format parseScanfFormatSpecifier(scope const char[] format, ref size_t idx,
  *          even if `Format.error` is returned
  *      widthStar = set if * for width
  *      precisionStar = set if * for precision
+ *      useGNUExts = true if parsing GNU format extensions
  * Returns:
  *      Format
  */
 Format parsePrintfFormatSpecifier(scope const char[] format, ref size_t idx,
-        out bool widthStar, out bool precisionStar) nothrow pure @safe
+        out bool widthStar, out bool precisionStar, bool useGNUExts =
+        findCondition(global.versionids, Identifier.idPool("CRuntime_Glibc"))) nothrow pure @safe
 {
     auto i = idx;
     assert(format[i] == '%');
@@ -730,14 +803,33 @@  Format parsePrintfFormatSpecifier(scope const char[] format, ref size_t idx,
     /* Read the specifier
      */
     char genSpec;
-    Format specifier = parseGenericFormatSpecifier(format, i, genSpec);
-    if (specifier == Format.error)
-        return error();
+    Format specifier;
+    switch (format[i])
+    {
+        case 'm':
+            // https://www.gnu.org/software/libc/manual/html_node/Other-Output-Conversions.html
+            if (useGNUExts)
+            {
+                specifier = Format.GNU_m;
+                genSpec = format[i];
+                ++i;
+                break;
+            }
+            goto default;
+
+        default:
+            specifier = parseGenericFormatSpecifier(format, i, genSpec);
+            if (specifier == Format.error)
+                return error();
+            break;
+    }
 
     switch (genSpec)
     {
         case 'c':
         case 's':
+        case 'C':
+        case 'S':
             if (hash || zero)
                 return error();
             break;
@@ -748,6 +840,11 @@  Format parsePrintfFormatSpecifier(scope const char[] format, ref size_t idx,
                 return error();
             break;
 
+        case 'm':
+            if (hash || zero || flags)
+                return error();
+            break;
+
         case 'n':
             if (hash || zero || precision || width || flags)
                 return error();
@@ -761,6 +858,22 @@  Format parsePrintfFormatSpecifier(scope const char[] format, ref size_t idx,
     return specifier;  // success
 }
 
+/* Different kinds of conversion modifiers. */
+enum Modifier
+{
+    none,
+    h,          // short
+    hh,         // char
+    j,          // intmax_t
+    l,          // wint_t/wchar_t
+    ll,         // long long int
+    L,          // long double
+    m,          // char**
+    ml,         // wchar_t**
+    t,          // ptrdiff_t
+    z           // size_t
+}
+
 /* Different kinds of formatting specifications, variations we don't
    care about are merged. (Like we don't care about the difference between
    f, e, g, a, etc.)
@@ -799,8 +912,9 @@  enum Format
     jn,         // pointer to intmax_t
     zn,         // pointer to size_t
     tn,         // pointer to ptrdiff_t
-    GNU_a,      // GNU ext. : address to a string with no maximum size (scanf)
-    GNU_m,      // GNU ext. : string corresponding to the error code in errno (printf) / length modifier (scanf)
+    GNU_m,      // GNU ext. : string corresponding to the error code in errno (printf)
+    POSIX_ms,   // POSIX ext. : dynamically allocated char string  (scanf)
+    POSIX_mls,  // POSIX ext. : dynamically allocated wchar_t string (scanf)
     percent,    // %% (i.e. no argument)
     error,      // invalid format specification
 }
@@ -820,38 +934,48 @@  enum Format
  *      Format
  */
 Format parseGenericFormatSpecifier(scope const char[] format,
-    ref size_t idx, out char genSpecifier, bool useGNUExts =
-    findCondition(global.versionids, Identifier.idPool("CRuntime_Glibc"))) nothrow pure @trusted
+    ref size_t idx, out char genSpecifier) nothrow pure @safe
 {
     const length = format.length;
 
     /* Read the `length modifier`
      */
     const lm = format[idx];
-    bool lm1;        // if jztL
-    bool lm2;        // if `hh` or `ll`
-    if (lm == 'j' ||
-        lm == 'z' ||
-        lm == 't' ||
-        lm == 'L')
+    Modifier flags;
+    switch (lm)
     {
-        ++idx;
-        if (idx == length)
-            return Format.error;
-        lm1 = true;
-    }
-    else if (lm == 'h' || lm == 'l')
-    {
-        ++idx;
-        if (idx == length)
-            return Format.error;
-        lm2 = lm == format[idx];
-        if (lm2)
-        {
+        case 'j':
+        case 'z':
+        case 't':
+        case 'L':
+            flags = lm == 'j' ? Modifier.j :
+                    lm == 'z' ? Modifier.z :
+                    lm == 't' ? Modifier.t :
+                                Modifier.L;
             ++idx;
             if (idx == length)
                 return Format.error;
-        }
+            break;
+
+        case 'h':
+        case 'l':
+            ++idx;
+            if (idx == length)
+                return Format.error;
+            if (lm == format[idx])
+            {
+                flags = lm == 'h' ? Modifier.hh : Modifier.ll;
+                ++idx;
+                if (idx == length)
+                    return Format.error;
+            }
+            else
+                flags = lm == 'h' ? Modifier.h : Modifier.l;
+            break;
+
+        default:
+            flags = Modifier.none;
+            break;
     }
 
     /* Read the `specifier`
@@ -863,103 +987,88 @@  Format parseGenericFormatSpecifier(scope const char[] format,
     {
         case 'd':
         case 'i':
-            if (lm == 'L')
-                specifier = Format.error;
-            else
-                specifier = lm == 'h' && lm2 ? Format.hhd :
-                            lm == 'h'        ? Format.hd  :
-                            lm == 'l' && lm2 ? Format.lld :
-                            lm == 'l'        ? Format.ld  :
-                            lm == 'j'        ? Format.jd  :
-                            lm == 'z'        ? Format.zd  :
-                            lm == 't'        ? Format.td  :
-                                               Format.d;
+            specifier = flags == Modifier.none ? Format.d   :
+                        flags == Modifier.hh   ? Format.hhd :
+                        flags == Modifier.h    ? Format.hd  :
+                        flags == Modifier.ll   ? Format.lld :
+                        flags == Modifier.l    ? Format.ld  :
+                        flags == Modifier.j    ? Format.jd  :
+                        flags == Modifier.z    ? Format.zd  :
+                        flags == Modifier.t    ? Format.td  :
+                                                 Format.error;
             break;
 
         case 'u':
         case 'o':
         case 'x':
         case 'X':
-            if (lm == 'L')
-                specifier = Format.error;
-            else
-                specifier = lm == 'h' && lm2 ? Format.hhu :
-                            lm == 'h'        ? Format.hu  :
-                            lm == 'l' && lm2 ? Format.llu :
-                            lm == 'l'        ? Format.lu  :
-                            lm == 'j'        ? Format.ju  :
-                            lm == 'z'        ? Format.zd  :
-                            lm == 't'        ? Format.td  :
-                                               Format.u;
+            specifier = flags == Modifier.none ? Format.u   :
+                        flags == Modifier.hh   ? Format.hhu :
+                        flags == Modifier.h    ? Format.hu  :
+                        flags == Modifier.ll   ? Format.llu :
+                        flags == Modifier.l    ? Format.lu  :
+                        flags == Modifier.j    ? Format.ju  :
+                        flags == Modifier.z    ? Format.zd  :
+                        flags == Modifier.t    ? Format.td  :
+                                                 Format.error;
             break;
 
-        case 'a':
-            if (useGNUExts)
-            {
-                // https://www.gnu.org/software/libc/manual/html_node/Dynamic-String-Input.html
-                specifier = Format.GNU_a;
-                break;
-            }
-            goto case;
-
         case 'f':
         case 'F':
         case 'e':
         case 'E':
         case 'g':
         case 'G':
+        case 'a':
         case 'A':
-            if (lm == 'L')
-                specifier = Format.Lg;
-            else if (lm1 || lm2 || lm == 'h')
-                specifier = Format.error;
-            else
-                specifier = lm == 'l' ? Format.lg : Format.g;
+            specifier = flags == Modifier.none ? Format.g  :
+                        flags == Modifier.L    ? Format.Lg :
+                        flags == Modifier.l    ? Format.lg :
+                                                 Format.error;
             break;
 
         case 'c':
-            if (lm1 || lm2 || lm == 'h')
-                specifier = Format.error;
-            else
-                specifier = lm == 'l' ? Format.lc : Format.c;
+            specifier = flags == Modifier.none ? Format.c       :
+                        flags == Modifier.l    ? Format.lc      :
+                                                 Format.error;
             break;
 
         case 's':
-            if (lm1 || lm2 || lm == 'h')
-                specifier = Format.error;
-            else
-                specifier = lm == 'l' ? Format.ls : Format.s;
+            specifier = flags == Modifier.none ? Format.s       :
+                        flags == Modifier.l    ? Format.ls      :
+                                                 Format.error;
             break;
 
         case 'p':
-            if (lm1 || lm2 || lm == 'h' || lm == 'l')
-                specifier = Format.error;
-            else
-                specifier = Format.p;
+            specifier = flags == Modifier.none ? Format.p :
+                                                 Format.error;
             break;
 
         case 'n':
-            if (lm == 'L')
-                specifier = Format.error;
-            else
-                specifier = lm == 'l' && lm2 ? Format.lln :
-                            lm == 'l'        ? Format.ln  :
-                            lm == 'h' && lm2 ? Format.hhn :
-                            lm == 'h'        ? Format.hn  :
-                            lm == 'j'        ? Format.jn  :
-                            lm == 'z'        ? Format.zn  :
-                            lm == 't'        ? Format.tn  :
-                                               Format.n;
+            specifier = flags == Modifier.none ? Format.n   :
+                        flags == Modifier.ll   ? Format.lln :
+                        flags == Modifier.l    ? Format.ln  :
+                        flags == Modifier.hh   ? Format.hhn :
+                        flags == Modifier.h    ? Format.hn  :
+                        flags == Modifier.j    ? Format.jn  :
+                        flags == Modifier.z    ? Format.zn  :
+                        flags == Modifier.t    ? Format.tn  :
+                                                 Format.error;
             break;
 
-        case 'm':
-            if (useGNUExts)
-            {
-                // https://www.gnu.org/software/libc/manual/html_node/Other-Output-Conversions.html
-                specifier = Format.GNU_m;
-                break;
-            }
-            goto default;
+        case 'C':
+            // POSIX.1-2017 X/Open System Interfaces (XSI)
+            // %C format is equivalent to %lc
+            specifier = flags == Modifier.none ? Format.lc :
+                                                 Format.error;
+            break;
+
+        case 'S':
+            // POSIX.1-2017 X/Open System Interfaces (XSI)
+            // %S format is equivalent to %ls
+            specifier = flags == Modifier.none ? Format.ls :
+                                                 Format.error;
+            break;
 
         default:
             specifier = Format.error;
@@ -1126,10 +1235,13 @@  unittest
      assert(idx == 2);
 
      idx = 0;
-     Format g = parsePrintfFormatSpecifier("%a", idx, widthStar, precisionStar);
-     assert(g == Format.g || g == Format.GNU_a);
+     assert(parsePrintfFormatSpecifier("%a", idx, widthStar, precisionStar) == Format.g);
      assert(idx == 2);
 
+     idx = 0;
+     assert(parsePrintfFormatSpecifier("%La", idx, widthStar, precisionStar) == Format.Lg);
+     assert(idx == 3);
+
      idx = 0;
      assert(parsePrintfFormatSpecifier("%A", idx, widthStar, precisionStar) == Format.g);
      assert(idx == 2);
@@ -1296,8 +1408,7 @@  unittest
     assert(idx == 2);
 
     idx = 0;
-    g = parseScanfFormatSpecifier("%a", idx, asterisk);
-    assert(g == Format.g || g == Format.GNU_a);
+    assert(parseScanfFormatSpecifier("%a", idx, asterisk) == Format.g);
     assert(idx == 2);
 
     idx = 0;
@@ -1322,15 +1433,25 @@  unittest
 
     // scansets
     idx = 0;
-    assert(parseScanfFormatSpecifier("%[a-zA-Z]s", idx, asterisk) == Format.s);
-    assert(idx == 10);
+    assert(parseScanfFormatSpecifier("%[a-zA-Z]", idx, asterisk) == Format.s);
+    assert(idx == 9);
     assert(!asterisk);
 
     idx = 0;
-    assert(parseScanfFormatSpecifier("%*25[a-z]hhd", idx, asterisk) == Format.hhd);
-    assert(idx == 12);
+    assert(parseScanfFormatSpecifier("%*25l[a-z]", idx, asterisk) == Format.ls);
+    assert(idx == 10);
     assert(asterisk);
 
+    idx = 0;
+    assert(parseScanfFormatSpecifier("%[]]", idx, asterisk) == Format.s);
+    assert(idx == 4);
+    assert(!asterisk);
+
+    idx = 0;
+    assert(parseScanfFormatSpecifier("%[^]]", idx, asterisk) == Format.s);
+    assert(idx == 5);
+    assert(!asterisk);
+
     // Too short formats
     foreach (s; ["%", "% ", "%#", "%0", "%*", "%1", "%19",
                  "%j", "%z", "%t", "%l", "%h", "%ll", "%hh", "%K"])
@@ -1354,11 +1475,108 @@  unittest
     }
 
     // Invalid scansets
-    foreach (s; ["%[]", "%[s", "%[0-9lld", "%[", "%[a-z]"])
+    foreach (s; ["%[]", "%[^", "%[^]", "%[s", "%[0-9lld", "%[", "%l[^]"])
+    {
+        idx = 0;
+        assert(parseScanfFormatSpecifier(s, idx, asterisk) == Format.error);
+        assert(idx == s.length);
+    }
+
+    // Posix extensions
+    foreach (s; ["%jm", "%zm", "%tm", "%Lm", "%hm", "%hhm", "%lm", "%llm",
+                 "%m", "%ma", "%md", "%ml", "%mm", "%mlb", "%mlj", "%mlr", "%mlz",
+                 "%LC", "%lC", "%llC", "%jC", "%tC", "%hC", "%hhC", "%zC",
+                 "%LS", "%lS", "%llS", "%jS", "%tS", "%hS", "%hhS", "%zS"])
     {
         idx = 0;
         assert(parseScanfFormatSpecifier(s, idx, asterisk) == Format.error);
         assert(idx == s.length);
     }
 
+    idx = 0;
+    assert(parseScanfFormatSpecifier("%mc", idx, asterisk) == Format.POSIX_ms);
+    assert(idx == 3);
+
+    idx = 0;
+    assert(parseScanfFormatSpecifier("%ms", idx, asterisk) == Format.POSIX_ms);
+    assert(idx == 3);
+
+    idx = 0;
+    assert(parseScanfFormatSpecifier("%m[0-9]", idx, asterisk) == Format.POSIX_ms);
+    assert(idx == 7);
+
+    idx = 0;
+    assert(parseScanfFormatSpecifier("%mlc", idx, asterisk) == Format.POSIX_mls);
+    assert(idx == 4);
+
+    idx = 0;
+    assert(parseScanfFormatSpecifier("%mls", idx, asterisk) == Format.POSIX_mls);
+    assert(idx == 4);
+
+    idx = 0;
+    assert(parseScanfFormatSpecifier("%ml[^0-9]", idx, asterisk) == Format.POSIX_mls);
+    assert(idx == 9);
+
+    idx = 0;
+    assert(parseScanfFormatSpecifier("%mC", idx, asterisk) == Format.POSIX_mls);
+    assert(idx == 3);
+
+    idx = 0;
+    assert(parseScanfFormatSpecifier("%mS", idx, asterisk) == Format.POSIX_mls);
+    assert(idx == 3);
+
+    idx = 0;
+    assert(parsePrintfFormatSpecifier("%C", idx, widthStar, precisionStar) == Format.lc);
+    assert(idx == 2);
+
+    idx = 0;
+    assert(parseScanfFormatSpecifier("%C", idx, asterisk) == Format.lc);
+    assert(idx == 2);
+
+    idx = 0;
+    assert(parsePrintfFormatSpecifier("%S", idx, widthStar, precisionStar) == Format.ls);
+    assert(idx == 2);
+
+    idx = 0;
+    assert(parseScanfFormatSpecifier("%S", idx, asterisk) == Format.ls);
+    assert(idx == 2);
+
+    // GNU extensions: explicitly toggle ISO/GNU flag.
+    // ISO printf()
+    bool useGNUExts = false;
+    {
+        foreach (s; ["%jm", "%zm", "%tm", "%Lm", "%hm", "%hhm", "%lm", "%llm",
+                     "%#m", "%+m", "%-m", "% m", "%0m"])
+        {
+            idx = 0;
+            assert(parsePrintfFormatSpecifier(s, idx, widthStar, precisionStar, useGNUExts) == Format.error);
+            assert(idx == s.length);
+        }
+        foreach (s; ["%m", "%md", "%mz", "%mc", "%mm", "%msyz", "%ml", "%mlz", "%mlc", "%mlm"])
+        {
+            idx = 0;
+            assert(parsePrintfFormatSpecifier(s, idx, widthStar, precisionStar, useGNUExts) == Format.error);
+            assert(idx == 2);
+        }
+    }
+
+    // GNU printf()
+    useGNUExts = true;
+    {
+        foreach (s; ["%jm", "%zm", "%tm", "%Lm", "%hm", "%hhm", "%lm", "%llm",
+                     "%#m", "%+m", "%-m", "% m", "%0m"])
+        {
+            idx = 0;
+            assert(parsePrintfFormatSpecifier(s, idx, widthStar, precisionStar, useGNUExts) == Format.error);
+            assert(idx == s.length);
+        }
+
+        // valid cases, all parsed as `%m`
+        foreach (s; ["%m", "%md", "%mz", "%mc", "%mm", "%msyz", "%ml", "%mlz", "%mlc", "%mlm"])
+        {
+            idx = 0;
+            assert(parsePrintfFormatSpecifier(s, idx, widthStar, precisionStar, useGNUExts) == Format.GNU_m);
+            assert(idx == 2);
+        }
+    }
 }
diff --git a/gcc/d/dmd/clone.d b/gcc/d/dmd/clone.d
index cf4ccbb955c..1a26eaa434b 100644
--- a/gcc/d/dmd/clone.d
+++ b/gcc/d/dmd/clone.d
@@ -1121,6 +1121,10 @@  private DtorDeclaration buildExternDDtor(AggregateDeclaration ad, Scope* sc)
     if (!dtor)
         return null;
 
+    // Don't try to call `@disable`d dtors
+    if (dtor.storage_class & STC.disable)
+        return null;
+
     // Generate shim only when ABI incompatible on target platform
     if (ad.classKind != ClassKind.cpp || !target.cpp.wrapDtorInExternD)
         return dtor;
diff --git a/gcc/d/dmd/constfold.d b/gcc/d/dmd/constfold.d
index d90542f3fd8..f4e44e812c8 100644
--- a/gcc/d/dmd/constfold.d
+++ b/gcc/d/dmd/constfold.d
@@ -234,99 +234,9 @@  UnionExp Add(const ref Loc loc, Type type, Expression e1, Expression e2)
 
 UnionExp Min(const ref Loc loc, Type type, Expression e1, Expression e2)
 {
-    UnionExp ue = void;
-    if (type.isreal())
-    {
-        emplaceExp!(RealExp)(&ue, loc, e1.toReal() - e2.toReal(), type);
-    }
-    else if (type.isimaginary())
-    {
-        emplaceExp!(RealExp)(&ue, loc, e1.toImaginary() - e2.toImaginary(), type);
-    }
-    else if (type.iscomplex())
-    {
-        // This rigamarole is necessary so that -0.0 doesn't get
-        // converted to +0.0 by doing an extraneous add with +0.0
-        auto c1 = complex_t(CTFloat.zero);
-        real_t r1 = CTFloat.zero;
-        real_t i1 = CTFloat.zero;
-        auto c2 = complex_t(CTFloat.zero);
-        real_t r2 = CTFloat.zero;
-        real_t i2 = CTFloat.zero;
-        auto v = complex_t(CTFloat.zero);
-        int x;
-        if (e1.type.isreal())
-        {
-            r1 = e1.toReal();
-            x = 0;
-        }
-        else if (e1.type.isimaginary())
-        {
-            i1 = e1.toImaginary();
-            x = 3;
-        }
-        else
-        {
-            c1 = e1.toComplex();
-            x = 6;
-        }
-        if (e2.type.isreal())
-        {
-            r2 = e2.toReal();
-        }
-        else if (e2.type.isimaginary())
-        {
-            i2 = e2.toImaginary();
-            x += 1;
-        }
-        else
-        {
-            c2 = e2.toComplex();
-            x += 2;
-        }
-        switch (x)
-        {
-        case 0 + 0:
-            v = complex_t(r1 - r2);
-            break;
-        case 0 + 1:
-            v = complex_t(r1, -i2);
-            break;
-        case 0 + 2:
-            v = complex_t(r1 - creall(c2), -cimagl(c2));
-            break;
-        case 3 + 0:
-            v = complex_t(-r2, i1);
-            break;
-        case 3 + 1:
-            v = complex_t(CTFloat.zero, i1 - i2);
-            break;
-        case 3 + 2:
-            v = complex_t(-creall(c2), i1 - cimagl(c2));
-            break;
-        case 6 + 0:
-            v = complex_t(creall(c1) - r2, cimagl(c1));
-            break;
-        case 6 + 1:
-            v = complex_t(creall(c1), cimagl(c1) - i2);
-            break;
-        case 6 + 2:
-            v = c1 - c2;
-            break;
-        default:
-            assert(0);
-        }
-        emplaceExp!(ComplexExp)(&ue, loc, v, type);
-    }
-    else if (SymOffExp soe = e1.isSymOffExp())
-    {
-        emplaceExp!(SymOffExp)(&ue, loc, soe.var, soe.offset - e2.toInteger());
-        ue.exp().type = type;
-    }
-    else
-    {
-        emplaceExp!(IntegerExp)(&ue, loc, e1.toInteger() - e2.toInteger(), type);
-    }
+    // Compute e1-e2 as e1+(-e2)
+    UnionExp neg = Neg(e2.type, e2);
+    UnionExp ue = Add(loc, type, e1, neg.exp());
     return ue;
 }
 
@@ -1213,6 +1123,10 @@  UnionExp ArrayLength(Type type, Expression e1)
         Expression e = (cast(TypeSArray)e1.type.toBasetype()).dim;
         emplaceExp!(UnionExp)(&ue, e);
     }
+    else if (e1.isNullExp())
+    {
+        emplaceExp!(IntegerExp)(&ue, loc, 0, type);
+    }
     else
         cantExp(ue);
     return ue;
@@ -1505,17 +1419,11 @@  UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
     Type t2 = e2.type.toBasetype();
     //printf("Cat(e1 = %s, e2 = %s)\n", e1.toChars(), e2.toChars());
     //printf("\tt1 = %s, t2 = %s, type = %s\n", t1.toChars(), t2.toChars(), type.toChars());
-    if (e1.op == EXP.null_ && (e2.op == EXP.int64 || e2.op == EXP.structLiteral))
-    {
-        e = e2;
-        t = t1;
-        goto L2;
-    }
-    else if ((e1.op == EXP.int64 || e1.op == EXP.structLiteral) && e2.op == EXP.null_)
+
+    /* e is the non-null operand, t is the type of the null operand
+     */
+    UnionExp catNull(Expression e, Type t)
     {
-        e = e1;
-        t = t2;
-    L2:
         Type tn = e.type.toBasetype();
         if (tn.ty.isSomeChar)
         {
@@ -1545,6 +1453,15 @@  UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
         assert(ue.exp().type);
         return ue;
     }
+
+    if (e1.op == EXP.null_ && (e2.op == EXP.int64 || e2.op == EXP.structLiteral))
+    {
+        return catNull(e2, t1);
+    }
+    else if ((e1.op == EXP.int64 || e1.op == EXP.structLiteral) && e2.op == EXP.null_)
+    {
+        return catNull(e1, t2);
+    }
     else if (e1.op == EXP.null_ && e2.op == EXP.null_)
     {
         if (type == e1.type)
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index a3bebb7365a..2679a63245c 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -1675,7 +1675,7 @@  final class CParser(AST) : Parser!AST
             auto stags = applySpecifier(stag, specifier);
             symbols.push(stags);
 
-            if (tt.tok == TOK.enum_)
+            if (0 && tt.tok == TOK.enum_)    // C11 proscribes enums with no members, but we allow it
             {
                 if (!tt.members)
                     error(tt.loc, "`enum %s` has no members", stag.toChars());
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index 12051d92215..afd19f3d0f5 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -1106,9 +1106,14 @@  MATCH implicitConvTo(Expression e, Type t)
 
     MATCH visitCond(CondExp e)
     {
-        auto result = visit(e);
-        if (result != MATCH.nomatch)
-            return result;
+        e.econd = e.econd.optimize(WANTvalue);
+        const opt = e.econd.toBool();
+        if (opt.isPresent())
+        {
+            auto result = visit(e);
+            if (result != MATCH.nomatch)
+                return result;
+        }
 
         MATCH m1 = e.e1.implicitConvTo(t);
         MATCH m2 = e.e2.implicitConvTo(t);
@@ -2942,6 +2947,9 @@  Lagain:
 
         t1 = Type.basic[ty1];
         t2 = Type.basic[ty2];
+
+        if (!(t1 && t2))
+            return null;
         e1 = e1.castTo(sc, t1);
         e2 = e2.castTo(sc, t2);
         return Lret(Type.basic[ty]);
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index 2c7d381e797..c8f6c2aab36 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -684,6 +684,7 @@  public:
     const char *kind() const override;
     bool isUnique();
     bool needsClosure();
+    bool checkClosure();
     bool hasNestedFrameRefs();
     ParameterList getParameterList();
 
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index 5841a252454..890c3b6fef2 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -2352,6 +2352,7 @@  public:
                 if (ExpInitializer ie = v._init.isExpInitializer())
                 {
                     result = interpretRegion(ie.exp, istate, goal);
+                    return;
                 }
                 else if (v._init.isVoidInitializer())
                 {
@@ -2359,12 +2360,16 @@  public:
                     // There is no AssignExp for void initializers,
                     // so set it here.
                     setValue(v, result);
+                    return;
                 }
-                else
+                else if (v._init.isArrayInitializer())
                 {
-                    e.error("declaration `%s` is not yet implemented in CTFE", e.toChars());
-                    result = CTFEExp.cantexp;
+                    result = v._init.initializerToExpression(v.type);
+                    if (result !is null)
+                        return;
                 }
+                e.error("declaration `%s` is not yet implemented in CTFE", e.toChars());
+                result = CTFEExp.cantexp;
             }
             else if (v.type.size() == 0)
             {
diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index 0be938ffdf5..5e802dab8cc 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/dmd/dmodule.d
@@ -619,7 +619,7 @@  extern (C++) final class Module : Package
         else
         {
             // if module is not named 'package' but we're trying to read 'package.d', we're looking for a package module
-            bool isPackageMod = (strcmp(toChars(), "package") != 0) && (strcmp(srcfile.name(), package_d) == 0 || (strcmp(srcfile.name(), package_di) == 0));
+            bool isPackageMod = (strcmp(toChars(), "package") != 0) && isPackageFileName(srcfile);
             if (isPackageMod)
                 .error(loc, "importing package '%s' requires a 'package.d' file which cannot be found in '%s'", toChars(), srcfile.toChars());
             else
@@ -824,8 +824,7 @@  extern (C++) final class Module : Package
 
         const(char)* srcname = srcfile.toChars();
         //printf("Module::parse(srcname = '%s')\n", srcname);
-        isPackageFile = (strcmp(srcfile.name(), package_d) == 0 ||
-                         strcmp(srcfile.name(), package_di) == 0);
+        isPackageFile = isPackageFileName(srcfile);
         const(char)[] buf = cast(const(char)[]) this.src;
 
         bool needsReencoding = true;
@@ -1032,8 +1031,7 @@  extern (C++) final class Module : Package
             }
             assert(dst);
             Module m = ppack ? ppack.isModule() : null;
-            if (m && (strcmp(m.srcfile.name(), package_d) != 0 &&
-                      strcmp(m.srcfile.name(), package_di) != 0))
+            if (m && !isPackageFileName(m.srcfile))
             {
                 .error(md.loc, "package name '%s' conflicts with usage as a module name in file %s", ppack.toPrettyChars(), m.srcfile.toChars());
             }
diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d
index 2b608f6974c..c940ff06c67 100644
--- a/gcc/d/dmd/dsymbol.d
+++ b/gcc/d/dmd/dsymbol.d
@@ -2441,6 +2441,15 @@  Dsymbol handleTagSymbols(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsymbol sds)
     auto sd = s.isScopeDsymbol(); // new declaration
     auto sd2 = s2.isScopeDsymbol(); // existing declaration
 
+    static if (log) void print(EnumDeclaration sd)
+    {
+        printf("members: %p\n", sd.members);
+        printf("symtab: %p\n", sd.symtab);
+        printf("endlinnum: %d\n", sd.endlinnum);
+        printf("type: %s\n", sd.type.toChars());
+        printf("memtype: %s\n", sd.memtype.toChars());
+    }
+
     if (!sd2)
     {
         /* Look in tag table
@@ -2473,6 +2482,23 @@  Dsymbol handleTagSymbols(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsymbol sds)
         {
             sd2.members = sd.members; // transfer definition to sd2
             sd.members = null;
+            if (auto ed2 = sd2.isEnumDeclaration())
+            {
+                auto ed = sd.isEnumDeclaration();
+                if (ed.memtype != ed2.memtype)
+                    return null;        // conflict
+
+                // transfer ed's members to sd2
+                ed2.members.foreachDsymbol( (s)
+                {
+                    if (auto em = s.isEnumMember())
+                        em.ed = ed2;
+                });
+
+                ed2.type = ed.type;
+                ed2.memtype = ed.memtype;
+                ed2.added = false;
+            }
             return sd2;
         }
         else
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index 11a51f10e99..7f57cbe12ca 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -2023,7 +2023,7 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
     override void visit(EnumDeclaration ed)
     {
         //printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc.scopesym, sc.scopesym.toChars(), ed.toChars());
-        //printf("EnumDeclaration::semantic() %p %s\n", this, ed.toChars());
+        //printf("EnumDeclaration::semantic() %p %s\n", ed, ed.toChars());
         if (ed.semanticRun >= PASS.semanticdone)
             return; // semantic() already completed
         if (ed.semanticRun == PASS.semantic)
@@ -4442,7 +4442,10 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
              invd.semanticRun < PASS.semantic &&
              !ad.isUnionDeclaration()           // users are on their own with union fields
            )
+        {
+            invd.fixupInvariantIdent(ad.invs.length);
             ad.invs.push(invd);
+        }
         if (!invd.type)
             invd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, invd.storage_class);
 
@@ -5713,6 +5716,7 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
  */
 void addEnumMembers(EnumDeclaration ed, Scope* sc, ScopeDsymbol sds)
 {
+    //printf("addEnumMembers(ed: %p)\n", ed);
     if (ed.added)
         return;
     ed.added = true;
@@ -5736,6 +5740,7 @@  void addEnumMembers(EnumDeclaration ed, Scope* sc, ScopeDsymbol sds)
             em.ed = ed;
             if (isCEnum)
             {
+                //printf("adding EnumMember %s to %p\n", em.toChars(), ed);
                 em.addMember(sc, ed);   // add em to ed's symbol table
                 em.addMember(sc, sds);  // add em to symbol table that ed is in
                 em.parent = ed; // restore it after previous addMember() changed it
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index c0a8e9f4664..02f12e42570 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -7323,7 +7323,7 @@  extern (C++) class TemplateInstance : ScopeDsymbol
                         errors = true;
                     }
                 L1:
-                    //printf("\tnested inside %s\n", enclosing.toChars());
+                    //printf("\tnested inside %s as it references %s\n", enclosing.toChars(), sa.toChars());
                     nested |= 1;
                 }
             }
diff --git a/gcc/d/dmd/entity.d b/gcc/d/dmd/entity.d
index ef2fdef02f4..c29d4999f26 100644
--- a/gcc/d/dmd/entity.d
+++ b/gcc/d/dmd/entity.d
@@ -17,18 +17,27 @@  import core.stdc.ctype;
 
 nothrow:
 
-public int HtmlNamedEntity(const(char)* p, size_t length)
+/**********************************
+ * See if `name` is an HTML Named Entity
+ * Params:
+ *      name = name of the entity
+ * Returns:
+ *      code point corresponding to the named entity
+ *      ~0 for not recognized as a named entity
+ */
+public uint HtmlNamedEntity(scope const char[] name) pure @nogc @safe
 {
-    int tableIndex = tolower(*p) - 'a';
-    if (tableIndex >= 0 && tableIndex < 26)
+    const firstC = tolower(name[0]);
+    if (firstC >= 'a' && firstC <= 'z')
     {
-        foreach (entity; namesTable[tableIndex])
+        // Linear search (use hash table instead?)
+        foreach (entity; namesTable[firstC - 'a'])
         {
-            if (entity.name == p[0 .. length])
+            if (entity.name == name)
                 return entity.value;
         }
     }
-    return -1;
+    return ~0;
 }
 
 private:
diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d
index 0646f57c5cd..fb5e092d25b 100644
--- a/gcc/d/dmd/escape.d
+++ b/gcc/d/dmd/escape.d
@@ -351,7 +351,7 @@  bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Parameter par, STC
         {
             unsafeAssign!"scope variable"(v);
         }
-        else if (v.storage_class & STC.variadic && p == sc.func)
+        else if (v.isTypesafeVariadicParameter && p == sc.func)
         {
             Type tb = v.type.toBasetype();
             if (tb.ty == Tarray || tb.ty == Tsarray)
@@ -649,7 +649,8 @@  bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
         Dsymbol p = v.toParent2();
 
         if (va && !vaIsRef && !va.isScope() && !v.isScope() &&
-            (va.storage_class & v.storage_class & (STC.maybescope | STC.variadic)) == STC.maybescope &&
+            !v.isTypesafeVariadicParameter && !va.isTypesafeVariadicParameter &&
+            (va.storage_class & v.storage_class & STC.maybescope) &&
             p == fd)
         {
             /* Add v to va's list of dependencies
@@ -663,7 +664,8 @@  bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
             !(v.storage_class & STC.return_) &&
             v.isParameter() &&
             fd.flags & FUNCFLAG.returnInprocess &&
-            p == fd)
+            p == fd &&
+            !v.isTypesafeVariadicParameter)
         {
             if (log) printf("inferring 'return' for parameter %s in function %s\n", v.toChars(), fd.toChars());
             inferReturn(fd, v, /*returnScope:*/ true); // infer addition of 'return' to make `return scope`
@@ -735,7 +737,7 @@  bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
             }
             result |= sc.setUnsafeDIP1000(gag, ae.loc, "scope variable `%s` assigned to non-scope `%s`", v, e1);
         }
-        else if (v.storage_class & STC.variadic && p == fd)
+        else if (v.isTypesafeVariadicParameter && p == fd)
         {
             Type tb = v.type.toBasetype();
             if (tb.ty == Tarray || tb.ty == Tsarray)
@@ -1022,7 +1024,7 @@  bool checkNewEscape(Scope* sc, Expression e, bool gag)
                 continue;
             }
         }
-        else if (v.storage_class & STC.variadic && p == sc.func)
+        else if (v.isTypesafeVariadicParameter && p == sc.func)
         {
             Type tb = v.type.toBasetype();
             if (tb.ty == Tarray || tb.ty == Tsarray)
@@ -1194,7 +1196,8 @@  private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
             v.isParameter() &&
             !v.doNotInferReturn &&
             sc.func.flags & FUNCFLAG.returnInprocess &&
-            p == sc.func)
+            p == sc.func &&
+            !v.isTypesafeVariadicParameter)
         {
             inferReturn(sc.func, v, /*returnScope:*/ true); // infer addition of 'return'
             continue;
@@ -1250,7 +1253,7 @@  private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
                 }
             }
         }
-        else if (v.storage_class & STC.variadic && p == sc.func)
+        else if (v.isTypesafeVariadicParameter && p == sc.func)
         {
             Type tb = v.type.toBasetype();
             if (tb.ty == Tarray || tb.ty == Tsarray)
@@ -1627,7 +1630,7 @@  void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
             {
                 if (tb.ty == Tsarray)
                     return;
-                if (v.storage_class & STC.variadic)
+                if (v.isTypesafeVariadicParameter)
                 {
                     er.byvalue.push(v);
                     return;
@@ -1943,7 +1946,7 @@  void escapeByRef(Expression e, EscapeByResults* er, bool live = false, bool retR
             VarDeclaration v = ve.var.isVarDeclaration();
             if (tb.ty == Tarray || tb.ty == Tsarray)
             {
-                if (v && v.storage_class & STC.variadic)
+                if (v && v.isTypesafeVariadicParameter)
                 {
                     er.pushRef(v, retRefTransition);
                     return;
@@ -2586,3 +2589,15 @@  private bool checkScopeVarAddr(VarDeclaration v, Expression e, Scope* sc, bool g
     return sc.setUnsafeDIP1000(gag, e.loc,
         "cannot take address of `scope` variable `%s` since `scope` applies to first indirection only", v);
 }
+
+/****************************
+ * Determine if `v` is a typesafe variadic parameter.
+ * Params:
+ *      v = variable to check
+ * Returns:
+ *      true if `v` is a variadic parameter
+ */
+bool isTypesafeVariadicParameter(VarDeclaration v)
+{
+    return !!(v.storage_class & STC.variadic);
+}
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index 35ba5fa83ed..30baabdad52 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -3463,8 +3463,17 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
         if (!exp.arguments && exp.newtype.isTypeSArray())
         {
             auto ts = exp.newtype.isTypeSArray();
-            edim = ts.dim;
-            exp.newtype = ts.next;
+            // check `new Value[Key]`
+            ts.dim = ts.dim.expressionSemantic(sc);
+            if (ts.dim.op == EXP.type)
+            {
+                exp.newtype = new TypeAArray(ts.next, ts.dim.isTypeExp().type);
+            }
+            else
+            {
+                edim = ts.dim;
+                exp.newtype = ts.next;
+            }
         }
 
         ClassDeclaration cdthis = null;
@@ -3518,18 +3527,7 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
         {
             return setError();
         }
-        //https://issues.dlang.org/show_bug.cgi?id=20547
-        //exp.arguments are the "parameters" to [], not to a real function
-        //so the errors that come from preFunctionParameters are misleading
-        if (originalNewtype.ty == Tsarray)
-        {
-            if (preFunctionParameters(sc, exp.arguments, false))
-            {
-                exp.error("cannot create a `%s` with `new`", originalNewtype.toChars());
-                return setError();
-            }
-        }
-        else if (preFunctionParameters(sc, exp.arguments))
+        if (preFunctionParameters(sc, exp.arguments))
         {
             return setError();
         }
@@ -3885,6 +3883,15 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
             exp.type = exp.type.pointerTo();
         }
+        else if (tb.ty == Taarray)
+        {
+            // e.g. `new Alias(args)`
+            if (nargs)
+            {
+                exp.error("`new` cannot take arguments for an associative array");
+                return setError();
+            }
+        }
         else
         {
             exp.error("cannot create a `%s` with `new`", exp.type.toChars());
@@ -5019,7 +5026,8 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
                         sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
                     err = true;
                 }
-                if (tf.trust <= TRUST.system && sc.setUnsafe())
+                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`",
                         sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
@@ -7588,11 +7596,20 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
         }
 
         // Check for unsafe casts
-        if (!isSafeCast(ex, t1b, tob) &&
-            (!sc.func && sc.stc & STC.safe || sc.setUnsafe()))
+        if (!isSafeCast(ex, t1b, tob))
         {
-            exp.error("cast from `%s` to `%s` not allowed in safe code", exp.e1.type.toChars(), exp.to.toChars());
-            return setError();
+            // This is an ad-hoc fix for https://issues.dlang.org/show_bug.cgi?id=19646
+            // Should be replaced by a more general @system variables implementation
+            if (!sc.func && sc.stc & STC.safe)
+            {
+                exp.error("cast from `%s` to `%s` not allowed in safe code", exp.e1.type.toChars(), exp.to.toChars());
+                return setError();
+            }
+
+            if (sc.setUnsafe(false, exp.loc, "cast from `%s` to `%s` not allowed in safe code", exp.e1.type, exp.to))
+            {
+                return setError();
+            }
         }
 
         // `object.__ArrayCast` is a rewrite of an old runtime hook `_d_arraycast`. `_d_arraycast` was not built
@@ -8900,6 +8917,15 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
             if ((t1.ty != Tstruct && t1.ty != Tclass && e2x.checkValue()) ||
                 e2x.checkSharedAccess(sc))
                 return setError();
+
+            if (e2x.type.isTypeNoreturn() && !e2x.isAssertExp() && !e2x.isThrowExp() && !e2x.isCallExp())
+            {
+                auto msg = new StringExp(e2x.loc, "Accessed expression of type `noreturn`");
+                msg.type = Type.tstring;
+                e2x = new AssertExp(e2x.loc, IntegerExp.literal!0, msg);
+                e2x.type = Type.tnoreturn;
+                return setResult(e2x);
+            }
             exp.e2 = e2x;
         }
 
@@ -9896,9 +9922,11 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 ae.e2.type.nextOf &&
                 ae.e1.type.nextOf.mutableOf.equals(ae.e2.type.nextOf.mutableOf);
 
+            /* Unlike isArrayCtor above, lower all Rvalues. If the RHS is a literal,
+             * then we do want to make a temporary for it and call its destructor.
+             */
             const isArraySetCtor =
                 (ae.e1.isSliceExp || ae.e1.type.ty == Tsarray) &&
-                ae.e2.isLvalue &&
                 (ae.e2.type.ty == Tstruct || ae.e2.type.ty == Tsarray) &&
                 ae.e1.type.nextOf &&
                 ae.e1.type.nextOf.equivalent(ae.e2.type);
@@ -10302,6 +10330,8 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     // `__appendtmp*` will be destroyed together with the array `exp.e1`.
                     auto vd = eValue2.isDeclarationExp().declaration.isVarDeclaration();
                     vd.storage_class |= STC.nodtor;
+                    // Be more explicit that this "declaration" is local to the expression
+                    vd.storage_class |= STC.exptemp;
                 }
 
                 auto ale = new ArrayLengthExp(exp.loc, value1);
@@ -11870,6 +11900,17 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
         {
             //printf("Lowering to __equals %s %s\n", exp.e1.toChars(), exp.e2.toChars());
 
+            // https://issues.dlang.org/show_bug.cgi?id=22390
+            // Equality comparison between array of noreturns simply lowers to length equality comparison
+            if (t1.nextOf.isTypeNoreturn() && t2.nextOf.isTypeNoreturn())
+            {
+                Expression exp_l1 = new DotIdExp(exp.e1.loc, exp.e1, Id.length);
+                Expression exp_l2 = new DotIdExp(exp.e2.loc, exp.e2, Id.length);
+                auto e = new EqualExp(EXP.equal, exp.loc, exp_l1, exp_l2);
+                result = e.expressionSemantic(sc);
+                return;
+            }
+
             if (!verifyHookExist(exp.loc, *sc, Id.__equals, "equal checks on arrays"))
                 return setError();
 
@@ -12638,7 +12679,7 @@  Expression semanticY(DotIdExp exp, Scope* sc, int flag)
                     e = new CommaExp(exp.loc, eleft, e);
                     e.type = Type.tvoid; // ambiguous type?
                 }
-                return e;
+                return e.expressionSemantic(sc);
             }
             if (auto o = s.isOverloadSet())
             {
@@ -13131,26 +13172,24 @@  bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)
 bool checkAddressVar(Scope* sc, Expression exp, VarDeclaration v)
 {
     //printf("checkAddressVar(exp: %s, v: %s)\n", exp.toChars(), v.toChars());
-    if (v)
+    if (v is null)
+        return true;
+
+    if (!v.canTakeAddressOf())
+    {
+        exp.error("cannot take address of `%s`", exp.toChars());
+        return false;
+    }
+    if (sc.func && !sc.intypeof && !v.isDataseg())
     {
-        if (!v.canTakeAddressOf())
+        v.storage_class &= ~STC.maybescope;
+        v.doNotInferScope = true;
+        if (global.params.useDIP1000 != FeatureState.enabled &&
+            !(v.storage_class & STC.temp) &&
+            sc.setUnsafe(false, exp.loc, "cannot take address of local `%s` in `@safe` function `%s`", v, sc.func))
         {
-            exp.error("cannot take address of `%s`", exp.toChars());
             return false;
         }
-        if (sc.func && !sc.intypeof && !v.isDataseg())
-        {
-            const(char)* p = v.isParameter() ? "parameter" : "local";
-            v.storage_class &= ~STC.maybescope;
-            v.doNotInferScope = true;
-            if (global.params.useDIP1000 != FeatureState.enabled &&
-                !(v.storage_class & STC.temp) &&
-                sc.setUnsafe())
-            {
-                exp.error("cannot take address of %s `%s` in `@safe` function `%s`", p, v.toChars(), sc.func.toChars());
-                return false;
-            }
-        }
     }
     return true;
 }
diff --git a/gcc/d/dmd/file_manager.d b/gcc/d/dmd/file_manager.d
index 9fe40bf0603..0ea73036a78 100644
--- a/gcc/d/dmd/file_manager.d
+++ b/gcc/d/dmd/file_manager.d
@@ -20,6 +20,12 @@  import dmd.identifier;
 enum package_d  = "package." ~ mars_ext;
 enum package_di = "package." ~ hdr_ext;
 
+/// Returns: whether a file with `name` is a special "package.d" module
+bool isPackageFileName(scope FileName fileName) nothrow
+{
+    return FileName.equals(fileName.name, package_d) || FileName.equals(fileName.name, package_di);
+}
+
 final class FileManager
 {
     private StringTable!(const(ubyte)[]) files;
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index 83bc2eab1fe..7475cb4f9f5 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -867,6 +867,8 @@  extern (C++) class FuncDeclaration : Declaration
             auto f = s.isFuncDeclaration();
             if (!f)
                 return 0;
+            if (f.storage_class & STC.disable)
+                return 0;
             if (t.equals(f.type))
             {
                 fd = f;
@@ -2048,9 +2050,11 @@  extern (C++) class FuncDeclaration : Declaration
                     }
                     if (!found)
                     {
-                        //printf("\tadding sibling %s\n", fdthis.toPrettyChars());
+                        //printf("\tadding sibling %s to %s\n", fdthis.toPrettyChars(), toPrettyChars());
                         if (!sc.intypeof && !(sc.flags & SCOPE.compile))
+                        {
                             siblingCallers.push(fdthis);
+                        }
                     }
                 }
 
@@ -2164,7 +2168,6 @@  extern (C++) class FuncDeclaration : Declaration
         return false;
 
     Lyes:
-        //printf("\tneeds closure\n");
         return true;
     }
 
@@ -2176,14 +2179,21 @@  extern (C++) class FuncDeclaration : Declaration
      * Returns:
      *      true if any errors occur.
      */
-    extern (D) final bool checkClosure()
+    extern (C++) final bool checkClosure()
     {
+        //printf("checkClosure() %s\n", toChars());
         if (!needsClosure())
             return false;
 
         if (setGC())
         {
-            error("is `@nogc` yet allocates closures with the GC");
+            error("is `@nogc` yet allocates closure for `%s()` with the GC", toChars());
+            if (global.gag)     // need not report supplemental errors
+                return true;
+        }
+        else if (global.params.betterC)
+        {
+            error("is `-betterC` yet allocates closure for `%s()` with the GC", toChars());
             if (global.gag)     // need not report supplemental errors
                 return true;
         }
@@ -2216,7 +2226,7 @@  extern (C++) class FuncDeclaration : Declaration
                                 break LcheckAncestorsOfANestedRef;
                         }
                         a.push(f);
-                        .errorSupplemental(f.loc, "%s closes over variable %s at %s",
+                        .errorSupplemental(f.loc, "`%s` closes over variable `%s` at %s",
                             f.toPrettyChars(), v.toChars(), v.loc.toChars());
                         break LcheckAncestorsOfANestedRef;
                     }
@@ -3293,7 +3303,8 @@  FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
                    td.kind(), td.parent.toPrettyChars(), td.ident.toChars(),
                    tiargsBuf.peekChars(), fargsBuf.peekChars());
 
-            printCandidates(loc, td, sc.isDeprecated());
+            if (!global.gag || global.params.showGaggedErrors)
+                printCandidates(loc, td, sc.isDeprecated());
             return null;
         }
         /* This case used to happen when several ctors are mixed in an agregate.
@@ -3331,7 +3342,8 @@  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());
-            printCandidates(loc, fd, sc.isDeprecated());
+            if (!global.gag || global.params.showGaggedErrors)
+                printCandidates(loc, fd, sc.isDeprecated());
             return null;
         }
 
@@ -3361,18 +3373,23 @@  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());
-        printCandidates(loc, fd, sc.isDeprecated());
+        if (!global.gag || global.params.showGaggedErrors)
+            printCandidates(loc, fd, sc.isDeprecated());
         return null;
     }
 
     .error(loc, "%s `%s%s%s` is not callable using argument types `%s`",
            fd.kind(), fd.toPrettyChars(), parametersTypeToChars(tf.parameterList),
            tf.modToChars(), fargsBuf.peekChars());
+
     // re-resolve to check for supplemental message
-    const(char)* failMessage;
-    functionResolve(m, orig_s, loc, sc, tiargs, tthis, fargs, &failMessage);
-    if (failMessage)
-        errorSupplemental(loc, failMessage);
+    if (!global.gag || global.params.showGaggedErrors)
+    {
+        const(char)* failMessage;
+        functionResolve(m, orig_s, loc, sc, tiargs, tthis, fargs, &failMessage);
+        if (failMessage)
+            errorSupplemental(loc, failMessage);
+    }
     return null;
 }
 
@@ -4220,6 +4237,7 @@  extern (C++) final class InvariantDeclaration : FuncDeclaration
 {
     extern (D) this(const ref Loc loc, const ref Loc endloc, StorageClass stc, Identifier id, Statement fbody)
     {
+        // Make a unique invariant for now; we'll fix it up as we add it to the aggregate invariant list.
         super(loc, endloc, id ? id : Identifier.generateId("__invariant"), stc, null);
         this.fbody = fbody;
     }
@@ -4256,6 +4274,15 @@  extern (C++) final class InvariantDeclaration : FuncDeclaration
     {
         v.visit(this);
     }
+
+    extern (D) void fixupInvariantIdent(size_t offset)
+    {
+        OutBuffer idBuf;
+        idBuf.writestring("__invariant");
+        idBuf.print(offset);
+
+        ident = Identifier.idPool(idBuf[]);
+    }
 }
 
 
@@ -4447,12 +4474,15 @@  void errorSupplementalInferredSafety(FuncDeclaration fd, int maxDepth, bool depr
             errorFunc(s.loc, s.fmtStr,
                 s.arg0 ? s.arg0.toChars() : "", s.arg1 ? s.arg1.toChars() : "", s.arg2 ? s.arg2.toChars() : "");
         }
-        else if (FuncDeclaration fd2 = cast(FuncDeclaration) s.arg0)
+        else if (s.arg0.dyncast() == DYNCAST.dsymbol)
         {
-            if (maxDepth > 0)
+            if (FuncDeclaration fd2 = (cast(Dsymbol) s.arg0).isFuncDeclaration())
             {
-                errorFunc(s.loc, "which calls `%s`", fd2.toPrettyChars());
-                errorSupplementalInferredSafety(fd2, maxDepth - 1, deprecation);
+                if (maxDepth > 0)
+                {
+                    errorFunc(s.loc, "which calls `%s`", fd2.toPrettyChars());
+                    errorSupplementalInferredSafety(fd2, maxDepth - 1, deprecation);
+                }
             }
         }
     }
diff --git a/gcc/d/dmd/impcnvtab.d b/gcc/d/dmd/impcnvtab.d
index ab46f5eebbd..832c331c314 100644
--- a/gcc/d/dmd/impcnvtab.d
+++ b/gcc/d/dmd/impcnvtab.d
@@ -64,6 +64,57 @@  enum ImpCnvTab impCnvTab = generateImpCnvTab();
 
 ImpCnvTab generateImpCnvTab()
 {
+    TY[TMAX] typeTYs =
+    [
+        Tarray,
+        Tsarray,
+        Taarray,
+        Tpointer,
+        Treference,
+        Tfunction,
+        Tident,
+        Tclass,
+        Tstruct,
+        Tenum,
+        Tdelegate,
+        Tnone,
+        Tvoid,
+        Tint8,
+        Tuns8,
+        Tint16,
+        Tuns16,
+        Tint32,
+        Tuns32,
+        Tint64,
+        Tuns64,
+        Tfloat32,
+        Tfloat64,
+        Tfloat80,
+        Timaginary32,
+        Timaginary64,
+        Timaginary80,
+        Tcomplex32,
+        Tcomplex64,
+        Tcomplex80,
+        Tbool,
+        Tchar,
+        Twchar,
+        Tdchar,
+        Terror,
+        Tinstance,
+        Ttypeof,
+        Ttuple,
+        Tslice,
+        Treturn,
+        Tnull,
+        Tvector,
+        Tint128,
+        Tuns128,
+        Ttraits,
+        Tmixin,
+        Tnoreturn,
+        Ttag,
+    ];
     ImpCnvTab impCnvTab;
 
     // Set conversion tables
@@ -375,5 +426,9 @@  ImpCnvTab generateImpCnvTab()
 
     X(Tcomplex80,Tcomplex80,  Tcomplex80,Tcomplex80, Tcomplex80);
 
+    // "No type is implicitly convertible to noreturn, but noreturn is implicitly convertible to every other type"
+    foreach(convertToTy; typeTYs)
+        X(Tnoreturn, convertToTy, convertToTy, convertToTy, convertToTy);
+
     return impCnvTab;
 }
diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d
index a1963dabcdc..a5767127104 100644
--- a/gcc/d/dmd/initsem.d
+++ b/gcc/d/dmd/initsem.d
@@ -567,18 +567,40 @@  extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
                     i.exp = e.optimize(WANTvalue);
             }
         }
+
+        // Look for the case of statically initializing an array with a single member.
+        // Recursively strip static array / enum layers until a compatible element is found,
+        // and return an `ArrayLiteralExp` repeating the initializer, or `null` if no match found
+        // int[2][3] = 7       => [[7, 7], [7, 7], [7, 7]]
+        // int[2] = new Object => null
+        Expression sarrayRepeat(Type tb)
         {
-        // Look for the case of statically initializing an array
-        // with a single member.
-        auto tba = tb.isTypeSArray();
-        if (tba && !tba.next.equals(ti.toBasetype().nextOf()) && i.exp.implicitConvTo(tba.next))
+            auto tsa = tb.isTypeSArray();
+            if (!tsa)
+                return null;
+
+            // printf("i.exp = %s, tsa = %s\n", i.exp.toChars(), tsa.toChars());
+            Expression elem = null;
+            if (i.exp.implicitConvTo(tb.nextOf()))
+                elem = i.exp.implicitCastTo(sc, tb.nextOf());
+            else if (auto ae = sarrayRepeat(tb.nextOf().toBasetype()))
+                elem = ae;
+            else
+                return null;
+
+            auto arrayElements = new Expressions(cast(size_t) tsa.dim.toInteger());
+            foreach (ref e; *arrayElements)
+                e = elem;
+            return new ArrayLiteralExp(i.exp.loc, tb, elem, arrayElements);
+        }
+
+        if (auto sa = sarrayRepeat(tb))
         {
-            /* If the variable is not actually used in compile time, array creation is
-             * redundant. So delay it until invocation of toExpression() or toDt().
-             */
-            t = tb.nextOf();
+            // printf("sa = %s\n", sa.toChars());
+            i.exp = sa;
         }
 
+        {
         auto tta = t.isTypeSArray();
         if (i.exp.implicitConvTo(t))
         {
@@ -595,6 +617,7 @@  extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
         }
         else
         {
+            auto tba = tb.isTypeSArray();
             // Look for mismatch of compile-time known length to emit
             // better diagnostic message, as same as AssignExp::semantic.
             if (tba && i.exp.implicitConvTo(tba.next.arrayOf()) > MATCH.nomatch)
diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d
index ef918e275d0..11afcdd9f0b 100644
--- a/gcc/d/dmd/lexer.d
+++ b/gcc/d/dmd/lexer.d
@@ -1326,7 +1326,7 @@  class Lexer
                 switch (*p)
                 {
                 case ';':
-                    c = HtmlNamedEntity(idstart, p - idstart);
+                    c = HtmlNamedEntity(idstart[0 .. p - idstart]);
                     if (c == ~0)
                     {
                         error(loc, "unnamed character entity &%.*s;", cast(int)(p - idstart), idstart);
diff --git a/gcc/d/dmd/mustuse.d b/gcc/d/dmd/mustuse.d
index 4eb422805db..369d60e208a 100644
--- a/gcc/d/dmd/mustuse.d
+++ b/gcc/d/dmd/mustuse.d
@@ -98,7 +98,7 @@  void checkMustUseReserved(Dsymbol sym)
  */
 private bool isAssignment(Expression e)
 {
-    if (e.isAssignExp || e.isBinAssignExp)
+    if (e.isAssignExp || e.isBinAssignExp || e.isConstructExp || e.isBlitExp)
         return true;
     if (auto ce = e.isCallExp())
     {
diff --git a/gcc/d/dmd/optimize.d b/gcc/d/dmd/optimize.d
index 2b7b9ac1013..be28d082405 100644
--- a/gcc/d/dmd/optimize.d
+++ b/gcc/d/dmd/optimize.d
@@ -1120,7 +1120,7 @@  Expression Expression_optimize(Expression e, int result, bool keepLvalue)
                     e.e1 = ci;
             }
         }
-        if (e.e1.op == EXP.string_ || e.e1.op == EXP.arrayLiteral || e.e1.op == EXP.assocArrayLiteral || e.e1.type.toBasetype().ty == Tsarray)
+        if (e.e1.op == EXP.string_ || e.e1.op == EXP.arrayLiteral || e.e1.op == EXP.assocArrayLiteral || e.e1.type.toBasetype().ty == Tsarray || e.e1.op == EXP.null_)
         {
             ret = ArrayLength(e.type, e.e1).copy();
         }
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index 4e3fd533c18..a2c364e7e15 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -2186,7 +2186,13 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         if (token.value == TOK.identifier)
             s = new AST.DebugSymbol(token.loc, token.ident);
         else if (token.value == TOK.int32Literal || token.value == TOK.int64Literal)
+        {
+            // @@@DEPRECATED_2.111@@@
+            // Deprecated in 2.101, remove in 2.111
+            deprecation("`debug = <integer>` is deprecated, use debug identifiers instead");
+
             s = new AST.DebugSymbol(token.loc, cast(uint)token.unsvalue);
+        }
         else
         {
             error("identifier or integer expected, not `%s`", token.toChars());
@@ -2215,7 +2221,13 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             if (token.value == TOK.identifier)
                 id = token.ident;
             else if (token.value == TOK.int32Literal || token.value == TOK.int64Literal)
+            {
+                // @@@DEPRECATED_2.111@@@
+                // Deprecated in 2.101, remove in 2.111
+                deprecation("`debug( <integer> )` is deprecated, use debug identifiers instead");
+
                 level = cast(uint)token.unsvalue;
+            }
             else
                 error("identifier or integer expected inside `debug(...)`, not `%s`", token.toChars());
             loc = token.loc;
@@ -2235,7 +2247,12 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         if (token.value == TOK.identifier)
             s = new AST.VersionSymbol(token.loc, token.ident);
         else if (token.value == TOK.int32Literal || token.value == TOK.int64Literal)
+        {
+            // @@@DEPRECATED_2.111@@@
+            // Deprecated in 2.101, remove in 2.111
+            deprecation("`version = <integer>` is deprecated, use version identifiers instead");
             s = new AST.VersionSymbol(token.loc, cast(uint)token.unsvalue);
+        }
         else
         {
             error("identifier or integer expected, not `%s`", token.toChars());
@@ -2269,7 +2286,13 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             if (token.value == TOK.identifier)
                 id = token.ident;
             else if (token.value == TOK.int32Literal || token.value == TOK.int64Literal)
+            {
+                // @@@DEPRECATED_2.111@@@
+                // Deprecated in 2.101, remove in 2.111
+                deprecation("`version( <integer> )` is deprecated, use version identifiers instead");
+
                 level = cast(uint)token.unsvalue;
+            }
             else if (token.value == TOK.unittest_)
                 id = Identifier.idPool(Token.toString(TOK.unittest_));
             else if (token.value == TOK.assert_)
@@ -9312,13 +9335,10 @@  LagainStc:
         {
             AST.TypeAArray taa = cast(AST.TypeAArray)t;
             AST.Type index = taa.index;
+            // `new Type[expr]` is a static array
             auto edim = AST.typeToExpression(index);
-            if (!edim)
-            {
-                error("cannot create a `%s` with `new`", t.toChars);
-                return new AST.NullExp(loc);
-            }
-            t = new AST.TypeSArray(taa.next, edim);
+            if (edim)
+                t = new AST.TypeSArray(taa.next, edim);
         }
         else if (token.value == TOK.leftParenthesis && t.ty != Tsarray)
         {
diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d
index c5d7667fefc..6f377700efc 100644
--- a/gcc/d/dmd/semantic3.d
+++ b/gcc/d/dmd/semantic3.d
@@ -470,14 +470,6 @@  private extern(C++) final class Semantic3Visitor : Visitor
                     if (f.parameterList.varargs == VarArg.typesafe && i + 1 == nparams)
                     {
                         stc |= STC.variadic;
-                        auto vtypeb = vtype.toBasetype();
-                        if (vtypeb.ty == Tarray || vtypeb.ty == Tclass)
-                        {
-                            /* Since it'll be pointing into the stack for the array
-                             * contents, it needs to be `scope`
-                             */
-                            stc |= STC.scope_;
-                        }
                     }
 
                     if ((funcdecl.flags & FUNCFLAG.inferScope) && !(fparam.storageClass & STC.scope_))
@@ -1379,7 +1371,7 @@  private extern(C++) final class Semantic3Visitor : Visitor
             funcdecl.flags &= ~FUNCFLAG.semantic3Errors;
         if (funcdecl.type.ty == Terror)
             funcdecl.errors = true;
-        //printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent.toChars(), toChars(), sc, loc.toChars());
+        //printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", funcdecl.parent.toChars(), funcdecl.toChars(), sc, funcdecl.loc.toChars());
         //fflush(stdout);
     }
 
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index f23b9882ae0..e5e57535b37 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -733,9 +733,26 @@  package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
         {
             assert(oaggr.type);
 
-            fs.error("invalid `foreach` aggregate `%s` of type `%s`", oaggr.toChars(), oaggr.type.toPrettyChars());
-            if (isAggregate(fs.aggr.type))
-                fs.loc.errorSupplemental("maybe define `opApply()`, range primitives, or use `.tupleof`");
+            fs.error("invalid `%s` aggregate `%s` of type `%s`",
+                Token.toChars(fs.op), oaggr.toChars(), oaggr.type.toPrettyChars());
+
+            if (auto ad = isAggregate(fs.aggr.type))
+            {
+                if (fs.op == TOK.foreach_reverse_)
+                {
+                    fs.loc.errorSupplemental("`foreach_reverse` works with bidirectional ranges"~
+                        " (implementing `back` and `popBack`), aggregates implementing" ~
+                        " `opApplyReverse`, or the result of an aggregate's `.tupleof` property");
+                    fs.loc.errorSupplemental("https://dlang.org/phobos/std_range_primitives.html#isBidirectionalRange");
+                }
+                else
+                {
+                    fs.loc.errorSupplemental("`foreach` works with input ranges"~
+                        " (implementing `front` and `popFront`), aggregates implementing" ~
+                        " `opApply`, or the result of an aggregate's `.tupleof` property");
+                    fs.loc.errorSupplemental("https://dlang.org/phobos/std_range_primitives.html#isInputRange");
+                }
+            }
 
             return setError();
         }
@@ -2828,10 +2845,20 @@  package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
             rs.error("`return` statements cannot be in contracts");
             errors = true;
         }
-        if (sc.os && sc.os.tok != TOK.onScopeFailure)
+        if (sc.os)
         {
-            rs.error("`return` statements cannot be in `%s` bodies", Token.toChars(sc.os.tok));
-            errors = true;
+            // @@@DEPRECATED_2.112@@@
+            // Deprecated in 2.100, transform into an error in 2.112
+            if (sc.os.tok == TOK.onScopeFailure)
+            {
+                rs.deprecation("`return` statements cannot be in `scope(failure)` bodies.");
+                deprecationSupplemental(rs.loc, "Use try-catch blocks for this purpose");
+            }
+            else
+            {
+                rs.error("`return` statements cannot be in `%s` bodies", Token.toChars(sc.os.tok));
+                errors = true;
+            }
         }
         if (sc.tf)
         {
@@ -2913,6 +2940,17 @@  package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
                     rs.exp.type = texp;
                 }
 
+                // @@@DEPRECATED_2.111@@@
+                const olderrors = global.startGagging();
+                // uncomment to turn deprecation into an error when
+                // deprecation cycle is over
+                if (discardValue(rs.exp))
+                {
+                    //errors = true;
+                }
+                if (global.endGagging(olderrors))
+                    rs.exp.deprecation("`%s` has no effect", rs.exp.toChars());
+
                 /* Replace:
                  *      return exp;
                  * with:
diff --git a/gcc/d/dmd/transitivevisitor.d b/gcc/d/dmd/transitivevisitor.d
index 25dee7f4185..5791a885068 100644
--- a/gcc/d/dmd/transitivevisitor.d
+++ b/gcc/d/dmd/transitivevisitor.d
@@ -862,6 +862,12 @@  package mixin template ParseVisitMethods(AST)
         visitFuncBody(d);
     }
 
+    override void visit(AST.CtorDeclaration d)
+    {
+        //printf("Visiting CtorDeclaration\n");
+        visitFuncBody(d);
+    }
+
     override void visit(AST.StaticCtorDeclaration d)
     {
         //printf("Visiting StaticCtorDeclaration\n");
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index 0469b927316..b1f1b1fa167 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -1272,6 +1272,16 @@  extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
                     errors = true;
                 }
 
+                const bool isTypesafeVariadic = i + 1 == dim &&
+                                                tf.parameterList.varargs == VarArg.typesafe &&
+                                                (t.isTypeDArray() || t.isTypeClass());
+                if (isTypesafeVariadic)
+                {
+                    /* typesafe variadic arguments are constructed on the stack, so must be `scope`
+                     */
+                    fparam.storageClass |= STC.scope_ | STC.scopeinferred;
+                }
+
                 if (fparam.storageClass & STC.return_)
                 {
                     if (fparam.isReference())
@@ -1300,8 +1310,7 @@  extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
                         }
                     }
 
-                    if (i + 1 == dim && tf.parameterList.varargs == VarArg.typesafe &&
-                        (t.isTypeDArray() || t.isTypeClass()))
+                    if (isTypesafeVariadic)
                     {
                         /* This is because they can be constructed on the stack
                          * https://dlang.org/spec/function.html#typesafe_variadic_functions
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index 1bb10a835d2..40c2689a3b9 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -873,6 +873,17 @@  public:
 	gcc_unreachable ();
       }
 
+    /* Look for exp = noreturn;  */
+    if (e->e2->type->isTypeNoreturn ())
+      {
+	/* If the RHS is a `noreturn' expression, there is no point generating
+	   any code for the assignment, just evaluate side effects.  */
+	tree t1 = build_expr (e->e1);
+	tree t2 = build_expr (e->e2);
+	this->result_ = compound_expr (t1, t2);
+	return;
+      }
+
     /* Look for array[] = n;  */
     if (e->e1->op == EXP::slice)
       {
diff --git a/gcc/d/lang.opt b/gcc/d/lang.opt
index bd9c61d540d..da652396468 100644
--- a/gcc/d/lang.opt
+++ b/gcc/d/lang.opt
@@ -249,7 +249,7 @@  Compile in debug code.
 
 fdebug=
 D Joined RejectNegative
--fdebug=<level|ident>	Compile in debug code, code <= <level>, or code identified by <ident>.
+-fdebug=<ident>	Compile in debug code identified by <ident>.
 
 fdoc
 D
@@ -466,7 +466,7 @@  Compile in unittest code.
 
 fversion=
 D Joined RejectNegative
--fversion=<level|ident>	Compile in version code >= <level> or identified by <ident>.
+-fversion=<ident>	Compile in version code identified by <ident>.
 
 fweak-templates
 D Var(flag_weak_templates) Init(1)
diff --git a/gcc/testsuite/gdc.test/compilable/backendfloatoptim.d b/gcc/testsuite/gdc.test/compilable/backendfloatoptim.d
new file mode 100644
index 00000000000..7ec9f614ef8
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/backendfloatoptim.d
@@ -0,0 +1,10 @@ 
+// REQUIRED_ARGS: -O -inline
+
+//https://issues.dlang.org/show_bug.cgi?id=20143
+real fun(int x) { return 0.0; }
+
+double bug()
+{
+    // value passed to fun is irrelevant
+    return 0.0 / fun(420);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/cppmangle3.d b/gcc/testsuite/gdc.test/compilable/cppmangle3.d
index 93e49c72c18..82c68f7a3a5 100644
--- a/gcc/testsuite/gdc.test/compilable/cppmangle3.d
+++ b/gcc/testsuite/gdc.test/compilable/cppmangle3.d
@@ -45,16 +45,12 @@  alias Alias(T) = T;
 static assert(is(Alias!(__traits(parent, Foo.bar)) == Foo));
 
 extern(C++, "std"):
-debug = 456;
 debug = def;
-version = 456;
 version = def;
 
 extern(C++, "std")
 {
-    debug = 456;
     debug = def;
-    version = 456;
     version = def;
 }
 
diff --git a/gcc/testsuite/gdc.test/compilable/must_use_initialize.d b/gcc/testsuite/gdc.test/compilable/must_use_initialize.d
new file mode 100644
index 00000000000..8caec434bdc
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/must_use_initialize.d
@@ -0,0 +1,16 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=23236
+// can't initialize a @mustuse member in constructor
+
+import core.attribute;
+
+@mustuse struct MyError { }
+
+struct S
+{
+    MyError lastError;
+
+    this(int x)
+    {
+        this.lastError = MyError();
+    }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/noreturn1.d b/gcc/testsuite/gdc.test/compilable/noreturn1.d
index 5bba9baa72a..e648a56d896 100644
--- a/gcc/testsuite/gdc.test/compilable/noreturn1.d
+++ b/gcc/testsuite/gdc.test/compilable/noreturn1.d
@@ -122,3 +122,31 @@  noreturn testdg(noreturn delegate() dg)
 {
     dg();
 }
+
+noreturn func()
+{
+    while(1)
+    {
+    }
+}
+alias AliasSeq(T...) = T;
+alias Types = AliasSeq!(bool, byte, ubyte, short, ushort, int, uint,
+                        long, ulong, char, wchar, dchar, float, double,
+                        real);
+void noreturnImplicit()
+{
+    /*
+        Testing both ways because, although the underlying table
+        is symmetrical the code that calls into it may be buggy.
+    */
+    {
+        int x = 2 + func();
+        int y = func() + 2;
+    }
+    foreach(T; Types)
+    {
+        T value;
+        auto x = value + throw new Exception("Hello");
+        auto y = (throw new Exception("wow")) + value;
+    }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test20832.d b/gcc/testsuite/gdc.test/compilable/test20832.d
new file mode 100644
index 00000000000..25617a9a398
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test20832.d
@@ -0,0 +1,12 @@ 
+// PERMUTE_ARGS: -preview=dip1000
+// https://issues.dlang.org/show_bug.cgi?id=20823
+
+void boo(T)(  scope   void delegate(T[] data) fun) {}
+void goo(T)(/+scope+/ void delegate(T[] data) fun) {}
+
+void main()
+{
+    void Execute(int[] data) {}
+    goo(&Execute);
+    boo(&Execute);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test21177.d b/gcc/testsuite/gdc.test/compilable/test21177.d
index b3b613bc0e9..b485304c188 100644
--- a/gcc/testsuite/gdc.test/compilable/test21177.d
+++ b/gcc/testsuite/gdc.test/compilable/test21177.d
@@ -4,15 +4,19 @@  DISABLED: win
 TEST_OUTPUT:
 ---
 compilable/test21177.d(103): Deprecation: more format specifiers than 0 arguments
+compilable/test21177.d(111): Deprecation: more format specifiers than 0 arguments
 compilable/test21177.d(150): Deprecation: more format specifiers than 0 arguments
 compilable/test21177.d(151): Deprecation: more format specifiers than 0 arguments
 compilable/test21177.d(152): Deprecation: more format specifiers than 0 arguments
 compilable/test21177.d(153): Deprecation: more format specifiers than 0 arguments
-compilable/test21177.d(200): Deprecation: more format specifiers than 0 arguments
-compilable/test21177.d(203): Deprecation: format specifier `"%m"` is invalid
-compilable/test21177.d(204): Deprecation: format specifier `"%m"` is invalid
-compilable/test21177.d(205): Deprecation: argument `c` for format specification `"%a"` must be `float*`, not `char*`
-compilable/test21177.d(206): Deprecation: argument `c` for format specification `"%a"` must be `float*`, not `char*`
+compilable/test21177.d(154): Deprecation: more format specifiers than 0 arguments
+compilable/test21177.d(155): Deprecation: more format specifiers than 0 arguments
+compilable/test21177.d(202): Deprecation: format specifier `"%m"` is invalid
+compilable/test21177.d(203): Deprecation: argument `d` for format specification `"%mc"` must be `char**`, not `int`
+compilable/test21177.d(204): Deprecation: argument `c` for format specification `"%ms"` must be `char**`, not `char*`
+compilable/test21177.d(205): Deprecation: format specifier `"%ml"` is invalid
+compilable/test21177.d(206): Deprecation: argument `d` for format specification `"%mlc"` must be `wchar_t**`, not `int`
+compilable/test21177.d(207): Deprecation: argument `c` for format specification `"%mls"` must be `wchar_t**`, not `char*`
 ---
 */
 
@@ -27,50 +31,45 @@  void main()
         #line 100
         printf("%m this is a string in errno");
         printf("%s %m", "str".ptr, 2);
-        printf("%a", 2.);
+        printf("%m %a", 2.);
         printf("%m %m %s");
+        printf("%m");
         printf("%*m");
-
+        pragma(msg, "compilable/test21177.d(111): Deprecation: more format specifiers than 0 arguments");
+    }
+    else
+    {
+        pragma(msg, "compilable/test21177.d(103): Deprecation: more format specifiers than 0 arguments");
+        printf("%m");
+    }
+    {
         char* a, b;
-        sscanf("salut poilu", "%a %m", a, b);
+        sscanf("salut poilu", "%ms %m[^\n]", &a, &b);
         assert(!strcmp(a, b));
         free(a);
         free(b);
 
-        char* t, p;
-        sscanf("Tomate Patate", "%ms %as", t, p);
+        char* t; wchar_t* p;
+        sscanf("Tomate Patate", "%mc %mlc", &t, &p);
         free(t);
         free(p);
 
         #line 150
         sscanf("150", "%m");
         sscanf("151", "%ms");
-        sscanf("152", "%a");
-        sscanf("153", "%as");
-
-        pragma(msg, "compilable/test21177.d(200): Deprecation: more format specifiers than 0 arguments");
-        pragma(msg, "compilable/test21177.d(203): Deprecation: format specifier `\"%m\"` is invalid");
-        pragma(msg, "compilable/test21177.d(204): Deprecation: format specifier `\"%m\"` is invalid");
-        pragma(msg, "compilable/test21177.d(205): Deprecation: argument `c` for format specification `\"%a\"` must be `float*`, not `char*`");
-        pragma(msg, "compilable/test21177.d(206): Deprecation: argument `c` for format specification `\"%a\"` must be `float*`, not `char*`");
-    }
-    else
-    {
-        // fake it
-        pragma(msg, "compilable/test21177.d(103): Deprecation: more format specifiers than 0 arguments");
-        pragma(msg, "compilable/test21177.d(150): Deprecation: more format specifiers than 0 arguments");
-        pragma(msg, "compilable/test21177.d(151): Deprecation: more format specifiers than 0 arguments");
-        pragma(msg, "compilable/test21177.d(152): Deprecation: more format specifiers than 0 arguments");
-        pragma(msg, "compilable/test21177.d(153): Deprecation: more format specifiers than 0 arguments");
+        sscanf("152", "%mc");
+        sscanf("153", "%ml");
+        sscanf("154", "%mls");
+        sscanf("155", "%mlc");
 
         #line 200
-        printf("%m");
-
         char* c;
+        int d;
         sscanf("204", "%m", c);
-        sscanf("205", "%ms", c);
-        sscanf("206", "%a", c);
-        sscanf("207", "%as", c);
-
+        sscanf("205", "%mc", d);
+        sscanf("206", "%ms", c);
+        sscanf("207", "%ml", d);
+        sscanf("208", "%mlc", d);
+        sscanf("209", "%mls", c);
     }
 }
diff --git a/gcc/testsuite/gdc.test/compilable/test21432.d b/gcc/testsuite/gdc.test/compilable/test21432.d
new file mode 100644
index 00000000000..2c83e246116
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test21432.d
@@ -0,0 +1,25 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=21432
+auto issue21432()
+{
+    enum int[] a = [];
+    return a;
+}
+
+enum test21432a = issue21432;
+
+///////////////////////
+
+double issue21432b(double r)
+{
+    enum double[4] poly = [
+        0x1.ffffffffffdbdp-2,
+        0x1.555555555543cp-3,
+        0x1.55555cf172b91p-5,
+        0x1.1111167a4d017p-7,
+    ];
+
+    immutable r2 = r * r;
+    return r + r2 * (poly[0] + r * poly[1]) + r2 * r2 * (poly[2] + r * poly[3]);
+}
+
+enum test21432b = issue21432b(-0x1p-1);
diff --git a/gcc/testsuite/gdc.test/compilable/test22390.d b/gcc/testsuite/gdc.test/compilable/test22390.d
new file mode 100644
index 00000000000..f045416c4c9
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test22390.d
@@ -0,0 +1,8 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=22390
+
+int main()
+{
+    noreturn[] empty;
+    assert(empty == empty);
+    return 0;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23082.d b/gcc/testsuite/gdc.test/compilable/test23082.d
new file mode 100644
index 00000000000..9df4e4e7774
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23082.d
@@ -0,0 +1,17 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=23082
+
+/*
+TEST_OUTPUT:
+---
+bar
+---
+*/
+
+void foo()() {}
+alias bar = foo;
+void bar() { }
+
+void main()
+{
+    pragma(msg, __traits(parent, main).bar.stringof);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23166.d b/gcc/testsuite/gdc.test/compilable/test23166.d
new file mode 100644
index 00000000000..66da4cd6963
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23166.d
@@ -0,0 +1,22 @@ 
+// REQUIRED_ARGS: -inline
+
+// https://issues.dlang.org/show_bug.cgi?id=23166
+
+// seg fault with -inline
+
+bool __equals(scope const char[] lhs, scope const char[] rhs)
+{
+    if (lhs.length != rhs.length)
+        return false;
+
+    {
+        import core.stdc.string : memcmp;
+        return lhs.length == 0;
+    }
+    return true;
+}
+
+int test(string type)
+{
+    return __equals(type, "as-is");
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23172.d b/gcc/testsuite/gdc.test/compilable/test23172.d
new file mode 100644
index 00000000000..18b6d4ce8c5
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23172.d
@@ -0,0 +1,33 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=23172
+
+enum E : ubyte { // `ubyte` is needed to trigger the bug
+    A,
+    B,
+}
+
+struct S {
+    E e;
+}
+
+void compiles(bool b, S s) {
+    E e = b ? E.A : s.e;
+}
+
+void errors(bool b, const ref S s) {
+    E e = b ? E.A : s.e;
+}
+
+// from https://issues.dlang.org/show_bug.cgi?id=23188
+
+enum Status : byte
+{
+    A, B, C
+}
+
+Status foo()
+{
+    Status t = Status.A;
+    const Status s = t;
+
+    return (s == Status.A) ? Status.B : s;  // <-- here
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23235.d b/gcc/testsuite/gdc.test/compilable/test23235.d
new file mode 100644
index 00000000000..99772adeba4
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23235.d
@@ -0,0 +1,20 @@ 
+/* https://issues.dlang.org/show_bug.cgi?id=23235
+ */
+
+@safe:
+
+void awkk(string[] ppp...)
+{
+}
+
+void bark(string[] foo...) {
+    awkk(foo);
+}
+
+void cack(string[] bar...) {
+    bark(bar);
+}
+
+void test() {
+    cack("abc", "def");
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23256.d b/gcc/testsuite/gdc.test/compilable/test23256.d
new file mode 100644
index 00000000000..1e5720128ca
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23256.d
@@ -0,0 +1,6 @@ 
+/* REQUIRED_ARGS: -os=windows
+ */
+
+// https://issues.dlang.org/show_bug.cgi?id=23256
+
+void test23256() { }
diff --git a/gcc/testsuite/gdc.test/compilable/test23262.d b/gcc/testsuite/gdc.test/compilable/test23262.d
new file mode 100644
index 00000000000..96da2721b1b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23262.d
@@ -0,0 +1,17 @@ 
+/* https://issues.dlang.org/show_bug.cgi?id=23262
+ */
+
+struct T()
+{
+    string[] tags;
+
+    this(string[] tags...)
+    {
+        this.tags = tags; // don't infer `return` attribute for `tags`
+    }
+}
+
+void test()
+{
+    T!() t;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/testgotoskips.d b/gcc/testsuite/gdc.test/compilable/testgotoskips.d
new file mode 100644
index 00000000000..659b5f776a5
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/testgotoskips.d
@@ -0,0 +1,17 @@ 
+/*
+    Tests to defend against false positives from the goto skips over decl errors
+*/
+// https://issues.dlang.org/show_bug.cgi?id=23271
+class A {
+        private static A[] active;
+        private void test() {
+                foreach(a; active) {
+                    if(a is this)
+                         goto label;
+                }
+                // used to say Error: `goto` skips declaration of variable `s.A.test.__appendtmp4` at s.d(...)
+                active ~= this;
+            label:
+                return;
+        }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/attributediagnostic.d b/gcc/testsuite/gdc.test/fail_compilation/attributediagnostic.d
index 1fdf5a5a722..8360e1ac484 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/attributediagnostic.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/attributediagnostic.d
@@ -1,12 +1,20 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/attributediagnostic.d(16): Error: `@safe` function `attributediagnostic.layer2` cannot call `@system` function `attributediagnostic.layer1`
-fail_compilation/attributediagnostic.d(18):        which calls `attributediagnostic.layer0`
-fail_compilation/attributediagnostic.d(20):        which calls `attributediagnostic.system`
-fail_compilation/attributediagnostic.d(22):        which was inferred `@system` because of:
-fail_compilation/attributediagnostic.d(22):        `asm` statement is assumed to be `@system` - mark it with `@trusted` if it is not
-fail_compilation/attributediagnostic.d(17):        `attributediagnostic.layer1` is declared here
+fail_compilation/attributediagnostic.d(24): Error: `@safe` function `attributediagnostic.layer2` cannot call `@system` function `attributediagnostic.layer1`
+fail_compilation/attributediagnostic.d(26):        which calls `attributediagnostic.layer0`
+fail_compilation/attributediagnostic.d(28):        which calls `attributediagnostic.system`
+fail_compilation/attributediagnostic.d(30):        which was inferred `@system` because of:
+fail_compilation/attributediagnostic.d(30):        `asm` statement is assumed to be `@system` - mark it with `@trusted` if it is not
+fail_compilation/attributediagnostic.d(25):        `attributediagnostic.layer1` is declared here
+fail_compilation/attributediagnostic.d(46): Error: `@safe` function `D main` cannot call `@system` function `attributediagnostic.system1`
+fail_compilation/attributediagnostic.d(35):        which was inferred `@system` because of:
+fail_compilation/attributediagnostic.d(35):        cast from `uint` to `int*` not allowed in safe code
+fail_compilation/attributediagnostic.d(33):        `attributediagnostic.system1` is declared here
+fail_compilation/attributediagnostic.d(47): Error: `@safe` function `D main` cannot call `@system` function `attributediagnostic.system2`
+fail_compilation/attributediagnostic.d(41):        which was inferred `@system` because of:
+fail_compilation/attributediagnostic.d(41):        `@safe` function `system2` cannot call `@system` `fsys`
+fail_compilation/attributediagnostic.d(39):        `attributediagnostic.system2` is declared here
 ---
 */
 
@@ -19,5 +27,22 @@  auto layer0() { system(); }
 
 auto system()
 {
-	asm {}
+    asm {}
+}
+
+auto system1()
+{
+    int* x = cast(int*) 0xDEADBEEF;
+}
+
+auto fsys = function void() @system {};
+auto system2()
+{
+    fsys();
+}
+
+void main() @safe
+{
+    system1();
+    system2();
 }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/chkformat.d b/gcc/testsuite/gdc.test/fail_compilation/chkformat.d
index e9ed2415d7c..fa8915e5fa9 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/chkformat.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/chkformat.d
@@ -169,3 +169,21 @@  void test409() { char* p; printf("%llu", p); }
 void test410() { char* p; printf("%lld", p); }
 void test411() { char* p; printf("%ju", p); }
 void test412() { char* p; printf("%jd", p); }
+
+/* https://issues.dlang.org/show_bug.cgi?id=23247
+TEST_OUTPUT:
+---
+fail_compilation/chkformat.d(501): Deprecation: argument `p` for format specification `"%a"` must be `double`, not `char*`
+fail_compilation/chkformat.d(502): Deprecation: argument `p` for format specification `"%La"` must be `real`, not `char*`
+fail_compilation/chkformat.d(503): Deprecation: argument `p` for format specification `"%a"` must be `float*`, not `char*`
+fail_compilation/chkformat.d(504): Deprecation: argument `p` for format specification `"%la"` must be `double*`, not `char*`
+fail_compilation/chkformat.d(505): Deprecation: argument `p` for format specification `"%La"` must be `real*`, not `char*`
+---
+*/
+#line 500
+
+void test501() { char* p; printf("%a", p); }
+void test502() { char* p; printf("%La", p); }
+void test503() { char* p; scanf("%a", p); }
+void test504() { char* p; scanf("%la", p); }
+void test505() { char* p; scanf("%La", p); }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag10319.d b/gcc/testsuite/gdc.test/fail_compilation/diag10319.d
index 416d56310e1..7b2eca79b80 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag10319.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag10319.d
@@ -1,15 +1,17 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag10319.d(27): Error: `pure` function `D main` cannot call impure function `diag10319.foo`
-fail_compilation/diag10319.d(27): Error: `@safe` function `D main` cannot call `@system` function `diag10319.foo`
-fail_compilation/diag10319.d(16):        `diag10319.foo` is declared here
-fail_compilation/diag10319.d(28): Error: `pure` function `D main` cannot call impure function `diag10319.bar!int.bar`
-fail_compilation/diag10319.d(28): Error: `@safe` function `D main` cannot call `@system` function `diag10319.bar!int.bar`
-fail_compilation/diag10319.d(18):        `diag10319.bar!int.bar` is declared here
-fail_compilation/diag10319.d(27): Error: function `diag10319.foo` is not `nothrow`
-fail_compilation/diag10319.d(28): Error: function `diag10319.bar!int.bar` is not `nothrow`
-fail_compilation/diag10319.d(25): Error: function `D main` may throw but is marked as `nothrow`
+fail_compilation/diag10319.d(29): Error: `pure` function `D main` cannot call impure function `diag10319.foo`
+fail_compilation/diag10319.d(29): Error: `@safe` function `D main` cannot call `@system` function `diag10319.foo`
+fail_compilation/diag10319.d(18):        `diag10319.foo` is declared here
+fail_compilation/diag10319.d(30): Error: `pure` function `D main` cannot call impure function `diag10319.bar!int.bar`
+fail_compilation/diag10319.d(30): Error: `@safe` function `D main` cannot call `@system` function `diag10319.bar!int.bar`
+fail_compilation/diag10319.d(23):        which was inferred `@system` because of:
+fail_compilation/diag10319.d(23):        cannot take address of local `x` in `@safe` function `bar`
+fail_compilation/diag10319.d(20):        `diag10319.bar!int.bar` is declared here
+fail_compilation/diag10319.d(29): Error: function `diag10319.foo` is not `nothrow`
+fail_compilation/diag10319.d(30): Error: function `diag10319.bar!int.bar` is not `nothrow`
+fail_compilation/diag10319.d(27): Error: function `D main` may throw but is marked as `nothrow`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag11198.d b/gcc/testsuite/gdc.test/fail_compilation/diag11198.d
index 279d62a5496..1be0f1e85a2 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag11198.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag11198.d
@@ -1,12 +1,14 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag11198.d(15): Error: version `blah` declaration must be at module level
-fail_compilation/diag11198.d(16): Error: debug `blah` declaration must be at module level
-fail_compilation/diag11198.d(17): Error: version `1` level declaration must be at module level
-fail_compilation/diag11198.d(18): Error: debug `2` level declaration must be at module level
-fail_compilation/diag11198.d(19): Error: identifier or integer expected, not `""`
-fail_compilation/diag11198.d(20): Error: identifier or integer expected, not `""`
+fail_compilation/diag11198.d(17): Error: version `blah` declaration must be at module level
+fail_compilation/diag11198.d(18): Error: debug `blah` declaration must be at module level
+fail_compilation/diag11198.d(19): Deprecation: `version = <integer>` is deprecated, use version identifiers instead
+fail_compilation/diag11198.d(19): Error: version `1` level declaration must be at module level
+fail_compilation/diag11198.d(20): Deprecation: `debug = <integer>` is deprecated, use debug identifiers instead
+fail_compilation/diag11198.d(20): Error: debug `2` level declaration must be at module level
+fail_compilation/diag11198.d(21): Error: identifier or integer expected, not `""`
+fail_compilation/diag11198.d(22): Error: identifier or integer expected, not `""`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag12829.d b/gcc/testsuite/gdc.test/fail_compilation/diag12829.d
index f6e764bd98d..1d37a1ecbfe 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag12829.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag12829.d
@@ -1,11 +1,11 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag12829.d(12): Error: function `diag12829.test1` is `@nogc` yet allocates closures with the GC
-fail_compilation/diag12829.d(15):        diag12829.test1.__lambda2 closes over variable x at fail_compilation/diag12829.d(14)
-fail_compilation/diag12829.d(19):        diag12829.test1.bar closes over variable x at fail_compilation/diag12829.d(14)
-fail_compilation/diag12829.d(26): Error: function `diag12829.test2` is `@nogc` yet allocates closures with the GC
-fail_compilation/diag12829.d(31):        diag12829.test2.S.foo closes over variable x at fail_compilation/diag12829.d(28)
+fail_compilation/diag12829.d(12): Error: function `diag12829.test1` is `@nogc` yet allocates closure for `test1()` with the GC
+fail_compilation/diag12829.d(15):        `diag12829.test1.__lambda2` closes over variable `x` at fail_compilation/diag12829.d(14)
+fail_compilation/diag12829.d(19):        `diag12829.test1.bar` closes over variable `x` at fail_compilation/diag12829.d(14)
+fail_compilation/diag12829.d(26): Error: function `diag12829.test2` is `@nogc` yet allocates closure for `test2()` with the GC
+fail_compilation/diag12829.d(31):        `diag12829.test2.S.foo` closes over variable `x` at fail_compilation/diag12829.d(28)
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail118.d b/gcc/testsuite/gdc.test/fail_compilation/fail118.d
index 3df797d6b8f..a526b908acd 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail118.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail118.d
@@ -1,15 +1,17 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail118.d(43): Error: invalid `foreach` aggregate `Iter` of type `Iter`
-fail_compilation/fail118.d(43):        maybe define `opApply()`, range primitives, or use `.tupleof`
-fail_compilation/fail118.d(44): Error: invalid `foreach` aggregate `Iter` of type `Iter`
-fail_compilation/fail118.d(44):        maybe define `opApply()`, range primitives, or use `.tupleof`
-fail_compilation/fail118.d(47): Error: invalid `foreach` aggregate `s` of type `S*`
-fail_compilation/fail118.d(49): Error: undefined identifier `unknown`
-fail_compilation/fail118.d(37): Error: undefined identifier `doesNotExist`
-fail_compilation/fail118.d(51): Error: template instance `fail118.error!()` error instantiating
-fail_compilation/fail118.d(51): Error: invalid `foreach` aggregate `error()` of type `void`
+fail_compilation/fail118.d(45): Error: invalid `foreach` aggregate `Iter` of type `Iter`
+fail_compilation/fail118.d(45):        `foreach` works with input ranges (implementing `front` and `popFront`), aggregates implementing `opApply`, or the result of an aggregate's `.tupleof` property
+fail_compilation/fail118.d(45):        https://dlang.org/phobos/std_range_primitives.html#isInputRange
+fail_compilation/fail118.d(46): Error: invalid `foreach` aggregate `Iter` of type `Iter`
+fail_compilation/fail118.d(46):        `foreach` works with input ranges (implementing `front` and `popFront`), aggregates implementing `opApply`, or the result of an aggregate's `.tupleof` property
+fail_compilation/fail118.d(46):        https://dlang.org/phobos/std_range_primitives.html#isInputRange
+fail_compilation/fail118.d(49): Error: invalid `foreach` aggregate `s` of type `S*`
+fail_compilation/fail118.d(51): Error: undefined identifier `unknown`
+fail_compilation/fail118.d(39): Error: undefined identifier `doesNotExist`
+fail_compilation/fail118.d(53): Error: template instance `fail118.error!()` error instantiating
+fail_compilation/fail118.d(53): Error: invalid `foreach` aggregate `error()` of type `void`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail20547.d b/gcc/testsuite/gdc.test/fail_compilation/fail20547.d
deleted file mode 100644
index c14977d0f12..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/fail20547.d
+++ /dev/null
@@ -1,15 +0,0 @@ 
-/*
-TEST_OUTPUT:
----
-fail_compilation/fail20547.d(12): Error: cannot create a `string[string]` with `new`
-fail_compilation/fail20547.d(14): Error: cannot create a `string[string]` with `new`
----
-*/
-
-void main()
-{
-    //https://issues.dlang.org/show_bug.cgi?id=11790
-    string[string] crash = new string[string];
-    //https://issues.dlang.org/show_bug.cgi?id=20547
-    int[string] c = new typeof(crash);
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22134.d b/gcc/testsuite/gdc.test/fail_compilation/fail22134.d
new file mode 100644
index 00000000000..5a4933ef325
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail22134.d
@@ -0,0 +1,17 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=22134
+/* REQUIRED_ARGS: -de
+TEST_OUTPUT:
+---
+fail_compilation/fail22134.d(12): Deprecation: `this.arr[i]` has no effect
+---
+*/
+struct StackBuffer
+{
+    auto opIndex(size_t i)
+    {
+        return arr[i];
+    }
+
+private:
+    void[] arr;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail23181.d b/gcc/testsuite/gdc.test/fail_compilation/fail23181.d
new file mode 100644
index 00000000000..519244c1cdf
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail23181.d
@@ -0,0 +1,16 @@ 
+/* https://issues.dlang.org/show_bug.cgi?id=23181
+TEST_OUTPUT:
+---
+$p:druntime/import/core/lifetime.d$($n$): Error: struct `fail23181.fail23181.NoPostblit` is not copyable because it has a disabled postblit
+$p:druntime/import/core/internal/array/construction.d$($n$): Error: template instance `core.lifetime.copyEmplace!(NoPostblit, NoPostblit)` error instantiating
+fail_compilation/fail23181.d(15):        instantiated from here: `_d_arraysetctor!(NoPostblit[], NoPostblit)`
+---
+*/
+void fail23181()
+{
+    struct NoPostblit
+    {
+        @disable this(this);
+    }
+    NoPostblit[4] noblit23181 = NoPostblit();
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail261.d b/gcc/testsuite/gdc.test/fail_compilation/fail261.d
index 85da957290c..d807dc8f3aa 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail261.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail261.d
@@ -1,8 +1,9 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail261.d(19): Error: invalid `foreach` aggregate `range` of type `MyRange`
-fail_compilation/fail261.d(19):        maybe define `opApply()`, range primitives, or use `.tupleof`
+fail_compilation/fail261.d(20): Error: invalid `foreach` aggregate `range` of type `MyRange`
+fail_compilation/fail261.d(20):        `foreach` works with input ranges (implementing `front` and `popFront`), aggregates implementing `opApply`, or the result of an aggregate's `.tupleof` property
+fail_compilation/fail261.d(20):        https://dlang.org/phobos/std_range_primitives.html#isInputRange
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail58.d b/gcc/testsuite/gdc.test/fail_compilation/fail58.d
index 15570554fac..89b2351acfe 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail58.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail58.d
@@ -7,7 +7,7 @@  fail_compilation/fail58.d(30): Error: function `fail58.SomeFunc(dchar[] pText, o
 fail_compilation/fail58.d(30):        cannot pass argument `""` of type `string` to parameter `dchar[] pText`
 ---
 */
-debug(1) import std.stdio;
+debug import std.stdio;
 const int anything = -1000; // Line #2
 dchar[] SomeFunc( dchar[] pText, out int pStopPosn)
 {
@@ -15,7 +15,7 @@  dchar[] SomeFunc( dchar[] pText, out int pStopPosn)
         pStopPosn = 0;
     else
         pStopPosn = -1;
-    debug(1) writefln("DEBUG: using '%s' we get %d", pText, pStopPosn);
+    debug writefln("DEBUG: using '%s' we get %d", pText, pStopPosn);
     return pText.dup;
 }
 
@@ -24,12 +24,12 @@  int main(char[][] pArgs)
     int sp;
 
     SomeFunc("123", sp);
-    debug(1) writefln("DEBUG: got %d", sp);
+    debug writefln("DEBUG: got %d", sp);
     assert(sp == -1);
 
     SomeFunc("", sp);
 //    if (sp != 0){} // Line #22
-    debug(1) writefln("DEBUG: got %d", sp);
+    debug writefln("DEBUG: got %d", sp);
     assert(sp == -1);
     return 0;
 }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail6889.d b/gcc/testsuite/gdc.test/fail_compilation/fail6889.d
index aa189770903..ee84a84ce79 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail6889.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail6889.d
@@ -55,7 +55,7 @@  L1:
     scope(failure) { L2: goto L1; } // OK
     goto L2;                        // NG
 
-    scope(failure) { return; }      // OK
+
 
     foreach (i; 0..1)
     {
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail7848.d b/gcc/testsuite/gdc.test/fail_compilation/fail7848.d
index e8371c4f7fe..001c7d75443 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail7848.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail7848.d
@@ -9,12 +9,12 @@  fail_compilation/fail7848.d(21):        `fail7848.func` is declared here
 fail_compilation/fail7848.d(27): Error: `@nogc` function `fail7848.C.__unittest_L25_C30` cannot call non-@nogc function `fail7848.func`
 fail_compilation/fail7848.d(27): Error: function `fail7848.func` is not `nothrow`
 fail_compilation/fail7848.d(25): Error: function `fail7848.C.__unittest_L25_C30` may throw but is marked as `nothrow`
-fail_compilation/fail7848.d(32): Error: `pure` function `fail7848.C.__invariant1` cannot call impure function `fail7848.func`
-fail_compilation/fail7848.d(32): Error: `@safe` function `fail7848.C.__invariant1` cannot call `@system` function `fail7848.func`
+fail_compilation/fail7848.d(32): Error: `pure` function `fail7848.C.__invariant0` cannot call impure function `fail7848.func`
+fail_compilation/fail7848.d(32): Error: `@safe` function `fail7848.C.__invariant0` cannot call `@system` function `fail7848.func`
 fail_compilation/fail7848.d(21):        `fail7848.func` is declared here
-fail_compilation/fail7848.d(32): Error: `@nogc` function `fail7848.C.__invariant1` cannot call non-@nogc function `fail7848.func`
+fail_compilation/fail7848.d(32): Error: `@nogc` function `fail7848.C.__invariant0` cannot call non-@nogc function `fail7848.func`
 fail_compilation/fail7848.d(32): Error: function `fail7848.func` is not `nothrow`
-fail_compilation/fail7848.d(30): Error: function `fail7848.C.__invariant1` may throw but is marked as `nothrow`
+fail_compilation/fail7848.d(30): Error: function `fail7848.C.__invariant0` may throw but is marked as `nothrow`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice11856_1.d b/gcc/testsuite/gdc.test/fail_compilation/ice11856_1.d
index d2a1d1dbcc5..24e39da85bb 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice11856_1.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice11856_1.d
@@ -1,8 +1,11 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice11856_1.d(13): Error: none of the overloads of template `ice11856_1.g` are callable using argument types `!()(A)`
-fail_compilation/ice11856_1.d(11):        Candidate is: `g(T)(T x)`
+fail_compilation/ice11856_1.d(16): Error: none of the overloads of template `ice11856_1.g` are callable using argument types `!()(A)`
+fail_compilation/ice11856_1.d(14):        Candidate is: `g(T)(T x)`
+  with `T = A`
+  must satisfy the following constraint:
+`       is(typeof(x.f()))`
 ---
 */
 struct A {}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d b/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d
index 22cf39241f8..b50a616ac97 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d
@@ -10,7 +10,6 @@  fail_compilation/misc_parser_err_cov1.d(31): Error: expression expected, not `)`
 fail_compilation/misc_parser_err_cov1.d(32): Error: `type identifier : specialization` expected following `is`
 fail_compilation/misc_parser_err_cov1.d(33): Error: semicolon expected following auto declaration, not `auto`
 fail_compilation/misc_parser_err_cov1.d(33): Error: found `+` when expecting `(` following `mixin`
-fail_compilation/misc_parser_err_cov1.d(34): Error: cannot create a `char[float]` with `new`
 fail_compilation/misc_parser_err_cov1.d(35): Error: `key:value` expected for associative array literal
 fail_compilation/misc_parser_err_cov1.d(36): Error: basic type expected, not `;`
 fail_compilation/misc_parser_err_cov1.d(36): Error: `{ members }` expected for anonymous class
@@ -44,7 +43,7 @@  void main()
     auto tt = __traits(<o<);
     auto b = is ;
     auto mx1 = mixin +);
-    auto aa1 = new char[float];
+
     aa +=  [key:value, key];
     auto anon1 = new class;
     auto anon2 = new class {};
diff --git a/gcc/testsuite/gdc.test/fail_compilation/newaa.d b/gcc/testsuite/gdc.test/fail_compilation/newaa.d
new file mode 100644
index 00000000000..ebc23fb352e
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/newaa.d
@@ -0,0 +1,19 @@ 
+/*
+TEST_OUTPUT:
+---
+fail_compilation/newaa.d(14): Error: cannot implicitly convert expression `new string[string]` of type `string[string]` to `int[string]`
+fail_compilation/newaa.d(15): Error: function expected before `()`, not `new int[int]` of type `int[int]`
+fail_compilation/newaa.d(17): Error: `new` cannot take arguments for an associative array
+---
+*/
+#line 9
+void main()
+{
+    //https://issues.dlang.org/show_bug.cgi?id=11790
+    string[string] crash = new string[string];
+    //https://issues.dlang.org/show_bug.cgi?id=20547
+    int[string] c = new typeof(crash);
+    auto d = new int[int](5);
+    alias AA = char[string];
+    auto e = new AA(5);
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/nogc3.d b/gcc/testsuite/gdc.test/fail_compilation/nogc3.d
index fdc3cde9784..3bd7167acba 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/nogc3.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/nogc3.d
@@ -43,10 +43,10 @@  fail_compilation/nogc3.d(35): Error: `@nogc` function `nogc3.testCall` cannot ca
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/nogc3.d(52): Error: function `nogc3.testClosure1` is `@nogc` yet allocates closures with the GC
-fail_compilation/nogc3.d(55):        nogc3.testClosure1.bar closes over variable x at fail_compilation/nogc3.d(54)
-fail_compilation/nogc3.d(64): Error: function `nogc3.testClosure3` is `@nogc` yet allocates closures with the GC
-fail_compilation/nogc3.d(67):        nogc3.testClosure3.bar closes over variable x at fail_compilation/nogc3.d(66)
+fail_compilation/nogc3.d(52): Error: function `nogc3.testClosure1` is `@nogc` yet allocates closure for `testClosure1()` with the GC
+fail_compilation/nogc3.d(55):        `nogc3.testClosure1.bar` closes over variable `x` at fail_compilation/nogc3.d(54)
+fail_compilation/nogc3.d(64): Error: function `nogc3.testClosure3` is `@nogc` yet allocates closure for `testClosure3()` with the GC
+fail_compilation/nogc3.d(67):        `nogc3.testClosure3.bar` closes over variable `x` at fail_compilation/nogc3.d(66)
 ---
 */
 @nogc auto testClosure1()
diff --git a/gcc/testsuite/gdc.test/fail_compilation/retscope.d b/gcc/testsuite/gdc.test/fail_compilation/retscope.d
index 93944040db9..2a69fe04f84 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/retscope.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/retscope.d
@@ -54,8 +54,8 @@  void test2(scope int* p, int[] a ...) @safe
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/retscope.d(75): Error: function `retscope.HTTP.Impl.onReceive` is `@nogc` yet allocates closures with the GC
-fail_compilation/retscope.d(77):        retscope.HTTP.Impl.onReceive.__lambda1 closes over variable this at fail_compilation/retscope.d(75)
+fail_compilation/retscope.d(75): Error: function `retscope.HTTP.Impl.onReceive` is `@nogc` yet allocates closure for `onReceive()` with the GC
+fail_compilation/retscope.d(77):        `retscope.HTTP.Impl.onReceive.__lambda1` closes over variable `this` at fail_compilation/retscope.d(75)
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test13786.d b/gcc/testsuite/gdc.test/fail_compilation/test13786.d
index 3524875e3ca..73ec588c777 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test13786.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test13786.d
@@ -1,11 +1,13 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/test13786.d(14): Error: debug `123` level declaration must be at module level
-fail_compilation/test13786.d(15): Error: debug `abc` declaration must be at module level
-fail_compilation/test13786.d(16): Error: version `123` level declaration must be at module level
-fail_compilation/test13786.d(17): Error: version `abc` declaration must be at module level
-fail_compilation/test13786.d(20): Error: template instance `test13786.T!()` error instantiating
+fail_compilation/test13786.d(16): Deprecation: `debug = <integer>` is deprecated, use debug identifiers instead
+fail_compilation/test13786.d(18): Deprecation: `version = <integer>` is deprecated, use version identifiers instead
+fail_compilation/test13786.d(16): Error: debug `123` level declaration must be at module level
+fail_compilation/test13786.d(17): Error: debug `abc` declaration must be at module level
+fail_compilation/test13786.d(18): Error: version `123` level declaration must be at module level
+fail_compilation/test13786.d(19): Error: version `abc` declaration must be at module level
+fail_compilation/test13786.d(22): Error: template instance `test13786.T!()` error instantiating
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test16193.d b/gcc/testsuite/gdc.test/fail_compilation/test16193.d
index 053f5832c77..6c80471c77b 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test16193.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test16193.d
@@ -2,8 +2,8 @@ 
 REQUIRED_ARGS: -preview=dip1000
 TEST_OUTPUT:
 ---
-fail_compilation/test16193.d(38): Error: function `test16193.abc` is `@nogc` yet allocates closures with the GC
-fail_compilation/test16193.d(40):        test16193.abc.__foreachbody2 closes over variable x at fail_compilation/test16193.d(39)
+fail_compilation/test16193.d(38): Error: function `test16193.abc` is `@nogc` yet allocates closure for `abc()` with the GC
+fail_compilation/test16193.d(40):        `test16193.abc.__foreachbody2` closes over variable `x` at fail_compilation/test16193.d(39)
 ---
 */
 //fail_compilation/test16193.d(22): To enforce `@safe`, the compiler allocates a closure unless `opApply()` uses `scope`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21443.d b/gcc/testsuite/gdc.test/fail_compilation/test21443.d
new file mode 100644
index 00000000000..2d99524da35
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21443.d
@@ -0,0 +1,21 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=21443
+// REQUIRED_ARGS: -de
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test21443.d(14): Deprecation: `return` statements cannot be in `scope(failure)` bodies.
+fail_compilation/test21443.d(14):        Use try-catch blocks for this purpose
+---
+*/
+
+ulong get () @safe nothrow
+{
+    scope (failure) return 10;
+    throw new Error("");
+}
+
+void main () @safe
+{
+    assert(get() == 10);  // passes
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21912.d b/gcc/testsuite/gdc.test/fail_compilation/test21912.d
index 925210bf875..9b07eba0df6 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test21912.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21912.d
@@ -2,14 +2,14 @@ 
 PERMUTE_ARGS: -preview=dip1000
 TEST_OUTPUT:
 ---
-fail_compilation/test21912.d(24): Error: function `test21912.escapeParam` is `@nogc` yet allocates closures with the GC
-fail_compilation/test21912.d(26):        test21912.escapeParam.__lambda2 closes over variable i at fail_compilation/test21912.d(24)
-fail_compilation/test21912.d(29): Error: function `test21912.escapeAssign` is `@nogc` yet allocates closures with the GC
-fail_compilation/test21912.d(31):        test21912.escapeAssign.__lambda3 closes over variable i at fail_compilation/test21912.d(29)
-fail_compilation/test21912.d(40): Error: function `test21912.escapeAssignRef` is `@nogc` yet allocates closures with the GC
-fail_compilation/test21912.d(42):        test21912.escapeAssignRef.__lambda3 closes over variable i at fail_compilation/test21912.d(40)
-fail_compilation/test21912.d(51): Error: function `test21912.escapeParamInferred` is `@nogc` yet allocates closures with the GC
-fail_compilation/test21912.d(53):        test21912.escapeParamInferred.__lambda2 closes over variable i at fail_compilation/test21912.d(51)
+fail_compilation/test21912.d(24): Error: function `test21912.escapeParam` is `@nogc` yet allocates closure for `escapeParam()` with the GC
+fail_compilation/test21912.d(26):        `test21912.escapeParam.__lambda2` closes over variable `i` at fail_compilation/test21912.d(24)
+fail_compilation/test21912.d(29): Error: function `test21912.escapeAssign` is `@nogc` yet allocates closure for `escapeAssign()` with the GC
+fail_compilation/test21912.d(31):        `test21912.escapeAssign.__lambda3` closes over variable `i` at fail_compilation/test21912.d(29)
+fail_compilation/test21912.d(40): Error: function `test21912.escapeAssignRef` is `@nogc` yet allocates closure for `escapeAssignRef()` with the GC
+fail_compilation/test21912.d(42):        `test21912.escapeAssignRef.__lambda3` closes over variable `i` at fail_compilation/test21912.d(40)
+fail_compilation/test21912.d(51): Error: function `test21912.escapeParamInferred` is `@nogc` yet allocates closure for `escapeParamInferred()` with the GC
+fail_compilation/test21912.d(53):        `test21912.escapeParamInferred.__lambda2` closes over variable `i` at fail_compilation/test21912.d(51)
 ---
 */
 @nogc:
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21939.d b/gcc/testsuite/gdc.test/fail_compilation/test21939.d
index 8f30bac97af..e513dc248c6 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test21939.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21939.d
@@ -2,8 +2,9 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/test21939.d(10): Error: invalid `foreach` aggregate `Object` of type `Object`
-fail_compilation/test21939.d(10):        maybe define `opApply()`, range primitives, or use `.tupleof`
+fail_compilation/test21939.d(11): Error: invalid `foreach` aggregate `Object` of type `Object`
+fail_compilation/test21939.d(11):        `foreach` works with input ranges (implementing `front` and `popFront`), aggregates implementing `opApply`, or the result of an aggregate's `.tupleof` property
+fail_compilation/test21939.d(11):        https://dlang.org/phobos/std_range_primitives.html#isInputRange
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test23022.d b/gcc/testsuite/gdc.test/fail_compilation/test23022.d
new file mode 100644
index 00000000000..8c4eca9c563
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test23022.d
@@ -0,0 +1,15 @@ 
+/*
+REQUIRED_ARGS: -preview=dip1000
+TEST_OUTPUT:
+---
+fail_compilation/test23022.d(14): Error: scope parameter `p` may not be returned
+---
+*/
+
+// https://issues.dlang.org/show_bug.cgi?id=23022
+// Typesafe variadic parameter should not infer return
+
+auto ir(string[] p...)
+{
+    return p;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test23112.d b/gcc/testsuite/gdc.test/fail_compilation/test23112.d
new file mode 100644
index 00000000000..325d89bd6c2
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test23112.d
@@ -0,0 +1,30 @@ 
+/* REQUIRED_ARGS: -betterC
+TEST_OUTPUT:
+---
+fail_compilation/test23112.d(106): Error: function `test23112.bar` is `@nogc` yet allocates closure for `bar()` with the GC
+fail_compilation/test23112.d(108):        `test23112.bar.f` closes over variable `a` at fail_compilation/test23112.d(106)
+---
+*/
+
+// https://issues.dlang.org/show_bug.cgi?id=23112
+
+#line 100
+
+struct Forward(alias F)
+{
+    auto call()() { return F(); }
+}
+
+auto bar(int a) nothrow @safe
+{
+    auto f()
+    {
+        return a;
+    }
+    return Forward!f();
+}
+
+extern(C) void main()
+{
+    assert(bar(3).call() == 3);
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test23170.d b/gcc/testsuite/gdc.test/fail_compilation/test23170.d
new file mode 100644
index 00000000000..eb79cd81565
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test23170.d
@@ -0,0 +1,12 @@ 
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test23170.d(10): Error: array literal in `@nogc` delegate `test23170.__lambda5` may cause a GC allocation
+---
+*/
+// https://issues.dlang.org/show_bug.cgi?id=23170
+
+@nogc:
+enum lambda = () => badAlias([1, 2, 3]);
+alias badAlias = (int[] array) => id(array);
+int[] id(int[] array) { return array; }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test23216.d b/gcc/testsuite/gdc.test/fail_compilation/test23216.d
new file mode 100644
index 00000000000..d7c12ed3207
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test23216.d
@@ -0,0 +1,24 @@ 
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test23216.d(23): Error: invalid `foreach_reverse` aggregate `r` of type `Range`
+fail_compilation/test23216.d(23):        `foreach_reverse` works with bidirectional ranges (implementing `back` and `popBack`), aggregates implementing `opApplyReverse`, or the result of an aggregate's `.tupleof` property
+fail_compilation/test23216.d(23):        https://dlang.org/phobos/std_range_primitives.html#isBidirectionalRange
+---
+*/
+
+// https://issues.dlang.org/show_bug.cgi?id=23216
+// Better Error Message For foreach_reverse Without Bidirectional Range
+
+struct Range
+{
+    bool empty = true;
+    int front = 0;
+    void popFront() { }
+}
+
+void main()
+{
+    Range r;
+    foreach_reverse (word; r) { }
+}
diff --git a/gcc/testsuite/gdc.test/runnable/closure.d b/gcc/testsuite/gdc.test/runnable/closure.d
index af304c1f38a..1382f2d35ce 100644
--- a/gcc/testsuite/gdc.test/runnable/closure.d
+++ b/gcc/testsuite/gdc.test/runnable/closure.d
@@ -922,7 +922,10 @@  void test14730()
 
 // This is questionable case. Currently it works without any errors,
 // but not sure it's really intentional
-
+// It showed up again in https://issues.dlang.org/show_bug.cgi?id=23112
+// where it's an @safe issue so it's a bug.
+static if (0)
+{
 struct S14730x(alias f)
 {
     auto foo()() { return f(0); }
@@ -947,6 +950,7 @@  void test14730x()
     // *after* the semantic3 completion of makeS() function.
     assert(s.foo() == 10);
 }
+}
 
 /************************************/
 
@@ -981,7 +985,7 @@  int main()
     test9685b();
     test12406();
     test14730();
-    test14730x();
+    //test14730x();
 
     printf("Success\n");
     return 0;
diff --git a/gcc/testsuite/gdc.test/runnable/evalorder.d b/gcc/testsuite/gdc.test/runnable/evalorder.d
index 6805ee2e649..f93aef541ce 100644
--- a/gcc/testsuite/gdc.test/runnable/evalorder.d
+++ b/gcc/testsuite/gdc.test/runnable/evalorder.d
@@ -46,6 +46,12 @@  int mul11ret3(T)(ref T s)
     return 3;
 }
 
+auto cat11ret3(T)(ref T s)
+{
+    s ~= 11;
+    return [3];
+}
+
 void add()
 {
     static int test1(int val) { val += add8ret3(val); return val; }
@@ -147,6 +153,25 @@  void shr()
     static assert(test(0x80) == 0x40);
 }
 
+void cat()
+{
+    static auto test1(int[] val) { val ~= cat11ret3(val); return val; }
+    assert(test1([1]) == [1, 11, 3]);
+    static assert(test1([1]) == [1, 11, 3]);
+
+    static auto test2(int[] val) { val = val ~ cat11ret3(val); return val; }
+    // FIXME: assert(test2([1]) == [1, 3]);
+    static assert(test2([1]) == [1, 3]);
+
+    static auto test3(int[] val) { (val ~= 7) ~= cat11ret3(val); return val; }
+    assert(test3([2]) == [2, 7, 11, 3]);
+    static assert(test3([2]) == [2, 7, 11, 3]);
+
+    static auto test4(int[] val) { (val ~= cat11ret3(val)) ~= 7; return val; }
+    assert(test4([2]) == [2, 11, 3, 7]);
+    static assert(test4([2]) == [2, 11, 3, 7]);
+}
+
 void ldc_github_1617()
 {
     add();
@@ -156,6 +181,7 @@  void ldc_github_1617()
     addptr();
     lhsCast();
     shr();
+    cat();
 }
 
 /******************************************/
diff --git a/gcc/testsuite/gdc.test/runnable/lexer.d b/gcc/testsuite/gdc.test/runnable/lexer.d
index ee2fef8f23f..6e31c07f9cb 100644
--- a/gcc/testsuite/gdc.test/runnable/lexer.d
+++ b/gcc/testsuite/gdc.test/runnable/lexer.d
@@ -1,5 +1,11 @@ 
 // REQUIRED_ARGS:
-
+/*
+TEST_OUTPUT:
+---
+runnable/lexer.d(81): Deprecation: `version( <integer> )` is deprecated, use version identifiers instead
+runnable/lexer.d(82): Deprecation: `debug( <integer> )` is deprecated, use debug identifiers instead
+---
+*/
 
 /*********************************************************/
 
diff --git a/gcc/testsuite/gdc.test/runnable/noreturn1.d b/gcc/testsuite/gdc.test/runnable/noreturn1.d
index 7d15b54a213..5ed46c16250 100644
--- a/gcc/testsuite/gdc.test/runnable/noreturn1.d
+++ b/gcc/testsuite/gdc.test/runnable/noreturn1.d
@@ -261,6 +261,37 @@  void testThrowDtor()
 
 /*****************************************/
 
+noreturn func()
+{
+    throw new Exception("B");
+}
+
+// https://issues.dlang.org/show_bug.cgi?id=23120
+void test23120()
+{
+    string a;
+    try
+    {
+        noreturn q = throw new Exception ("A");
+    }
+    catch(Exception e)
+    {
+        a ~= e.msg;
+    }
+
+    try
+    {
+        noreturn z = func();
+    }
+    catch(Exception e)
+    {
+        a ~= e.msg;
+    }
+
+    assert(a == "AB");
+}
+
+/*****************************************/
 int main()
 {
     test1();
@@ -269,5 +300,6 @@  int main()
     testThrowExpression();
     testThrowSideEffect();
     testThrowDtor();
+    test23120();
     return 0;
 }
diff --git a/gcc/testsuite/gdc.test/runnable/test11.d b/gcc/testsuite/gdc.test/runnable/test11.d
index 6735a817c5e..333b6005827 100644
--- a/gcc/testsuite/gdc.test/runnable/test11.d
+++ b/gcc/testsuite/gdc.test/runnable/test11.d
@@ -1193,41 +1193,6 @@  void test63()
      printf("%.*s\n", cast(int)s.length, s.ptr);
 }
 
-
-/**************************************/
-
-debug = 3;
-
-void test64()
-{
-    debug(5)
-    {
-        assert(0);
-    }
-    debug(3)
-    {
-        int x = 3;
-    }
-    assert(x == 3);
-}
-
-/**************************************/
-
-version = 3;
-
-void test65()
-{
-    version(5)
-    {
-        assert(0);
-    }
-    version(3)
-    {
-        int x = 3;
-    }
-    assert(x == 3);
-}
-
 /**************************************/
 // https://issues.dlang.org/show_bug.cgi?id=8809
 
@@ -1381,8 +1346,6 @@  int main(string[] argv)
     test61();
     test62();
     test63();
-    test64();
-    test65();
     test8809();
     test9734();
 
diff --git a/gcc/testsuite/gdc.test/runnable/test18973.d b/gcc/testsuite/gdc.test/runnable/test18973.d
new file mode 100644
index 00000000000..29fcfa75774
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/test18973.d
@@ -0,0 +1,25 @@ 
+// This is a runnable test as we are testing a linker error
+
+// https://issues.dlang.org/show_bug.cgi?id=18973
+struct X {
+    @disable size_t toHash() const;
+    @disable string toString() const;
+    @disable bool opEquals(const ref X) const;
+    @disable int opCmp(const ref X) const;
+}
+
+// https://issues.dlang.org/show_bug.cgi?id=9161
+public struct dummy
+{
+    static auto opCall(C)(in C[] name)
+    {
+        return name;
+    }
+
+    @disable ~this(); //comment this out to avoid error
+}
+
+void main()
+{
+    assert(dummy("ABCDE") == "ABCDE");
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test19.d b/gcc/testsuite/gdc.test/runnable/test19.d
index 372d32f71e3..eda6172abc0 100644
--- a/gcc/testsuite/gdc.test/runnable/test19.d
+++ b/gcc/testsuite/gdc.test/runnable/test19.d
@@ -59,22 +59,7 @@  void test2()
 void test3()
 {
     debug printf("debug\n");
-    debug(1) printf("debug(1)\n");
-    debug(2) printf("debug(2)\n");
-    debug(3) printf("debug(3)\n");
     debug(bar) printf("debug(bar)\n");
-    debug(10) assert(0);
-
-    debug(1)
-    {
-        int d1 = 3;
-
-        printf("debug(1) { }\n");
-    }
-    debug(2)
-    {
-        printf("debug(2): d1 = %d\n", d1);
-    }
 }
 
 /* ================================ */
diff --git a/gcc/testsuite/gdc.test/runnable/test20734.d b/gcc/testsuite/gdc.test/runnable/test20734.d
index 264602bccc5..b3c5916ada5 100644
--- a/gcc/testsuite/gdc.test/runnable/test20734.d
+++ b/gcc/testsuite/gdc.test/runnable/test20734.d
@@ -16,6 +16,7 @@  extern(C) int main() nothrow @nogc @safe
 {
     takeScopeSlice([ S(1), S(2) ]); // @nogc => no GC allocation
     (() @trusted { assert(numDtor == 2); })(); // stack-allocated array literal properly destructed
+    assert23100([]);
     return 0;
 }
 
@@ -26,3 +27,9 @@  void test23098() @safe
 {
     f23098([10, 20]);
 }
+
+// https://issues.dlang.org/show_bug.cgi?id=23100
+void assert23100(scope int[] d) @safe nothrow @nogc
+{
+    assert(!d);
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test23181.d b/gcc/testsuite/gdc.test/runnable/test23181.d
new file mode 100644
index 00000000000..b961690a2bc
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/test23181.d
@@ -0,0 +1,27 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=23181
+void main()
+{
+    int count;
+    struct HasDtor
+    {
+        ~this() { ++count; }
+    }
+
+    // array[] = elem()
+    // -> creates temporary to construct array and calls destructor.
+    {
+        count = 0;
+        HasDtor[4] dtor1 = HasDtor();
+        assert(count == 1);
+    }
+    assert(count == 5);
+
+    // array[] = array[elem()]
+    // -> constructs array using direct emplacement.
+    {
+        count = 0;
+        HasDtor[2] dtor2 = [HasDtor(), HasDtor()];
+        assert(count == 0);
+    }
+    assert(count == 2);
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test8.d b/gcc/testsuite/gdc.test/runnable/test8.d
index 7d66eb6c623..d65ba0eb7ad 100644
--- a/gcc/testsuite/gdc.test/runnable/test8.d
+++ b/gcc/testsuite/gdc.test/runnable/test8.d
@@ -591,6 +591,44 @@  void test34()
             assert(b[i][j] == 16);
 }
 
+/***********************************/
+// https://issues.dlang.org/show_bug.cgi?id=19178
+
+float[3][4] arr2f = 10;
+Int3_4[1] arr3i = 20;
+short[3][4][1][1] arr4s = 30;
+
+enum Int3 : int[3] {
+    a = [0, 1, 2],
+}
+
+enum Int3_4 : Int3[4] {
+    b = Int3[4].init,
+}
+
+struct S35
+{
+    int[3][3] arr = [2, 1];
+}
+
+void test35()
+{
+    for (int i = 0; i < 4; i++)
+    {
+        for (int j = 0; j < 3; j++)
+        {
+            // printf("[%d %d]: %f %d %d\n", i, j, arr2f[i][j], arr3i[0][i][j], arr4s[0][0][i][j]);
+            assert(arr2f[i][j] == 10);
+            assert(arr3i[0][i][j] == 20);
+            assert(arr4s[0][0][i][j] == 30);
+        }
+    }
+
+    S35 t = S35.init;
+    assert(t.arr[0] == [2, 2, 2]);
+    assert(t.arr[1] == [1, 1, 1]);
+    assert(t.arr[2] == [0, 0, 0]);
+}
 /***********************************/
 
 string itoa(int i)
@@ -868,6 +906,7 @@  int main()
     test32();
     test33();
     test34();
+    test35();
     test36();
     test37();
     test38();
diff --git a/gcc/testsuite/gdc.test/runnable/version.d b/gcc/testsuite/gdc.test/runnable/version.d
index 1186e4c6a36..e225d5e4be3 100644
--- a/gcc/testsuite/gdc.test/runnable/version.d
+++ b/gcc/testsuite/gdc.test/runnable/version.d
@@ -1,10 +1,9 @@ 
 /*
 PERMUTE_ARGS:
-REQUIRED_ARGS: -version=3 -version=foo
+REQUIRED_ARGS: -version=foo
 RUN_OUTPUT:
 ---
 i = 2
-i = 2
 ---
 */
 
@@ -15,20 +14,6 @@  extern(C) int printf(const char*, ...);
 void test1()
 {
     int i = 3;
-
-    version(2)
-    {
-        i = 2;
-    }
-    else
-    {
-        i = 0;
-    }
-    printf("i = %d\n", i);
-    assert(i == 2);
-
-    i = 3;
-
     version(foo)
     {
         i = 2;
@@ -47,10 +32,6 @@  version(foo)
 {
     version = bar;
 }
-else
-{
-    version = 4;
-}
 
 void test2()
 {
@@ -59,8 +40,6 @@  void test2()
     }
     else
         assert(0);
-
-    version(4) assert(0);
 }
 
 /*******************************************/
diff --git a/gcc/testsuite/gdc.test/runnable/warning1.d b/gcc/testsuite/gdc.test/runnable/warning1.d
index 537088e97cc..01ac20c0baf 100644
--- a/gcc/testsuite/gdc.test/runnable/warning1.d
+++ b/gcc/testsuite/gdc.test/runnable/warning1.d
@@ -133,15 +133,6 @@  void test6518()
     }
 }
 
-/******************************************/
-// https://issues.dlang.org/show_bug.cgi?id=7232
-
-bool test7232()
-{
-    scope(failure) return false;
-    return true;
-}
-
 /***************************************************/
 
 struct S9332
diff --git a/libphobos/configure b/libphobos/configure
index 9da06f087d0..69d2d440d69 100755
--- a/libphobos/configure
+++ b/libphobos/configure
@@ -15554,7 +15554,7 @@  SPEC_PHOBOS_DEPS="$LIBS"
 
 
 # Libdruntime / phobos soname version
-libtool_VERSION=3:0:0
+libtool_VERSION=4:0:0
 
 
 # Set default flags (after DRUNTIME_WERROR!)
diff --git a/libphobos/configure.ac b/libphobos/configure.ac
index 31209ba2920..8bdf7332b86 100644
--- a/libphobos/configure.ac
+++ b/libphobos/configure.ac
@@ -253,7 +253,7 @@  SPEC_PHOBOS_DEPS="$LIBS"
 AC_SUBST(SPEC_PHOBOS_DEPS)
 
 # Libdruntime / phobos soname version
-libtool_VERSION=3:0:0
+libtool_VERSION=4:0:0
 AC_SUBST(libtool_VERSION)
 
 # Set default flags (after DRUNTIME_WERROR!)
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index 6e25a9d6f92..c358b69e3fc 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@ 
-651389b52243dcadb338dd0c14dd27e7850cda8d
+d7772a236983ec37b92d21b28bad3cd2de57b945
 
 The first line of this file holds the git revision number of the last
-merge done from the dlang/druntime repository.
+merge done from the dlang/dmd repository.
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 56b332d4efa..2e1e91da79f 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -174,14 +174,14 @@  DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	core/internal/array/appending.d core/internal/array/capacity.d \
 	core/internal/array/casting.d core/internal/array/comparison.d \
 	core/internal/array/concatenation.d core/internal/array/construction.d \
-	core/internal/array/equality.d core/internal/array/operations.d \
-	core/internal/array/utils.d core/internal/atomic.d \
-	core/internal/attributes.d core/internal/container/array.d \
-	core/internal/container/common.d core/internal/container/hashtab.d \
-	core/internal/container/treap.d core/internal/convert.d \
-	core/internal/dassert.d core/internal/destruction.d \
-	core/internal/entrypoint.d core/internal/gc/bits.d \
-	core/internal/gc/impl/conservative/gc.d \
+	core/internal/array/duplication.d core/internal/array/equality.d \
+	core/internal/array/operations.d core/internal/array/utils.d \
+	core/internal/atomic.d core/internal/attributes.d \
+	core/internal/container/array.d core/internal/container/common.d \
+	core/internal/container/hashtab.d core/internal/container/treap.d \
+	core/internal/convert.d core/internal/dassert.d \
+	core/internal/destruction.d core/internal/entrypoint.d \
+	core/internal/gc/bits.d core/internal/gc/impl/conservative/gc.d \
 	core/internal/gc/impl/manual/gc.d core/internal/gc/impl/proto/gc.d \
 	core/internal/gc/os.d core/internal/gc/pooltable.d \
 	core/internal/gc/proxy.d core/internal/hash.d core/internal/lifetime.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 24865fb258a..de6656c552b 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -196,6 +196,7 @@  am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
 	core/internal/array/comparison.lo \
 	core/internal/array/concatenation.lo \
 	core/internal/array/construction.lo \
+	core/internal/array/duplication.lo \
 	core/internal/array/equality.lo \
 	core/internal/array/operations.lo core/internal/array/utils.lo \
 	core/internal/atomic.lo core/internal/attributes.lo \
@@ -841,14 +842,14 @@  DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	core/internal/array/appending.d core/internal/array/capacity.d \
 	core/internal/array/casting.d core/internal/array/comparison.d \
 	core/internal/array/concatenation.d core/internal/array/construction.d \
-	core/internal/array/equality.d core/internal/array/operations.d \
-	core/internal/array/utils.d core/internal/atomic.d \
-	core/internal/attributes.d core/internal/container/array.d \
-	core/internal/container/common.d core/internal/container/hashtab.d \
-	core/internal/container/treap.d core/internal/convert.d \
-	core/internal/dassert.d core/internal/destruction.d \
-	core/internal/entrypoint.d core/internal/gc/bits.d \
-	core/internal/gc/impl/conservative/gc.d \
+	core/internal/array/duplication.d core/internal/array/equality.d \
+	core/internal/array/operations.d core/internal/array/utils.d \
+	core/internal/atomic.d core/internal/attributes.d \
+	core/internal/container/array.d core/internal/container/common.d \
+	core/internal/container/hashtab.d core/internal/container/treap.d \
+	core/internal/convert.d core/internal/dassert.d \
+	core/internal/destruction.d core/internal/entrypoint.d \
+	core/internal/gc/bits.d core/internal/gc/impl/conservative/gc.d \
 	core/internal/gc/impl/manual/gc.d core/internal/gc/impl/proto/gc.d \
 	core/internal/gc/os.d core/internal/gc/pooltable.d \
 	core/internal/gc/proxy.d core/internal/hash.d core/internal/lifetime.d \
@@ -1208,6 +1209,8 @@  core/internal/array/concatenation.lo:  \
 	core/internal/array/$(am__dirstamp)
 core/internal/array/construction.lo:  \
 	core/internal/array/$(am__dirstamp)
+core/internal/array/duplication.lo:  \
+	core/internal/array/$(am__dirstamp)
 core/internal/array/equality.lo: core/internal/array/$(am__dirstamp)
 core/internal/array/operations.lo:  \
 	core/internal/array/$(am__dirstamp)
diff --git a/libphobos/libdruntime/core/cpuid.d b/libphobos/libdruntime/core/cpuid.d
index e31f776d7ee..1c2ac067704 100644
--- a/libphobos/libdruntime/core/cpuid.d
+++ b/libphobos/libdruntime/core/cpuid.d
@@ -170,6 +170,8 @@  public:
     bool hle()          {return _hle;}
     /// Is RTM (restricted transactional memory) supported
     bool rtm()          {return _rtm;}
+    /// Is AVX512F supported
+    bool avx512f()      {return _avx512f;}
     /// Is rdseed supported
     bool hasRdseed()    {return _hasRdseed;}
     /// Is SHA supported
@@ -279,6 +281,7 @@  private immutable
     bool _avx2;
     bool _hle;
     bool _rtm;
+    bool _avx512f;
     bool _hasRdseed;
     bool _hasSha;
     bool _amd3dnow;
@@ -389,6 +392,7 @@  CpuFeatures* getCpuFeatures() @nogc nothrow
     enum : uint
     {
         FSGSBASE_BIT = 1 << 0,
+        SGX_BIT = 1 << 2,
         BMI1_BIT = 1 << 3,
         HLE_BIT = 1 << 4,
         AVX2_BIT = 1 << 5,
@@ -397,8 +401,19 @@  CpuFeatures* getCpuFeatures() @nogc nothrow
         ERMS_BIT = 1 << 9,
         INVPCID_BIT = 1 << 10,
         RTM_BIT = 1 << 11,
+        AVX512F_BIT = 1 << 16,
+        AVX512DQ_BIT = 1 << 17,
         RDSEED_BIT = 1 << 18,
+        ADX_BIT = 1 << 19,
+        AVX512IFMA_BIT = 1 << 21,
+        CLFLUSHOPT_BIT = 1 << 23,
+        CLWB_BIT = 1 << 24,
+        AVX512PF_BIT = 1 << 26,
+        AVX512ER_BIT = 1 << 27,
+        AVX512CD_BIT = 1 << 28,
         SHA_BIT = 1 << 29,
+        AVX512BW_BIT = 1 << 30,
+        AVX512VL_BIT = 1 << 31,
     }
     // feature flags XFEATURES_ENABLED_MASK
     enum : ulong
@@ -1122,6 +1137,7 @@  shared static this()
     _avx2 =           avx && (cf.extfeatures & AVX2_BIT) != 0;
     _hle =            (cf.extfeatures & HLE_BIT) != 0;
     _rtm =            (cf.extfeatures & RTM_BIT) != 0;
+    _avx512f =        (cf.extfeatures & AVX512F_BIT) != 0;
     _hasRdseed =      (cf.extfeatures&RDSEED_BIT)!=0;
     _hasSha =         (cf.extfeatures&SHA_BIT)!=0;
     _amd3dnow =       (cf.amdfeatures&AMD_3DNOW_BIT)!=0;
diff --git a/libphobos/libdruntime/core/int128.d b/libphobos/libdruntime/core/int128.d
index e4326fd54c3..46eb9b27556 100644
--- a/libphobos/libdruntime/core/int128.d
+++ b/libphobos/libdruntime/core/int128.d
@@ -943,5 +943,3 @@  unittest
     assert(rol(C7_9, 1) == rol1(C7_9));
     assert(ror(C7_9, 1) == ror1(C7_9));
 }
-
-
diff --git a/libphobos/libdruntime/core/internal/array/appending.d b/libphobos/libdruntime/core/internal/array/appending.d
index d416efe1c50..616d27cfe83 100644
--- a/libphobos/libdruntime/core/internal/array/appending.d
+++ b/libphobos/libdruntime/core/internal/array/appending.d
@@ -30,26 +30,14 @@  template _d_arrayappendcTXImpl(Tarr : T[], T)
      * Returns:
      *  The new value of `px`
      * Bugs:
-    *   This function template was ported from a much older runtime hook that bypassed safety,
-    *   purity, and throwabilty checks. To prevent breaking existing code, this function template
-    *   is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations.
+     *  This function template was ported from a much older runtime hook that bypassed safety,
+     *  purity, and throwabilty checks. To prevent breaking existing code, this function template
+     *  is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations.
      */
-    static if (isCopyingNothrow!T) // `nothrow` deduction doesn't work, so this is needed
-        ref Tarr _d_arrayappendcTX(return ref scope Tarr px, size_t n) @trusted pure nothrow
-        {
-            pragma(inline, false);
-
-            mixin(_d_arrayappendcTXBody);
-        }
-    else
-        ref Tarr _d_arrayappendcTX(return ref scope Tarr px, size_t n) @trusted pure nothrow
-        {
-            pragma(inline, false);
-
-            mixin(_d_arrayappendcTXBody);
-        }
-
-    private enum _d_arrayappendcTXBody = q{
+    ref Tarr _d_arrayappendcTX(return ref scope Tarr px, size_t n) @trusted pure nothrow
+    {
+        // needed for CTFE: https://github.com/dlang/druntime/pull/3870#issuecomment-1178800718
+        pragma(inline, false);
         version (D_TypeInfo)
         {
             auto ti = typeid(Tarr);
@@ -64,7 +52,7 @@  template _d_arrayappendcTXImpl(Tarr : T[], T)
         }
         else
             assert(0, "Cannot append arrays if compiling without support for runtime type information!");
-    };
+    }
 
     /**
      * TraceGC wrapper around $(REF _d_arrayappendcTX, rt,array,appending,_d_arrayappendcTXImpl).
diff --git a/libphobos/libdruntime/core/internal/array/duplication.d b/libphobos/libdruntime/core/internal/array/duplication.d
new file mode 100644
index 00000000000..41dfab6f349
--- /dev/null
+++ b/libphobos/libdruntime/core/internal/array/duplication.d
@@ -0,0 +1,346 @@ 
+/**
+The `.dup` and `.idup` properties for Associative Arrays and Dynamic Arrays
+
+Copyright: Copyright Digital Mars 2000 - 2022.
+License: Distributed under the $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
+    (See accompanying file LICENSE)
+Source: $(DRUNTIMESRC core/internal/_array/_duplication.d)
+*/
+module core.internal.array.duplication;
+
+private extern (C) void[] _d_newarrayU(const scope TypeInfo ti, size_t length) pure nothrow;
+
+U[] _dup(T, U)(scope T[] a) pure nothrow @trusted if (__traits(isPOD, T))
+{
+    if (__ctfe)
+        return _dupCtfe!(T, U)(a);
+
+    import core.stdc.string : memcpy;
+    auto arr = _d_newarrayU(typeid(T[]), a.length);
+    memcpy(arr.ptr, cast(const(void)*) a.ptr, T.sizeof * a.length);
+    return *cast(U[]*) &arr;
+}
+
+U[] _dupCtfe(T, U)(scope T[] a)
+{
+    static if (is(T : void))
+        assert(0, "Cannot dup a void[] array at compile time.");
+    else
+    {
+        U[] res;
+        foreach (ref e; a)
+            res ~= e;
+        return res;
+    }
+}
+
+U[] _dup(T, U)(T[] a) if (!__traits(isPOD, T))
+{
+    // note: copyEmplace is `@system` inside a `@trusted` block, so the __ctfe branch
+    // has the extra duty to infer _dup `@system` when the copy-constructor is `@system`.
+    if (__ctfe)
+        return _dupCtfe!(T, U)(a);
+
+    import core.lifetime: copyEmplace;
+    U[] res = () @trusted {
+        auto arr = cast(U*) _d_newarrayU(typeid(T[]), a.length);
+        size_t i;
+        scope (failure)
+        {
+            import core.internal.lifetime: emplaceInitializer;
+            // Initialize all remaining elements to not destruct garbage
+            foreach (j; i .. a.length)
+                emplaceInitializer(cast() arr[j]);
+        }
+        for (; i < a.length; i++)
+        {
+            copyEmplace(a.ptr[i], arr[i]);
+        }
+        return cast(U[])(arr[0..a.length]);
+    } ();
+
+    return res;
+}
+
+// https://issues.dlang.org/show_bug.cgi?id=22107
+@safe unittest
+{
+    static int i;
+    @safe struct S
+    {
+        this(this) { i++; }
+    }
+
+    void fun(scope S[] values...) @safe
+    {
+        values.dup;
+    }
+}
+
+@safe unittest
+{
+    static struct S1 { int* p; }
+    static struct S2 { @disable this(); }
+    static struct S3 { @disable this(this); }
+
+    int dg1() pure nothrow @safe
+    {
+        {
+           char[] m;
+           string i;
+           m = m.dup;
+           i = i.idup;
+           m = i.dup;
+           i = m.idup;
+        }
+        {
+           S1[] m;
+           immutable(S1)[] i;
+           m = m.dup;
+           i = i.idup;
+           static assert(!is(typeof(m.idup)));
+           static assert(!is(typeof(i.dup)));
+        }
+        {
+            S3[] m;
+            immutable(S3)[] i;
+            static assert(!is(typeof(m.dup)));
+            static assert(!is(typeof(i.idup)));
+        }
+        {
+            shared(S1)[] m;
+            m = m.dup;
+            static assert(!is(typeof(m.idup)));
+        }
+        {
+            int[] a = (inout(int)) { inout(const(int))[] a; return a.dup; }(0);
+        }
+        return 1;
+    }
+
+    int dg2() pure nothrow @safe
+    {
+        {
+           S2[] m = [S2.init, S2.init];
+           immutable(S2)[] i = [S2.init, S2.init];
+           m = m.dup;
+           m = i.dup;
+           i = m.idup;
+           i = i.idup;
+        }
+        return 2;
+    }
+
+    enum a = dg1();
+    enum b = dg2();
+    assert(dg1() == a);
+    assert(dg2() == b);
+}
+
+@system unittest
+{
+    static struct Sunpure { this(this) @safe nothrow {} }
+    static struct Sthrow { this(this) @safe pure {} }
+    static struct Sunsafe { this(this) @system pure nothrow {} }
+    static struct Snocopy { @disable this(this); }
+
+    [].dup!Sunpure;
+    [].dup!Sthrow;
+    cast(void) [].dup!Sunsafe;
+    static assert(!__traits(compiles, () pure    { [].dup!Sunpure; }));
+    static assert(!__traits(compiles, () nothrow { [].dup!Sthrow; }));
+    static assert(!__traits(compiles, () @safe   { [].dup!Sunsafe; }));
+    static assert(!__traits(compiles, ()         { [].dup!Snocopy; }));
+
+    [].idup!Sunpure;
+    [].idup!Sthrow;
+    [].idup!Sunsafe;
+    static assert(!__traits(compiles, () pure    { [].idup!Sunpure; }));
+    static assert(!__traits(compiles, () nothrow { [].idup!Sthrow; }));
+    static assert(!__traits(compiles, () @safe   { [].idup!Sunsafe; }));
+    static assert(!__traits(compiles, ()         { [].idup!Snocopy; }));
+}
+
+@safe unittest
+{
+    // test that the copy-constructor is called with .dup
+    static struct ArrElem
+    {
+        int a;
+        this(int a)
+        {
+            this.a = a;
+        }
+        this(ref const ArrElem)
+        {
+            a = 2;
+        }
+        this(ref ArrElem) immutable
+        {
+            a = 3;
+        }
+    }
+
+    auto arr = [ArrElem(1), ArrElem(1)];
+
+    ArrElem[] b = arr.dup;
+    assert(b[0].a == 2 && b[1].a == 2);
+
+    immutable ArrElem[] c = arr.idup;
+    assert(c[0].a == 3 && c[1].a == 3);
+}
+
+@system unittest
+{
+    static struct Sunpure { this(ref const typeof(this)) @safe nothrow {} }
+    static struct Sthrow { this(ref const typeof(this)) @safe pure {} }
+    static struct Sunsafe { this(ref const typeof(this)) @system pure nothrow {} }
+    [].dup!Sunpure;
+    [].dup!Sthrow;
+    cast(void) [].dup!Sunsafe;
+    static assert(!__traits(compiles, () pure    { [].dup!Sunpure; }));
+    static assert(!__traits(compiles, () nothrow { [].dup!Sthrow; }));
+    static assert(!__traits(compiles, () @safe   { [].dup!Sunsafe; }));
+
+    // for idup to work on structs that have copy constructors, it is necessary
+    // that the struct defines a copy constructor that creates immutable objects
+    static struct ISunpure { this(ref const typeof(this)) immutable @safe nothrow {} }
+    static struct ISthrow { this(ref const typeof(this)) immutable @safe pure {} }
+    static struct ISunsafe { this(ref const typeof(this)) immutable @system pure nothrow {} }
+    [].idup!ISunpure;
+    [].idup!ISthrow;
+    [].idup!ISunsafe;
+    static assert(!__traits(compiles, () pure    { [].idup!ISunpure; }));
+    static assert(!__traits(compiles, () nothrow { [].idup!ISthrow; }));
+    static assert(!__traits(compiles, () @safe   { [].idup!ISunsafe; }));
+}
+
+@safe unittest
+{
+    static int*[] pureFoo() pure { return null; }
+    { char[] s; immutable x = s.dup; }
+    { immutable x = (cast(int*[])null).dup; }
+    { immutable x = pureFoo(); }
+    { immutable x = pureFoo().dup; }
+}
+
+@safe unittest
+{
+    auto a = [1, 2, 3];
+    auto b = a.dup;
+    debug(SENTINEL) {} else
+        assert(b.capacity >= 3);
+}
+
+@system unittest
+{
+    // Bugzilla 12580
+    void[] m = [0];
+    shared(void)[] s = [cast(shared)1];
+    immutable(void)[] i = [cast(immutable)2];
+
+    s = s.dup;
+    static assert(is(typeof(s.dup) == shared(void)[]));
+
+    m = i.dup;
+    i = m.dup;
+    i = i.idup;
+    i = m.idup;
+    i = s.idup;
+    i = s.dup;
+    static assert(!__traits(compiles, m = s.dup));
+}
+
+@safe unittest
+{
+    // Bugzilla 13809
+    static struct S
+    {
+        this(this) {}
+        ~this() {}
+    }
+
+    S[] arr;
+    auto a = arr.dup;
+}
+
+@system unittest
+{
+    // Bugzilla 16504
+    static struct S
+    {
+        __gshared int* gp;
+        int* p;
+        // postblit and hence .dup could escape
+        this(this) { gp = p; }
+    }
+
+    int p;
+    scope S[1] arr = [S(&p)];
+    auto a = arr.dup; // dup does escape
+}
+
+// https://issues.dlang.org/show_bug.cgi?id=21983
+// dup/idup destroys partially constructed arrays on failure
+@safe unittest
+{
+    static struct SImpl(bool postblit)
+    {
+        int num;
+        long l = 0xDEADBEEF;
+
+        static if (postblit)
+        {
+            this(this)
+            {
+                if (this.num == 3)
+                    throw new Exception("");
+            }
+        }
+        else
+        {
+            this(scope ref const SImpl other)
+            {
+                if (other.num == 3)
+                    throw new Exception("");
+
+                this.num = other.num;
+                this.l = other.l;
+            }
+        }
+
+        ~this() @trusted
+        {
+            if (l != 0xDEADBEEF)
+            {
+                import core.stdc.stdio;
+                printf("Unexpected value: %lld\n", l);
+                fflush(stdout);
+                assert(false);
+            }
+        }
+    }
+
+    alias Postblit = SImpl!true;
+    alias Copy = SImpl!false;
+
+    static int test(S)()
+    {
+        S[4] arr = [ S(1), S(2), S(3), S(4) ];
+        try
+        {
+            arr.dup();
+            assert(false);
+        }
+        catch (Exception)
+        {
+            return 1;
+        }
+    }
+
+    static assert(test!Postblit());
+    assert(test!Postblit());
+
+    static assert(test!Copy());
+    assert(test!Copy());
+}
diff --git a/libphobos/libdruntime/core/internal/dassert.d b/libphobos/libdruntime/core/internal/dassert.d
index 2c51b8641ae..07486c216f0 100644
--- a/libphobos/libdruntime/core/internal/dassert.d
+++ b/libphobos/libdruntime/core/internal/dassert.d
@@ -14,7 +14,7 @@ 
  *
  * Copyright: D Language Foundation 2018 - 2020
  * License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source:    $(LINK2 https://github.com/dlang/druntime/blob/master/src/core/internal/dassert.d, _dassert.d)
+ * Source:    $(LINK2 https://github.com/dlang/dmd/blob/master/druntime/src/core/internal/dassert.d, _dassert.d)
  * Documentation: https://dlang.org/phobos/core_internal_dassert.html
  */
 module core.internal.dassert;
diff --git a/libphobos/libdruntime/core/runtime.d b/libphobos/libdruntime/core/runtime.d
index d1378afca91..75e671cb34b 100644
--- a/libphobos/libdruntime/core/runtime.d
+++ b/libphobos/libdruntime/core/runtime.d
@@ -4,7 +4,7 @@ 
  * Copyright: Copyright Sean Kelly 2005 - 2009.
  * License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
  * Authors:   Sean Kelly
- * Source:    $(LINK2 https://github.com/dlang/druntime/blob/master/src/core/runtime.d, _runtime.d)
+ * Source:    $(LINK2 https://github.com/dlang/dmd/blob/master/druntime/src/core/runtime.d, _runtime.d)
  * Documentation: https://dlang.org/phobos/core_runtime.html
  */
 
diff --git a/libphobos/libdruntime/core/stdc/errno.d b/libphobos/libdruntime/core/stdc/errno.d
index 24b4138153d..c992a5ff0de 100644
--- a/libphobos/libdruntime/core/stdc/errno.d
+++ b/libphobos/libdruntime/core/stdc/errno.d
@@ -8,7 +8,7 @@ 
  *      $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
  *    (See accompanying file LICENSE)
  * Authors:   Sean Kelly, Alex Rønne Petersen
- * Source:    https://github.com/dlang/druntime/blob/master/src/core/stdc/errno.d
+ * Source:    https://github.com/dlang/dmd/blob/master/druntime/src/core/stdc/errno.d
  * Standards: ISO/IEC 9899:1999 (E)
  */
 
diff --git a/libphobos/libdruntime/core/stdc/stdio.d b/libphobos/libdruntime/core/stdc/stdio.d
index 2e8381180db..fc98350e139 100644
--- a/libphobos/libdruntime/core/stdc/stdio.d
+++ b/libphobos/libdruntime/core/stdc/stdio.d
@@ -9,7 +9,7 @@ 
  *    (See accompanying file LICENSE)
  * Authors:   Sean Kelly,
  *            Alex Rønne Petersen
- * Source:    https://github.com/dlang/druntime/blob/master/src/core/stdc/stdio.d
+ * Source:    https://github.com/dlang/dmd/blob/master/druntime/src/core/stdc/stdio.d
  * Standards: ISO/IEC 9899:1999 (E)
  */
 
@@ -1286,6 +1286,57 @@  version (MinGW)
     ///
     alias __mingw_scanf scanf;
 }
+else version (CRuntime_Glibc)
+{
+    ///
+    pragma(printf)
+    int fprintf(FILE* stream, scope const char* format, scope const ...);
+    ///
+    pragma(scanf)
+    int __isoc99_fscanf(FILE* stream, scope const char* format, scope ...);
+    ///
+    alias fscanf = __isoc99_fscanf;
+    ///
+    pragma(printf)
+    int sprintf(scope char* s, scope const char* format, scope const ...);
+    ///
+    pragma(scanf)
+    int __isoc99_sscanf(scope const char* s, scope const char* format, scope ...);
+    ///
+    alias sscanf = __isoc99_sscanf;
+    ///
+    pragma(printf)
+    int vfprintf(FILE* stream, scope const char* format, va_list arg);
+    ///
+    pragma(scanf)
+    int __isoc99_vfscanf(FILE* stream, scope const char* format, va_list arg);
+    ///
+    alias vfscanf = __isoc99_vfscanf;
+    ///
+    pragma(printf)
+    int vsprintf(scope char* s, scope const char* format, va_list arg);
+    ///
+    pragma(scanf)
+    int __isoc99_vsscanf(scope const char* s, scope const char* format, va_list arg);
+    ///
+    alias vsscanf = __isoc99_vsscanf;
+    ///
+    pragma(printf)
+    int vprintf(scope const char* format, va_list arg);
+    ///
+    pragma(scanf)
+    int __isoc99_vscanf(scope const char* format, va_list arg);
+    ///
+    alias vscanf = __isoc99_vscanf;
+    ///
+    pragma(printf)
+    int printf(scope const char* format, scope const ...);
+    ///
+    pragma(scanf)
+    int __isoc99_scanf(scope const char* format, scope ...);
+    ///
+    alias scanf = __isoc99_scanf;
+}
 else
 {
     ///
diff --git a/libphobos/libdruntime/core/stdc/wchar_.d b/libphobos/libdruntime/core/stdc/wchar_.d
index e8fb94b11e6..d0870290854 100644
--- a/libphobos/libdruntime/core/stdc/wchar_.d
+++ b/libphobos/libdruntime/core/stdc/wchar_.d
@@ -127,30 +127,72 @@  alias wchar_t wint_t;
 ///
 enum wchar_t WEOF = 0xFFFF;
 
-///
-int fwprintf(FILE* stream, const scope wchar_t* format, scope const ...);
-///
-int fwscanf(FILE* stream, const scope wchar_t* format, scope ...);
-///
-int swprintf(wchar_t* s, size_t n, const scope wchar_t* format, scope const ...);
-///
-int swscanf(const scope wchar_t* s, const scope wchar_t* format, scope ...);
-///
-int vfwprintf(FILE* stream, const scope wchar_t* format, va_list arg);
-///
-int vfwscanf(FILE* stream, const scope wchar_t* format, va_list arg);
-///
-int vswprintf(wchar_t* s, size_t n, const scope wchar_t* format, va_list arg);
-///
-int vswscanf(const scope wchar_t* s, const scope wchar_t* format, va_list arg);
-///
-int vwprintf(const scope wchar_t* format, va_list arg);
-///
-int vwscanf(const scope wchar_t* format, va_list arg);
-///
-int wprintf(const scope wchar_t* format, scope const ...);
-///
-int wscanf(const scope wchar_t* format, scope ...);
+version (CRuntime_Glibc)
+{
+    ///
+    int fwprintf(FILE* stream, const scope wchar_t* format, scope const ...);
+    ///
+    int __isoc99_fwscanf(FILE* stream, const scope wchar_t* format, scope ...);
+    ///
+    alias fwscanf = __isoc99_fwscanf;
+    ///
+    int swprintf(wchar_t* s, size_t n, const scope wchar_t* format, scope const ...);
+    ///
+    int __isoc99_swscanf(const scope wchar_t* s, const scope wchar_t* format, scope ...);
+    ///
+    alias swscanf = __isoc99_swscanf;
+    ///
+    int vfwprintf(FILE* stream, const scope wchar_t* format, va_list arg);
+    ///
+    int __isoc99_vfwscanf(FILE* stream, const scope wchar_t* format, va_list arg);
+    ///
+    alias vfwscanf = __isoc99_vfwscanf;
+    ///
+    int vswprintf(wchar_t* s, size_t n, const scope wchar_t* format, va_list arg);
+    ///
+    int __isoc99_vswscanf(const scope wchar_t* s, const scope wchar_t* format, va_list arg);
+    ///
+    alias vswscanf = __isoc99_vswscanf;
+    ///
+    int vwprintf(const scope wchar_t* format, va_list arg);
+    ///
+    int __isoc99_vwscanf(const scope wchar_t* format, va_list arg);
+    ///
+    alias vwscanf = __isoc99_vwscanf;
+    ///
+    int wprintf(const scope wchar_t* format, scope const ...);
+    ///
+    int __isoc99_wscanf(const scope wchar_t* format, scope ...);
+    ///
+    alias wscanf = __isoc99_wscanf;
+}
+else
+{
+    ///
+    int fwprintf(FILE* stream, const scope wchar_t* format, scope const ...);
+    ///
+    int fwscanf(FILE* stream, const scope wchar_t* format, scope ...);
+    ///
+    int swprintf(wchar_t* s, size_t n, const scope wchar_t* format, scope const ...);
+    ///
+    int swscanf(const scope wchar_t* s, const scope wchar_t* format, scope ...);
+    ///
+    int vfwprintf(FILE* stream, const scope wchar_t* format, va_list arg);
+    ///
+    int vfwscanf(FILE* stream, const scope wchar_t* format, va_list arg);
+    ///
+    int vswprintf(wchar_t* s, size_t n, const scope wchar_t* format, va_list arg);
+    ///
+    int vswscanf(const scope wchar_t* s, const scope wchar_t* format, va_list arg);
+    ///
+    int vwprintf(const scope wchar_t* format, va_list arg);
+    ///
+    int vwscanf(const scope wchar_t* format, va_list arg);
+    ///
+    int wprintf(const scope wchar_t* format, scope const ...);
+    ///
+    int wscanf(const scope wchar_t* format, scope ...);
+}
 
 // No unsafe pointer manipulation.
 @trusted
diff --git a/libphobos/libdruntime/core/sys/darwin/mach/getsect.d b/libphobos/libdruntime/core/sys/darwin/mach/getsect.d
index fd1a8e4ea36..dc42a2dc450 100644
--- a/libphobos/libdruntime/core/sys/darwin/mach/getsect.d
+++ b/libphobos/libdruntime/core/sys/darwin/mach/getsect.d
@@ -468,4 +468,3 @@  const(section)* getsectbynamefromheaderwithswap_64(
     const scope char* section,
     int fSwap
 );
-
diff --git a/libphobos/libdruntime/core/sys/dragonflybsd/string.d b/libphobos/libdruntime/core/sys/dragonflybsd/string.d
index 4b8422748b6..1a85ba606a1 100644
--- a/libphobos/libdruntime/core/sys/dragonflybsd/string.d
+++ b/libphobos/libdruntime/core/sys/dragonflybsd/string.d
@@ -19,4 +19,3 @@  static if (__BSD_VISIBLE)
 {
     pure void* memmem(return scope const void* haystack, size_t haystacklen, scope const void* needle, size_t needlelen);
 }
-
diff --git a/libphobos/libdruntime/core/sys/linux/sys/time.d b/libphobos/libdruntime/core/sys/linux/sys/time.d
index 6ea626ed390..4b56229687c 100644
--- a/libphobos/libdruntime/core/sys/linux/sys/time.d
+++ b/libphobos/libdruntime/core/sys/linux/sys/time.d
@@ -65,4 +65,3 @@  extern (D) pure @safe @nogc nothrow {
     }
 
 }
-
diff --git a/libphobos/libdruntime/core/sys/linux/sys/xattr.d b/libphobos/libdruntime/core/sys/linux/sys/xattr.d
index 2f8d3f376f9..6446ff8b9a3 100644
--- a/libphobos/libdruntime/core/sys/linux/sys/xattr.d
+++ b/libphobos/libdruntime/core/sys/linux/sys/xattr.d
@@ -66,4 +66,3 @@  ssize_t flistxattr (int __fd, char *list, size_t size);
 int removexattr (const scope char *path, const scope char *name);
 int lremovexattr (const scope char *path, const scope char *name);
 int fremovexattr (int fd, const scope char *name);
-
diff --git a/libphobos/libdruntime/core/sys/linux/tipc.d b/libphobos/libdruntime/core/sys/linux/tipc.d
index 3246e62ec04..4d5d886269a 100644
--- a/libphobos/libdruntime/core/sys/linux/tipc.d
+++ b/libphobos/libdruntime/core/sys/linux/tipc.d
@@ -208,4 +208,3 @@  enum: int
         TIPC_DEST_DROPPABLE = 129,
         TIPC_CONN_TIMEOUT   = 130,
 }
-
diff --git a/libphobos/libdruntime/core/sys/posix/signal.d b/libphobos/libdruntime/core/sys/posix/signal.d
index 68aee980ef3..542e83a1679 100644
--- a/libphobos/libdruntime/core/sys/posix/signal.d
+++ b/libphobos/libdruntime/core/sys/posix/signal.d
@@ -14,7 +14,7 @@  module core.sys.posix.signal;
 import core.sys.posix.config;
 public import core.stdc.signal;
 public import core.sys.posix.sys.types; // for pid_t
-//public import core.sys.posix.time;      // for timespec, now defined here
+public import core.sys.posix.time; // for timespec
 
 version (OSX)
     version = Darwin;
@@ -2804,83 +2804,6 @@  else
     static assert(false, "Unsupported platform");
 }
 
-//
-// Timer (TMR)
-//
-/*
-NOTE: This should actually be defined in core.sys.posix.time.
-      It is defined here instead to break a circular import.
-
-struct timespec
-{
-    time_t  tv_sec;
-    int     tv_nsec;
-}
-*/
-
-version (linux)
-{
-    struct timespec
-    {
-        time_t  tv_sec;
-        c_long  tv_nsec;
-    }
-}
-else version (Darwin)
-{
-    struct timespec
-    {
-        time_t  tv_sec;
-        c_long  tv_nsec;
-    }
-}
-else version (FreeBSD)
-{
-    struct timespec
-    {
-        time_t  tv_sec;
-        c_long  tv_nsec;
-    }
-}
-else version (NetBSD)
-{
-    struct timespec
-    {
-        time_t  tv_sec;
-        c_long  tv_nsec;
-    }
-}
-else version (OpenBSD)
-{
-    struct timespec
-    {
-        time_t  tv_sec;
-        c_long  tv_nsec;
-    }
-}
-else version (DragonFlyBSD)
-{
-    struct timespec
-    {
-        time_t  tv_sec;
-        c_long  tv_nsec;
-    }
-}
-else version (Solaris)
-{
-    struct timespec
-    {
-        time_t tv_sec;
-        c_long tv_nsec;
-    }
-
-    alias timespec timestruc_t;
-}
-else
-{
-    static assert(false, "Unsupported platform");
-}
-
 //
 // Realtime Signals (RTS)
 //
diff --git a/libphobos/libdruntime/core/sys/posix/spawn.d b/libphobos/libdruntime/core/sys/posix/spawn.d
index cfa3a40057c..206496261b0 100644
--- a/libphobos/libdruntime/core/sys/posix/spawn.d
+++ b/libphobos/libdruntime/core/sys/posix/spawn.d
@@ -4,7 +4,7 @@ 
  * Copyright: Copyright (C) 2018 by The D Language Foundation, All Rights Reserved
  * Authors:   Petar Kirov
  * License:   $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source:    $(LINK2 https://github.com/dlang/druntime/blob/master/src/core/sys/posix/spawn.d, _spawn.d)
+ * Source:    $(LINK2 https://github.com/dlang/dmd/blob/master/druntime/src/core/sys/posix/spawn.d, _spawn.d)
  * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
  */
 module core.sys.posix.spawn;
diff --git a/libphobos/libdruntime/core/sys/posix/stdio.d b/libphobos/libdruntime/core/sys/posix/stdio.d
index 077838d50aa..d0d3d60ff46 100644
--- a/libphobos/libdruntime/core/sys/posix/stdio.d
+++ b/libphobos/libdruntime/core/sys/posix/stdio.d
@@ -487,7 +487,7 @@  else version (CRuntime_Musl)
 
 version (HaveMemstream)
 {
-    FILE*  fmemopen(const scope void* buf, in size_t size, const scope char* mode);
+    FILE*  fmemopen(const scope void* buf, size_t size, const scope char* mode);
     FILE*  open_memstream(char** ptr, size_t* sizeloc);
     version (CRuntime_UClibc) {} else
     FILE*  open_wmemstream(wchar_t** ptr, size_t* sizeloc);
diff --git a/libphobos/libdruntime/core/sys/posix/sys/select.d b/libphobos/libdruntime/core/sys/posix/sys/select.d
index 2a659c30dc0..925976d3e33 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/select.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/select.d
@@ -608,4 +608,3 @@  pure unittest
         assert(!FD_ISSET(i, &fd));
     }
 }
-
diff --git a/libphobos/libdruntime/core/sys/posix/time.d b/libphobos/libdruntime/core/sys/posix/time.d
index a9be87c8597..ff3a3c46cd0 100644
--- a/libphobos/libdruntime/core/sys/posix/time.d
+++ b/libphobos/libdruntime/core/sys/posix/time.d
@@ -167,9 +167,6 @@  else
 CLOCK_PROCESS_CPUTIME_ID (TMR|CPT)
 CLOCK_THREAD_CPUTIME_ID (TMR|TCT)
 
-NOTE: timespec must be defined in core.sys.posix.signal to break
-      a circular import.
-
 struct timespec
 {
     time_t  tv_sec;
@@ -199,6 +196,69 @@  int timer_getoverrun(timer_t);
 int timer_settime(timer_t, int, const scope itimerspec*, itimerspec*);
 */
 
+version (linux)
+{
+    struct timespec
+    {
+        time_t  tv_sec;
+        c_long  tv_nsec;
+    }
+}
+else version (Darwin)
+{
+    struct timespec
+    {
+        time_t  tv_sec;
+        c_long  tv_nsec;
+    }
+}
+else version (FreeBSD)
+{
+    struct timespec
+    {
+        time_t  tv_sec;
+        c_long  tv_nsec;
+    }
+}
+else version (NetBSD)
+{
+    struct timespec
+    {
+        time_t  tv_sec;
+        c_long  tv_nsec;
+    }
+}
+else version (OpenBSD)
+{
+    struct timespec
+    {
+        time_t  tv_sec;
+        c_long  tv_nsec;
+    }
+}
+else version (DragonFlyBSD)
+{
+    struct timespec
+    {
+        time_t  tv_sec;
+        c_long  tv_nsec;
+    }
+}
+else version (Solaris)
+{
+    struct timespec
+    {
+        time_t tv_sec;
+        c_long tv_nsec;
+    }
+
+    alias timespec timestruc_t;
+}
+else
+{
+    static assert(false, "Unsupported platform");
+}
+
 version (CRuntime_Glibc)
 {
     enum CLOCK_PROCESS_CPUTIME_ID = 2;
diff --git a/libphobos/libdruntime/core/sys/posix/ucontext.d b/libphobos/libdruntime/core/sys/posix/ucontext.d
index 20297f50b90..e8c2f87bbd3 100644
--- a/libphobos/libdruntime/core/sys/posix/ucontext.d
+++ b/libphobos/libdruntime/core/sys/posix/ucontext.d
@@ -1628,4 +1628,3 @@  version (Solaris)
     int addrtosymstr(uintptr_t, char*, int);
     int printstack(int);
 }
-
diff --git a/libphobos/libdruntime/core/sys/solaris/sys/priocntl.d b/libphobos/libdruntime/core/sys/solaris/sys/priocntl.d
index bfbf3ee2abc..c56be3b00f8 100644
--- a/libphobos/libdruntime/core/sys/solaris/sys/priocntl.d
+++ b/libphobos/libdruntime/core/sys/solaris/sys/priocntl.d
@@ -113,4 +113,3 @@  struct pcadmin_t
     id_t    pc_cid;
     caddr_t pc_cladmin;
 }
-
diff --git a/libphobos/libdruntime/core/sys/solaris/sys/procset.d b/libphobos/libdruntime/core/sys/solaris/sys/procset.d
index 43fa9978af3..8bd91157007 100644
--- a/libphobos/libdruntime/core/sys/solaris/sys/procset.d
+++ b/libphobos/libdruntime/core/sys/solaris/sys/procset.d
@@ -50,4 +50,3 @@  void setprocset(ref procset_t psp, idop_t op, idtype_t ltype, id_t lid, idtype_t
     psp.p_ridtype = rtype;
     psp.p_rid = rid;
 }
-
diff --git a/libphobos/libdruntime/core/sys/windows/cguid.d b/libphobos/libdruntime/core/sys/windows/cguid.d
index 0afbc42e8b0..d0a8fb9f087 100644
--- a/libphobos/libdruntime/core/sys/windows/cguid.d
+++ b/libphobos/libdruntime/core/sys/windows/cguid.d
@@ -10,4 +10,3 @@  module core.sys.windows.cguid;
 version (Windows):
 
 import core.sys.windows.basetyps;
-
diff --git a/libphobos/libdruntime/core/sys/windows/ntsecpkg.d b/libphobos/libdruntime/core/sys/windows/ntsecpkg.d
index d4c93d7b573..d8c5e95edbd 100644
--- a/libphobos/libdruntime/core/sys/windows/ntsecpkg.d
+++ b/libphobos/libdruntime/core/sys/windows/ntsecpkg.d
@@ -444,4 +444,3 @@  alias NTSTATUS function(ULONG, PULONG,
  PSECPKG_FUNCTION_TABLE *, PULONG) SpLsaModeInitializeFn;
 alias NTSTATUS function(ULONG, PULONG,
  PSECPKG_USER_FUNCTION_TABLE *, PULONG) SpUserModeInitializeFn;
-
diff --git a/libphobos/libdruntime/core/sys/windows/olectlid.d b/libphobos/libdruntime/core/sys/windows/olectlid.d
index 8bbe657134b..b58c14ae1fe 100644
--- a/libphobos/libdruntime/core/sys/windows/olectlid.d
+++ b/libphobos/libdruntime/core/sys/windows/olectlid.d
@@ -10,4 +10,3 @@  module core.sys.windows.olectlid;
 version (Windows):
 
 import core.sys.windows.basetyps;
-
diff --git a/libphobos/libdruntime/core/sys/windows/shlguid.d b/libphobos/libdruntime/core/sys/windows/shlguid.d
index 1c0c98fc070..e0c1af1045a 100644
--- a/libphobos/libdruntime/core/sys/windows/shlguid.d
+++ b/libphobos/libdruntime/core/sys/windows/shlguid.d
@@ -16,4 +16,3 @@  import core.sys.windows.basetyps, core.sys.windows.w32api;
 
 // I think this is just a helper macro for other win32 headers?
 //MACRO #define DEFINE_SHLGUID(n,l,w1,w2) DEFINE_GUID(n,l,w1,w2,0xC0,0,0,0,0,0,0,0x46)
-
diff --git a/libphobos/libdruntime/core/sys/windows/sspi.d b/libphobos/libdruntime/core/sys/windows/sspi.d
index 07a259622d2..21e982daa81 100644
--- a/libphobos/libdruntime/core/sys/windows/sspi.d
+++ b/libphobos/libdruntime/core/sys/windows/sspi.d
@@ -380,4 +380,3 @@  version (Unicode) {
     alias QUERY_SECURITY_PACKAGE_INFO_FN_A QUERY_SECURITY_PACKAGE_INFO_FN;
     alias INIT_SECURITY_INTERFACE_A INIT_SECURITY_INTERFACE;
 }
-
diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d
index fe65c0973e1..8ef6548981f 100644
--- a/libphobos/libdruntime/object.d
+++ b/libphobos/libdruntime/object.d
@@ -3765,6 +3765,7 @@  private size_t getArrayHash(const scope TypeInfo element, const scope void* ptr,
     if (!is(const(T) : T))
 {
     import core.internal.traits : Unconst;
+    import core.internal.array.duplication : _dup;
     static assert(is(T : Unconst!T), "Cannot implicitly convert type "~T.stringof~
                   " to "~Unconst!T.stringof~" in dup.");
 
@@ -3786,6 +3787,7 @@  private size_t getArrayHash(const scope TypeInfo element, const scope void* ptr,
 @property T[] dup(T)(const(T)[] a)
     if (is(const(T) : T))
 {
+    import core.internal.array.duplication : _dup;
     return _dup!(const(T), T)(a);
 }
 
@@ -3793,6 +3795,7 @@  private size_t getArrayHash(const scope TypeInfo element, const scope void* ptr,
 /// Provide the .idup array property.
 @property immutable(T)[] idup(T)(T[] a)
 {
+    import core.internal.array.duplication : _dup;
     static assert(is(T : immutable(T)), "Cannot implicitly convert type "~T.stringof~
                   " to immutable in idup.");
     return _dup!(T, immutable(T))(a);
@@ -3813,73 +3816,6 @@  private size_t getArrayHash(const scope TypeInfo element, const scope void* ptr,
     assert(s == "abc");
 }
 
-private U[] _dup(T, U)(scope T[] a) pure nothrow @trusted if (__traits(isPOD, T))
-{
-    if (__ctfe)
-        return _dupCtfe!(T, U)(a);
-
-    import core.stdc.string : memcpy;
-    auto arr = _d_newarrayU(typeid(T[]), a.length);
-    memcpy(arr.ptr, cast(const(void)*) a.ptr, T.sizeof * a.length);
-    return *cast(U[]*) &arr;
-}
-
-private U[] _dupCtfe(T, U)(scope T[] a)
-{
-    static if (is(T : void))
-        assert(0, "Cannot dup a void[] array at compile time.");
-    else
-    {
-        U[] res;
-        foreach (ref e; a)
-            res ~= e;
-        return res;
-    }
-}
-
-private U[] _dup(T, U)(T[] a) if (!__traits(isPOD, T))
-{
-    // note: copyEmplace is `@system` inside a `@trusted` block, so the __ctfe branch
-    // has the extra duty to infer _dup `@system` when the copy-constructor is `@system`.
-    if (__ctfe)
-        return _dupCtfe!(T, U)(a);
-
-    import core.lifetime: copyEmplace;
-    U[] res = () @trusted {
-        auto arr = cast(U*) _d_newarrayU(typeid(T[]), a.length);
-        size_t i;
-        scope (failure)
-        {
-            import core.internal.lifetime: emplaceInitializer;
-            // Initialize all remaining elements to not destruct garbage
-            foreach (j; i .. a.length)
-                emplaceInitializer(cast() arr[j]);
-        }
-        for (; i < a.length; i++)
-        {
-            copyEmplace(a.ptr[i], arr[i]);
-        }
-        return cast(U[])(arr[0..a.length]);
-    } ();
-
-    return res;
-}
-
-// https://issues.dlang.org/show_bug.cgi?id=22107
-@safe unittest
-{
-    static int i;
-    @safe struct S
-    {
-        this(this) { i++; }
-    }
-
-    void fun(scope S[] values...) @safe
-    {
-        values.dup;
-    }
-}
-
 // HACK:  This is a lie.  `_d_arraysetcapacity` is neither `nothrow` nor `pure`, but this lie is
 // necessary for now to prevent breaking code.
 private extern (C) size_t _d_arraysetcapacity(const TypeInfo ti, size_t newcapacity, void[]* arrptr) pure nothrow;
@@ -4067,8 +4003,6 @@  auto ref inout(T[]) assumeSafeAppend(T)(auto ref inout(T[]) arr) nothrow @system
     assert(is(typeof(b3) == immutable(int[])));
 }
 
-private extern (C) void[] _d_newarrayU(const scope TypeInfo ti, size_t length) pure nothrow;
-
 private void _doPostblit(T)(T[] arr)
 {
     // infer static postblit type, run postblit if any
@@ -4085,274 +4019,6 @@  private void _doPostblit(T)(T[] arr)
     }
 }
 
-@safe unittest
-{
-    static struct S1 { int* p; }
-    static struct S2 { @disable this(); }
-    static struct S3 { @disable this(this); }
-
-    int dg1() pure nothrow @safe
-    {
-        {
-           char[] m;
-           string i;
-           m = m.dup;
-           i = i.idup;
-           m = i.dup;
-           i = m.idup;
-        }
-        {
-           S1[] m;
-           immutable(S1)[] i;
-           m = m.dup;
-           i = i.idup;
-           static assert(!is(typeof(m.idup)));
-           static assert(!is(typeof(i.dup)));
-        }
-        {
-            S3[] m;
-            immutable(S3)[] i;
-            static assert(!is(typeof(m.dup)));
-            static assert(!is(typeof(i.idup)));
-        }
-        {
-            shared(S1)[] m;
-            m = m.dup;
-            static assert(!is(typeof(m.idup)));
-        }
-        {
-            int[] a = (inout(int)) { inout(const(int))[] a; return a.dup; }(0);
-        }
-        return 1;
-    }
-
-    int dg2() pure nothrow @safe
-    {
-        {
-           S2[] m = [S2.init, S2.init];
-           immutable(S2)[] i = [S2.init, S2.init];
-           m = m.dup;
-           m = i.dup;
-           i = m.idup;
-           i = i.idup;
-        }
-        return 2;
-    }
-
-    enum a = dg1();
-    enum b = dg2();
-    assert(dg1() == a);
-    assert(dg2() == b);
-}
-
-@system unittest
-{
-    static struct Sunpure { this(this) @safe nothrow {} }
-    static struct Sthrow { this(this) @safe pure {} }
-    static struct Sunsafe { this(this) @system pure nothrow {} }
-    static struct Snocopy { @disable this(this); }
-
-    [].dup!Sunpure;
-    [].dup!Sthrow;
-    cast(void) [].dup!Sunsafe;
-    static assert(!__traits(compiles, () pure    { [].dup!Sunpure; }));
-    static assert(!__traits(compiles, () nothrow { [].dup!Sthrow; }));
-    static assert(!__traits(compiles, () @safe   { [].dup!Sunsafe; }));
-    static assert(!__traits(compiles, ()         { [].dup!Snocopy; }));
-
-    [].idup!Sunpure;
-    [].idup!Sthrow;
-    [].idup!Sunsafe;
-    static assert(!__traits(compiles, () pure    { [].idup!Sunpure; }));
-    static assert(!__traits(compiles, () nothrow { [].idup!Sthrow; }));
-    static assert(!__traits(compiles, () @safe   { [].idup!Sunsafe; }));
-    static assert(!__traits(compiles, ()         { [].idup!Snocopy; }));
-}
-
-@safe unittest
-{
-    // test that the copy-constructor is called with .dup
-    static struct ArrElem
-    {
-        int a;
-        this(int a)
-        {
-            this.a = a;
-        }
-        this(ref const ArrElem)
-        {
-            a = 2;
-        }
-        this(ref ArrElem) immutable
-        {
-            a = 3;
-        }
-    }
-
-    auto arr = [ArrElem(1), ArrElem(1)];
-
-    ArrElem[] b = arr.dup;
-    assert(b[0].a == 2 && b[1].a == 2);
-
-    immutable ArrElem[] c = arr.idup;
-    assert(c[0].a == 3 && c[1].a == 3);
-}
-
-@system unittest
-{
-    static struct Sunpure { this(ref const typeof(this)) @safe nothrow {} }
-    static struct Sthrow { this(ref const typeof(this)) @safe pure {} }
-    static struct Sunsafe { this(ref const typeof(this)) @system pure nothrow {} }
-    [].dup!Sunpure;
-    [].dup!Sthrow;
-    cast(void) [].dup!Sunsafe;
-    static assert(!__traits(compiles, () pure    { [].dup!Sunpure; }));
-    static assert(!__traits(compiles, () nothrow { [].dup!Sthrow; }));
-    static assert(!__traits(compiles, () @safe   { [].dup!Sunsafe; }));
-
-    // for idup to work on structs that have copy constructors, it is necessary
-    // that the struct defines a copy constructor that creates immutable objects
-    static struct ISunpure { this(ref const typeof(this)) immutable @safe nothrow {} }
-    static struct ISthrow { this(ref const typeof(this)) immutable @safe pure {} }
-    static struct ISunsafe { this(ref const typeof(this)) immutable @system pure nothrow {} }
-    [].idup!ISunpure;
-    [].idup!ISthrow;
-    [].idup!ISunsafe;
-    static assert(!__traits(compiles, () pure    { [].idup!ISunpure; }));
-    static assert(!__traits(compiles, () nothrow { [].idup!ISthrow; }));
-    static assert(!__traits(compiles, () @safe   { [].idup!ISunsafe; }));
-}
-
-@safe unittest
-{
-    static int*[] pureFoo() pure { return null; }
-    { char[] s; immutable x = s.dup; }
-    { immutable x = (cast(int*[])null).dup; }
-    { immutable x = pureFoo(); }
-    { immutable x = pureFoo().dup; }
-}
-
-@safe unittest
-{
-    auto a = [1, 2, 3];
-    auto b = a.dup;
-    debug(SENTINEL) {} else
-        assert(b.capacity >= 3);
-}
-
-@system unittest
-{
-    // Bugzilla 12580
-    void[] m = [0];
-    shared(void)[] s = [cast(shared)1];
-    immutable(void)[] i = [cast(immutable)2];
-
-    s = s.dup;
-    static assert(is(typeof(s.dup) == shared(void)[]));
-
-    m = i.dup;
-    i = m.dup;
-    i = i.idup;
-    i = m.idup;
-    i = s.idup;
-    i = s.dup;
-    static assert(!__traits(compiles, m = s.dup));
-}
-
-@safe unittest
-{
-    // Bugzilla 13809
-    static struct S
-    {
-        this(this) {}
-        ~this() {}
-    }
-
-    S[] arr;
-    auto a = arr.dup;
-}
-
-@system unittest
-{
-    // Bugzilla 16504
-    static struct S
-    {
-        __gshared int* gp;
-        int* p;
-        // postblit and hence .dup could escape
-        this(this) { gp = p; }
-    }
-
-    int p;
-    scope S[1] arr = [S(&p)];
-    auto a = arr.dup; // dup does escape
-}
-
-// https://issues.dlang.org/show_bug.cgi?id=21983
-// dup/idup destroys partially constructed arrays on failure
-@safe unittest
-{
-    static struct SImpl(bool postblit)
-    {
-        int num;
-        long l = 0xDEADBEEF;
-
-        static if (postblit)
-        {
-            this(this)
-            {
-                if (this.num == 3)
-                    throw new Exception("");
-            }
-        }
-        else
-        {
-            this(scope ref const SImpl other)
-            {
-                if (other.num == 3)
-                    throw new Exception("");
-
-                this.num = other.num;
-                this.l = other.l;
-            }
-        }
-
-        ~this() @trusted
-        {
-            if (l != 0xDEADBEEF)
-            {
-                import core.stdc.stdio;
-                printf("Unexpected value: %lld\n", l);
-                fflush(stdout);
-                assert(false);
-            }
-        }
-    }
-
-    alias Postblit = SImpl!true;
-    alias Copy = SImpl!false;
-
-    static int test(S)()
-    {
-        S[4] arr = [ S(1), S(2), S(3), S(4) ];
-        try
-        {
-            arr.dup();
-            assert(false);
-        }
-        catch (Exception)
-        {
-            return 1;
-        }
-    }
-
-    static assert(test!Postblit());
-    assert(test!Postblit());
-
-    static assert(test!Copy());
-    assert(test!Copy());
-}
-
 /**
 Destroys the given object and optionally resets to initial state. It's used to
 _destroy an object, calling its destructor or finalizer so it no longer
diff --git a/libphobos/libdruntime/rt/dylib_fixes.c b/libphobos/libdruntime/rt/dylib_fixes.c
index e484fed7fb1..c1391b8538f 100644
--- a/libphobos/libdruntime/rt/dylib_fixes.c
+++ b/libphobos/libdruntime/rt/dylib_fixes.c
@@ -25,4 +25,3 @@  __attribute__((destructor)) static void finalizer ()
 {
     rt_term();
 }
-
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE
index 744e5ad5e78..1f0cfbf3e29 100644
--- a/libphobos/src/MERGE
+++ b/libphobos/src/MERGE
@@ -1,4 +1,4 @@ 
-1516ecad932d88a1618163384e6f69009d125391
+5748ca43fd5c3e31ce7a8511f542b67e5d5a3dc6
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/phobos repository.
diff --git a/libphobos/src/etc/c/curl.d b/libphobos/src/etc/c/curl.d
index 0c5b727944c..e6a10435d2b 100644
--- a/libphobos/src/etc/c/curl.d
+++ b/libphobos/src/etc/c/curl.d
@@ -1372,9 +1372,9 @@  alias curl_TimeCond = int;
 /** curl_strequal() and curl_strnequal() are subject for removal in a future
    libcurl, see lib/README.curlx for details */
 extern (C) {
-int  curl_strequal(in const(char) *s1, in const(char) *s2);
+int  curl_strequal(scope const(char) *s1, scope const(char) *s2);
 /// ditto
-int  curl_strnequal(in const(char) *s1, in const(char) *s2, size_t n);
+int  curl_strnequal(scope const(char) *s1, scope const(char) *s2, size_t n);
 }
 enum CurlForm {
     nothing, /********** the first one is unused ************/
@@ -1464,7 +1464,7 @@  CURLFORMcode  curl_formadd(curl_httppost **httppost, curl_httppost **last_post,.
  * Should return the buffer length passed to it as the argument "len" on
  *   success.
  */
-alias curl_formget_callback = size_t function(void *arg, in const(char) *buf, size_t len);
+alias curl_formget_callback = size_t function(void *arg, const(char) *buf, size_t len);
 
 /**
  * Name: curl_formget()
@@ -1494,7 +1494,7 @@  void  curl_formfree(curl_httppost *form);
  * Returns a malloc()'ed string that MUST be curl_free()ed after usage is
  * complete. DEPRECATED - see lib/README.curlx
  */
-char * curl_getenv(in const(char) *variable);
+char * curl_getenv(scope const(char) *variable);
 
 /**
  * Name: curl_version()
@@ -1514,10 +1514,10 @@  char * curl_version();
  * %XX versions). This function returns a new allocated string or NULL if an
  * error occurred.
  */
-char * curl_easy_escape(CURL *handle, in const(char) *string, int length);
+char * curl_easy_escape(CURL *handle, scope const(char) *string, int length);
 
 /** the previous version: */
-char * curl_escape(in const(char) *string, int length);
+char * curl_escape(scope const(char) *string, int length);
 
 
 /**
@@ -1531,10 +1531,10 @@  char * curl_escape(in const(char) *string, int length);
  * Conversion Note: On non-ASCII platforms the ASCII %XX codes are
  * converted into the host encoding.
  */
-char * curl_easy_unescape(CURL *handle, in const(char) *string, int length, int *outlength);
+char * curl_easy_unescape(CURL *handle, scope const(char) *string, int length, int *outlength);
 
 /** the previous version */
-char * curl_unescape(in const(char) *string, int length);
+char * curl_unescape(scope const(char) *string, int length);
 
 /**
  * Name: curl_free()
@@ -1608,7 +1608,7 @@  struct curl_slist
  * Appends a string to a linked list. If no list exists, it will be created
  * first. Returns the new list, after appending.
  */
-curl_slist * curl_slist_append(curl_slist *, in const(char) *);
+curl_slist * curl_slist_append(curl_slist *, const(char) *);
 
 /**
  * Name: curl_slist_free_all()
diff --git a/libphobos/src/std/algorithm/comparison.d b/libphobos/src/std/algorithm/comparison.d
index 2fcc2bacd5c..b810fbb9258 100644
--- a/libphobos/src/std/algorithm/comparison.d
+++ b/libphobos/src/std/algorithm/comparison.d
@@ -1027,7 +1027,7 @@  template equal(alias pred = "a == b")
         }
     }
 
-    private bool equalLoop(Rs...)(Rs rs)
+    private bool equalLoop(Rs...)(ref Rs rs)
     {
         for (; !rs[0].empty; rs[0].popFront)
             static foreach (r; rs[1 .. $])
diff --git a/libphobos/src/std/algorithm/iteration.d b/libphobos/src/std/algorithm/iteration.d
index af665c41197..300a8978fe5 100644
--- a/libphobos/src/std/algorithm/iteration.d
+++ b/libphobos/src/std/algorithm/iteration.d
@@ -1263,19 +1263,22 @@  public:
 
 // filter
 /**
-Implements the higher order filter function. The predicate is passed to
-$(REF unaryFun, std,functional), and can either accept a string, or any callable
-that can be executed via `pred(element)`.
+`filter!(predicate)(range)` returns a new range containing only elements `x` in `range` for
+which `predicate(x)` returns `true`.
+
+The predicate is passed to $(REF unaryFun, std,functional), and can be either a string, or
+any callable that can be executed via `pred(element)`.
 
 Params:
     predicate = Function to apply to each element of range
 
 Returns:
-    `filter!(predicate)(range)` returns a new range containing only elements `x` in `range` for
-    which `predicate(x)` returns `true`.
+    An input range that contains the filtered elements. If `range` is at least a forward range, the return value of `filter`
+    will also be a forward range.
 
 See_Also:
-    $(HTTP en.wikipedia.org/wiki/Filter_(higher-order_function), Filter (higher-order function))
+    $(HTTP en.wikipedia.org/wiki/Filter_(higher-order_function), Filter (higher-order function)),
+    $(REF filterBidirectional, std,algorithm,iteration)
  */
 template filter(alias predicate)
 if (is(typeof(unaryFun!predicate)))
diff --git a/libphobos/src/std/algorithm/searching.d b/libphobos/src/std/algorithm/searching.d
index 55a14385e8a..daa4b99045e 100644
--- a/libphobos/src/std/algorithm/searching.d
+++ b/libphobos/src/std/algorithm/searching.d
@@ -2512,6 +2512,8 @@  RandomAccessRange find(RandomAccessRange, alias pred, InputRange)(
 Convenience function. Like find, but only returns whether or not the search
 was successful.
 
+For more information about `pred` see $(LREF find).
+
 See_Also:
 $(REF among, std,algorithm,comparison) for checking a value against multiple possibilities.
  +/
@@ -2622,6 +2624,8 @@  Advances `r` until it finds the first two adjacent elements `a`,
 `b` that satisfy `pred(a, b)`. Performs $(BIGOH r.length)
 evaluations of `pred`.
 
+For more information about `pred` see $(LREF find).
+
 Params:
     pred = The predicate to satisfy.
     r = A $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) to
@@ -2698,6 +2702,8 @@  Advances `seq` by calling `seq.popFront` until either
 `find!(pred)(choices, seq.front)` is `true`, or `seq` becomes empty.
 Performs $(BIGOH seq.length * choices.length) evaluations of `pred`.
 
+For more information about `pred` see $(LREF find).
+
 Params:
     pred = The predicate to use for determining a match.
     seq = The $(REF_ALTTEXT input range, isInputRange, std,range,primitives) to
@@ -2758,6 +2764,8 @@  if (isInputRange!InputRange && isForwardRange!ForwardRange)
  * Similarly, the haystack is positioned so as `pred` evaluates to `false` for
  * `haystack.front`.
  *
+ * For more information about `pred` see $(LREF find).
+
  * Params:
  *  haystack = The
  *   $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) to search
@@ -2882,6 +2890,8 @@  $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) and
 the type of `result[0]` and `result[1]` is the same as $(REF takeExactly,
 std,range).
 
+For more information about `pred` see $(LREF find).
+
 Params:
     pred = Predicate to use for comparing needle against haystack.
     haystack = The range to search.
@@ -4595,6 +4605,8 @@  $(REF_ALTTEXT input range, isInputRange, std,range,primitives) starts with (one
 of) the given needle(s) or, if no needles are given,
 if its front element fulfils predicate `pred`.
 
+For more information about `pred` see $(LREF find).
+
 Params:
 
     pred = Predicate to use in comparing the elements of the haystack and the
diff --git a/libphobos/src/std/conv.d b/libphobos/src/std/conv.d
index 8f6c3bf568e..9164e079865 100644
--- a/libphobos/src/std/conv.d
+++ b/libphobos/src/std/conv.d
@@ -3419,17 +3419,20 @@  if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum
         }
     }
 
+    Target result = cast(Target) (sign ? -ldval : ldval);
+
     // if overflow occurred
-    enforce(ldval != real.infinity, new ConvException("Range error"));
+    import std.math : isFinite;
+    enforce(isFinite(result), new ConvException("Range error"));
 
     advanceSource();
     static if (doCount)
     {
-        return tuple!("data", "count")(cast (Target) (sign ? -ldval : ldval), count);
+        return tuple!("data", "count")(result, count);
     }
     else
     {
-        return cast (Target) (sign ? -ldval : ldval);
+        return result;
     }
 }
 
@@ -3785,6 +3788,16 @@  if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum
         assertThrown!ConvException(parse!double(s));
 }
 
+@safe unittest // https://issues.dlang.org/show_bug.cgi?id=22637
+{
+    import std.exception : assertThrown, assertNotThrown;
+    auto src = "9991232549867999698999493543521458974414359998784641646846435132132543645435456345634541999999999999999"
+    ~ "9999999943321231321311999231345312413646846354354354399999934153465464654646464654134135354199999999996515734999"
+    ~ "9999999320135273486741354354731567431324134999999999999999999999999999999999999999999999135411.9";
+    assertThrown!ConvException(parse!double(src));
+    static if (real.max_10_exp > 310) assertNotThrown!ConvException(parse!real(src));
+}
+
 /**
 Parsing one character off a range returns the first element and calls `popFront`.
 
diff --git a/libphobos/src/std/experimental/checkedint.d b/libphobos/src/std/experimental/checkedint.d
index 9237341d418..2be5a2ea150 100644
--- a/libphobos/src/std/experimental/checkedint.d
+++ b/libphobos/src/std/experimental/checkedint.d
@@ -1,6 +1,6 @@ 
 
 /**
- * This module is now deprecated, use $(MREF std, experimental)
+ * This module is now deprecated, use $(MREF std, checkedint)
  * instead.
  *
  * Copyright: Copyright The D Language Foundation 2005 - 2015.
diff --git a/libphobos/src/std/experimental/logger/core.d b/libphobos/src/std/experimental/logger/core.d
index d899db70793..f3c69324ba1 100644
--- a/libphobos/src/std/experimental/logger/core.d
+++ b/libphobos/src/std/experimental/logger/core.d
@@ -4,6 +4,7 @@  Source: $(PHOBOSSRC std/experimental/logger/core.d)
 */
 module std.experimental.logger.core;
 
+import core.atomic : atomicLoad, atomicOp, atomicStore, MemoryOrder;
 import core.sync.mutex : Mutex;
 import std.datetime.date : DateTime;
 import std.datetime.systime : Clock, SysTime;
@@ -555,14 +556,14 @@  abstract class Logger
     Params:
          lv = `LogLevel` to use for this `Logger` instance.
     */
-    this(LogLevel lv) @safe
+    this(this This)(LogLevel lv)
     {
         this.logLevel_ = lv;
         this.fatalHandler_ = delegate() {
             throw new Error("A fatal log message was logged");
         };
 
-        this.mutex = new Mutex();
+        this.mutex = new typeof(mutex)();
     }
 
     /** A custom logger must implement this method in order to work in a
@@ -661,7 +662,7 @@  abstract class Logger
     /// Ditto
     @property final void logLevel(const LogLevel lv) @safe @nogc
     {
-        synchronized (mutex) this.logLevel_ = lv;
+        atomicStore(this.logLevel_, lv);
     }
 
     /** This `delegate` is called in case a log message with
@@ -1403,28 +1404,28 @@  abstract class Logger
 
 // Thread Global
 
-private __gshared Logger stdSharedDefaultLogger;
+private shared Logger stdSharedDefaultLogger;
 private shared Logger stdSharedLogger;
 private shared LogLevel stdLoggerGlobalLogLevel = LogLevel.all;
 
 /* This method returns the global default Logger.
  * Marked @trusted because of excessive reliance on __gshared data
  */
-private @property Logger defaultSharedLoggerImpl() @trusted
+private @property shared(Logger) defaultSharedLoggerImpl() @trusted
 {
     import core.lifetime : emplace;
     import std.stdio : stderr;
 
     __gshared align(__traits(classInstanceAlignment, FileLogger))
-        void[__traits(classInstanceSize, FileLogger)] _buffer;
+        void[__traits(classInstanceSize, FileLogger)] _buffer = void;
 
     import std.concurrency : initOnce;
     initOnce!stdSharedDefaultLogger({
         auto buffer = cast(ubyte[]) _buffer;
-        return emplace!FileLogger(buffer, stderr, LogLevel.info);
+        return cast(shared) emplace!(FileLogger)(buffer, stderr, LogLevel.info);
     }());
 
-    return stdSharedDefaultLogger;
+    return atomicLoad(stdSharedDefaultLogger);
 }
 
 /** This property sets and gets the default `Logger`. Unless set to another
@@ -1452,19 +1453,12 @@  if (sharedLog !is myLogger)
     sharedLog = new myLogger;
 -------------
 */
-@property Logger sharedLog() @safe
+@property shared(Logger) sharedLog() @safe
 {
-    static auto trustedLoad(ref shared Logger logger) @trusted
-    {
-        import core.atomic : atomicLoad, MemoryOrder;
-        return cast() atomicLoad!(MemoryOrder.acq)(logger);
-            //FIXME: Casting shared away here. Not good. See issue 16232.
-    }
-
     // If we have set up our own logger use that
-    if (auto logger = trustedLoad(stdSharedLogger))
+    if (auto logger = atomicLoad!(MemoryOrder.seq)(stdSharedLogger))
     {
-        return logger;
+        return atomicLoad(logger);
     }
     else
     {
@@ -1474,10 +1468,9 @@  if (sharedLog !is myLogger)
 }
 
 /// Ditto
-@property void sharedLog(Logger logger) @trusted
+@property void sharedLog(shared(Logger) logger) @safe
 {
-    import core.atomic : atomicStore, MemoryOrder;
-    atomicStore!(MemoryOrder.rel)(stdSharedLogger, cast(shared) logger);
+    atomicStore!(MemoryOrder.seq)(stdSharedLogger, atomicLoad(logger));
 }
 
 /** This methods get and set the global `LogLevel`.
@@ -1523,9 +1516,12 @@  class StdForwardLogger : Logger
         this.fatalHandler = delegate() {};
     }
 
-    override protected void writeLogMsg(ref LogEntry payload)
+    override protected void writeLogMsg(ref LogEntry payload) @trusted
     {
-          sharedLog.forwardMsg(payload);
+        synchronized (sharedLog.mutex)
+        {
+            (cast() sharedLog).forwardMsg(payload);
+        }
     }
 }
 
@@ -1535,6 +1531,40 @@  class StdForwardLogger : Logger
     auto nl1 = new StdForwardLogger(LogLevel.all);
 }
 
+@safe unittest
+{
+    import core.thread : Thread, msecs;
+
+    static class RaceLogger : Logger
+    {
+        int value;
+        this() @safe shared
+        {
+            super(LogLevel.init);
+        }
+        override void writeLogMsg(ref LogEntry payload) @safe
+        {
+            import core.thread : Thread, msecs;
+            if (payload.msg == "foo")
+            {
+                value = 42;
+                () @trusted { Thread.sleep(100.msecs); }();
+                assert(value == 42, "Another thread changed the value");
+            }
+            else
+            {
+                () @trusted { Thread.sleep(50.msecs); } ();
+                value = 13;
+            }
+        }
+    }
+
+    sharedLog = new shared RaceLogger;
+    scope(exit) { sharedLog = null; }
+    () @trusted { new Thread(() { log("foo"); }).start(); }();
+    log("bar");
+}
+
 /** This `LogLevel` is unqiue to every thread.
 
 The thread local `Logger` will use this `LogLevel` to filter log calls
@@ -1561,7 +1591,7 @@  private @property Logger stdThreadLocalLogImpl() @trusted
 }
 
 /** This function returns a thread unique `Logger`, that by default
-propergates all data logged to it to the `sharedLog`.
+propagates all data logged to it to the `sharedLog`.
 
 These properties can be used to set and get this `Logger`. Every
 modification to this `Logger` will only be visible in the thread the
@@ -1671,10 +1701,12 @@  version (StdUnittest) private void testFuncNames(Logger logger) @safe
 
     auto oldunspecificLogger = sharedLog;
     scope(exit) {
-        sharedLog = oldunspecificLogger;
+        sharedLog = atomicLoad(oldunspecificLogger);
     }
 
-    sharedLog = tl1;
+    () @trusted {
+        sharedLog = cast(shared) tl1;
+    }();
 
     log();
     assert(tl1.line == __LINE__ - 1);
@@ -1793,22 +1825,34 @@  version (StdUnittest) private void testFuncNames(Logger logger) @safe
     assert(l.line == lineNumber);
     assert(l.logLevel == LogLevel.all);
 
-    auto oldunspecificLogger = sharedLog;
+    Logger oldunspecificLogger;
+    () @trusted {
+        oldunspecificLogger = cast() sharedLog;
+    }();
 
     assert(oldunspecificLogger.logLevel == LogLevel.info,
          to!string(oldunspecificLogger.logLevel));
 
     assert(l.logLevel == LogLevel.all);
-    sharedLog = l;
+
+    () @trusted {
+        sharedLog = cast(shared) l;
+    }();
+
     assert(globalLogLevel == LogLevel.all,
             to!string(globalLogLevel));
 
     scope(exit)
     {
-        sharedLog = oldunspecificLogger;
+        () @trusted {
+            sharedLog = atomicLoad(cast(shared) oldunspecificLogger);
+        }();
     }
 
-    assert(sharedLog.logLevel == LogLevel.all);
+    () @trusted {
+        assert((cast() sharedLog).logLevel == LogLevel.all);
+    }();
+
     assert(stdThreadLocalLog.logLevel == LogLevel.all);
     assert(globalLogLevel == LogLevel.all);
 
@@ -1880,13 +1924,14 @@  version (StdUnittest) private void testFuncNames(Logger logger) @safe
     string filename = deleteme ~ __FUNCTION__ ~ ".tempLogFile";
     FileLogger l = new FileLogger(filename);
     auto oldunspecificLogger = sharedLog;
-    sharedLog = l;
+
+    sharedLog = cast(shared) l;
 
     scope(exit)
     {
         remove(filename);
         assert(!exists(filename));
-        sharedLog = oldunspecificLogger;
+        sharedLog = atomicLoad(oldunspecificLogger);
         globalLogLevel = LogLevel.all;
     }
 
@@ -1923,7 +1968,7 @@  version (StdUnittest) private void testFuncNames(Logger logger) @safe
     scope(exit)
     {
         remove(filename);
-        sharedLog = oldunspecificLogger;
+        sharedLog = atomicLoad(oldunspecificLogger);
         globalLogLevel = LogLevel.all;
     }
 
@@ -1931,8 +1976,11 @@  version (StdUnittest) private void testFuncNames(Logger logger) @safe
     string written = "this should be written to file";
 
     auto l = new FileLogger(filename);
-    sharedLog = l;
-    sharedLog.logLevel = LogLevel.critical;
+    sharedLog = cast(shared) l;
+
+    () @trusted {
+        (cast() sharedLog).logLevel = LogLevel.critical;
+    }();
 
     log(LogLevel.error, false, notWritten);
     log(LogLevel.critical, true, written);
@@ -1974,11 +2022,14 @@  version (StdUnittest) private void testFuncNames(Logger logger) @safe
 
     auto mem = new TestLogger;
     mem.fatalHandler = delegate() {};
-    sharedLog = mem;
+
+    () @trusted {
+        sharedLog = cast(shared) mem;
+    }();
 
     scope(exit)
     {
-        sharedLog = oldunspecificLogger;
+        sharedLog = atomicLoad(oldunspecificLogger);
         globalLogLevel = LogLevel.all;
     }
 
@@ -2221,11 +2272,14 @@  version (StdUnittest) private void testFuncNames(Logger logger) @safe
 
     auto mem = new TestLogger;
     mem.fatalHandler = delegate() {};
-    sharedLog = mem;
+
+    () @trusted {
+        sharedLog = cast(shared) mem;
+    }();
 
     scope(exit)
     {
-        sharedLog = oldunspecificLogger;
+        sharedLog = atomicLoad(oldunspecificLogger);
         globalLogLevel = LogLevel.all;
     }
 
@@ -2477,10 +2531,13 @@  version (StdUnittest) private void testFuncNames(Logger logger) @safe
 
     stdThreadLocalLog.logLevel = LogLevel.all;
 
-    sharedLog = mem;
+    () @trusted {
+        sharedLog = cast(shared) mem;
+    }();
+
     scope(exit)
     {
-        sharedLog = oldunspecificLogger;
+        sharedLog = atomicLoad(oldunspecificLogger);
         globalLogLevel = LogLevel.all;
     }
 
@@ -2707,12 +2764,15 @@  version (StdUnittest) private void testFuncNames(Logger logger) @safe
 
     scope(exit)
     {
-        sharedLog = oldunspecificLogger;
+        sharedLog = atomicLoad(oldunspecificLogger);
         globalLogLevel = LogLevel.all;
     }
 
     auto tl = new TestLogger(LogLevel.info);
-    sharedLog = tl;
+
+    () @trusted {
+        sharedLog = cast(shared) tl;
+    }();
 
     trace("trace");
     assert(tl.msg.indexOf("trace") == -1);
@@ -2730,7 +2790,7 @@  version (StdUnittest) private void testFuncNames(Logger logger) @safe
 
     scope(exit)
     {
-        sharedLog = oldunspecificLogger;
+        sharedLog = atomicLoad(oldunspecificLogger);
         globalLogLevel = LogLevel.all;
     }
 
@@ -2738,7 +2798,10 @@  version (StdUnittest) private void testFuncNames(Logger logger) @safe
 
     auto tl = new TestLogger(LogLevel.info);
     logger.insertLogger("required", tl);
-    sharedLog = logger;
+
+    () @trusted {
+        sharedLog = cast(shared) logger;
+    }();
 
     trace("trace");
     assert(tl.msg.indexOf("trace") == -1);
@@ -2774,14 +2837,12 @@  version (StdUnittest) private void testFuncNames(Logger logger) @safe
 // Workaround for atomics not allowed in @safe code
 private auto trustedLoad(T)(ref shared T value) @trusted
 {
-    import core.atomic : atomicLoad, MemoryOrder;
     return atomicLoad!(MemoryOrder.acq)(value);
 }
 
 // ditto
 private void trustedStore(T)(ref shared T dst, ref T src) @trusted
 {
-    import core.atomic : atomicStore, MemoryOrder;
     atomicStore!(MemoryOrder.rel)(dst, src);
 }
 
@@ -2789,7 +2850,7 @@  private void trustedStore(T)(ref shared T dst, ref T src) @trusted
 // to shared logger
 @system unittest
 {
-    import core.atomic, core.thread, std.concurrency;
+    import core.thread, std.concurrency;
 
     static shared logged_count = 0;
 
@@ -2826,10 +2887,13 @@  private void trustedStore(T)(ref shared T dst, ref T src) @trusted
     auto oldSharedLog = sharedLog;
     scope(exit)
     {
-        sharedLog = oldSharedLog;
+        sharedLog = atomicLoad(oldSharedLog);
     }
 
-    sharedLog = new IgnoredLog;
+    () @trusted {
+        sharedLog = cast(shared) new IgnoredLog;
+    }();
+
     Thread[] spawned;
 
     foreach (i; 0 .. 4)
@@ -2849,7 +2913,9 @@  private void trustedStore(T)(ref shared T dst, ref T src) @trusted
 
 @safe unittest
 {
-    auto dl = cast(FileLogger) sharedLog;
+    auto dl = () @trusted {
+        return cast(FileLogger) cast() sharedLog;
+    }();
     assert(dl !is null);
     assert(dl.logLevel == LogLevel.info);
     assert(globalLogLevel == LogLevel.all);
@@ -2946,7 +3012,7 @@  private void trustedStore(T)(ref shared T dst, ref T src) @trusted
     auto oldShared = sharedLog;
     scope(exit)
     {
-        sharedLog = oldShared;
+        sharedLog = atomicLoad(oldShared);
         if (exists(fn))
         {
             remove(fn);
@@ -2956,7 +3022,11 @@  private void trustedStore(T)(ref shared T dst, ref T src) @trusted
     auto ts = [ "Test log 1", "Test log 2", "Test log 3"];
 
     auto fl = new FileLogger(fn);
-    sharedLog = fl;
+
+    () @trusted {
+        sharedLog = cast(shared) fl;
+    }();
+
     assert(exists(fn));
 
     foreach (t; ts)
diff --git a/libphobos/src/std/experimental/logger/filelogger.d b/libphobos/src/std/experimental/logger/filelogger.d
index 5112e520bc0..457012e21b5 100644
--- a/libphobos/src/std/experimental/logger/filelogger.d
+++ b/libphobos/src/std/experimental/logger/filelogger.d
@@ -259,7 +259,7 @@  class FileLogger : Logger
     file.close();
 }
 
-@safe unittest
+@system unittest
 {
     auto dl = cast(FileLogger) sharedLog;
     assert(dl !is null);
diff --git a/libphobos/src/std/experimental/logger/multilogger.d b/libphobos/src/std/experimental/logger/multilogger.d
index 9acd23a59cd..35936901964 100644
--- a/libphobos/src/std/experimental/logger/multilogger.d
+++ b/libphobos/src/std/experimental/logger/multilogger.d
@@ -187,7 +187,7 @@  class MultiLogger : Logger
     assert(line.indexOf(iMsg) != -1, line ~ ":" ~ tMsg);
 }
 
-@safe unittest
+@system unittest
 {
     auto dl = cast(FileLogger) sharedLog;
     assert(dl !is null);
diff --git a/libphobos/src/std/file.d b/libphobos/src/std/file.d
index b8b4a8ce6c6..d6cac41ef04 100644
--- a/libphobos/src/std/file.d
+++ b/libphobos/src/std/file.d
@@ -1510,7 +1510,7 @@  private
         ushort bitmapcount, reserved;
         attrgroup_t commonattr, volattr, dirattr, fileattr, forkattr;
     }
-    extern(C) int setattrlist(in char* path, scope ref attrlist attrs,
+    extern(C) int setattrlist(scope const(char)* path, scope ref attrlist attrs,
         scope void* attrbuf, size_t attrBufSize, c_ulong options) nothrow @nogc @system;
 }
 
diff --git a/libphobos/src/std/format/internal/write.d b/libphobos/src/std/format/internal/write.d
index f1d69643495..2fd6ff72990 100644
--- a/libphobos/src/std/format/internal/write.d
+++ b/libphobos/src/std/format/internal/write.d
@@ -1337,7 +1337,7 @@  if (is(StringTypeOf!T) && !is(StaticArrayTypeOf!T) && !is(T == enum) && !hasToSt
 /*
     Static-size arrays are formatted as dynamic arrays.
  */
-void formatValueImpl(Writer, T, Char)(auto ref Writer w, auto ref const(T) obj,
+void formatValueImpl(Writer, T, Char)(auto ref Writer w, auto ref T obj,
     scope const ref FormatSpec!Char f)
 if (is(StaticArrayTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
 {
@@ -1782,13 +1782,13 @@  void formatChar(Writer)(ref Writer w, in dchar c, in char quote)
     Associative arrays are formatted by using `':'` and $(D ", ") as
     separators, and enclosed by `'['` and `']'`.
  */
-void formatValueImpl(Writer, T, Char)(auto ref Writer w, const(T) obj, scope const ref FormatSpec!Char f)
+void formatValueImpl(Writer, T, Char)(auto ref Writer w, T obj, scope const ref FormatSpec!Char f)
 if (is(AssocArrayTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
 {
     import std.format : enforceFmt, formatValue;
     import std.range.primitives : put;
 
-    AssocArrayTypeOf!(const(T)) val = obj;
+    AssocArrayTypeOf!T val = obj;
     const spec = f.spec;
 
     enforceFmt(spec == 's' || spec == '(',
diff --git a/libphobos/src/std/format/package.d b/libphobos/src/std/format/package.d
index 76d68f6cff6..3f6f33adf6e 100644
--- a/libphobos/src/std/format/package.d
+++ b/libphobos/src/std/format/package.d
@@ -1356,6 +1356,30 @@  if (isSomeChar!Char)
     assert(result == "    1");
 }
 
+// https://issues.dlang.org/show_bug.cgi?id=23245
+@safe unittest
+{
+    static struct S
+    {
+        string toString() { return "S"; }
+    }
+
+    S[1] s;
+    assert(format("%s", s) == "[S]");
+}
+
+// https://issues.dlang.org/show_bug.cgi?id=23246
+@safe unittest
+{
+    static struct S
+    {
+        string toString() { return "S"; }
+    }
+
+    S[int] s = [0 : S()];
+    assert(format("%s", s) == "[0:S]");
+}
+
 /// ditto
 typeof(fmt) format(alias fmt, Args...)(Args args)
 if (isSomeString!(typeof(fmt)))
diff --git a/libphobos/src/std/math/package.d b/libphobos/src/std/math/package.d
index 7443b0dea2e..19982ec216a 100644
--- a/libphobos/src/std/math/package.d
+++ b/libphobos/src/std/math/package.d
@@ -383,6 +383,7 @@  template floatTraits(T)
             enum ushort EXPBIAS = 0x3FE0;
             enum uint EXPMASK_INT = 0x7FF0_0000;
             enum uint MANTISSAMASK_INT = 0x000F_FFFF; // for the MSB only
+            enum ulong MANTISSAMASK_LONG = 0x000F_FFFF_FFFF_FFFF;
             enum realFormat = RealFormat.ieeeDouble;
             version (LittleEndian)
             {
diff --git a/libphobos/src/std/math/rounding.d b/libphobos/src/std/math/rounding.d
index 5c8d708c489..7dbe89b2dee 100644
--- a/libphobos/src/std/math/rounding.d
+++ b/libphobos/src/std/math/rounding.d
@@ -908,7 +908,9 @@  T floorImpl(T)(const T x) @trusted pure nothrow @nogc
 
         // Other kinds of extractors for real formats.
         static if (F.realFormat == RealFormat.ieeeSingle)
-            int vi;
+            uint vi;
+        else static if (F.realFormat == RealFormat.ieeeDouble)
+            ulong vi;
     }
     floatBits y = void;
     y.rv = x;
@@ -919,15 +921,14 @@  T floorImpl(T)(const T x) @trusted pure nothrow @nogc
     static if (F.realFormat == RealFormat.ieeeSingle)
     {
         int exp = ((y.vi >> (T.mant_dig - 1)) & 0xff) - 0x7f;
+        enum mantissa_mask = F.MANTISSAMASK_INT;
+        enum sign_shift = 31;
     }
     else static if (F.realFormat == RealFormat.ieeeDouble)
     {
-        int exp = ((y.vu[F.EXPPOS_SHORT] >> 4) & 0x7ff) - 0x3ff;
-
-        version (LittleEndian)
-            int pos = 0;
-        else
-            int pos = 3;
+        long exp = ((y.vi >> (T.mant_dig - 1)) & 0x7ff) - 0x3ff;
+        enum mantissa_mask = F.MANTISSAMASK_LONG;
+        enum sign_shift = 63;
     }
     else static if (F.realFormat == RealFormat.ieeeExtended ||
                     F.realFormat == RealFormat.ieeeExtended53)
@@ -959,18 +960,21 @@  T floorImpl(T)(const T x) @trusted pure nothrow @nogc
             return 0.0;
     }
 
-    static if (F.realFormat == RealFormat.ieeeSingle)
+    static if (F.realFormat == RealFormat.ieeeSingle ||
+               F.realFormat == RealFormat.ieeeDouble)
     {
         if (exp < (T.mant_dig - 1))
         {
             // Clear all bits representing the fraction part.
-            const uint fraction_mask = F.MANTISSAMASK_INT >> exp;
+            // Note: the fraction mask represents the floating point number 0.999999...
+            // i.e: `2.0 ^^ (exp - T.mant_dig + 1) * (fraction_mask + 1) == 1.0`
+            const fraction_mask = mantissa_mask >> exp;
 
             if ((y.vi & fraction_mask) != 0)
             {
-                // If 'x' is negative, then first substract 1.0 from the value.
-                if (y.vi < 0)
-                    y.vi += 0x00800000 >> exp;
+                // If 'x' is negative, then first substract (1.0 - T.epsilon) from the value.
+                if (y.vi >> sign_shift)
+                    y.vi += fraction_mask;
                 y.vi &= ~fraction_mask;
             }
         }
diff --git a/libphobos/src/std/random.d b/libphobos/src/std/random.d
index 106e51ceedb..b2206ce56ba 100644
--- a/libphobos/src/std/random.d
+++ b/libphobos/src/std/random.d
@@ -2762,7 +2762,7 @@  Returns:
     return a `ref` to the $(D range element), otherwise it will return
     a copy.
  */
-auto ref choice(Range, RandomGen = Random)(auto ref Range range, ref RandomGen urng)
+auto ref choice(Range, RandomGen = Random)(Range range, ref RandomGen urng)
 if (isRandomAccessRange!Range && hasLength!Range && isUniformRNG!RandomGen)
 {
     assert(range.length > 0,
@@ -2772,7 +2772,22 @@  if (isRandomAccessRange!Range && hasLength!Range && isUniformRNG!RandomGen)
 }
 
 /// ditto
-auto ref choice(Range)(auto ref Range range)
+auto ref choice(Range)(Range range)
+{
+    return choice(range, rndGen);
+}
+
+/// ditto
+auto ref choice(Range, RandomGen = Random)(ref Range range, ref RandomGen urng)
+if (isRandomAccessRange!Range && hasLength!Range && isUniformRNG!RandomGen)
+{
+    assert(range.length > 0,
+           __PRETTY_FUNCTION__ ~ ": invalid Range supplied. Range cannot be empty");
+    return range[uniform(size_t(0), $, urng)];
+}
+
+/// ditto
+auto ref choice(Range)(ref Range range)
 {
     return choice(range, rndGen);
 }
@@ -2827,6 +2842,39 @@  auto ref choice(Range)(auto ref Range range)
            "Choice did not return a valid element from the given Range");
 }
 
+@safe unittest // issue 18631
+{
+    auto rng = MinstdRand0(42);
+    const a = [0,1,2];
+    const(int[]) b = [0, 1, 2];
+    auto x = choice(a);
+    auto y = choice(b);
+    auto z = choice(cast(const)[1, 2, 3]);
+    auto x1 = choice(a, rng);
+    auto y1 = choice(b, rng);
+    auto z1 = choice(cast(const)[1, 2, 3], rng);
+}
+
+@safe unittest // Ref range (issue 18631 PR)
+{
+    struct TestRange
+    {
+        int x;
+        ref int front() return {return x;}
+        ref int back() return {return x;}
+        void popFront() {}
+        void popBack() {}
+        bool empty = false;
+        TestRange save() {return this;}
+        size_t length = 10;
+        alias opDollar = length;
+        ref int opIndex(size_t i) return {return x;}
+    }
+
+    TestRange r = TestRange(10);
+    int* s = &choice(r);
+}
+
 /**
 Shuffles elements of `r` using `gen` as a shuffler. `r` must be
 a random-access range with length.  If no RNG is specified, `rndGen`
@@ -3008,8 +3056,16 @@  if (isRandomAccessRange!Range)
 }
 
 /**
-Rolls a dice with relative probabilities stored in $(D
-proportions). Returns the index in `proportions` that was chosen.
+Get a random index into a list of weights corresponding to each index
+
+Similar to rolling a die with relative probabilities stored in `proportions`.
+Returns the index in `proportions` that was chosen.
+
+Note:
+    Usually, dice are 'fair', meaning that each side has equal probability
+    to come up, in which case `1 + uniform(0, 6)` can simply be used.
+    In future Phobos versions, this function might get renamed to something like
+    `weightedChoice` to avoid confusion.
 
 Params:
     rnd = (optional) random number generator to use; if not
@@ -3055,6 +3111,9 @@  if (isNumeric!Num)
 ///
 @safe unittest
 {
+    auto d6  = 1 + dice(1, 1, 1, 1, 1, 1); // fair dice roll
+    auto d6b = 1 + dice(2, 1, 1, 1, 1, 1); // double the chance to roll '1'
+
     auto x = dice(0.5, 0.5);   // x is 0 or 1 in equal proportions
     auto y = dice(50, 50);     // y is 0 or 1 in equal proportions
     auto z = dice(70, 20, 10); // z is 0 70% of the time, 1 20% of the time,
diff --git a/libphobos/src/std/stdio.d b/libphobos/src/std/stdio.d
index 8614dc96901..a1fe962906b 100644
--- a/libphobos/src/std/stdio.d
+++ b/libphobos/src/std/stdio.d
@@ -1132,10 +1132,9 @@  each item is inferred from the size and type of the input array, respectively.
 
 Returns: The slice of `buffer` containing the data that was actually read.
 This will be shorter than `buffer` if EOF was reached before the buffer
-could be filled.
+could be filled. If the buffer is empty, it will be returned.
 
-Throws: `Exception` if `buffer` is empty.
-        `ErrnoException` if the file is not opened or the call to `fread` fails.
+Throws: `ErrnoException` if the file is not opened or the call to `fread` fails.
 
 `rawRead` always reads in binary mode on Windows.
  */
@@ -1144,7 +1143,7 @@  Throws: `Exception` if `buffer` is empty.
         import std.exception : enforce, errnoEnforce;
 
         if (!buffer.length)
-            throw new Exception("rawRead must take a non-empty buffer");
+            return buffer;
         enforce(isOpen, "Attempting to read from an unopened file");
         version (Windows)
         {
@@ -1211,6 +1210,16 @@  Throws: `Exception` if `buffer` is empty.
         }
     }
 
+    // https://issues.dlang.org/show_bug.cgi?id=13893
+    @system unittest
+    {
+        import std.exception : assertNotThrown;
+
+        File f;
+        ubyte[0] u;
+        assertNotThrown(f.rawRead(u));
+    }
+
 /**
 Calls $(HTTP cplusplus.com/reference/clibrary/cstdio/fwrite.html, fwrite) for the file
 handle. The number of items to write and the size of each
diff --git a/libphobos/src/std/sumtype.d b/libphobos/src/std/sumtype.d
index 1d375ef4d7e..160665c6a31 100644
--- a/libphobos/src/std/sumtype.d
+++ b/libphobos/src/std/sumtype.d
@@ -1941,79 +1941,8 @@  private template matchImpl(Flag!"exhaustive" exhaustive, handlers...)
     auto ref matchImpl(SumTypes...)(auto ref SumTypes args)
     if (allSatisfy!(isSumType, SumTypes) && args.length > 0)
     {
-        enum typeCount(SumType) = SumType.Types.length;
         alias stride(size_t i) = .stride!(i, Map!(typeCount, SumTypes));
-
-        /* A TagTuple represents a single possible set of tags that `args`
-         * could have at runtime.
-         *
-         * Because D does not allow a struct to be the controlling expression
-         * of a switch statement, we cannot dispatch on the TagTuple directly.
-         * Instead, we must map each TagTuple to a unique integer and generate
-         * a case label for each of those integers.
-         *
-         * This mapping is implemented in `fromCaseId` and `toCaseId`. It uses
-         * the same technique that's used to map index tuples to memory offsets
-         * in a multidimensional static array.
-         *
-         * For example, when `args` consists of two SumTypes with two member
-         * types each, the TagTuples corresponding to each case label are:
-         *
-         *   case 0:  TagTuple([0, 0])
-         *   case 1:  TagTuple([1, 0])
-         *   case 2:  TagTuple([0, 1])
-         *   case 3:  TagTuple([1, 1])
-         *
-         * When there is only one argument, the caseId is equal to that
-         * argument's tag.
-         */
-        static struct TagTuple
-        {
-            size_t[SumTypes.length] tags;
-            alias tags this;
-
-            invariant
-            {
-                static foreach (i; 0 .. tags.length)
-                {
-                    assert(tags[i] < SumTypes[i].Types.length, "Invalid tag");
-                }
-            }
-
-            this(ref const(SumTypes) args)
-            {
-                static foreach (i; 0 .. tags.length)
-                {
-                    tags[i] = args[i].tag;
-                }
-            }
-
-            static TagTuple fromCaseId(size_t caseId)
-            {
-                TagTuple result;
-
-                // Most-significant to least-significant
-                static foreach_reverse (i; 0 .. result.length)
-                {
-                    result[i] = caseId / stride!i;
-                    caseId %= stride!i;
-                }
-
-                return result;
-            }
-
-            size_t toCaseId()
-            {
-                size_t result;
-
-                static foreach (i; 0 .. tags.length)
-                {
-                    result += tags[i] * stride!i;
-                }
-
-                return result;
-            }
-        }
+        alias TagTuple = .TagTuple!(SumTypes);
 
         /*
          * A list of arguments to be passed to a handler needed for the case
@@ -2149,6 +2078,81 @@  private template matchImpl(Flag!"exhaustive" exhaustive, handlers...)
     }
 }
 
+private enum typeCount(SumType) = SumType.Types.length;
+
+/* A TagTuple represents a single possible set of tags that `args`
+ * could have at runtime.
+ *
+ * Because D does not allow a struct to be the controlling expression
+ * of a switch statement, we cannot dispatch on the TagTuple directly.
+ * Instead, we must map each TagTuple to a unique integer and generate
+ * a case label for each of those integers.
+ *
+ * This mapping is implemented in `fromCaseId` and `toCaseId`. It uses
+ * the same technique that's used to map index tuples to memory offsets
+ * in a multidimensional static array.
+ *
+ * For example, when `args` consists of two SumTypes with two member
+ * types each, the TagTuples corresponding to each case label are:
+ *
+ *   case 0:  TagTuple([0, 0])
+ *   case 1:  TagTuple([1, 0])
+ *   case 2:  TagTuple([0, 1])
+ *   case 3:  TagTuple([1, 1])
+ *
+ * When there is only one argument, the caseId is equal to that
+ * argument's tag.
+ */
+private struct TagTuple(SumTypes...)
+{
+    size_t[SumTypes.length] tags;
+    alias tags this;
+
+    alias stride(size_t i) = .stride!(i, Map!(typeCount, SumTypes));
+
+    invariant
+    {
+        static foreach (i; 0 .. tags.length)
+        {
+            assert(tags[i] < SumTypes[i].Types.length, "Invalid tag");
+        }
+    }
+
+    this(ref const(SumTypes) args)
+    {
+        static foreach (i; 0 .. tags.length)
+        {
+            tags[i] = args[i].tag;
+        }
+    }
+
+    static TagTuple fromCaseId(size_t caseId)
+    {
+        TagTuple result;
+
+        // Most-significant to least-significant
+        static foreach_reverse (i; 0 .. result.length)
+        {
+            result[i] = caseId / stride!i;
+            caseId %= stride!i;
+        }
+
+        return result;
+    }
+
+    size_t toCaseId()
+    {
+        size_t result;
+
+        static foreach (i; 0 .. tags.length)
+        {
+            result += tags[i] * stride!i;
+        }
+
+        return result;
+    }
+}
+
 // Matching
 @safe unittest
 {
diff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d
index 8a3e22f74a9..4ecfb1051d1 100644
--- a/libphobos/src/std/typecons.d
+++ b/libphobos/src/std/typecons.d
@@ -4905,8 +4905,14 @@  if (is(Interface == interface) && is(BaseClass == class))
         // - try default first
         // - only on a failure run & return fallback
         enum fallback = q{
-            scope (failure) return fallback.%1$s(args);
-            return default_.%1$s(args);
+            try
+            {
+                return default_.%1$s(args);
+            }
+            catch (Exception)
+            {
+                return fallback.%1$s(args);
+            }
         }.format(__traits(identifier, func));
     }
 
@@ -6589,15 +6595,11 @@  if (!is(T == class) && !(is(T == interface)))
         private enum enableGCScan = hasIndirections!T;
     }
 
-    // TODO remove pure when https://issues.dlang.org/show_bug.cgi?id=15862 has been fixed
     extern(C) private pure nothrow @nogc static
     {
         pragma(mangle, "free") void pureFree( void *ptr );
         static if (enableGCScan)
-        {
-            pragma(mangle, "gc_addRange") void pureGcAddRange( in void* p, size_t sz, const TypeInfo ti = null );
-            pragma(mangle, "gc_removeRange") void pureGcRemoveRange( in void* p );
-        }
+            import core.memory : GC;
     }
 
     /// `RefCounted` storage implementation.
@@ -6637,7 +6639,7 @@  if (!is(T == class) && !(is(T == interface)))
             {
                 import std.internal.memory : enforceCalloc;
                 _store = cast(Impl*) enforceCalloc(1, Impl.sizeof);
-                pureGcAddRange(&_store._payload, T.sizeof);
+                GC.addRange(&_store._payload, T.sizeof);
             }
             else
             {
@@ -6650,7 +6652,7 @@  if (!is(T == class) && !(is(T == interface)))
         {
             static if (enableGCScan)
             {
-                pureGcRemoveRange(&this._store._payload);
+                GC.removeRange(&this._store._payload);
             }
             pureFree(_store);
             _store = null;
diff --git a/libphobos/src/std/uni/package.d b/libphobos/src/std/uni/package.d
index 98735ac1a88..e12a70cfe80 100644
--- a/libphobos/src/std/uni/package.d
+++ b/libphobos/src/std/uni/package.d
@@ -7032,9 +7032,7 @@  template genericDecodeGrapheme(bool getValue)
             case RI:
                 if (isRegionalIndicator(ch))
                     mixin(eat);
-                else
-                    goto L_End_Extend;
-            break;
+                goto L_End_Extend;
             case L:
                 if (isHangL(ch))
                     mixin(eat);
@@ -7166,6 +7164,10 @@  if (isInputRange!Input && is(immutable ElementType!Input == immutable dchar))
     s = "\u11A8\u0308\uAC01";
     assert(equal(decodeGrapheme(s)[], "\u11A8\u0308"));
     assert(equal(decodeGrapheme(s)[], "\uAC01"));
+
+    // Two Union Jacks of the Great Britain
+    s = "\U0001F1EC\U0001F1E7\U0001F1EC\U0001F1E7";
+    assert(equal(decodeGrapheme(s)[], "\U0001F1EC\U0001F1E7"));
 }
 
 /++
diff --git a/libphobos/testsuite/libphobos.gc/nocollect.d b/libphobos/testsuite/libphobos.gc/nocollect.d
index 5df1483a284..64ed2221134 100644
--- a/libphobos/testsuite/libphobos.gc/nocollect.d
+++ b/libphobos/testsuite/libphobos.gc/nocollect.d
@@ -12,4 +12,4 @@  void main()
 
     stats = GC.profileStats();
     assert(stats.numCollections == 0);
-}
\ No newline at end of file
+}