diff mbox series

[committed] d: Merge upstream dmd, druntime a88e1335f7, phobos 1921d29df.

Message ID 20230710220957.1579524-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] d: Merge upstream dmd, druntime a88e1335f7, phobos 1921d29df. | expand

Commit Message

Iain Buclaw July 10, 2023, 10:09 p.m. UTC
Hi,

This patch merges the D front-end and run-time library with upstream dmd
a88e1335f7, and standard library with phobos 1921d29df.

Synchronizing with the latest bug fixes in the v2.104.1 release.

D front-end changes:

	- Import dmd v2.104.1.
	- Deprecation phase ended for access to private method when
	  overloaded with public method.

D runtime changes:

	- Import druntime v2.104.1.
	- Linux input header translations were added to druntime.
	- Integration with the Valgrind `memcheck' tool has been added
	  to the garbage collector.

Phobos changes:

	- Import phobos v2.104.1.

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

Regards,
Iain.

---
gcc/d/ChangeLog:

	* dmd/MERGE: Merge upstream dmd a88e1335f7.
	* dmd/VERSION: Bump version to v2.104.1.

libphobos/ChangeLog:

	* libdruntime/MERGE: Merge upstream druntime a88e1335f7.
	* src/MERGE: Merge upstream phobos 1921d29df.
	* config.h.in: Regenerate.
	* configure: Regenerate.
	* configure.ac (libphobos-checking): Add valgrind flag.
	(DRUNTIME_LIBRARIES_VALGRIND): Call.
	* libdruntime/Makefile.am (DRUNTIME_CSOURCES): Add
	etc/valgrind/valgrind_.c.
	(DRUNTIME_DSOURCES): Add etc/valgrind/valgrind.d.
	(DRUNTIME_DSOURCES_LINUX): Add core/sys/linux/input.d,
	core/sys/linux/input_event_codes.d, core/sys/linux/uinput.d.
	* libdruntime/Makefile.in: Regenerate.
	* m4/druntime/libraries.m4 (DRUNTIME_LIBRARIES_VALGRIND): Define.
---
 gcc/d/dmd/MERGE                               |   2 +-
 gcc/d/dmd/README.md                           |   1 -
 gcc/d/dmd/VERSION                             |   2 +-
 gcc/d/dmd/access.d                            |   4 -
 gcc/d/dmd/attrib.d                            |   3 +-
 gcc/d/dmd/canthrow.d                          |   4 +-
 gcc/d/dmd/cparse.d                            |   2 +-
 gcc/d/dmd/dcast.d                             |   1 +
 gcc/d/dmd/declaration.d                       |   2 +-
 gcc/d/dmd/dinterpret.d                        |  28 +-
 gcc/d/dmd/dmangle.d                           |   2 +-
 gcc/d/dmd/dmodule.d                           |  19 +-
 gcc/d/dmd/dsymbolsem.d                        |  51 +-
 gcc/d/dmd/dtemplate.d                         |  64 +-
 gcc/d/dmd/dtoh.d                              |   2 +-
 gcc/d/dmd/escape.d                            |  36 +-
 gcc/d/dmd/expression.d                        |  25 +-
 gcc/d/dmd/expressionsem.d                     | 103 ++-
 gcc/d/dmd/hdrgen.d                            |   8 +-
 gcc/d/dmd/initsem.d                           |  14 +-
 gcc/d/dmd/inline.d                            |   4 +-
 gcc/d/dmd/lexer.d                             |   2 +-
 gcc/d/dmd/mtype.d                             |  19 +-
 gcc/d/dmd/opover.d                            |   8 +-
 gcc/d/dmd/optimize.d                          |   2 +-
 gcc/d/dmd/parse.d                             |  21 +-
 gcc/d/dmd/root/array.d                        |  18 +
 gcc/d/dmd/semantic2.d                         |   7 +
 gcc/d/dmd/semantic3.d                         |   4 +-
 gcc/d/dmd/statementsem.d                      |  30 +-
 gcc/d/dmd/traits.d                            |   6 +-
 gcc/d/dmd/transitivevisitor.d                 |   8 +-
 gcc/d/dmd/typesem.d                           |  12 +-
 gcc/testsuite/gdc.test/compilable/b20938.d    |   3 +-
 .../gdc.test/compilable/commontype.d          |  12 +-
 .../compilable/imports/pkg20008/package.d     |   9 +
 .../compilable/imports/pkg20008/submod.d      |   2 +
 .../imports/pkg20008/subpkg/package.d         |   7 +
 .../imports/pkg20008/subpkg/subsubmod.d       |   9 +
 .../gdc.test/compilable/imports/test9692b.d   |   2 +-
 .../gdc.test/compilable/issue24018.d          |  10 +
 .../gdc.test/compilable/stc_traits.d          | 106 +--
 gcc/testsuite/gdc.test/compilable/test13668.d |   2 +-
 gcc/testsuite/gdc.test/compilable/test16635.d |   2 +-
 gcc/testsuite/gdc.test/compilable/test17143.d |   2 +-
 gcc/testsuite/gdc.test/compilable/test17373.d |   4 +-
 gcc/testsuite/gdc.test/compilable/test17545.d |   2 +-
 gcc/testsuite/gdc.test/compilable/test19728.d |  14 +-
 gcc/testsuite/gdc.test/compilable/test20008.d |   6 +
 gcc/testsuite/gdc.test/compilable/test21282.d |   2 +-
 gcc/testsuite/gdc.test/compilable/test21330.d |   4 +-
 gcc/testsuite/gdc.test/compilable/test23965.d |  11 +
 gcc/testsuite/gdc.test/compilable/test23978.d |  30 +
 gcc/testsuite/gdc.test/compilable/test23979.d |  17 +
 gcc/testsuite/gdc.test/compilable/test23986.d |  11 +
 gcc/testsuite/gdc.test/compilable/test24013.d |  43 +
 gcc/testsuite/gdc.test/compilable/test24017.d |  11 +
 gcc/testsuite/gdc.test/compilable/test9692.d  |   4 +-
 .../gdc.test/compilable/testInference.d       |   6 +-
 .../gdc.test/fail_compilation/callconst.d     |  16 +
 .../gdc.test/fail_compilation/casttuple.d     |   6 +-
 .../gdc.test/fail_compilation/cppmangle.d     |   2 +-
 .../gdc.test/fail_compilation/dassert.d       |   2 +-
 .../gdc.test/fail_compilation/diag13884.d     |   2 +-
 .../gdc.test/fail_compilation/diag14876.d     |   2 +-
 .../fail_compilation/dtor_attributes.d        |   2 +-
 .../gdc.test/fail_compilation/e15876_1.d      |  13 +-
 .../gdc.test/fail_compilation/e15876_2.d      |   9 +-
 .../gdc.test/fail_compilation/e15876_3.d      |  27 +-
 .../gdc.test/fail_compilation/e15876_4.d      |  23 +-
 .../gdc.test/fail_compilation/e15876_5.d      |  11 +-
 .../gdc.test/fail_compilation/enum_init.d     |   2 +
 .../gdc.test/fail_compilation/fail12436.d     |   2 +-
 .../gdc.test/fail_compilation/fail15755.d     |   2 +-
 .../gdc.test/fail_compilation/fail16772.d     |   3 +-
 .../gdc.test/fail_compilation/fail19209.d     |   2 +-
 .../gdc.test/fail_compilation/fail196.d       |  38 +-
 .../gdc.test/fail_compilation/fail21206.d     |   3 +-
 .../gdc.test/fail_compilation/fail21275.d     |   5 +-
 .../gdc.test/fail_compilation/fail222.d       |   4 +-
 .../gdc.test/fail_compilation/fail22729.d     |  39 +
 .../gdc.test/fail_compilation/fail23745.d     |   2 +-
 .../gdc.test/fail_compilation/fail315.d       |  15 +-
 .../gdc.test/fail_compilation/funcpostattr.d  |  21 +
 .../gdc.test/fail_compilation/ice11965.d      |   9 +-
 .../gdc.test/fail_compilation/ice11982.d      |  17 +-
 .../gdc.test/fail_compilation/ice12574.d      |   2 +-
 .../gdc.test/fail_compilation/ice14424.d      |   2 +-
 .../gdc.test/fail_compilation/ice15855.d      |  21 +-
 .../fail_compilation/imports/issue23947a.d    |   8 +
 .../gdc.test/fail_compilation/issue20422.d    |   9 +-
 .../gdc.test/fail_compilation/issue23947.d    |  10 +
 .../gdc.test/fail_compilation/lexer4.d        |   2 +-
 .../fail_compilation/misc_parser_err_cov1.d   |   3 +-
 .../gdc.test/fail_compilation/missingbrace.d  |  10 +
 .../gdc.test/fail_compilation/retscope.d      |   2 +-
 .../gdc.test/fail_compilation/test20245.d     |   2 +-
 .../gdc.test/fail_compilation/test21025.d     |  25 +
 .../gdc.test/fail_compilation/test23968.d     |  23 +
 .../gdc.test/fail_compilation/test23982.d     |  36 +
 .../gdc.test/fail_compilation/typeerrors.d    |   2 +-
 .../fail_compilation/unmatchedbrace.d         |  10 +
 gcc/testsuite/gdc.test/runnable/functype.d    |   2 +-
 gcc/testsuite/gdc.test/runnable/interface2.d  |   4 +-
 gcc/testsuite/gdc.test/runnable/link10425.d   |   2 +-
 gcc/testsuite/gdc.test/runnable/sdtor.d       |  36 +
 gcc/testsuite/gdc.test/runnable/template9.d   |   3 +-
 gcc/testsuite/gdc.test/runnable/test23959.d   |  30 +
 .../gdc.test/runnable/testcontracts.d         |   2 +-
 gcc/testsuite/gdc.test/runnable/uda.d         |  42 +-
 gcc/testsuite/gdc.test/runnable/xtest46.d     |  10 +-
 gcc/testsuite/gdc.test/runnable/xtest46_gc.d  |  10 +-
 libphobos/config.h.in                         |  12 +
 libphobos/configure                           | 101 ++-
 libphobos/configure.ac                        |  16 +-
 libphobos/libdruntime/MERGE                   |   2 +-
 libphobos/libdruntime/Makefile.am             |  16 +-
 libphobos/libdruntime/Makefile.in             |  58 +-
 libphobos/libdruntime/core/atomic.d           |  10 +-
 .../core/internal/array/concatenation.d       |  17 +-
 .../core/internal/gc/impl/conservative/gc.d   | 131 ++-
 .../libdruntime/core/internal/gc/proxy.d      |   7 +-
 .../libdruntime/core/internal/parseoptions.d  |  12 +-
 libphobos/libdruntime/core/lifetime.d         |  10 +-
 libphobos/libdruntime/core/stdc/assert_.d     |  13 +-
 libphobos/libdruntime/core/stdc/wchar_.d      |   5 +-
 libphobos/libdruntime/core/sys/linux/input.d  | 236 ++++++
 .../core/sys/linux/input_event_codes.d        | 758 ++++++++++++++++++
 libphobos/libdruntime/core/sys/linux/uinput.d |  85 ++
 .../libdruntime/core/sys/openbsd/unistd.d     |   4 +
 libphobos/libdruntime/core/sys/windows/dll.d  |  49 +-
 libphobos/libdruntime/etc/valgrind/valgrind.d |  85 ++
 .../libdruntime/etc/valgrind/valgrind_.c      | 102 +++
 libphobos/libdruntime/object.d                |  40 +-
 libphobos/libdruntime/rt/lifetime.d           |  12 +-
 libphobos/libdruntime/rt/minfo.d              |   4 +-
 libphobos/libdruntime/rt/util/typeinfo.d      |   2 +-
 libphobos/m4/druntime/libraries.m4            |  53 ++
 libphobos/src/MERGE                           |   2 +-
 libphobos/src/std/algorithm/iteration.d       |   4 +-
 libphobos/src/std/algorithm/mutation.d        |   2 +-
 libphobos/src/std/algorithm/searching.d       |  48 +-
 libphobos/src/std/complex.d                   |   4 +-
 libphobos/src/std/container/array.d           |   2 +-
 libphobos/src/std/conv.d                      |  22 +-
 libphobos/src/std/exception.d                 |   2 +-
 .../building_blocks/kernighan_ritchie.d       |   2 +-
 libphobos/src/std/format/internal/floats.d    |  12 +-
 libphobos/src/std/format/internal/write.d     |   8 +-
 libphobos/src/std/math/operations.d           |  15 +-
 libphobos/src/std/path.d                      |  22 +-
 libphobos/src/std/random.d                    |   4 +-
 libphobos/src/std/range/package.d             |  41 +-
 libphobos/src/std/regex/internal/ir.d         |  25 +-
 libphobos/src/std/signals.d                   |   4 +-
 libphobos/src/std/stdio.d                     |  90 ++-
 libphobos/src/std/traits.d                    |   6 +-
 libphobos/src/std/typecons.d                  | 134 ++++
 libphobos/src/std/uni/package.d               |  39 +-
 159 files changed, 3079 insertions(+), 681 deletions(-)
 create mode 100644 gcc/testsuite/gdc.test/compilable/imports/pkg20008/package.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/imports/pkg20008/submod.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/imports/pkg20008/subpkg/package.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/imports/pkg20008/subpkg/subsubmod.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/issue24018.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test20008.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test23965.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test23978.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test23979.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test23986.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test24013.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test24017.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/callconst.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/fail22729.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/funcpostattr.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/imports/issue23947a.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/issue23947.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/missingbrace.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test21025.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test23968.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test23982.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/unmatchedbrace.d
 create mode 100644 gcc/testsuite/gdc.test/runnable/test23959.d
 create mode 100644 libphobos/libdruntime/core/sys/linux/input.d
 create mode 100644 libphobos/libdruntime/core/sys/linux/input_event_codes.d
 create mode 100644 libphobos/libdruntime/core/sys/linux/uinput.d
 create mode 100644 libphobos/libdruntime/etc/valgrind/valgrind.d
 create mode 100644 libphobos/libdruntime/etc/valgrind/valgrind_.c
diff mbox series

Patch

diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 1cff48a7b2a..308d51b55d0 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@ 
-17ccd12af386543c0b9935bf7e0a8e701b903105
+a88e1335f7ea767ef438c34998f5d1f26008c586
 
 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/README.md b/gcc/d/dmd/README.md
index 79215b7a0ea..4fd7831866a 100644
--- a/gcc/d/dmd/README.md
+++ b/gcc/d/dmd/README.md
@@ -174,7 +174,6 @@ 
 | [cond.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/cond.d)              | Evaluate `static if`, `version` `debug `                                                    |
 | [staticcond.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/staticcond.d)  | Lazily evaluate static conditions for `static if`, `static assert` and template constraints |
 | [delegatize.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/delegatize.d)  | Converts expression to delegates for `lazy` parameters                                      |
-| [eh.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/eh.d)                  | Generate tables for exception handling                                                      |
 | [nspace.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/nspace.d)          | Namespace for `extern (C++, Module)`                                                        |
 | [intrange.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/intrange.d)      | [Value range propagation](https://digitalmars.com/articles/b62.html)                        |
 | [dimport.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dimport.d)        | Renamed imports (`import aliasSymbol = pkg1.pkg2.symbol`)                                   |
diff --git a/gcc/d/dmd/VERSION b/gcc/d/dmd/VERSION
index d5aee89f2cb..9c46eea2d8c 100644
--- a/gcc/d/dmd/VERSION
+++ b/gcc/d/dmd/VERSION
@@ -1 +1 @@ 
-v2.104.0
+v2.104.1
diff --git a/gcc/d/dmd/access.d b/gcc/d/dmd/access.d
index f2d68d53d75..668129a5385 100644
--- a/gcc/d/dmd/access.d
+++ b/gcc/d/dmd/access.d
@@ -16,17 +16,13 @@  module dmd.access;
 import dmd.aggregate;
 import dmd.astenums;
 import dmd.dclass;
-import dmd.declaration;
 import dmd.dmodule;
 import dmd.dscope;
 import dmd.dstruct;
 import dmd.dsymbol;
-import dmd.errors;
 import dmd.expression;
-import dmd.func;
 import dmd.globals;
 import dmd.location;
-import dmd.mtype;
 import dmd.tokens;
 
 private enum LOG = false;
diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d
index c08382cbd04..ff4ebe8eaf9 100644
--- a/gcc/d/dmd/attrib.d
+++ b/gcc/d/dmd/attrib.d
@@ -653,7 +653,8 @@  extern (C++) final class VisibilityDeclaration : AttribDeclaration
         {
             Module m = sc._module;
 
-            // While isAncestorPackageOf does an equality check, the fix for issue 17441 adds a check to see if
+            // https://issues.dlang.org/show_bug.cgi?id=17441
+            // While isAncestorPackageOf does an equality check, the fix for the issue adds a check to see if
             // each package's .isModule() properites are equal.
             //
             // Properties generated from `package(foo)` i.e. visibility.pkg have .isModule() == null.
diff --git a/gcc/d/dmd/canthrow.d b/gcc/d/dmd/canthrow.d
index 09d39ca6f1c..89d5519b5d8 100644
--- a/gcc/d/dmd/canthrow.d
+++ b/gcc/d/dmd/canthrow.d
@@ -80,7 +80,7 @@  extern (C++) /* CT */ BE canThrow(Expression e, FuncDeclaration func, bool mustN
                     if (!f.isDtorDeclaration())
                         errorSupplementalInferredAttr(f, 10, false, STC.nothrow_);
 
-                    e.checkOverridenDtor(null, f, dd => dd.type.toTypeFunction().isnothrow, "not nothrow");
+                    e.checkOverriddenDtor(null, f, dd => dd.type.toTypeFunction().isnothrow, "not nothrow");
                 }
                 else if (func)
                 {
@@ -118,7 +118,7 @@  extern (C++) /* CT */ BE canThrow(Expression e, FuncDeclaration func, bool mustN
                     {
                         auto sd = ts.sym;
                         const id = ce.f.ident;
-                        if (sd.postblit && isArrayConstructionOrAssign(id))
+                        if (sd.postblit && isArrayConstruction(id))
                         {
                             checkFuncThrows(ce, sd.postblit);
                             return;
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index 33669e38c41..1b6b2bb4b1b 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -4235,7 +4235,7 @@  final class CParser(AST) : Parser!AST
                         return false;
                     /*
                         https://issues.dlang.org/show_bug.cgi?id=22267
-                        Fix issue 22267: If the parser encounters the following
+                        If the parser encounters the following
                             `identifier variableName = (expression);`
                         the initializer is not identified as such since the parentheses
                         cause the parser to keep walking indefinitely
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index 6fcc2806585..b2aa6433baf 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -2922,6 +2922,7 @@  Type typeMerge(Scope* sc, EXP op, ref Expression pe1, ref Expression pe2)
         ubyte mod = MODmerge(t1.mod, t2.mod);
         t1 = t1.castMod(mod);
         t2 = t2.castMod(mod);
+        return Lret(t1);
     }
 
 Lagain:
diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d
index cfa6988a861..5559b93eb20 100644
--- a/gcc/d/dmd/declaration.d
+++ b/gcc/d/dmd/declaration.d
@@ -599,7 +599,7 @@  extern (C++) final class TupleDeclaration : Declaration
 
     override const(char)* kind() const
     {
-        return "tuple";
+        return "sequence";
     }
 
     override Type getType()
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index 5b27a07339a..cb74a079cd4 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -2412,7 +2412,7 @@  public:
                 continue;
             if (ex.op == EXP.voidExpression)
             {
-                e.error("CTFE internal error: void element `%s` in tuple", exp.toChars());
+                e.error("CTFE internal error: void element `%s` in sequence", exp.toChars());
                 assert(0);
             }
 
@@ -3890,7 +3890,7 @@  public:
             newval = copyLiteral(newval).copy();
             assignInPlace(oldval, newval);
         }
-        else if (wantCopy && e.op == EXP.assign)
+        else if (wantCopy && (e.op == EXP.assign || e.op == EXP.loweredAssignExp))
         {
             // Currently postblit/destructor calls on static array are done
             // in the druntime internal functions so they don't appear in AST.
@@ -4299,7 +4299,7 @@  public:
             rb.newval = newval;
             rb.refCopy = wantRef || cow;
             rb.needsPostblit = sd && sd.postblit && e.op != EXP.blit && e.e2.isLvalue();
-            rb.needsDtor = sd && sd.dtor && e.op == EXP.assign;
+            rb.needsDtor = sd && sd.dtor && (e.op == EXP.assign || e.op == EXP.loweredAssignExp);
             if (Expression ex = rb.assignTo(existingAE, cast(size_t)lowerbound, cast(size_t)upperbound))
                 return ex;
 
@@ -4773,12 +4773,11 @@  public:
                     result = CTFEExp.voidexp;
                 return;
             }
-            else if (isArrayConstructionOrAssign(fd.ident))
+            else if (isArrayConstruction(fd.ident))
             {
-                // In expressionsem.d, the following lowerings were performed:
-                // * `T[x] ea = eb;` to `_d_array{,set}ctor(ea[], eb[]);`.
-                // * `ea = eb` to `_d_array{,setassign,assign_l,assign_r}(ea[], eb)`.
-                // The following code will rewrite them back to `ea = eb` and
+                // In expressionsem.d, `T[x] ea = eb;` was lowered to:
+                // `_d_array{,set}ctor(ea[], eb[]);`.
+                // The following code will rewrite it back to `ea = eb` and
                 // then interpret that expression.
 
                 if (fd.ident == Id._d_arrayctor)
@@ -4791,17 +4790,14 @@  public:
                     ea = ea.isCastExp.e1;
 
                 Expression eb = (*e.arguments)[1];
-                if (eb.isCastExp() && fd.ident != Id._d_arraysetctor)
+                if (eb.isCastExp() && fd.ident == Id._d_arrayctor)
                     eb = eb.isCastExp.e1;
 
-                Expression rewrittenExp;
-                if (fd.ident == Id._d_arrayctor || fd.ident == Id._d_arraysetctor)
-                    rewrittenExp = new ConstructExp(e.loc, ea, eb);
-                else
-                    rewrittenExp = new AssignExp(e.loc, ea, eb);
+                ConstructExp ce = new ConstructExp(e.loc, ea, eb);
+                ce.type = ea.type;
 
-                rewrittenExp.type = ea.type;
-                result = interpret(rewrittenExp, istate);
+                ce.type = ea.type;
+                result = interpret(ce, istate);
 
                 return;
             }
diff --git a/gcc/d/dmd/dmangle.d b/gcc/d/dmd/dmangle.d
index 72a44765787..ad1e8165668 100644
--- a/gcc/d/dmd/dmangle.d
+++ b/gcc/d/dmd/dmangle.d
@@ -888,7 +888,7 @@  public:
                 buf.writeByte('V');
                 if (ea.op == EXP.tuple)
                 {
-                    ea.error("tuple is not a valid template value argument");
+                    ea.error("sequence is not a valid template value argument");
                     continue;
                 }
                 // Now that we know it is not an alias, we MUST obtain a value
diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index 149a5b1aeb5..f00dec7a4e3 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/dmd/dmodule.d
@@ -53,6 +53,10 @@  import dmd.target;
 import dmd.utils;
 import dmd.visitor;
 
+version (IN_GCC) {}
+else version (IN_LLVM) {}
+else version = MARS;
+
 // function used to call semantic3 on a module's dependencies
 void semantic3OnDependencies(Module m)
 {
@@ -615,9 +619,18 @@  extern (C++) final class Module : Package
         if (FileName.equals(srcfile.toString(), "object.d"))
         {
             .error(loc, "cannot find source code for runtime library file 'object.d'");
-            errorSupplemental(loc, "dmd might not be correctly installed. Run 'dmd -man' for installation instructions.");
-            const dmdConfFile = global.inifilename.length ? FileName.canonicalName(global.inifilename) : "not found";
-            errorSupplemental(loc, "config file: %.*s", cast(int)dmdConfFile.length, dmdConfFile.ptr);
+            version (IN_LLVM)
+            {
+                errorSupplemental(loc, "ldc2 might not be correctly installed.");
+                errorSupplemental(loc, "Please check your ldc2.conf configuration file.");
+                errorSupplemental(loc, "Installation instructions can be found at http://wiki.dlang.org/LDC.");
+            }
+            version (MARS)
+            {
+                errorSupplemental(loc, "dmd might not be correctly installed. Run 'dmd -man' for installation instructions.");
+                const dmdConfFile = global.inifilename.length ? FileName.canonicalName(global.inifilename) : "not found";
+                errorSupplemental(loc, "config file: %.*s", cast(int)dmdConfFile.length, dmdConfFile.ptr);
+            }
         }
         else if (FileName.ext(this.arg) || !loc.isValid())
         {
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index a5cd63b1d4f..622e28691a6 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -587,6 +587,8 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
                     const loc = (s ? s : dsym).loc;
                     loc.errorSupplemental("required by type `%s`", dsym.type.toChars());
                 }
+                errorSupplemental(dsym.loc, "see https://dlang.org/spec/struct.html#opaque_struct_unions");
+                errorSupplemental(dsym.loc, "perhaps declare a variable with pointer type `%s*` instead", dsym.type.toChars());
 
                 // Flag variable as error to avoid invalid error messages due to unknown size
                 dsym.type = Type.terror;
@@ -693,7 +695,7 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 size_t tedim = te.exps.length;
                 if (tedim != nelems)
                 {
-                    error(dsym.loc, "tuple of %d elements cannot be assigned to tuple of %d elements", cast(int)tedim, cast(int)nelems);
+                    error(dsym.loc, "sequence of %d elements cannot be assigned to sequence of %d elements", cast(int)tedim, cast(int)nelems);
                     for (size_t u = tedim; u < nelems; u++) // fill dummy expression
                         te.exps.push(ErrorExp.get());
                 }
@@ -2042,7 +2044,7 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
         {
         }
         else
-            ns.exp.error("compile time string constant (or tuple) expected, not `%s`",
+            ns.exp.error("compile time string constant (or sequence) expected, not `%s`",
                          ns.exp.toChars());
         attribSemantic(ns);
     }
@@ -2712,7 +2714,7 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
             }
             if (i + 1 != tempdecl.parameters.length && tp.isTemplateTupleParameter())
             {
-                tempdecl.error("template tuple parameter must be last one");
+                tempdecl.error("template sequence parameter must be the last one");
                 tempdecl.errors = true;
             }
         }
@@ -3963,13 +3965,13 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
                             hgs.fullQual = true;
 
                         // https://issues.dlang.org/show_bug.cgi?id=23745
-                        // If the potentially overriden function contains errors,
+                        // If the potentially overridden function contains errors,
                         // inform the user to fix that one first
                         if (fd.errors)
                         {
                             error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?",
                                 funcdecl.toChars(), fd.toPrettyChars());
-                            errorSupplemental(fd.loc, "Function `%s` contains errors in its declaration, therefore it cannot be correctly overriden",
+                            errorSupplemental(fd.loc, "Function `%s` contains errors in its declaration, therefore it cannot be correctly overridden",
                                 fd.toPrettyChars());
                         }
                         else
@@ -3985,7 +3987,7 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
                     {
                         error(funcdecl.loc, "function `%s` does not override any function, did you mean to override %s `%s`?",
                             funcdeclToChars, s.kind, s.toPrettyChars());
-                        errorSupplemental(funcdecl.loc, "Functions are the only declarations that may be overriden");
+                        errorSupplemental(funcdecl.loc, "Functions are the only declarations that may be overridden");
                     }
                 }
                 else
@@ -5897,6 +5899,31 @@  void addEnumMembers(EnumDeclaration ed, Scope* sc, ScopeDsymbol sds)
     });
 }
 
+/******************************************************
+ * Verifies if the given Identifier is a DRuntime hook. It uses the hooks
+ * defined in `id.d`.
+ *
+ * Params:
+ *  id = Identifier to verify
+ * Returns:
+ *  true if `id` is a DRuntime hook
+ *  false otherwise
+ */
+private bool isDRuntimeHook(Identifier id)
+{
+    return id == Id._d_HookTraceImpl ||
+        id == Id._d_newclassT || id == Id._d_newclassTTrace ||
+        id == Id._d_arraycatnTX || id == Id._d_arraycatnTXTrace ||
+        id == Id._d_newThrowable || id == Id._d_delThrowable ||
+        id == Id._d_arrayassign_l || id == Id._d_arrayassign_r ||
+        id == Id._d_arraysetassign || id == Id._d_arraysetctor ||
+        id == Id._d_arrayctor ||
+        id == Id._d_arraysetlengthTImpl || id == Id._d_arraysetlengthT ||
+        id == Id._d_arraysetlengthTTrace ||
+        id == Id._d_arrayappendT || id == Id._d_arrayappendTTrace ||
+        id == Id._d_arrayappendcTXImpl;
+}
+
 void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList argumentList)
 {
     //printf("[%s] TemplateInstance.dsymbolSemantic('%s', this=%p, gag = %d, sc = %p)\n", tempinst.loc.toChars(), tempinst.toChars(), tempinst, global.gag, sc);
@@ -6376,8 +6403,20 @@  void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList
         tempinst.deferred = &deferred;
 
         //printf("Run semantic3 on %s\n", toChars());
+
+        /* https://issues.dlang.org/show_bug.cgi?id=23965
+         * DRuntime hooks are not deprecated, but may be used for deprecated
+         * types. Deprecations are disabled while analysing hooks to avoid
+         * spurious error messages.
+         */
+        auto saveUseDeprecated = global.params.useDeprecated;
+        if (sc.isDeprecated() && isDRuntimeHook(tempinst.name))
+            global.params.useDeprecated = DiagnosticReporting.off;
+
         tempinst.trySemantic3(sc2);
 
+        global.params.useDeprecated = saveUseDeprecated;
+
         for (size_t i = 0; i < deferred.length; i++)
         {
             //printf("+ run deferred semantic3 on %s\n", deferred[i].toChars());
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index 5b98d2f4877..f2ab69444bc 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -1302,36 +1302,19 @@  extern (C++) final class TemplateDeclaration : ScopeDsymbol
 
     /*************************************************
      * Match function arguments against a specific template function.
-     * Input:
-     *      ti
-     *      sc              instantiation scope
-     *      fd
-     *      tthis           'this' argument if !NULL
-     *      argumentList    arguments to function
-     * Output:
-     *      fd              Partially instantiated function declaration
-     *      ti.tdtypes     Expression/Type deduced template arguments
+     *
+     * Params:
+     *     ti = template instance. `ti.tdtypes` will be set to Expression/Type deduced template arguments
+     *     sc = instantiation scope
+     *     fd = Partially instantiated function declaration, which is set to an instantiated function declaration
+     *     tthis = 'this' argument if !NULL
+     *     argumentList = arguments to function
+     *
      * Returns:
      *      match pair of initial and inferred template arguments
      */
     extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateInstance ti, Scope* sc, ref FuncDeclaration fd, Type tthis, ArgumentList argumentList)
     {
-        size_t nfparams;
-        size_t nfargs;
-        size_t ntargs; // array size of tiargs
-        size_t fptupindex = IDX_NOTFOUND;
-        MATCH match = MATCH.exact;
-        MATCH matchTiargs = MATCH.exact;
-        ParameterList fparameters; // function parameter list
-        VarArg fvarargs; // function varargs
-        uint wildmatch = 0;
-        size_t inferStart = 0;
-
-        Loc instLoc = ti.loc;
-        Objects* tiargs = ti.tiargs;
-        auto dedargs = new Objects(parameters.length);
-        Objects* dedtypes = &ti.tdtypes; // for T:T*, the dedargs is the T*, dedtypes is the T
-
         version (none)
         {
             printf("\nTemplateDeclaration.deduceFunctionTemplateMatch() %s\n", toChars());
@@ -1348,8 +1331,10 @@  extern (C++) final class TemplateDeclaration : ScopeDsymbol
 
         assert(_scope);
 
+        auto dedargs = new Objects(parameters.length);
         dedargs.zero();
 
+        Objects* dedtypes = &ti.tdtypes; // for T:T*, the dedargs is the T*, dedtypes is the T
         dedtypes.setDim(parameters.length);
         dedtypes.zero();
 
@@ -1393,8 +1378,12 @@  extern (C++) final class TemplateDeclaration : ScopeDsymbol
             }
         }
 
-        ntargs = 0;
-        if (tiargs)
+        size_t ntargs = 0; // array size of tiargs
+        size_t inferStart = 0; // index of first parameter to infer
+        const Loc instLoc = ti.loc;
+        MATCH matchTiargs = MATCH.exact;
+
+        if (auto tiargs = ti.tiargs)
         {
             // Set initial template arguments
             ntargs = tiargs.length;
@@ -1460,9 +1449,9 @@  extern (C++) final class TemplateDeclaration : ScopeDsymbol
             }
         }
 
-        fparameters = fd.getParameterList();
-        nfparams = fparameters.length; // number of function parameters
-        nfargs = argumentList.length; // number of function arguments
+        ParameterList fparameters = fd.getParameterList(); // function parameter list
+        const nfparams = fparameters.length; // number of function parameters
+        const nfargs = argumentList.length; // number of function arguments
         if (argumentList.hasNames)
             return matcherror(); // TODO: resolve named args
         Expressions* fargs = argumentList.arguments; // TODO: resolve named args
@@ -1473,6 +1462,7 @@  extern (C++) final class TemplateDeclaration : ScopeDsymbol
          * void foo(T, A...)(T t, A a);
          * void main() { foo(1,2,3); }
          */
+        size_t fptupindex = IDX_NOTFOUND;
         if (tp) // if variadic
         {
             // TemplateTupleParameter always makes most lesser matching.
@@ -1515,6 +1505,7 @@  extern (C++) final class TemplateDeclaration : ScopeDsymbol
             }
         }
 
+        MATCH match = MATCH.exact;
         if (toParent().isModule())
             tthis = null;
         if (tthis)
@@ -1579,6 +1570,7 @@  extern (C++) final class TemplateDeclaration : ScopeDsymbol
             //printf("\ttp = %p, fptupindex = %d, found = %d, declaredTuple = %s\n", tp, fptupindex, fptupindex != IDX_NOTFOUND, declaredTuple ? declaredTuple.toChars() : NULL);
             size_t argi = 0;
             size_t nfargs2 = nfargs; // nfargs + supplied defaultArgs
+            uint inoutMatch = 0; // for debugging only
             for (size_t parami = 0; parami < nfparams; parami++)
             {
                 Parameter fparam = fparameters[parami];
@@ -1643,7 +1635,7 @@  extern (C++) final class TemplateDeclaration : ScopeDsymbol
                             MATCH m;
                             if (ubyte wm = deduceWildHelper(farg.type, &tt, tid))
                             {
-                                wildmatch |= wm;
+                                inoutMatch |= wm;
                                 m = MATCH.constant;
                             }
                             else
@@ -1896,10 +1888,10 @@  extern (C++) final class TemplateDeclaration : ScopeDsymbol
                     if (fparameters.varargs == VarArg.typesafe && parami + 1 == nfparams && argi + 1 < nfargs)
                         goto Lvarargs;
 
-                    uint wm = 0;
-                    MATCH m = deduceType(oarg, paramscope, prmtype, parameters, dedtypes, &wm, inferStart);
-                    //printf("\tL%d deduceType m = %d, wm = x%x, wildmatch = x%x\n", __LINE__, m, wm, wildmatch);
-                    wildmatch |= wm;
+                    uint im = 0;
+                    MATCH m = deduceType(oarg, paramscope, prmtype, parameters, dedtypes, &im, inferStart);
+                    //printf("\tL%d deduceType m = %d, im = x%x, inoutMatch = x%x\n", __LINE__, m, im, inoutMatch);
+                    inoutMatch |= im;
 
                     /* If no match, see if the argument can be matched by using
                      * implicit conversions.
@@ -2087,7 +2079,7 @@  extern (C++) final class TemplateDeclaration : ScopeDsymbol
                             {
                                 uint wm = 0;
                                 m = deduceType(arg, paramscope, ta.next, parameters, dedtypes, &wm, inferStart);
-                                wildmatch |= wm;
+                                inoutMatch |= wm;
                             }
                             if (m == MATCH.nomatch)
                                 return nomatch();
diff --git a/gcc/d/dmd/dtoh.d b/gcc/d/dmd/dtoh.d
index f00b8dba86c..b9bbad0a7a4 100644
--- a/gcc/d/dmd/dtoh.d
+++ b/gcc/d/dmd/dtoh.d
@@ -2450,7 +2450,7 @@  public:
     {
         debug (Debug_DtoH) mixin(traceVisit!e);
 
-        // Valid in most cases, others should be overriden below
+        // Valid in most cases, others should be overridden below
         // to use the appropriate operators  (:: and ->)
         buf.writestring(e.toString());
     }
diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d
index c0dd17f2ea6..efd6bea6821 100644
--- a/gcc/d/dmd/escape.d
+++ b/gcc/d/dmd/escape.d
@@ -93,22 +93,7 @@  bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf,
         bool isMutable;         // true if reference to mutable
     }
 
-    /* Store escapeBy as static data escapeByStorage so we can keep reusing the same
-     * arrays rather than reallocating them.
-     */
-    __gshared EscapeBy[] escapeByStorage;
-    auto escapeBy = escapeByStorage;
-    if (escapeBy.length < len)
-    {
-        auto newPtr = cast(EscapeBy*)mem.xrealloc(escapeBy.ptr, len * EscapeBy.sizeof);
-        // Clear the new section
-        memset(newPtr + escapeBy.length, 0, (len - escapeBy.length) * EscapeBy.sizeof);
-        escapeBy = newPtr[0 .. len];
-        escapeByStorage = escapeBy;
-    }
-    else
-        escapeBy = escapeBy[0 .. len];
-
+    auto escapeBy = new EscapeBy[len];
     const paramLength = tf.parameterList.length;
 
     // Fill in escapeBy[] with arguments[], ethis, and outerVars[]
@@ -181,7 +166,7 @@  bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf,
         if (!(eb.isMutable || eb2.isMutable))
             return;
 
-        if (!tf.islive && !(global.params.useDIP1000 == FeatureState.enabled && sc.func.setUnsafe()))
+        if (!tf.islive && !(global.params.useDIP1000 == FeatureState.enabled && sc.func && sc.func.setUnsafe()))
             return;
 
         if (!gag)
@@ -228,13 +213,6 @@  bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf,
         escape(i, eb, false);
     }
 
-    /* Reset the arrays in escapeBy[] so we can reuse them next time through
-     */
-    foreach (ref eb; escapeBy)
-    {
-        eb.er.reset();
-    }
-
     return errors;
 }
 
@@ -387,8 +365,9 @@  bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier parId,
             (!fdc && parId) ? (desc ~ " `%s` assigned to non-scope parameter `%s`") :
             (desc ~ " `%s` assigned to non-scope anonymous parameter");
 
-        auto param = isThis ? v : (parId ? parId : fdc);
-        if (sc.setUnsafeDIP1000(gag, arg.loc, msg, v, param, fdc))
+        if (isThis ?
+            sc.setUnsafeDIP1000(gag, arg.loc, msg, arg, fdc.toParent2(), fdc) :
+            sc.setUnsafeDIP1000(gag, arg.loc, msg, v, parId ? parId : fdc, fdc))
         {
             result = true;
             printScopeFailure(previewSupplementalFunc(sc.isDeprecated(), global.params.useDIP1000), vPar, 10);
@@ -508,7 +487,7 @@  bool checkParamArgumentReturn(Scope* sc, Expression firstArg, Expression arg, Pa
     const byRef = param.isReference() && !(param.storageClass & STC.scope_)
         && !(param.storageClass & STC.returnScope); // fixme: it's possible to infer returnScope without scope with vaIsFirstRef
 
-    scope e = new AssignExp(arg.loc, firstArg, arg);
+    auto e = new AssignExp(arg.loc, firstArg, arg);
     return checkAssignEscape(sc, e, gag, byRef);
 }
 
@@ -2487,6 +2466,9 @@  bool isReferenceToMutable(Type t)
             }
             break;
 
+        case Tnull:
+            return false;
+
         default:
             assert(0);
     }
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index 473efb8c99a..35f11afdc93 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -1242,7 +1242,7 @@  extern (C++) abstract class Expression : ASTNode
             if (!f.isDtorDeclaration())
                 errorSupplementalInferredAttr(f, /*max depth*/ 10, /*deprecation*/ false, STC.pure_);
 
-            checkOverridenDtor(sc, f, dd => dd.type.toTypeFunction().purity != PURE.impure, "impure");
+            checkOverriddenDtor(sc, f, dd => dd.type.toTypeFunction().purity != PURE.impure, "impure");
             return true;
         }
         return false;
@@ -1261,7 +1261,7 @@  extern (C++) abstract class Expression : ASTNode
      *   check = current check (e.g. whether it's pure)
      *   checkName = the kind of check (e.g. `"pure"`)
      */
-    extern (D) final void checkOverridenDtor(Scope* sc, FuncDeclaration f,
+    extern (D) final void checkOverriddenDtor(Scope* sc, FuncDeclaration f,
                 scope bool function(DtorDeclaration) check, const string checkName
     ) {
         auto dd = f.isDtorDeclaration();
@@ -1314,7 +1314,7 @@  extern (C++) abstract class Expression : ASTNode
                 field.loc.errorSupplemental(" - %s %s", field.type.toChars(), field.toChars());
 
                 if (fieldSd.dtor.isGenerated())
-                    checkOverridenDtor(sc, fieldSd.dtor, check, checkName);
+                    checkOverriddenDtor(sc, fieldSd.dtor, check, checkName);
                 else
                     fieldSd.dtor.loc.errorSupplemental("   %.*s `%s.~this` is declared here",
                                             cast(int) checkName.length, checkName.ptr, fieldSd.toChars());
@@ -1505,7 +1505,7 @@  extern (C++) abstract class Expression : ASTNode
                     errorSupplementalInferredAttr(f, /*max depth*/ 10, /*deprecation*/ false, STC.safe);
                 .errorSupplemental(f.loc, "`%s` is declared here", prettyChars);
 
-                checkOverridenDtor(sc, f, dd => dd.type.toTypeFunction().trust > TRUST.system, "@system");
+                checkOverriddenDtor(sc, f, dd => dd.type.toTypeFunction().trust > TRUST.system, "@system");
 
                 return true;
             }
@@ -1569,7 +1569,7 @@  extern (C++) abstract class Expression : ASTNode
                         f.errorSupplementalInferredAttr(/*max depth*/ 10, /*deprecation*/ false, STC.nogc);
                 }
 
-                checkOverridenDtor(sc, f, dd => dd.type.toTypeFunction().isnogc, "non-@nogc");
+                checkOverriddenDtor(sc, f, dd => dd.type.toTypeFunction().isnogc, "non-@nogc");
 
                 return true;
             }
@@ -4512,7 +4512,7 @@  extern (C++) abstract class BinExp : Expression
         Type t2 = e2.type;
 
         // T opAssign floating yields a floating. Prevent truncating conversions (float to int).
-        // See issue 3841.
+        // See https://issues.dlang.org/show_bug.cgi?id=3841.
         // Should we also prevent double to float (type.isfloating() && type.size() < t2.size()) ?
         if (op == EXP.addAssign || op == EXP.minAssign ||
             op == EXP.mulAssign || op == EXP.divAssign || op == EXP.modAssign ||
@@ -7425,23 +7425,20 @@  extern(D) Modifiable checkModifiable(Expression exp, Scope* sc, ModifyFlags flag
 }
 
 /**
- * Verify if the given identifier is any of
- * _d_array{ctor,setctor,setassign,assign_l, assign_r}.
+ * Verify if the given identifier is _d_array{,set}ctor.
  *
  * Params:
  *  id = the identifier to verify
  *
  * Returns:
- *  `true` if the identifier corresponds to a construction of assignement
- *  runtime hook, `false` otherwise.
+ *  `true` if the identifier corresponds to a construction runtime hook,
+ *  `false` otherwise.
  */
-bool isArrayConstructionOrAssign(const Identifier id)
+bool isArrayConstruction(const Identifier id)
 {
     import dmd.id : Id;
 
-    return id == Id._d_arrayctor || id == Id._d_arraysetctor ||
-        id == Id._d_arrayassign_l || id == Id._d_arrayassign_r ||
-        id == Id._d_arraysetassign;
+    return id == Id._d_arrayctor || id == Id._d_arraysetctor;
 }
 
 /******************************
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index 8ac8866a85b..be597dfa90f 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -386,34 +386,6 @@  Expression checkNoreturnVarAccess(Expression exp)
     return result;
 }
 
-/******************************
- * Check the tail CallExp is really property function call.
- * Bugs:
- * This doesn't appear to do anything.
- */
-private bool checkPropertyCall(Expression e)
-{
-    e = lastComma(e);
-
-    if (auto ce = e.isCallExp())
-    {
-        if (ce.f)
-        {
-            auto tf = ce.f.type.isTypeFunction();
-            /* If a forward reference to ce.f, try to resolve it
-             */
-            if (!tf.deco && ce.f.semanticRun < PASS.semanticdone)
-            {
-                ce.f.dsymbolSemantic(null);
-                tf = ce.f.type.isTypeFunction();
-            }
-        }
-        else if (!ce.e1.type.isFunction_Delegate_PtrToFunction())
-            assert(0);
-    }
-    return false;
-}
-
 /******************************
  * Find symbol in accordance with the UFCS name look up rule
  */
@@ -489,6 +461,15 @@  private Expression searchUFCS(Scope* sc, UnaExp ue, Identifier ident)
 
     if (auto dti = ue.isDotTemplateInstanceExp())
     {
+        // https://issues.dlang.org/show_bug.cgi?id=23968
+        // Typically, deprecated alias declarations are caught
+        // when `TemplateInstance.findTempDecl` is called,
+        // however, in this case the tempdecl field is updated
+        // therefore `findTempDecl` will return immediately
+        // and not get the chance to issue the deprecation.
+        if (s.isAliasDeclaration())
+            s.checkDeprecated(ue.loc, sc);
+
         auto ti = new TemplateInstance(loc, s.ident, dti.ti.tiargs);
         if (!ti.updateTempDecl(sc, s))
             return ErrorExp.get();
@@ -717,7 +698,6 @@  private Expression resolveUFCSProperties(Scope* sc, Expression e1, Expression e2
         }
         else if (ex && !e)
         {
-            checkPropertyCall(ex);
             ex = new AssignExp(loc, ex, e2);
             return ex.expressionSemantic(sc);
         }
@@ -726,7 +706,6 @@  private Expression resolveUFCSProperties(Scope* sc, Expression e1, Expression e2
             // strict setter prints errors if fails
             e = e.expressionSemantic(sc);
         }
-        checkPropertyCall(e);
         return e;
     }
     else
@@ -736,9 +715,13 @@  private Expression resolveUFCSProperties(Scope* sc, Expression e1, Expression e2
         auto arguments = new Expressions(1);
         (*arguments)[0] = eleft;
         e = new CallExp(loc, e, arguments);
+
+        // https://issues.dlang.org/show_bug.cgi?id=24017
+        if (sc.flags & SCOPE.debug_)
+            e.isCallExp().inDebugStatement = true;
+
         e = e.expressionSemantic(sc);
-        checkPropertyCall(e);
-        return e.expressionSemantic(sc);
+        return e;
     }
 }
 
@@ -1189,6 +1172,13 @@  L1:
  */
 private bool haveSameThis(FuncDeclaration outerFunc, FuncDeclaration calledFunc)
 {
+    // https://issues.dlang.org/show_bug.cgi?id=24013
+    // traits(getOverloads) inserts an alias to select the overload.
+    // When searching for the right this we need to use the aliased
+    // overload/function, not the alias.
+    outerFunc = outerFunc.toAliasFunc();
+    calledFunc = calledFunc.toAliasFunc();
+
     auto thisAd = outerFunc.isMemberLocal();
     if (!thisAd)
         return false;
@@ -1386,15 +1376,6 @@  private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
             {
                 if (fd.errors)
                     return ErrorExp.get();
-                if (!checkSymbolAccess(sc, fd))
-                {
-                    // @@@DEPRECATED_2.105@@@
-                    // When turning into error, uncomment the return statement
-                    TypeFunction tf = fd.type.isTypeFunction();
-                    deprecation(loc, "function `%s` of type `%s` is not accessible from module `%s`",
-                                fd.toPrettyChars(), tf.toChars, sc._module.toChars);
-                    //return ErrorExp.get();
-                }
                 assert(fd.type.ty == Tfunction);
                 Expression e = new CallExp(loc, e1, e2);
                 return e.expressionSemantic(sc);
@@ -1409,14 +1390,6 @@  private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
                 TypeFunction tf = fd.type.isTypeFunction();
                 if (!e2 || tf.isref)
                 {
-                    if (!checkSymbolAccess(sc, fd))
-                    {
-                        // @@@DEPRECATED_2.105@@@
-                        // When turning into error, uncomment the return statement
-                        deprecation(loc, "function `%s` of type `%s` is not accessible from module `%s`",
-                                    fd.toPrettyChars(), tf.toChars, sc._module.toChars);
-                        //return ErrorExp.get();
-                    }
                     Expression e = new CallExp(loc, e1);
                     if (e2)
                     {
@@ -3404,7 +3377,7 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
             if (ve && ve.var && exp.parens && !ve.var.isStatic() && !(sc.stc & STC.static_) &&
                 sc.func && sc.func.needThis && ve.var.isMember2())
             {
-                // printf("apply fix for issue 9490: add `this.` to `%s`...\n", e.toChars());
+                // printf("apply fix for bugzilla issue 9490: add `this.` to `%s`...\n", e.toChars());
                 e = new DotVarExp(exp.loc, new ThisExp(exp.loc), ve.var, false);
             }
             //printf("e = %s %s\n", Token.toChars(e.op), e.toChars());
@@ -4092,9 +4065,10 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 if (arg.op == EXP.error)
                     return setError();
                 arg = arg.optimize(WANTvalue);
-                if (arg.op == EXP.int64 && cast(sinteger_t)arg.toInteger() < 0)
+                if (arg.op == EXP.int64 && (target.isLP64 ?
+                    cast(sinteger_t)arg.toInteger() : cast(int)arg.toInteger()) < 0)
                 {
-                    exp.error("negative array index `%s`", arg.toChars());
+                    exp.error("negative array dimension `%s`", (*exp.arguments)[i].toChars());
                     return setError();
                 }
                 (*exp.arguments)[i] = arg;
@@ -5024,7 +4998,21 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
             if (!exp.ignoreAttributes)
                 checkFunctionAttributes(exp, sc, exp.f);
-            checkAccess(exp.loc, sc, ue.e1, exp.f);
+
+            // Cut-down version of checkAccess() that doesn't use the "most visible" version of exp.f.
+            // We've already selected an overload here.
+            const parent = exp.f.toParent();
+            if (parent && parent.isTemplateInstance())
+            {
+                // already a deprecation
+            }
+            else if (!checkSymbolAccess(sc, exp.f))
+            {
+                exp.error("%s `%s` of type `%s` is not accessible from module `%s`",
+                    exp.f.kind(), exp.f.toPrettyChars(), exp.f.type.toChars(), sc._module.toChars);
+                return setError();
+            }
+
             if (!exp.f.needThis())
             {
                 exp.e1 = Expression.combine(ue.e1, new VarExp(exp.loc, exp.f, false));
@@ -7828,7 +7816,7 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
         if (exp.to.ty == Ttuple)
         {
-            exp.error("cannot cast `%s` of type `%s` to tuple type `%s`", exp.e1.toChars(), exp.e1.type.toChars(), exp.to.toChars());
+            exp.error("cannot cast `%s` of type `%s` to type sequence `%s`", exp.e1.toChars(), exp.e1.type.toChars(), exp.to.toChars());
             return setError();
         }
 
@@ -8174,7 +8162,7 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
             }
             if (!exp.lwr || !exp.upr)
             {
-                exp.error("need upper and lower bound to slice tuple");
+                exp.error("need upper and lower bound to slice a sequence");
                 return setError();
             }
         }
@@ -9219,7 +9207,7 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 Expression e = null;
                 if (dim != tup2.exps.length)
                 {
-                    exp.error("mismatched tuple lengths, %d and %d", cast(int)dim, cast(int)tup2.exps.length);
+                    exp.error("mismatched sequence lengths, %d and %d", cast(int)dim, cast(int)tup2.exps.length);
                     return setError();
                 }
                 if (dim == 0)
@@ -10363,6 +10351,9 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
         if (global.params.verbose)
             message("lowered   %s =>\n          %s", ae.toChars(), res.toChars());
 
+        res = new LoweredAssignExp(ae, res);
+        res.type = ae.type;
+
         return res;
     }
 
diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d
index a159c2f1561..62e0d49fdd5 100644
--- a/gcc/d/dmd/hdrgen.d
+++ b/gcc/d/dmd/hdrgen.d
@@ -927,7 +927,7 @@  public:
         }
         if (d.decl.length == 0 || (hgs.hdrgen && d.decl.length == 1 && (*d.decl)[0].isUnitTestDeclaration()))
         {
-            // hack for bugzilla 8081
+            // hack for https://issues.dlang.org/show_bug.cgi?id=8081
             if (hasSTC) buf.writeByte(' ');
             buf.writestring("{}");
         }
@@ -2217,13 +2217,13 @@  private void expressionPrettyPrint(Expression e, OutBuffer* buf, HdrGenState* hg
         {
             buf.writeByte('(');
             e.e0.expressionPrettyPrint(buf, hgs);
-            buf.writestring(", tuple(");
+            buf.writestring(", AliasSeq!(");
             argsToBuffer(e.exps, buf, hgs);
             buf.writestring("))");
         }
         else
         {
-            buf.writestring("tuple(");
+            buf.writestring("AliasSeq!(");
             argsToBuffer(e.exps, buf, hgs);
             buf.writeByte(')');
         }
@@ -4141,7 +4141,7 @@  string EXPtoString(EXP op)
         EXP.delegatePointer : "delegateptr",
         EXP.delegateFunctionPointer : "delegatefuncptr",
         EXP.remove : "remove",
-        EXP.tuple : "tuple",
+        EXP.tuple : "sequence",
         EXP.traits : "__traits",
         EXP.overloadSet : "__overloadset",
         EXP.void_ : "void",
diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d
index ca770bd77b6..ee288d1e474 100644
--- a/gcc/d/dmd/initsem.d
+++ b/gcc/d/dmd/initsem.d
@@ -582,7 +582,7 @@  extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
 
     Initializer visitC(CInitializer ci)
     {
-        //printf("CInitializer::semantic() (%s) %s\n", t.toChars(), ci.toChars());
+        //printf("CInitializer::semantic() tx: %s t: %s ci: %s\n", (tx ? tx.toChars() : "".ptr), t.toChars(), ci.toChars());
         /* Rewrite CInitializer into ExpInitializer, ArrayInitializer, or StructInitializer
          */
         t = t.toBasetype();
@@ -770,7 +770,6 @@  extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
                 return err();
             }
             const nfields = sd.fields.length;
-
             size_t fieldi = 0;
 
             for (size_t index = 0; index < ci.initializerList.length; )
@@ -807,6 +806,12 @@  extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
                 {
                     if (fieldi == nfields)
                         break;
+                    if (index == 0 && ci.initializerList.length == 1 && di.initializer.isCInitializer())
+                    {
+                        ci = di.initializer.isCInitializer();
+                        continue;
+                    }
+
                     VarDeclaration field;
                     while (1)   // skip field if it overlaps with previously seen fields
                     {
@@ -954,10 +959,13 @@  extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
             return initializerSemantic(ai, sc, tx, needInterpret);
         }
         else if (ExpInitializer ei = isBraceExpression())
+        {
             return visitExp(ei);
+        }
         else
         {
-            assert(0);
+            error(ci.loc, "unrecognized C initializer `%s`", ci.toChars());
+            return err();
         }
     }
 
diff --git a/gcc/d/dmd/inline.d b/gcc/d/dmd/inline.d
index 8e63122f4cb..afab8315f92 100644
--- a/gcc/d/dmd/inline.d
+++ b/gcc/d/dmd/inline.d
@@ -21,8 +21,8 @@  import dmd.expression;
  * Perform the "inline copying" of a default argument for a function parameter.
  *
  * Todo:
- *  The hack for bugzilla 4820 case is still questionable. Perhaps would have to
- *  handle a delegate expression with 'null' context properly in front-end.
+ *  The hack for https://issues.dlang.org/show_bug.cgi?id=4820 case is still questionable.
+ *  Perhaps would have to handle a delegate expression with 'null' context properly in front-end.
  */
 public Expression inlineCopy(Expression e, Scope* sc)
 {
diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d
index a878cc9523d..add1ce68468 100644
--- a/gcc/d/dmd/lexer.d
+++ b/gcc/d/dmd/lexer.d
@@ -2205,7 +2205,7 @@  class Lexer
                 p++;
                 if ((flags & f) && !err)
                 {
-                    error("unrecognized token");
+                    error("repeated integer suffix `%c`", p[-1]);
                     err = true;
                 }
                 flags = cast(FLAGS)(flags | f);
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index cb3e6cddd20..7ecd4023ee1 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -2054,7 +2054,7 @@  extern (C++) abstract class Type : ASTNode
                 return Type.terror;
 
             auto t = fd.type.nextOf();
-            if (!t) // issue 14185
+            if (!t) // https://issues.dlang.org/show_bug.cgi?id=14185
                 return Type.terror;
             t = t.substWildTo(mod == 0 ? MODFlags.mutable : mod);
             return t;
@@ -4597,10 +4597,9 @@  extern (C++) final class TypeFunction : TypeNext
         // show qualification when toChars() is the same but types are different
         // https://issues.dlang.org/show_bug.cgi?id=19948
         // when comparing the type with strcmp, we need to drop the qualifier
-        auto at = arg.type.mutableOf().toChars();
-        bool qual = !arg.type.equals(par.type) && strcmp(at, par.type.mutableOf().toChars()) == 0;
-        if (qual)
-            at = arg.type.toPrettyChars(true);
+        bool qual = !arg.type.mutableOf().equals(par.type.mutableOf()) &&
+            strcmp(arg.type.mutableOf().toChars(), par.type.mutableOf().toChars()) == 0;
+        auto at = qual ? arg.type.toPrettyChars(true) : arg.type.toChars();
         OutBuffer buf;
         // only mention rvalue if it's relevant
         const rv = !arg.isLvalue() && par.isReference();
@@ -4940,7 +4939,7 @@  extern (C++) final class TypeFunction : TypeNext
         }
         if (tb.ty == Ttuple)
         {
-            error(loc, "functions cannot return a tuple");
+            error(loc, "functions cannot return a sequence (use `std.typecons.Tuple`)");
             next = Type.terror;
         }
         if (!isref && (tb.ty == Tstruct || tb.ty == Tsarray))
@@ -5105,7 +5104,7 @@  extern (C++) final class TypeDelegate : TypeNext
  * This is a shell containing a TraitsExp that can be
  * either resolved to a type or to a symbol.
  *
- * The point is to allow AliasDeclarationY to use `__traits()`, see issue 7804.
+ * The point is to allow AliasDeclarationY to use `__traits()`, see https://issues.dlang.org/show_bug.cgi?id=7804.
  */
 extern (C++) final class TypeTraits : Type
 {
@@ -6218,7 +6217,7 @@  extern (C++) final class TypeTuple : Type
             {
                 Expression e = (*exps)[i];
                 if (e.type.ty == Ttuple)
-                    e.error("cannot form tuple of tuples");
+                    e.error("cannot form sequence of sequences");
                 auto arg = new Parameter(STC.undefined_, e.type, null, null, null);
                 (*arguments)[i] = arg;
             }
@@ -6273,7 +6272,7 @@  extern (C++) final class TypeTuple : Type
 
     override const(char)* kind() const
     {
-        return "tuple";
+        return "sequence";
     }
 
     override TypeTuple syntaxCopy()
@@ -7271,7 +7270,7 @@  private extern(D) bool isCopyConstructorCallable (StructDeclaration argStruct,
             {
                 /* Although a copy constructor may exist, no suitable match was found.
                  * i.e: `inout` constructor creates `const` object, not mutable.
-                 * Fallback to using the original generic error before bugzilla 22202.
+                 * Fallback to using the original generic error before https://issues.dlang.org/show_bug.cgi?id=22202.
                  */
                 goto Lnocpctor;
             }
diff --git a/gcc/d/dmd/opover.d b/gcc/d/dmd/opover.d
index 0e64d9c7c8d..8b42a91f0af 100644
--- a/gcc/d/dmd/opover.d
+++ b/gcc/d/dmd/opover.d
@@ -416,9 +416,11 @@  Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
                      *      op(e1.aliasthis)
                      */
                     //printf("att una %s e1 = %s\n", EXPtoString(op).ptr, this.e1.type.toChars());
-                    e.e1 = resolveAliasThis(sc, e.e1, true);
-                    if (e.e1)
+                    if (auto e1 = resolveAliasThis(sc, e.e1, true))
+                    {
+                        e.e1 = e1;
                         continue;
+                    }
                     break;
                 }
                 break;
@@ -1043,7 +1045,7 @@  Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
                 size_t dim = tup1.exps.length;
                 if (dim != tup2.exps.length)
                 {
-                    e.error("mismatched tuple lengths, `%d` and `%d`",
+                    e.error("mismatched sequence lengths, `%d` and `%d`",
                         cast(int)dim, cast(int)tup2.exps.length);
                     return ErrorExp.get();
                 }
diff --git a/gcc/d/dmd/optimize.d b/gcc/d/dmd/optimize.d
index 335310de65d..f98e7c76bcc 100644
--- a/gcc/d/dmd/optimize.d
+++ b/gcc/d/dmd/optimize.d
@@ -189,7 +189,7 @@  private Expression fromConstInitializer(int result, Expression e1)
         {
             // If it is a comma expression involving a declaration, we mustn't
             // perform a copy -- we'd get two declarations of the same variable.
-            // See bugzilla 4465.
+            // See https://issues.dlang.org/show_bug.cgi?id=4465.
             if (e.op == EXP.comma && e.isCommaExp().e1.isDeclarationExp())
                 e = e1;
             else if (e.type != e1.type && e1.type && e1.type.ty != Tident)
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index b7e07911cb9..eeaef8d7d8b 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -1155,6 +1155,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
 
         case TOK.leftCurly:
             {
+                const lcLoc = token.loc;
                 const lookingForElseSave = lookingForElse;
                 lookingForElse = Loc();
 
@@ -1164,6 +1165,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                 {
                     /* { */
                     error("matching `}` expected, not `%s`", token.toChars());
+                    eSink.errorSupplemental(lcLoc, "unmatched `{`");
                 }
                 else
                     nextToken();
@@ -1405,6 +1407,15 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                     break;
                 }
             default:
+                Token* tk;
+                if (skipAttributes(&token, &tk) && tk.ptr != token.ptr ||
+                    token.value == TOK.static_ || token.value == TOK.extern_)
+                {
+                    error("`%s` token is not allowed in postfix position",
+                        Token.toChars(token.value));
+                    nextToken();
+                    continue;
+                }
                 return storageClass;
             }
             storageClass = appendStorageClass(storageClass, stc);
@@ -6006,6 +6017,7 @@  LagainStc:
             }
         case TOK.leftCurly:
             {
+                const lcLoc = token.loc;
                 const lookingForElseSave = lookingForElse;
                 lookingForElse = Loc.initial;
 
@@ -6028,7 +6040,14 @@  LagainStc:
                 s = new AST.CompoundStatement(loc, statements);
                 if (flags & (ParseStatementFlags.scope_ | ParseStatementFlags.curlyScope))
                     s = new AST.ScopeStatement(loc, s, token.loc);
-                check(TOK.rightCurly, "compound statement");
+                if (token.value != TOK.rightCurly)
+                {
+                    error(token.loc, "matching `}` expected following compound statement, not `%s`",
+                        token.toChars());
+                    eSink.errorSupplemental(lcLoc, "unmatched `{`");
+                }
+                else
+                    nextToken();
                 lookingForElse = lookingForElseSave;
                 break;
             }
diff --git a/gcc/d/dmd/root/array.d b/gcc/d/dmd/root/array.d
index d1c61be7344..f36ddb4f29e 100644
--- a/gcc/d/dmd/root/array.d
+++ b/gcc/d/dmd/root/array.d
@@ -251,6 +251,18 @@  public:
         length++;
     }
 
+    /// Insert 'count' copies of 'value' at 'index' position
+    void insert(size_t index, size_t count, T value) pure nothrow
+    {
+        if (count == 0)
+            return;
+        reserve(count);
+        if (length != index)
+            memmove(data.ptr + index + count, data.ptr + index, (length - index) * T.sizeof);
+        data[index .. index + count] = value;
+        length += count;
+    }
+
     void setDim(size_t newdim) pure nothrow
     {
         if (length < newdim)
@@ -458,6 +470,12 @@  unittest
     arrayA.insert(0, [7, 8]);
     arrayA.insert(arrayA.length, [0, 9]);
     assert(arrayA[] == [7, 8, 5, 1, 2, 6, 0, 9]);
+    arrayA.insert(4, 3, 8);
+    assert(arrayA[] == [7, 8, 5, 1, 8, 8, 8, 2, 6, 0, 9]);
+    arrayA.insert(0, 3, 8);
+    assert(arrayA[] == [8, 8, 8, 7, 8, 5, 1, 8, 8, 8, 2, 6, 0, 9]);
+    arrayA.insert(arrayA.length, 3, 8);
+    assert(arrayA[] == [8, 8, 8, 7, 8, 5, 1, 8, 8, 8, 2, 6, 0, 9, 8, 8, 8]);
 }
 
 /**
diff --git a/gcc/d/dmd/semantic2.d b/gcc/d/dmd/semantic2.d
index c40e72c0862..3cbf14f2b8f 100644
--- a/gcc/d/dmd/semantic2.d
+++ b/gcc/d/dmd/semantic2.d
@@ -657,6 +657,13 @@  private extern(C++) final class Semantic2Visitor : Visitor
         {
             foreach (base; cd.interfaces)
             {
+                // https://issues.dlang.org/show_bug.cgi?id=22729
+                // interfaces that have errors or that
+                // inherit from interfaces that have errors
+                // might have an uninitialized vtable
+                if (!base.sym.vtbl.length)
+                    continue;
+
                 // first entry is ClassInfo reference
                 auto methods = base.sym.vtbl[base.sym.vtblOffset .. $];
 
diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d
index 33c2f02249e..e4ca22a98b5 100644
--- a/gcc/d/dmd/semantic3.d
+++ b/gcc/d/dmd/semantic3.d
@@ -1367,6 +1367,8 @@  private extern(C++) final class Semantic3Visitor : Visitor
             if (isCppNonMappableType(f.next.toBasetype()))
             {
                 funcdecl.error("cannot return type `%s` because its linkage is `extern(C++)`", f.next.toChars());
+                if (f.next.isTypeDArray())
+                    errorSupplemental(funcdecl.loc, "slices are specific to D and do not have a counterpart representation in C++", f.next.toChars());
                 funcdecl.errors = true;
             }
             foreach (i, param; f.parameterList)
@@ -1605,7 +1607,7 @@  private struct FuncDeclSem3
         sc = s;
     }
 
-    /* Checks that the overriden functions (if any) have in contracts if
+    /* Checks that the overridden functions (if any) have in contracts if
      * funcdecl has an in contract.
      */
     void checkInContractOverrides()
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index f0454163224..2def2539597 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -257,8 +257,7 @@  Statement statementSemanticVisit(Statement s, Scope* sc)
                 continue;
             }
 
-            Statements* flt = s.flatten(sc);
-            if (flt)
+            if (auto flt = s.flatten(sc))
             {
                 cs.statements.remove(i);
                 cs.statements.insert(i, flt);
@@ -279,6 +278,24 @@  Statement statementSemanticVisit(Statement s, Scope* sc)
                 ++i;
                 continue;       // look for errors in rest of statements
             }
+
+            // expand tuple variables in order to attach destruction/exception logic
+            if (auto es = s.isExpStatement())
+            {
+                if (es.exp && es.exp.isDeclarationExp())
+                {
+                    auto de = es.exp.isDeclarationExp();
+                    auto vd = de.declaration.isVarDeclaration();
+                    if (vd && vd.aliasTuple && vd.aliasTuple.objects.length)
+                    {
+                        auto j = i;
+                        cs.statements.insert(i, vd.aliasTuple.objects.length - 1, null);
+                        vd.aliasTuple.foreachVar((v) { (*cs.statements)[j++] = toStatement(v); });
+                        s = (*cs.statements)[i];
+                    }
+                }
+            }
+
             Statement sentry;
             Statement sexception;
             Statement sfinally;
@@ -384,12 +401,11 @@  Statement statementSemanticVisit(Statement s, Scope* sc)
 
         /* Flatten them in place
          */
-        void flatten(Statements* statements)
+        void flattenStatements(ref Statements statements)
         {
             for (size_t i = 0; i < statements.length;)
             {
-                Statement s = (*statements)[i];
-                if (s)
+                if (auto s = statements[i])
                 {
                     if (auto flt = s.flatten(sc))
                     {
@@ -406,7 +422,7 @@  Statement statementSemanticVisit(Statement s, Scope* sc)
          * 'semantic' may return another CompoundStatement
          * (eg. CaseRangeStatement), so flatten it here.
          */
-        flatten(cs.statements);
+        flattenStatements(*cs.statements);
 
         foreach (s; *cs.statements)
         {
@@ -4298,7 +4314,7 @@  public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState
     const bool skipCheck = isStatic && needExpansion;
     if (!skipCheck && (dim < 1 || dim > 2))
     {
-        fs.error("only one (value) or two (key,value) arguments for tuple `foreach`");
+        fs.error("only one (value) or two (key,value) arguments allowed for sequence `foreach`");
         return returnEarly();
     }
 
diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d
index 53c8fb08b50..caebf1cee25 100644
--- a/gcc/d/dmd/traits.d
+++ b/gcc/d/dmd/traits.d
@@ -1556,7 +1556,9 @@  Expression semanticTraits(TraitsExp e, Scope* sc)
         if (auto imp = s.isImport())
         {
             // https://issues.dlang.org/show_bug.cgi?id=9692
-            s = imp.mod;
+            // https://issues.dlang.org/show_bug.cgi?id=20008
+            if (imp.pkg)
+                s = imp.pkg;
         }
 
         // https://issues.dlang.org/show_bug.cgi?id=16044
@@ -2116,7 +2118,7 @@  private bool isSame(RootObject o1, RootObject o2, Scope* sc)
             return true;
     }
 
-    // issue 12001, allow isSame, <BasicType>, <BasicType>
+    // https://issues.dlang.org/show_bug.cgi?id=12001, allow isSame, <BasicType>, <BasicType>
     Type t1 = isType(o1);
     Type t2 = isType(o2);
     if (t1 && t2 && t1.equals(t2))
diff --git a/gcc/d/dmd/transitivevisitor.d b/gcc/d/dmd/transitivevisitor.d
index a82a268eb66..376c12fa808 100644
--- a/gcc/d/dmd/transitivevisitor.d
+++ b/gcc/d/dmd/transitivevisitor.d
@@ -162,14 +162,14 @@  package mixin template ParseVisitMethods(AST)
     }
 
     override void visit(AST.StaticForeachStatement s)
-	{
+    {
         // printf("Visiting StaticForeachStatement\n");
-		if (s.sfe.aggrfe)
+        if (s.sfe.aggrfe)
             s.sfe.aggrfe.accept(this);
 
-		if (s.sfe.rangefe)
+        if (s.sfe.rangefe)
             s.sfe.rangefe.accept(this);
-	}
+    }
 
     override void visit(AST.IfStatement s)
     {
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index 09eef83ba08..d0923953663 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -121,7 +121,7 @@  private void resolveTupleIndex(const ref Loc loc, Scope* sc, Dsymbol s, out Expr
     const(uinteger_t) d = eindex.toUInteger();
     if (d >= tup.objects.length)
     {
-        .error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", d, cast(ulong)tup.objects.length);
+        .error(loc, "sequence index `%llu` out of bounds `[0 .. %llu]`", d, cast(ulong)tup.objects.length);
         pt = Type.terror;
         return;
     }
@@ -525,7 +525,7 @@  extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
             uinteger_t d = mtype.dim.toUInteger();
             if (d >= tup.objects.length)
             {
-                .error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", cast(ulong)d, cast(ulong)tup.objects.length);
+                .error(loc, "sequence index `%llu` out of bounds `[0 .. %llu]`", cast(ulong)d, cast(ulong)tup.objects.length);
                 return error();
             }
 
@@ -621,7 +621,7 @@  extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
                 uinteger_t d = mtype.dim.toUInteger();
                 if (d >= tt.arguments.length)
                 {
-                    .error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", cast(ulong)d, cast(ulong)tt.arguments.length);
+                    .error(loc, "sequence index `%llu` out of bounds `[0 .. %llu]`", cast(ulong)d, cast(ulong)tt.arguments.length);
                     return error();
                 }
                 Type telem = (*tt.arguments)[cast(size_t)d].type;
@@ -1684,7 +1684,7 @@  extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
         Type tbn = tn.toBasetype();
         if (tbn.ty != Ttuple)
         {
-            .error(loc, "can only slice tuple types, not `%s`", tbn.toChars());
+            .error(loc, "can only slice type sequences, not `%s`", tbn.toChars());
             return error();
         }
         TypeTuple tt = cast(TypeTuple)tbn;
@@ -2436,7 +2436,7 @@  Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier iden
         }
         else
         {
-            error(loc, "no property `%s` for tuple `%s`", ident.toChars(), mt.toChars());
+            error(loc, "no property `%s` for sequence `%s`", ident.toChars(), mt.toChars());
             e = ErrorExp.get();
         }
         return e;
@@ -2563,7 +2563,7 @@  void resolve(Type mt, const ref Loc loc, Scope* sc, out Expression pe, out Type
                 const d = mt.dim.toUInteger();
                 if (d >= tup.objects.length)
                 {
-                    error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", d, cast(ulong) tup.objects.length);
+                    error(loc, "sequence index `%llu` out of bounds `[0 .. %llu]`", d, cast(ulong) tup.objects.length);
                     return returnError();
                 }
 
diff --git a/gcc/testsuite/gdc.test/compilable/b20938.d b/gcc/testsuite/gdc.test/compilable/b20938.d
index ba3565ae8f9..b3aa46c2435 100644
--- a/gcc/testsuite/gdc.test/compilable/b20938.d
+++ b/gcc/testsuite/gdc.test/compilable/b20938.d
@@ -1,4 +1,5 @@ 
-// issue 20938 - Cannot create const arrays mixing immutable and mutable structs with indirections
+// https://issues.dlang.org/show_bug.cgi?id=20938
+// Cannot create const arrays mixing immutable and mutable structs with indirections
 struct S { int[] a; }
 enum A { a }
 enum B { b }
diff --git a/gcc/testsuite/gdc.test/compilable/commontype.d b/gcc/testsuite/gdc.test/compilable/commontype.d
index abe956c8094..a980ace2177 100644
--- a/gcc/testsuite/gdc.test/compilable/commontype.d
+++ b/gcc/testsuite/gdc.test/compilable/commontype.d
@@ -117,18 +117,18 @@  static assert(is( X!( Ei, Ei ) == Ei ));
 static assert(is( X!( Ei, const(Ei) ) == const(Ei) ));
 static assert(is( X!( Ei, immutable(Ei) ) == const(Ei) ));
 static assert(is( X!( Eb, Eb ) == Eb ));
-static assert(is( X!( Eb, const(Eb) ) == int ));
-static assert(is( X!( Eb, immutable(Eb) ) == int ));
+static assert(is( X!( Eb, const(Eb) ) == const(Eb) ));
+static assert(is( X!( Eb, immutable(Eb) ) == const(Eb) ));
 static assert(is( X!( Ei, Eb ) == int ));
 static assert(is( X!( Ei, const(Eb) ) == int ));
 static assert(is( X!( Ei, immutable(Eb) ) == int ));
 
 static assert(is( X!( Ec, Ec ) == Ec ));
-static assert(is( X!( Ec, const(Ec) ) == const(char) ));
-static assert(is( X!( Ec, immutable(Ec) ) == const(char) ));
+static assert(is( X!( Ec, const(Ec) ) == const(Ec) ));
+static assert(is( X!( Ec, immutable(Ec) ) == const(Ec) ));
 static assert(is( X!( Ew, Ew ) == Ew ));
-static assert(is( X!( Ew, const(Ew) ) == const(wchar) ));
-static assert(is( X!( Ew, immutable(Ew) ) == const(wchar) ));
+static assert(is( X!( Ew, const(Ew) ) == const(Ew) ));
+static assert(is( X!( Ew, immutable(Ew) ) == const(Ew) ));
 static assert(is( X!( Ew, Ec ) == dchar ));
 static assert(is( X!( Ew, const(Ec) ) == dchar ));
 static assert(is( X!( Ew, immutable(Ec) ) == dchar ));
diff --git a/gcc/testsuite/gdc.test/compilable/imports/pkg20008/package.d b/gcc/testsuite/gdc.test/compilable/imports/pkg20008/package.d
new file mode 100644
index 00000000000..ecd1568ad34
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/pkg20008/package.d
@@ -0,0 +1,9 @@ 
+module pkg20008;
+
+import pkg20008.submod;
+
+enum T2 { y }
+enum T3 { z }
+
+static assert([__traits(allMembers, pkg20008)] == ["object", "pkg20008", "T2", "T3"]);
+static assert([__traits(allMembers, pkg20008.submod)] == ["object", "T1"]);
diff --git a/gcc/testsuite/gdc.test/compilable/imports/pkg20008/submod.d b/gcc/testsuite/gdc.test/compilable/imports/pkg20008/submod.d
new file mode 100644
index 00000000000..a38a5e88cfb
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/pkg20008/submod.d
@@ -0,0 +1,2 @@ 
+module pkg20008.submod;
+enum T1 { x }
diff --git a/gcc/testsuite/gdc.test/compilable/imports/pkg20008/subpkg/package.d b/gcc/testsuite/gdc.test/compilable/imports/pkg20008/subpkg/package.d
new file mode 100644
index 00000000000..cf3e4dfb422
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/pkg20008/subpkg/package.d
@@ -0,0 +1,7 @@ 
+module pkg20008.subpkg;
+
+import pkg20008.subpkg.subsubmod;
+
+enum T9 { x }
+
+static assert([__traits(allMembers, pkg20008.subpkg)] == ["object", "pkg20008", "T9"]);
diff --git a/gcc/testsuite/gdc.test/compilable/imports/pkg20008/subpkg/subsubmod.d b/gcc/testsuite/gdc.test/compilable/imports/pkg20008/subpkg/subsubmod.d
new file mode 100644
index 00000000000..69a416a021d
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/pkg20008/subpkg/subsubmod.d
@@ -0,0 +1,9 @@ 
+module pkg20008.subpkg.subsubmod;
+
+import pkg20008.subpkg;
+import pkg20008.subpkg.subsubmod;
+
+enum T8 { x }
+
+static assert([__traits(allMembers, pkg20008.subpkg)] == ["object", "pkg20008", "T9"]);
+static assert([__traits(allMembers, pkg20008.subpkg.subsubmod)] == ["object", "pkg20008", "T8"]);
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test9692b.d b/gcc/testsuite/gdc.test/compilable/imports/test9692b.d
index 25be84b3413..dab7a986aaf 100644
--- a/gcc/testsuite/gdc.test/compilable/imports/test9692b.d
+++ b/gcc/testsuite/gdc.test/compilable/imports/test9692b.d
@@ -1,2 +1,2 @@ 
 module imports.test9692b;
-int j;
+int k;
diff --git a/gcc/testsuite/gdc.test/compilable/issue24018.d b/gcc/testsuite/gdc.test/compilable/issue24018.d
new file mode 100644
index 00000000000..559710c27df
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/issue24018.d
@@ -0,0 +1,10 @@ 
+struct S
+{
+    @disable this();
+}
+
+void main()
+{
+    S[] s;
+    s = s ~ s;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/stc_traits.d b/gcc/testsuite/gdc.test/compilable/stc_traits.d
index c5c4e5f0ac0..71d17315510 100644
--- a/gcc/testsuite/gdc.test/compilable/stc_traits.d
+++ b/gcc/testsuite/gdc.test/compilable/stc_traits.d
@@ -2,59 +2,59 @@ 
 /*
 TEST_OUTPUT:
 ---
-100 tuple()
-101 tuple("return", "ref")
-102 tuple("ref")
-103 tuple()
-104 tuple("ref")
-105 tuple()
-106 tuple()
-107 tuple("ref")
-108 tuple("ref")
-109 tuple("ref")
-110 tuple("ref")
-111 tuple()
-112 tuple("ref")
-113 tuple("ref")
-114 tuple("ref")
-115 tuple("ref")
-116 tuple()
-117 tuple("ref")
-118 tuple("ref")
-119 tuple()
-120 tuple("ref")
-121 tuple()
-122 tuple("ref")
-123 tuple("in")
-124 tuple("in")
-m       tuple("ref")
-m-mixin tuple("ref")
-m       tuple("ref")
-m-mixin tuple("ref")
-m       tuple("ref")
-m-mixin tuple("ref")
-m       tuple("return", "ref")
-m-mixin tuple("return", "ref")
-m       tuple("ref")
-m-mixin tuple("ref")
-m       tuple("ref")
-m-mixin tuple("ref")
-m       tuple()
-m-mixin tuple()
-m       tuple("ref")
-m-mixin tuple("ref")
-m       tuple("ref")
-m-mixin tuple("ref")
-m       tuple("ref")
-m-mixin tuple("ref")
-m       tuple("ref")
-m-mixin tuple("ref")
-m       tuple("ref")
-m-mixin tuple("ref")
-m       tuple("ref")
-m-mixin tuple("ref")
-m       tuple("in")
-m-mixin tuple("in")
+100 AliasSeq!()
+101 AliasSeq!("return", "ref")
+102 AliasSeq!("ref")
+103 AliasSeq!()
+104 AliasSeq!("ref")
+105 AliasSeq!()
+106 AliasSeq!()
+107 AliasSeq!("ref")
+108 AliasSeq!("ref")
+109 AliasSeq!("ref")
+110 AliasSeq!("ref")
+111 AliasSeq!()
+112 AliasSeq!("ref")
+113 AliasSeq!("ref")
+114 AliasSeq!("ref")
+115 AliasSeq!("ref")
+116 AliasSeq!()
+117 AliasSeq!("ref")
+118 AliasSeq!("ref")
+119 AliasSeq!()
+120 AliasSeq!("ref")
+121 AliasSeq!()
+122 AliasSeq!("ref")
+123 AliasSeq!("in")
+124 AliasSeq!("in")
+m       AliasSeq!("ref")
+m-mixin AliasSeq!("ref")
+m       AliasSeq!("ref")
+m-mixin AliasSeq!("ref")
+m       AliasSeq!("ref")
+m-mixin AliasSeq!("ref")
+m       AliasSeq!("return", "ref")
+m-mixin AliasSeq!("return", "ref")
+m       AliasSeq!("ref")
+m-mixin AliasSeq!("ref")
+m       AliasSeq!("ref")
+m-mixin AliasSeq!("ref")
+m       AliasSeq!()
+m-mixin AliasSeq!()
+m       AliasSeq!("ref")
+m-mixin AliasSeq!("ref")
+m       AliasSeq!("ref")
+m-mixin AliasSeq!("ref")
+m       AliasSeq!("ref")
+m-mixin AliasSeq!("ref")
+m       AliasSeq!("ref")
+m-mixin AliasSeq!("ref")
+m       AliasSeq!("ref")
+m-mixin AliasSeq!("ref")
+m       AliasSeq!("ref")
+m-mixin AliasSeq!("ref")
+m       AliasSeq!("in")
+m-mixin AliasSeq!("in")
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/compilable/test13668.d b/gcc/testsuite/gdc.test/compilable/test13668.d
index d69c764b91c..2cf758cc98b 100644
--- a/gcc/testsuite/gdc.test/compilable/test13668.d
+++ b/gcc/testsuite/gdc.test/compilable/test13668.d
@@ -3,7 +3,7 @@ 
 /*
 TEST_OUTPUT:
 ---
-tuple("id", "toString", "toHash", "opCmp", "opEquals", "Monitor", "factory")
+AliasSeq!("id", "toString", "toHash", "opCmp", "opEquals", "Monitor", "factory")
 genProps
 ---
 */
diff --git a/gcc/testsuite/gdc.test/compilable/test16635.d b/gcc/testsuite/gdc.test/compilable/test16635.d
index 5f3d0ba9b6c..dcdd35b3bb0 100644
--- a/gcc/testsuite/gdc.test/compilable/test16635.d
+++ b/gcc/testsuite/gdc.test/compilable/test16635.d
@@ -39,7 +39,7 @@  void test16635_1()
     Vector2 b = Vector2(3, 4);
 
     // this line causes application to run infinitely
-    // Already fixed. It was issue 16621
+    // Already fixed. It was https://issues.dlang.org/show_bug.cgi?id=16621
     Vector2 c = a + b;
 
     // OK <- this line seg faults without the above line
diff --git a/gcc/testsuite/gdc.test/compilable/test17143.d b/gcc/testsuite/gdc.test/compilable/test17143.d
index 4ec029572f4..272d65934b8 100644
--- a/gcc/testsuite/gdc.test/compilable/test17143.d
+++ b/gcc/testsuite/gdc.test/compilable/test17143.d
@@ -13,4 +13,4 @@  Tuple!T tuple(T...)(T args)
 
 enum foo = tuple(1, 2).expand;
 static assert(typeof(foo).stringof == "(int, int)");
-static assert(foo.stringof == "tuple(1, 2)");
+static assert(foo.stringof == "AliasSeq!(1, 2)");
diff --git a/gcc/testsuite/gdc.test/compilable/test17373.d b/gcc/testsuite/gdc.test/compilable/test17373.d
index 9a5ee6431a2..1f83f51685d 100644
--- a/gcc/testsuite/gdc.test/compilable/test17373.d
+++ b/gcc/testsuite/gdc.test/compilable/test17373.d
@@ -28,5 +28,5 @@  interface ConnectionStream : Stream
     void close();
 }
 
-static assert(__traits(getOverloads, ConnectionStream, "connected").stringof == "tuple(connected)");
-static assert(__traits(getOverloads, ConnectionStream, "close").stringof == "tuple(close)");
+static assert(__traits(getOverloads, ConnectionStream, "connected").stringof == "AliasSeq!(connected)");
+static assert(__traits(getOverloads, ConnectionStream, "close").stringof == "AliasSeq!(close)");
diff --git a/gcc/testsuite/gdc.test/compilable/test17545.d b/gcc/testsuite/gdc.test/compilable/test17545.d
index 6285418b806..d1ba7cddea1 100644
--- a/gcc/testsuite/gdc.test/compilable/test17545.d
+++ b/gcc/testsuite/gdc.test/compilable/test17545.d
@@ -1,6 +1,6 @@ 
 /* TEST_OUTPUT:
 ---
-tuple((Attrib))
+AliasSeq!((Attrib))
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/compilable/test19728.d b/gcc/testsuite/gdc.test/compilable/test19728.d
index 551ac0f6a89..73ed9c4a3d8 100644
--- a/gcc/testsuite/gdc.test/compilable/test19728.d
+++ b/gcc/testsuite/gdc.test/compilable/test19728.d
@@ -1,13 +1,13 @@ 
 /*
 TEST_OUTPUT:
 ---
-tuple((A), (B))
-tuple((A), (B), 0)
-tuple((A), (B), (A))
-tuple((A), (B), (A), (B))
-tuple((A), (B), (A), (B))
-tuple((A), (B), (A), (B), (A), (B), (A), (B))
-tuple((Attr))
+AliasSeq!((A), (B))
+AliasSeq!((A), (B), 0)
+AliasSeq!((A), (B), (A))
+AliasSeq!((A), (B), (A), (B))
+AliasSeq!((A), (B), (A), (B))
+AliasSeq!((A), (B), (A), (B), (A), (B), (A), (B))
+AliasSeq!((Attr))
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/compilable/test20008.d b/gcc/testsuite/gdc.test/compilable/test20008.d
new file mode 100644
index 00000000000..5a37248c15e
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test20008.d
@@ -0,0 +1,6 @@ 
+/*
+REQUIRED_ARGS: -Icompilable/imports -c -o-
+EXTRA_FILES: imports/pkg20008/package.d imports/pkg20008/submod.d imports/pkg20008/subpkg/package.d imports/pkg20008/subpkg/subsubmod.d
+*/
+import pkg20008;
+import pkg20008.subpkg;
diff --git a/gcc/testsuite/gdc.test/compilable/test21282.d b/gcc/testsuite/gdc.test/compilable/test21282.d
index 761a6a60dd7..276591f6b07 100644
--- a/gcc/testsuite/gdc.test/compilable/test21282.d
+++ b/gcc/testsuite/gdc.test/compilable/test21282.d
@@ -1,7 +1,7 @@ 
 /*
 TEST_OUTPUT:
 ---
-tuple(func)
+AliasSeq!(func)
 ---
 */
 // https://issues.dlang.org/show_bug.cgi?id=21282
diff --git a/gcc/testsuite/gdc.test/compilable/test21330.d b/gcc/testsuite/gdc.test/compilable/test21330.d
index 4abf36717b5..66f9e29a63a 100644
--- a/gcc/testsuite/gdc.test/compilable/test21330.d
+++ b/gcc/testsuite/gdc.test/compilable/test21330.d
@@ -2,8 +2,8 @@ 
 REQUIRED_ARGS: -unittest
 TEST_OUTPUT:
 ---
-tuple(__unittest_L14_C5_1, __unittest_L14_C5_2)
-tuple(__unittest_L14_C5_2)
+AliasSeq!(__unittest_L14_C5_1, __unittest_L14_C5_2)
+AliasSeq!(__unittest_L14_C5_2)
 ---
 */
 // https://issues.dlang.org/show_bug.cgi?id=21330
diff --git a/gcc/testsuite/gdc.test/compilable/test23965.d b/gcc/testsuite/gdc.test/compilable/test23965.d
new file mode 100644
index 00000000000..36e4e428a85
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23965.d
@@ -0,0 +1,11 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=23965
+// REQUIRED_ARGS: -de
+deprecated:
+
+struct S {}
+
+void fun()
+{
+    S[] arr;
+    arr ~= S();
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23978.d b/gcc/testsuite/gdc.test/compilable/test23978.d
new file mode 100644
index 00000000000..cc30f728dee
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23978.d
@@ -0,0 +1,30 @@ 
+// REQUIRED_ARGS: -preview=dip1021 -lowmem
+// https://issues.dlang.org/show_bug.cgi?id=23978
+
+// Note: this is a memory corruption bug.
+// Memory returned by `GC.realloc` retains references to old memory in it,
+// mostly because of the smallarray optimization for `Array(T)`.
+// If this fails again, it might not be consistent, so try running it multiple times.
+
+class LUBench { }
+void lup(ulong , ulong , int , int = 1)
+{
+    new LUBench;
+}
+void lup_3200(ulong iters, ulong flops)
+{
+    lup(iters, flops, 3200);
+}
+void raytrace()
+{
+    struct V
+    {
+        float x, y, z;
+        auto normalize() { }
+        struct Tid { }
+        auto spawnLinked() { }
+        string[] namesByTid;
+        class MessageBox { }
+        auto cross() { }
+    }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23979.d b/gcc/testsuite/gdc.test/compilable/test23979.d
new file mode 100644
index 00000000000..f7eb2c554ee
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23979.d
@@ -0,0 +1,17 @@ 
+// REQUIRED_ARGS: -o-
+// https://issues.dlang.org/show_bug.cgi?id=23979
+// Issue 23979 - ICE on failed alias this attempt on pointer expression
+
+class A {}
+
+void h()
+{
+    const auto classPtr = SPtr.init;
+    assert(!__traits(compiles, *classPtr));
+}
+
+struct SPtr
+{
+    A ptr() { return A.init; }
+    alias ptr this;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23986.d b/gcc/testsuite/gdc.test/compilable/test23986.d
new file mode 100644
index 00000000000..6bbf1c2aeaa
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23986.d
@@ -0,0 +1,11 @@ 
+// REQUIRED_ARGS: -preview=dip1021 -o-
+// https://issues.dlang.org/show_bug.cgi?id=23986
+// dip1021 asserts on `typeof(null)` parameter
+@safe:
+
+void f(typeof(null) obj, int* x) {}
+
+void g()
+{
+    f(null, null);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test24013.d b/gcc/testsuite/gdc.test/compilable/test24013.d
new file mode 100644
index 00000000000..132ada61c8e
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test24013.d
@@ -0,0 +1,43 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=24013
+
+struct PropDescriptor(T)
+{
+    void define(T delegate() aGetter, string aName) {}
+}
+
+enum Get;
+
+mixin template PropertyPublisherImpl()
+{
+    void collectPublicationsFromPairs(T)()
+    {
+        foreach (member; __traits(derivedMembers, T))
+        foreach (overload; __traits(getOverloads, T, member))
+        {
+            alias Attributes = __traits(getAttributes, overload);
+            static if (Attributes.length != 0)
+            {
+                auto descriptor = new PropDescriptor!size_t;
+                auto dg = &overload;
+                descriptor.define(dg, member);
+            }
+        }
+    }
+}
+
+void main()
+{
+    class Bar
+    {
+        size_t _field;
+        mixin PropertyPublisherImpl;
+        this()
+        {
+            collectPublicationsFromPairs!Bar;
+        }
+        @Get size_t field()
+        {
+            return _field;
+        }
+    }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test24017.d b/gcc/testsuite/gdc.test/compilable/test24017.d
new file mode 100644
index 00000000000..0d039781201
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test24017.d
@@ -0,0 +1,11 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=24017
+
+// REQUIRED_ARGS: -debug
+
+void writeln(string) {}
+
+void main() nothrow
+{
+    debug writeln("Hello");
+    debug "Hello".writeln;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test9692.d b/gcc/testsuite/gdc.test/compilable/test9692.d
index 57131b8080c..cb5da6a3422 100644
--- a/gcc/testsuite/gdc.test/compilable/test9692.d
+++ b/gcc/testsuite/gdc.test/compilable/test9692.d
@@ -4,5 +4,5 @@  module test9692;
 import test9692a;
 import imports.test9692b;
 
-enum x = [__traits(allMembers, imports.test9692b)];  // ok
-enum y = [__traits(allMembers, test9692a)];  // ng: should work
+static assert([__traits(allMembers, imports.test9692b)] == ["object", "k"]); // ok
+static assert([__traits(allMembers, test9692a)] == ["object", "j"]); // ng: should work
diff --git a/gcc/testsuite/gdc.test/compilable/testInference.d b/gcc/testsuite/gdc.test/compilable/testInference.d
index 31b10494148..bddbaf42946 100644
--- a/gcc/testsuite/gdc.test/compilable/testInference.d
+++ b/gcc/testsuite/gdc.test/compilable/testInference.d
@@ -171,9 +171,9 @@  template map7017(fun...) if (fun.length >= 1)
     auto map7017()
     {
         struct Result {
-            this(int dummy){}   // impure member function -> inferred to pure by fixing issue 10329
+            this(int dummy){}   // impure member function -> inferred to pure by fixing https://issues.dlang.org/show_bug.cgi?id=10329
         }
-        return Result(0);   // impure call -> inferred to pure by fixing issue 10329
+        return Result(0);   // impure call -> inferred to pure by fixing https://issues.dlang.org/show_bug.cgi?id=10329
     }
 }
 
@@ -588,7 +588,7 @@  auto fb10148(T)()
             static assert(is(typeof(&fc) == void delegate()));
             fa10148();
         }
-        // [1] this is now inferred to @safe by implementing issue 7511
+        // [1] this is now inferred to @safe by implementing https://issues.dlang.org/show_bug.cgi?id=7511
         this(S a) {}
     }
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/callconst.d b/gcc/testsuite/gdc.test/fail_compilation/callconst.d
new file mode 100644
index 00000000000..74c1902b2d4
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/callconst.d
@@ -0,0 +1,16 @@ 
+/*
+TEST_OUTPUT:
+---
+fail_compilation/callconst.d(13): Error: function `callconst.func(ref X)` is not callable using argument types `(const(X))`
+fail_compilation/callconst.d(13):        cannot pass argument `x` of type `const(X)` to parameter `ref X`
+---
+*/
+struct X {}
+
+void main()
+{
+    auto x = const X();
+    func(x);
+}
+
+void func(ref X);
diff --git a/gcc/testsuite/gdc.test/fail_compilation/casttuple.d b/gcc/testsuite/gdc.test/fail_compilation/casttuple.d
index d08de08b553..89e5f3de7ee 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/casttuple.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/casttuple.d
@@ -1,9 +1,9 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/casttuple.d(104): Error: cannot cast `__tup1_field_0` of type `int` to tuple type `(string)`
-fail_compilation/casttuple.d(107): Error: cannot cast `tuple(__tup2_field_0, __tup2_field_1)` of type `(int, int)` to tuple type `(string, string)`
-fail_compilation/casttuple.d(111): Error: cannot cast `tuple(foo, 123)` of type `(int, int)` to tuple type `(string, string)`
+fail_compilation/casttuple.d(104): Error: cannot cast `__tup1_field_0` of type `int` to type sequence `(string)`
+fail_compilation/casttuple.d(107): Error: cannot cast `AliasSeq!(__tup2_field_0, __tup2_field_1)` of type `(int, int)` to type sequence `(string, string)`
+fail_compilation/casttuple.d(111): Error: cannot cast `AliasSeq!(foo, 123)` of type `(int, int)` to type sequence `(string, string)`
 ---
  */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/cppmangle.d b/gcc/testsuite/gdc.test/fail_compilation/cppmangle.d
index 8134afb18d2..b3c89b46d2a 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/cppmangle.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/cppmangle.d
@@ -3,7 +3,7 @@  TEST_OUTPUT:
 ---
 fail_compilation/cppmangle.d(11): Error: expected valid identifier for C++ namespace but got ``
 fail_compilation/cppmangle.d(15): Error: expected valid identifier for C++ namespace but got `0num`
-fail_compilation/cppmangle.d(19): Error: compile time string constant (or tuple) expected, not `2`
+fail_compilation/cppmangle.d(19): Error: compile time string constant (or sequence) expected, not `2`
 fail_compilation/cppmangle.d(23): Error: expected valid identifier for C++ namespace but got `invalid@namespace`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/dassert.d b/gcc/testsuite/gdc.test/fail_compilation/dassert.d
index 8a813177c35..c18a28d2ffb 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/dassert.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/dassert.d
@@ -2,7 +2,7 @@ 
 REQUIRED_ARGS: -checkaction=context
 TEST_OUTPUT:
 ---
-fail_compilation/dassert.d(14): Error: expression `tuple(0, 0)` of type `(int, int)` does not have a boolean value
+fail_compilation/dassert.d(14): Error: expression `AliasSeq!(0, 0)` of type `(int, int)` does not have a boolean value
 fail_compilation/dassert.d(21): Error: assignment cannot be used as a condition, perhaps `==` was meant?
 fail_compilation/dassert.d(29): Error: assignment cannot be used as a condition, perhaps `==` was meant?
 fail_compilation/dassert.d(40): Error: expression `issue()` of type `void` does not have a boolean value
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag13884.d b/gcc/testsuite/gdc.test/fail_compilation/diag13884.d
index fe47c838dd9..14af2c884a9 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag13884.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag13884.d
@@ -1,7 +1,7 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag13884.d(14): Error: functions cannot return a tuple
+fail_compilation/diag13884.d(14): Error: functions cannot return a sequence (use `std.typecons.Tuple`)
 fail_compilation/diag13884.d(21):        instantiated from here: `MapResult!((t) => t.tupleof, Foo[])`
 fail_compilation/diag13884.d(14):        instantiated from here: `map!(Foo[])`
 ---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag14876.d b/gcc/testsuite/gdc.test/fail_compilation/diag14876.d
index 0ca03602f97..4beea959001 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag14876.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag14876.d
@@ -8,7 +8,7 @@  fail_compilation/diag14876.d(20): Deprecation: class `diag14876.Dep` is deprecat
 fail_compilation/diag14876.d(21): Deprecation: class `diag14876.Dep` is deprecated
 fail_compilation/diag14876.d(22): Deprecation: class `diag14876.Dep` is deprecated
 fail_compilation/diag14876.d(23): Deprecation: class `diag14876.Dep` is deprecated
-fail_compilation/diag14876.d(23): Error: can only slice tuple types, not `diag14876.Dep`
+fail_compilation/diag14876.d(23): Error: can only slice type sequences, not `diag14876.Dep`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/dtor_attributes.d b/gcc/testsuite/gdc.test/fail_compilation/dtor_attributes.d
index 21a12ed0253..02d95586eae 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/dtor_attributes.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/dtor_attributes.d
@@ -30,7 +30,7 @@  struct HasDtor
     ~this() {}
 }
 
-// The user-defined dtor is overriden by a generated dtor calling both
+// The user-defined dtor is overridden by a generated dtor calling both
 // - HasDtor.~this
 // - Strict.~this
 struct Strict
diff --git a/gcc/testsuite/gdc.test/fail_compilation/e15876_1.d b/gcc/testsuite/gdc.test/fail_compilation/e15876_1.d
index 92e07342d49..0152cdee276 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/e15876_1.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/e15876_1.d
@@ -1,12 +1,13 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/e15876_1.d(16): Error: valid scope identifiers are `exit`, `failure`, or `success`, not `x`
-fail_compilation/e15876_1.d(17): Error: found `End of File` when expecting `)`
-fail_compilation/e15876_1.d(17): Error: found `End of File` instead of statement
-fail_compilation/e15876_1.d(17): Error: found `End of File` when expecting `}` following compound statement
-fail_compilation/e15876_1.d(17): Error: found `End of File` when expecting `]`
-fail_compilation/e15876_1.d(17): Error: no identifier for declarator `o[()
+fail_compilation/e15876_1.d(17): Error: valid scope identifiers are `exit`, `failure`, or `success`, not `x`
+fail_compilation/e15876_1.d(18): Error: found `End of File` when expecting `)`
+fail_compilation/e15876_1.d(18): Error: found `End of File` instead of statement
+fail_compilation/e15876_1.d(18): Error: matching `}` expected following compound statement, not `End of File`
+fail_compilation/e15876_1.d(17):        unmatched `{`
+fail_compilation/e15876_1.d(18): Error: found `End of File` when expecting `]`
+fail_compilation/e15876_1.d(18): Error: no identifier for declarator `o[()
 {
 scope(exit) __error__
 }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/e15876_2.d b/gcc/testsuite/gdc.test/fail_compilation/e15876_2.d
index 10ff7d53a98..92164a4fd8b 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/e15876_2.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/e15876_2.d
@@ -1,10 +1,11 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/e15876_2.d(15): Error: identifier expected following `template`
-fail_compilation/e15876_2.d(15): Error: found `End of File` when expecting `}` following compound statement
-fail_compilation/e15876_2.d(15): Error: found `End of File` when expecting `]`
-fail_compilation/e15876_2.d(15): Error: no identifier for declarator `o[()
+fail_compilation/e15876_2.d(16): Error: identifier expected following `template`
+fail_compilation/e15876_2.d(16): Error: matching `}` expected following compound statement, not `End of File`
+fail_compilation/e15876_2.d(15):        unmatched `{`
+fail_compilation/e15876_2.d(16): Error: found `End of File` when expecting `]`
+fail_compilation/e15876_2.d(16): Error: no identifier for declarator `o[()
 {
 ;
 }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/e15876_3.d b/gcc/testsuite/gdc.test/fail_compilation/e15876_3.d
index 0ac72296639..0482e87a549 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/e15876_3.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/e15876_3.d
@@ -1,18 +1,19 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/e15876_3.d(27): Error: unexpected `(` in declarator
-fail_compilation/e15876_3.d(27): Error: basic type expected, not `=`
-fail_compilation/e15876_3.d(28): Error: found `End of File` when expecting `(`
-fail_compilation/e15876_3.d(28): Error: found `End of File` instead of statement
-fail_compilation/e15876_3.d(28): Error: expression expected, not `End of File`
-fail_compilation/e15876_3.d(28): Error: found `End of File` when expecting `;` following `for` condition
-fail_compilation/e15876_3.d(28): Error: expression expected, not `End of File`
-fail_compilation/e15876_3.d(28): Error: found `End of File` when expecting `)`
-fail_compilation/e15876_3.d(28): Error: found `End of File` instead of statement
-fail_compilation/e15876_3.d(28): Error: found `End of File` when expecting `}` following compound statement
-fail_compilation/e15876_3.d(28): Error: found `End of File` when expecting `)`
-fail_compilation/e15876_3.d(28): Error: no identifier for declarator `d(_error_ = ()
+fail_compilation/e15876_3.d(28): Error: unexpected `(` in declarator
+fail_compilation/e15876_3.d(28): Error: basic type expected, not `=`
+fail_compilation/e15876_3.d(29): Error: found `End of File` when expecting `(`
+fail_compilation/e15876_3.d(29): Error: found `End of File` instead of statement
+fail_compilation/e15876_3.d(29): Error: expression expected, not `End of File`
+fail_compilation/e15876_3.d(29): Error: found `End of File` when expecting `;` following `for` condition
+fail_compilation/e15876_3.d(29): Error: expression expected, not `End of File`
+fail_compilation/e15876_3.d(29): Error: found `End of File` when expecting `)`
+fail_compilation/e15876_3.d(29): Error: found `End of File` instead of statement
+fail_compilation/e15876_3.d(29): Error: matching `}` expected following compound statement, not `End of File`
+fail_compilation/e15876_3.d(28):        unmatched `{`
+fail_compilation/e15876_3.d(29): Error: found `End of File` when expecting `)`
+fail_compilation/e15876_3.d(29): Error: no identifier for declarator `d(_error_ = ()
 {
 for (__error__
  0; 0)
@@ -21,7 +22,7 @@  __error__
 }
 }
 )`
-fail_compilation/e15876_3.d(28): Error: semicolon expected following function declaration, not `End of File`
+fail_compilation/e15876_3.d(29): Error: semicolon expected following function declaration, not `End of File`
 ---
 */
 d(={for
diff --git a/gcc/testsuite/gdc.test/fail_compilation/e15876_4.d b/gcc/testsuite/gdc.test/fail_compilation/e15876_4.d
index f4bd407b9c0..e5c3bbf5673 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/e15876_4.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/e15876_4.d
@@ -1,17 +1,18 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/e15876_4.d(25): Error: found `)` when expecting `(`
-fail_compilation/e15876_4.d(26): Error: found `End of File` when expecting `(`
-fail_compilation/e15876_4.d(26): Error: found `End of File` instead of statement
-fail_compilation/e15876_4.d(26): Error: expression expected, not `End of File`
-fail_compilation/e15876_4.d(26): Error: found `End of File` when expecting `;` following `for` condition
-fail_compilation/e15876_4.d(26): Error: expression expected, not `End of File`
-fail_compilation/e15876_4.d(26): Error: found `End of File` when expecting `)`
-fail_compilation/e15876_4.d(26): Error: found `End of File` instead of statement
-fail_compilation/e15876_4.d(26): Error: found `End of File` when expecting `}` following compound statement
-fail_compilation/e15876_4.d(26): Error: found `End of File` when expecting `)`
-fail_compilation/e15876_4.d(26): Error: no identifier for declarator `typeof(()
+fail_compilation/e15876_4.d(26): Error: found `)` when expecting `(`
+fail_compilation/e15876_4.d(27): Error: found `End of File` when expecting `(`
+fail_compilation/e15876_4.d(27): Error: found `End of File` instead of statement
+fail_compilation/e15876_4.d(27): Error: expression expected, not `End of File`
+fail_compilation/e15876_4.d(27): Error: found `End of File` when expecting `;` following `for` condition
+fail_compilation/e15876_4.d(27): Error: expression expected, not `End of File`
+fail_compilation/e15876_4.d(27): Error: found `End of File` when expecting `)`
+fail_compilation/e15876_4.d(27): Error: found `End of File` instead of statement
+fail_compilation/e15876_4.d(27): Error: matching `}` expected following compound statement, not `End of File`
+fail_compilation/e15876_4.d(26):        unmatched `{`
+fail_compilation/e15876_4.d(27): Error: found `End of File` when expecting `)`
+fail_compilation/e15876_4.d(27): Error: no identifier for declarator `typeof(()
 {
 for (__error__
  0; 0)
diff --git a/gcc/testsuite/gdc.test/fail_compilation/e15876_5.d b/gcc/testsuite/gdc.test/fail_compilation/e15876_5.d
index 96b23e278cd..6bebc29fcb6 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/e15876_5.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/e15876_5.d
@@ -1,11 +1,12 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/e15876_5.d(16): Error: basic type expected, not `End of File`
-fail_compilation/e15876_5.d(16): Error: semicolon expected to close `alias` declaration, not `End of File`
-fail_compilation/e15876_5.d(16): Error: found `End of File` when expecting `}` following compound statement
-fail_compilation/e15876_5.d(16): Error: found `End of File` when expecting `]`
-fail_compilation/e15876_5.d(16): Error: no identifier for declarator `p[()
+fail_compilation/e15876_5.d(17): Error: basic type expected, not `End of File`
+fail_compilation/e15876_5.d(17): Error: semicolon expected to close `alias` declaration, not `End of File`
+fail_compilation/e15876_5.d(17): Error: matching `}` expected following compound statement, not `End of File`
+fail_compilation/e15876_5.d(16):        unmatched `{`
+fail_compilation/e15876_5.d(17): Error: found `End of File` when expecting `]`
+fail_compilation/e15876_5.d(17): Error: no identifier for declarator `p[()
 {
 alias ;
 }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/enum_init.d b/gcc/testsuite/gdc.test/fail_compilation/enum_init.d
index 8344a4701c7..c968f5ee184 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/enum_init.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/enum_init.d
@@ -58,6 +58,8 @@  TEST_OUTPUT:
 ---
 fail_compilation/enum_init.d(306): Error: variable `enum_init.fooOB.ob` - no definition of struct `S`
 fail_compilation/enum_init.d(302):        required by type `OpaqueBase`
+fail_compilation/enum_init.d(306):        see https://dlang.org/spec/struct.html#opaque_struct_unions
+fail_compilation/enum_init.d(306):        perhaps declare a variable with pointer type `OpaqueBase*` instead
 ---
 */
 #line 300
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail12436.d b/gcc/testsuite/gdc.test/fail_compilation/fail12436.d
index 5bdf0d5a891..415e362bf29 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail12436.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail12436.d
@@ -12,7 +12,7 @@  alias Tuple!(int, int) TupleType;
 TEST_OUTPUT:
 ---
 fail_compilation/fail12436.d(18): Error: functions cannot return a function
-fail_compilation/fail12436.d(19): Error: functions cannot return a tuple
+fail_compilation/fail12436.d(19): Error: functions cannot return a sequence (use `std.typecons.Tuple`)
 ---
 */
 FuncType test1();
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail15755.d b/gcc/testsuite/gdc.test/fail_compilation/fail15755.d
index 8fd2b51b60a..502eedcd6e3 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail15755.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail15755.d
@@ -1,7 +1,7 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail15755.d(28): Error: `tuple(123)` has no effect
+fail_compilation/fail15755.d(28): Error: `AliasSeq!(123)` has no effect
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail16772.d b/gcc/testsuite/gdc.test/fail_compilation/fail16772.d
index e77951d3302..0bc97512c9a 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail16772.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail16772.d
@@ -1,7 +1,8 @@ 
 // https://issues.dlang.org/show_bug.cgi?id=16772
 /* TEST_OUTPUT:
 ---
-fail_compilation/fail16772.d(7): Error: function `fail16772.ice16772` cannot return type `ubyte[]` because its linkage is `extern(C++)`
+fail_compilation/fail16772.d(8): Error: function `fail16772.ice16772` cannot return type `ubyte[]` because its linkage is `extern(C++)`
+fail_compilation/fail16772.d(8):        slices are specific to D and do not have a counterpart representation in C++
 ---
 */
 extern(C++) ubyte[] ice16772() { return []; }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19209.d b/gcc/testsuite/gdc.test/fail_compilation/fail19209.d
index ceede5e0eed..56b85815150 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail19209.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19209.d
@@ -2,7 +2,7 @@ 
 TEST_OUTPUT:
 ---
 fail_compilation/fail19209.d(16): Error: function `fail19209.Spammer.method()` does not override any function, did you mean to override variable `fail19209.Spam.method`?
-fail_compilation/fail19209.d(16):        Functions are the only declarations that may be overriden
+fail_compilation/fail19209.d(16):        Functions are the only declarations that may be overridden
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail196.d b/gcc/testsuite/gdc.test/fail_compilation/fail196.d
index 53505f496c2..cdad5c491db 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail196.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail196.d
@@ -1,24 +1,26 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail196.d(27): Error: delimited string must end in `)"`
-fail_compilation/fail196.d(27): Error: implicit string concatenation is error-prone and disallowed in D
-fail_compilation/fail196.d(27):        Use the explicit syntax instead (concatenating literals is `@nogc`): "foo(xxx)" ~ ";\n    assert(s == "
-fail_compilation/fail196.d(28): Error: semicolon needed to end declaration of `s`, instead of `foo`
-fail_compilation/fail196.d(27):        `s` declared here
-fail_compilation/fail196.d(28): Error: found `");\n\n    s = q"` when expecting `;` following statement `foo(xxx)` on line fail_compilation/fail196.d(28)
-fail_compilation/fail196.d(30): Error: found `";\n    assert(s == "` when expecting `;` following statement `[foo[xxx]]` on line fail_compilation/fail196.d(30)
-fail_compilation/fail196.d(31): Error: found `");\n\n    s = q"` when expecting `;` following statement `foo[xxx]` on line fail_compilation/fail196.d(31)
-fail_compilation/fail196.d(33): Error: found `{` when expecting `;` following statement `foo` on line fail_compilation/fail196.d(33)
-fail_compilation/fail196.d(33): Error: found `}` when expecting `;` following statement `xxx` on line fail_compilation/fail196.d(33)
-fail_compilation/fail196.d(34): Error: found `foo` when expecting `;` following statement `";\n    assert(s == "` on line fail_compilation/fail196.d(33)
-fail_compilation/fail196.d(34): Error: found `}` when expecting `;` following statement `xxx` on line fail_compilation/fail196.d(34)
-fail_compilation/fail196.d(36): Error: found `<` when expecting `;` following statement `");\n\n    s = q" < foo` on line fail_compilation/fail196.d(34)
-fail_compilation/fail196.d(37): Error: found `foo` when expecting `;` following statement `xxx >> ";\n    assert(s == "` on line fail_compilation/fail196.d(36)
-fail_compilation/fail196.d(37): Error: found `<` instead of statement
-fail_compilation/fail196.d(43): Error: unterminated string constant starting at fail_compilation/fail196.d(43)
-fail_compilation/fail196.d(45): Error: found `End of File` when expecting `}` following compound statement
-fail_compilation/fail196.d(45): Error: found `End of File` when expecting `}` following compound statement
+fail_compilation/fail196.d(29): Error: delimited string must end in `)"`
+fail_compilation/fail196.d(29): Error: implicit string concatenation is error-prone and disallowed in D
+fail_compilation/fail196.d(29):        Use the explicit syntax instead (concatenating literals is `@nogc`): "foo(xxx)" ~ ";\n    assert(s == "
+fail_compilation/fail196.d(30): Error: semicolon needed to end declaration of `s`, instead of `foo`
+fail_compilation/fail196.d(29):        `s` declared here
+fail_compilation/fail196.d(30): Error: found `");\n\n    s = q"` when expecting `;` following statement `foo(xxx)` on line fail_compilation/fail196.d(30)
+fail_compilation/fail196.d(32): Error: found `";\n    assert(s == "` when expecting `;` following statement `[foo[xxx]]` on line fail_compilation/fail196.d(32)
+fail_compilation/fail196.d(33): Error: found `");\n\n    s = q"` when expecting `;` following statement `foo[xxx]` on line fail_compilation/fail196.d(33)
+fail_compilation/fail196.d(35): Error: found `{` when expecting `;` following statement `foo` on line fail_compilation/fail196.d(35)
+fail_compilation/fail196.d(35): Error: found `}` when expecting `;` following statement `xxx` on line fail_compilation/fail196.d(35)
+fail_compilation/fail196.d(36): Error: found `foo` when expecting `;` following statement `";\n    assert(s == "` on line fail_compilation/fail196.d(35)
+fail_compilation/fail196.d(36): Error: found `}` when expecting `;` following statement `xxx` on line fail_compilation/fail196.d(36)
+fail_compilation/fail196.d(38): Error: found `<` when expecting `;` following statement `");\n\n    s = q" < foo` on line fail_compilation/fail196.d(36)
+fail_compilation/fail196.d(39): Error: found `foo` when expecting `;` following statement `xxx >> ";\n    assert(s == "` on line fail_compilation/fail196.d(38)
+fail_compilation/fail196.d(39): Error: found `<` instead of statement
+fail_compilation/fail196.d(45): Error: unterminated string constant starting at fail_compilation/fail196.d(45)
+fail_compilation/fail196.d(47): Error: matching `}` expected following compound statement, not `End of File`
+fail_compilation/fail196.d(36):        unmatched `{`
+fail_compilation/fail196.d(47): Error: matching `}` expected following compound statement, not `End of File`
+fail_compilation/fail196.d(28):        unmatched `{`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21206.d b/gcc/testsuite/gdc.test/fail_compilation/fail21206.d
index c3d648e5d75..b3b42f34296 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail21206.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail21206.d
@@ -1,7 +1,8 @@ 
 // https://issues.dlang.org/show_bug.cgi?id=21206
 /* TEST_OUTPUT:
 ---
-fail_compilation/fail21206.d(9): Error: function `fail21206.Obj.toString` cannot return type `string` because its linkage is `extern(C++)`
+fail_compilation/fail21206.d(10): Error: function `fail21206.Obj.toString` cannot return type `string` because its linkage is `extern(C++)`
+fail_compilation/fail21206.d(10):        slices are specific to D and do not have a counterpart representation in C++
 ---
 */
 extern(C++) struct Obj
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21275.d b/gcc/testsuite/gdc.test/fail_compilation/fail21275.d
index 69cdf1ada9a..b7bbcfa6250 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail21275.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail21275.d
@@ -1,12 +1,11 @@ 
 // https://issues.dlang.org/show_bug.cgi?id=21275
-// REQUIRED_ARGS: -de
 // EXTRA_FILES: imports/fail21275a.d
 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail21275.d(18): Deprecation: function `imports.fail21275a.Foo.x` of type `ref int() return` is not accessible from module `fail21275`
-fail_compilation/fail21275.d(21): Deprecation: function `imports.fail21275a.Bar.x` of type `int(int)` is not accessible from module `fail21275`
+fail_compilation/fail21275.d(17): Error: function `imports.fail21275a.Foo.x` of type `ref int() return` is not accessible from module `fail21275`
+fail_compilation/fail21275.d(20): Error: function `imports.fail21275a.Bar.x` of type `int(int)` is not accessible from module `fail21275`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail222.d b/gcc/testsuite/gdc.test/fail_compilation/fail222.d
index 30eb0144d99..e196b253065 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail222.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail222.d
@@ -1,10 +1,10 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail222.d(11): Error: template `fail222.getMixin(TArg..., int i = 0)()` template tuple parameter must be last one
+fail_compilation/fail222.d(11): Error: template `fail222.getMixin(TArg..., int i = 0)()` template sequence parameter must be the last one
 fail_compilation/fail222.d(18): Error: template instance `getMixin!()` does not match template declaration `getMixin(TArg..., int i = 0)()`
 fail_compilation/fail222.d(21): Error: template instance `fail222.Thing!()` error instantiating
-fail_compilation/fail222.d(23): Error: template `fail222.fooBar(A..., B...)()` template tuple parameter must be last one
+fail_compilation/fail222.d(23): Error: template `fail222.fooBar(A..., B...)()` template sequence parameter must be the last one
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22729.d b/gcc/testsuite/gdc.test/fail_compilation/fail22729.d
new file mode 100644
index 00000000000..38bbfeeed2b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail22729.d
@@ -0,0 +1,39 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=22729
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail22729.d(12): Error: field `getChildAtPosition` not allowed in interface
+---
+*/
+
+interface ContainerFunctionSetI
+{
+    Tuple!(WidgetI) getChildAtPosition;
+}
+
+interface WidgetI : ContainerFunctionSetI
+{
+}
+
+class Form : WidgetI
+{
+}
+
+template Tuple(Specs)
+{
+    enum areCompatibleTuples(Tup2)(Tuple tup1, Tup2 tup2)
+    {
+        tup1.field == tup2;
+    }
+
+    struct Tuple
+    {
+        Specs field;
+
+        bool opEquals(R)(R) if (areCompatibleTuples!R)
+        {
+        }
+
+    }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail23745.d b/gcc/testsuite/gdc.test/fail_compilation/fail23745.d
index eda9e1e63fa..46d92f0fa10 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail23745.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail23745.d
@@ -5,7 +5,7 @@  TEST_OUTPUT:
 ---
 fail_compilation/fail23745.d(21): Error: undefined identifier `UndefinedType`
 fail_compilation/fail23745.d(14): Error: function `fun` does not override any function, did you mean to override `fail23745.A.fun`?
-fail_compilation/fail23745.d(21):        Function `fail23745.A.fun` contains errors in its declaration, therefore it cannot be correctly overriden
+fail_compilation/fail23745.d(21):        Function `fail23745.A.fun` contains errors in its declaration, therefore it cannot be correctly overridden
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail315.d b/gcc/testsuite/gdc.test/fail_compilation/fail315.d
index c7fd78f8fc1..1a7e0f35f91 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail315.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail315.d
@@ -1,13 +1,14 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail315.d-mixin-16(16): Error: found `;` when expecting `,`
-fail_compilation/fail315.d-mixin-16(16): Error: expression expected, not `}`
-fail_compilation/fail315.d-mixin-16(16): Error: found `End of File` when expecting `,`
-fail_compilation/fail315.d-mixin-16(16): Error: found `End of File` when expecting `]`
-fail_compilation/fail315.d-mixin-16(16): Error: found `End of File` when expecting `;` following `return` statement
-fail_compilation/fail315.d-mixin-16(16): Error: found `End of File` when expecting `}` following compound statement
-fail_compilation/fail315.d(21): Error: template instance `fail315.foo!()` error instantiating
+fail_compilation/fail315.d-mixin-17(17): Error: found `;` when expecting `,`
+fail_compilation/fail315.d-mixin-17(17): Error: expression expected, not `}`
+fail_compilation/fail315.d-mixin-17(17): Error: found `End of File` when expecting `,`
+fail_compilation/fail315.d-mixin-17(17): Error: found `End of File` when expecting `]`
+fail_compilation/fail315.d-mixin-17(17): Error: found `End of File` when expecting `;` following `return` statement
+fail_compilation/fail315.d-mixin-17(17): Error: matching `}` expected following compound statement, not `End of File`
+fail_compilation/fail315.d-mixin-17(17):        unmatched `{`
+fail_compilation/fail315.d(22): Error: template instance `fail315.foo!()` error instantiating
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/funcpostattr.d b/gcc/testsuite/gdc.test/fail_compilation/funcpostattr.d
new file mode 100644
index 00000000000..b50db058e32
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/funcpostattr.d
@@ -0,0 +1,21 @@ 
+/*
+TEST_OUTPUT:
+---
+fail_compilation/funcpostattr.d(11): Error: `deprecated` token is not allowed in postfix position
+fail_compilation/funcpostattr.d(11): Error: `extern` token is not allowed in postfix position
+fail_compilation/funcpostattr.d(15): Error: `static` token is not allowed in postfix position
+fail_compilation/funcpostattr.d(15): Error: `ref` token is not allowed in postfix position
+fail_compilation/funcpostattr.d(20): Error: `override` token is not allowed in postfix position
+---
+*/
+void foo() deprecated extern;
+
+void main() {
+    int i;
+    int foo() static ref => i;
+}
+
+class C
+{
+    void foo() override {}
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice11965.d b/gcc/testsuite/gdc.test/fail_compilation/ice11965.d
index c8db60fe9c9..9e6da3bbf84 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice11965.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice11965.d
@@ -1,10 +1,11 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice11965.d(15): Error: no identifier for declarator `b*`
-fail_compilation/ice11965.d(15): Error: found `End of File` when expecting `}` following compound statement
-fail_compilation/ice11965.d(15): Error: found `End of File` when expecting `]`
-fail_compilation/ice11965.d(15): Error: no identifier for declarator `u[()
+fail_compilation/ice11965.d(16): Error: no identifier for declarator `b*`
+fail_compilation/ice11965.d(16): Error: matching `}` expected following compound statement, not `End of File`
+fail_compilation/ice11965.d(15):        unmatched `{`
+fail_compilation/ice11965.d(16): Error: found `End of File` when expecting `]`
+fail_compilation/ice11965.d(16): Error: no identifier for declarator `u[()
 {
 b* A;
 }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice11982.d b/gcc/testsuite/gdc.test/fail_compilation/ice11982.d
index 0f2ce413c40..0886df61678 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice11982.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice11982.d
@@ -1,19 +1,20 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice11982.d(19): Error: basic type expected, not `scope`
-fail_compilation/ice11982.d(19): Error: found `scope` when expecting `;` following statement `new _error_` on line fail_compilation/ice11982.d(19)
-fail_compilation/ice11982.d(19): Error: basic type expected, not `}`
-fail_compilation/ice11982.d(19): Error: missing `{ ... }` for function literal
-fail_compilation/ice11982.d(19): Error: C style cast illegal, use `cast(funk)function _error_()
+fail_compilation/ice11982.d(20): Error: basic type expected, not `scope`
+fail_compilation/ice11982.d(20): Error: found `scope` when expecting `;` following statement `new _error_` on line fail_compilation/ice11982.d(20)
+fail_compilation/ice11982.d(20): Error: basic type expected, not `}`
+fail_compilation/ice11982.d(20): Error: missing `{ ... }` for function literal
+fail_compilation/ice11982.d(20): Error: C style cast illegal, use `cast(funk)function _error_()
 {
 }
 `
-fail_compilation/ice11982.d(19): Error: found `}` when expecting `;` following statement `cast(funk)function _error_()
+fail_compilation/ice11982.d(20): Error: found `}` when expecting `;` following statement `cast(funk)function _error_()
 {
 }
-` on line fail_compilation/ice11982.d(19)
-fail_compilation/ice11982.d(20): Error: found `End of File` when expecting `}` following compound statement
+` on line fail_compilation/ice11982.d(20)
+fail_compilation/ice11982.d(21): Error: matching `}` expected following compound statement, not `End of File`
+fail_compilation/ice11982.d(20):        unmatched `{`
 ---
 */
 void main() { new scope ( funk ) function }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice12574.d b/gcc/testsuite/gdc.test/fail_compilation/ice12574.d
index 93e5f1d8cc0..ecb0fd69a05 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice12574.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice12574.d
@@ -1,7 +1,7 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice12574.d(40): Error: tuple index `2` out of bounds `[0 .. 2]`
+fail_compilation/ice12574.d(40): Error: sequence index `2` out of bounds `[0 .. 2]`
 fail_compilation/ice12574.d(53): Error: template instance `ice12574.reduce!("a", "a").reduce!(Tuple!(int, int, int))` error instantiating
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice14424.d b/gcc/testsuite/gdc.test/fail_compilation/ice14424.d
index c99522dceb6..b0e0cd6407f 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice14424.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice14424.d
@@ -3,7 +3,7 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice14424.d(13): Error: `tuple(__unittest_L3_C1)` has no effect
+fail_compilation/ice14424.d(13): Error: `AliasSeq!(__unittest_L3_C1)` has no effect
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice15855.d b/gcc/testsuite/gdc.test/fail_compilation/ice15855.d
index b26fe4cda04..f7ad3900683 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice15855.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice15855.d
@@ -2,16 +2,17 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice15855.d(27): Error: found `End of File` when expecting `(`
-fail_compilation/ice15855.d(27): Error: found `End of File` instead of statement
-fail_compilation/ice15855.d(27): Error: expression expected, not `End of File`
-fail_compilation/ice15855.d(27): Error: found `End of File` when expecting `;` following `for` condition
-fail_compilation/ice15855.d(27): Error: expression expected, not `End of File`
-fail_compilation/ice15855.d(27): Error: found `End of File` when expecting `)`
-fail_compilation/ice15855.d(27): Error: found `End of File` instead of statement
-fail_compilation/ice15855.d(27): Error: found `End of File` when expecting `}` following compound statement
-fail_compilation/ice15855.d(27): Error: found `End of File` when expecting `]`
-fail_compilation/ice15855.d(27): Error: no identifier for declarator `a[()
+fail_compilation/ice15855.d(28): Error: found `End of File` when expecting `(`
+fail_compilation/ice15855.d(28): Error: found `End of File` instead of statement
+fail_compilation/ice15855.d(28): Error: expression expected, not `End of File`
+fail_compilation/ice15855.d(28): Error: found `End of File` when expecting `;` following `for` condition
+fail_compilation/ice15855.d(28): Error: expression expected, not `End of File`
+fail_compilation/ice15855.d(28): Error: found `End of File` when expecting `)`
+fail_compilation/ice15855.d(28): Error: found `End of File` instead of statement
+fail_compilation/ice15855.d(28): Error: matching `}` expected following compound statement, not `End of File`
+fail_compilation/ice15855.d(27):        unmatched `{`
+fail_compilation/ice15855.d(28): Error: found `End of File` when expecting `]`
+fail_compilation/ice15855.d(28): Error: no identifier for declarator `a[()
 {
 for (__error__
  0; 0)
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/issue23947a.d b/gcc/testsuite/gdc.test/fail_compilation/imports/issue23947a.d
new file mode 100644
index 00000000000..270bf5fd538
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/issue23947a.d
@@ -0,0 +1,8 @@ 
+module imports.issue23947a;
+
+struct X { }
+struct Y { }
+class Class {
+    private void handle(X x) { }
+    public void handle(Y y) { }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/issue20422.d b/gcc/testsuite/gdc.test/fail_compilation/issue20422.d
index 1964f8ac888..9dcab004d2c 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/issue20422.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/issue20422.d
@@ -1,12 +1,19 @@ 
 // https://issues.dlang.org/show_bug.cgi?id=20422
 
 /*
+REQUIRED_ARGS: -m32
 TEST_OUTPUT:
 ---
-fail_compilation/issue20422.d(11): Error: missing length argument for array
+fail_compilation/issue20422.d(15): Error: missing length argument for array
+fail_compilation/issue20422.d(16): Error: negative array dimension `-1`
+fail_compilation/issue20422.d(17): Error: negative array dimension `-2147483648`
+fail_compilation/issue20422.d(18): Error: too many arguments for array
 ---
 */
 
 void main() {
     new int[];
+    new int[-1];
+    new int[](int.min);
+    new int[](1, 2);
 }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/issue23947.d b/gcc/testsuite/gdc.test/fail_compilation/issue23947.d
new file mode 100644
index 00000000000..d73cd8572fa
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/issue23947.d
@@ -0,0 +1,10 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=23947
+/*
+TEST_OUTPUT:
+---
+fail_compilation/issue23947.d(10): Error: function `imports.issue23947a.Class.handle` of type `void(X x)` is not accessible from module `issue23947`
+---
+*/
+import imports.issue23947a;
+
+void main() { Class.init.handle(X.init); }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/lexer4.d b/gcc/testsuite/gdc.test/fail_compilation/lexer4.d
index c9db26434df..c4bdb4fd64c 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/lexer4.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/lexer4.d
@@ -8,7 +8,7 @@  fail_compilation/lexer4.d(26): Error: binary digit expected, not `2`
 fail_compilation/lexer4.d(27): Error: octal digit expected, not `8`
 fail_compilation/lexer4.d(27): Error: octal literals larger than 7 are no longer supported
 fail_compilation/lexer4.d(28): Error: decimal digit expected, not `a`
-fail_compilation/lexer4.d(29): Error: unrecognized token
+fail_compilation/lexer4.d(29): Error: repeated integer suffix `U`
 fail_compilation/lexer4.d(30): Error: exponent required for hex float
 fail_compilation/lexer4.d(31): Error: lower case integer suffix 'l' is not allowed. Please use 'L' instead
 fail_compilation/lexer4.d(32): Error: use 'i' suffix instead of 'I'
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 d1361440920..a719b123a6a 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
@@ -24,7 +24,8 @@  fail_compilation/misc_parser_err_cov1.d(40): Error: identifier or `new` expected
 fail_compilation/misc_parser_err_cov1.d(41): Error: identifier or new keyword expected following `(...)`.
 fail_compilation/misc_parser_err_cov1.d(41): Error: expression expected, not `;`
 fail_compilation/misc_parser_err_cov1.d(42): Error: found `}` when expecting `;` following statement `(__error) + 0` on line fail_compilation/misc_parser_err_cov1.d(41)
-fail_compilation/misc_parser_err_cov1.d(43): Error: found `End of File` when expecting `}` following compound statement
+fail_compilation/misc_parser_err_cov1.d(43): Error: matching `}` expected following compound statement, not `End of File`
+fail_compilation/misc_parser_err_cov1.d(33):        unmatched `{`
 ---
 */
 module misc_parser_err_cov1;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/missingbrace.d b/gcc/testsuite/gdc.test/fail_compilation/missingbrace.d
new file mode 100644
index 00000000000..5c8166eaa6e
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/missingbrace.d
@@ -0,0 +1,10 @@ 
+/*
+TEST_OUTPUT:
+---
+fail_compilation/missingbrace.d(11): Error: matching `}` expected following compound statement, not `End of File`
+fail_compilation/missingbrace.d(9):        unmatched `{`
+---
+*/
+void main()
+{
+    int a;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/retscope.d b/gcc/testsuite/gdc.test/fail_compilation/retscope.d
index 50cfdd3ef9c..c08747fa7e3 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/retscope.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/retscope.d
@@ -403,7 +403,7 @@  class Foo13
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/retscope.d(1205): Error: scope variable `f14` calling non-scope member function `f14.foo()`
+fail_compilation/retscope.d(1205): Error: scope variable `f14` calling non-scope member function `Foo14.foo()`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test20245.d b/gcc/testsuite/gdc.test/fail_compilation/test20245.d
index 3c43c5cfe4b..a6bbba29128 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test20245.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test20245.d
@@ -9,7 +9,7 @@  fail_compilation/test20245.d(27): Error: cannot take address of `scope` variable
 fail_compilation/test20245.d(33): Error: reference to local variable `x` assigned to non-scope parameter `ptr` calling `escape`
 fail_compilation/test20245.d(34): Error: copying `&x` into allocated memory escapes a reference to parameter `x`
 fail_compilation/test20245.d(50): Error: reference to local variable `price` assigned to non-scope `this.minPrice`
-fail_compilation/test20245.d(69): Error: reference to local variable `this` calling non-scope member function `this.this()`
+fail_compilation/test20245.d(69): Error: reference to local variable `this.content[]` calling non-scope member function `Exception.this()`
 fail_compilation/test20245.d(89): Error: reference to local variable `this` assigned to non-scope parameter `content` calling `listUp`
 fail_compilation/test20245.d(82):        which is not `scope` because of `charPtr = content`
 ---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21025.d b/gcc/testsuite/gdc.test/fail_compilation/test21025.d
new file mode 100644
index 00000000000..85641998751
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21025.d
@@ -0,0 +1,25 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=21025
+// REQUIRED_ARGS: -preview=dip1021
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test21025.d(15): Error: variable `r` cannot be read at compile time
+fail_compilation/test21025.d(15):        called from here: `binaryFun(r, r)`
+fail_compilation/test21025.d(24): Error: template `test21025.uniq` is not callable using argument types `!()(void[])`
+fail_compilation/test21025.d(14):        Candidate is: `uniq()(int[] r)`
+---
+*/
+
+void uniq()(int[] r)
+if (binaryFun(r, r)) {}
+
+bool binaryFun(T, U)(T, U)
+{
+    return true;
+}
+
+void generateStatements()
+{
+    uniq([]);
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test23968.d b/gcc/testsuite/gdc.test/fail_compilation/test23968.d
new file mode 100644
index 00000000000..4456e75c707
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test23968.d
@@ -0,0 +1,23 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=23968
+
+// REQUIRED_ARGS: -de
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test23968.d(22): Deprecation: alias `test23968.a` is deprecated
+---
+*/
+
+int fun()(int)
+{
+    return 0;
+}
+
+deprecated alias a = fun;
+
+void main()
+{
+    int v;
+    int y = v.a!();  // No deprecation?
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test23982.d b/gcc/testsuite/gdc.test/fail_compilation/test23982.d
new file mode 100644
index 00000000000..f8eee238ed8
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test23982.d
@@ -0,0 +1,36 @@ 
+/*
+REQUIRED_ARGS: -preview=dip1000
+TEST_OUTPUT:
+---
+fail_compilation/test23982.d(35): Error: scope variable `a` assigned to non-scope parameter `a` calling `foo2`
+fail_compilation/test23982.d(26):        which is not `scope` because of `b = a`
+---
+*/
+// https://issues.dlang.org/show_bug.cgi?id=23982
+// Issue 23982 - segfault when printing scope inference failure
+@safe:
+
+struct B()
+{
+    this(int* a)
+    {
+        this.a = a;
+    }
+    int* a;
+}
+
+class C()
+{
+    int* foo2(int* a)
+    {
+        auto b = B!()(a);
+     	return b.a;
+    }
+}
+
+void main()
+{
+    scope int* a;
+    C!() c;
+    c.foo2(a);
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/typeerrors.d b/gcc/testsuite/gdc.test/fail_compilation/typeerrors.d
index 9d527b75d71..404a4c0e3fe 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/typeerrors.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/typeerrors.d
@@ -2,7 +2,7 @@ 
 TEST_OUTPUT:
 ---
 fail_compilation/typeerrors.d(32): Deprecation: `scope` as a type constraint is deprecated.  Use `scope` at the usage site.
-fail_compilation/typeerrors.d(37): Error: tuple index `4` out of bounds `[0 .. 4]`
+fail_compilation/typeerrors.d(37): Error: sequence index `4` out of bounds `[0 .. 4]`
 fail_compilation/typeerrors.d(39): Error: variable `x` cannot be read at compile time
 fail_compilation/typeerrors.d(40): Error: cannot have array of `void()`
 fail_compilation/typeerrors.d(41): Error: cannot have array of scope `typeerrors.C`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/unmatchedbrace.d b/gcc/testsuite/gdc.test/fail_compilation/unmatchedbrace.d
new file mode 100644
index 00000000000..30dc3b5d90e
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/unmatchedbrace.d
@@ -0,0 +1,10 @@ 
+/*
+TEST_OUTPUT:
+---
+fail_compilation/unmatchedbrace.d(11): Error: matching `}` expected, not `End of File`
+fail_compilation/unmatchedbrace.d(8):        unmatched `{`
+---
+*/
+@safe {
+    //
+    struct S {}
diff --git a/gcc/testsuite/gdc.test/runnable/functype.d b/gcc/testsuite/gdc.test/runnable/functype.d
index 5dad6186fba..cdeb4182a1f 100644
--- a/gcc/testsuite/gdc.test/runnable/functype.d
+++ b/gcc/testsuite/gdc.test/runnable/functype.d
@@ -301,7 +301,7 @@  void test10734()
 
 void test14656()
 {
-    //void unaryFun()(auto int a) pure nothrow @safe @nogc {}   // changed to invalid by fixing issue 14669
+    //void unaryFun()(auto int a) pure nothrow @safe @nogc {}   // changed to invalid by fixing https://issues.dlang.org/show_bug.cgi?id=14669
     alias Identity(F) = F;
     //unaryFun!()(41);
     static void fun(int n) pure nothrow @safe @nogc {}
diff --git a/gcc/testsuite/gdc.test/runnable/interface2.d b/gcc/testsuite/gdc.test/runnable/interface2.d
index fabbbfd4bfc..603e4b25108 100644
--- a/gcc/testsuite/gdc.test/runnable/interface2.d
+++ b/gcc/testsuite/gdc.test/runnable/interface2.d
@@ -962,11 +962,11 @@  void test1747()
     assert(pia == pc + n);
 
     assert(id.mA() == 1);
-    assert(id.mB() == 2);   // OK <- NG (bugzilla 2013 case)
+    assert(id.mB() == 2);   // OK <- NG (https://issues.dlang.org/show_bug.cgi?id=2013 case)
     assert(id.mD() == 3);
 
     assert(ic.mA() == 1);
-    assert(ic.mB() == 2);   // OK <- NG (bugzilla 2013 case)
+    assert(ic.mB() == 2);   // OK <- NG (https://issues.dlang.org/show_bug.cgi?id=2013 case)
 
     assert(ib.mA() == 1);
     assert(ib.mB() == 2);   // OK <- NG
diff --git a/gcc/testsuite/gdc.test/runnable/link10425.d b/gcc/testsuite/gdc.test/runnable/link10425.d
index d0825165765..ae135ea703a 100644
--- a/gcc/testsuite/gdc.test/runnable/link10425.d
+++ b/gcc/testsuite/gdc.test/runnable/link10425.d
@@ -10,7 +10,7 @@  void main()
      * the TypeInfo object on comdat section (done by TypeInfoDeclaration::toObjFile),
      * even if the associated struct belongs *non-root modules*.
      *
-     * And, from 2.062, issue 7511 is implemented.
+     * And, from 2.062, https://issues.dlang.org/show_bug.cgi?id=7511 is implemented.
      * The attribute inference for member functions in instantiated struct may modify
      * their actual mangled names. Then TypeInfo object compiled in this module would
      * use wrong symbol names, to link non-template opEquals/opCmp/toHash/toString
diff --git a/gcc/testsuite/gdc.test/runnable/sdtor.d b/gcc/testsuite/gdc.test/runnable/sdtor.d
index e6b3238149e..be15cb244a1 100644
--- a/gcc/testsuite/gdc.test/runnable/sdtor.d
+++ b/gcc/testsuite/gdc.test/runnable/sdtor.d
@@ -4813,6 +4813,41 @@  void testPR12012()
 }
 }
 
+/**********************************/
+// https://issues.dlang.org/show_bug.cgi?id=24010
+
+alias AliasSeq(TList...) = TList;
+
+__gshared int x24010 = 7;
+
+struct A24010 {
+    int x;
+    ~this() {
+        printf("A.~this\n");
+        x24010 += 1;
+    }
+}
+
+struct B24010 {
+    ~this() {
+        printf("B.~this\n");
+        x24010 *= 10;
+    }
+}
+
+void test24010()
+{
+    {
+        AliasSeq!(A24010, B24010) params;
+        printf("statement\n");
+        params[0].x = 3;
+        printf(".x = %d\n", params[0].x);
+        assert(params[0].x == 3);
+        assert(x24010 == 7);
+    }
+    assert(x24010 == 71);
+}
+
 /**********************************/
 
 int main()
@@ -4954,6 +4989,7 @@  int main()
     test67();
     test68();
     testPR12012();
+    test24010();
 
     printf("Success\n");
     return 0;
diff --git a/gcc/testsuite/gdc.test/runnable/template9.d b/gcc/testsuite/gdc.test/runnable/template9.d
index cb3de5bc6f0..dbad3f1daec 100644
--- a/gcc/testsuite/gdc.test/runnable/template9.d
+++ b/gcc/testsuite/gdc.test/runnable/template9.d
@@ -4689,7 +4689,8 @@  struct S14604
 }
 alias Id14604(alias thing) = thing;
 alias c14604 = Id14604!(S14604.opDispatch!"go");     // ok
-alias d14604 = Id14604!(S14604.go);                  // issue 14604, 'Error: template instance opDispatch!"go" cannot resolve forward reference'
+// https://issues.dlang.org/show_bug.cgi?id=14604
+alias d14604 = Id14604!(S14604.go);                  // 'Error: template instance opDispatch!"go" cannot resolve forward reference'
 
 /******************************************/
 // https://issues.dlang.org/show_bug.cgi?id=14735
diff --git a/gcc/testsuite/gdc.test/runnable/test23959.d b/gcc/testsuite/gdc.test/runnable/test23959.d
new file mode 100644
index 00000000000..32883736d44
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/test23959.d
@@ -0,0 +1,30 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=23959;
+
+struct ST()
+{
+    int i;
+    this(this) {}
+}
+
+alias S = ST!();
+
+void poison()
+{
+    static S g;
+    auto s = g;
+}
+
+S[1] sa;
+
+void fun(S[] values...)
+{
+    sa[] = values;
+}
+
+int main()
+{
+    fun(S(1));
+    assert(sa[0].i);
+
+    return 0;
+}
diff --git a/gcc/testsuite/gdc.test/runnable/testcontracts.d b/gcc/testsuite/gdc.test/runnable/testcontracts.d
index e79c6a05716..439040b7b38 100644
--- a/gcc/testsuite/gdc.test/runnable/testcontracts.d
+++ b/gcc/testsuite/gdc.test/runnable/testcontracts.d
@@ -936,7 +936,7 @@  void test9383()
 
 /*******************************************/
 // https://issues.dlang.org/show_bug.cgi?id=15524
-// Different from issue 9383 cases, closed variable size is bigger than REGSIZE.
+// Different from https://issues.dlang.org/show_bug.cgi?id=9383 cases, closed variable size is bigger than REGSIZE.
 
 class A15524
 {
diff --git a/gcc/testsuite/gdc.test/runnable/uda.d b/gcc/testsuite/gdc.test/runnable/uda.d
index 1d010989646..d4e4c2ae95e 100644
--- a/gcc/testsuite/gdc.test/runnable/uda.d
+++ b/gcc/testsuite/gdc.test/runnable/uda.d
@@ -2,30 +2,30 @@ 
 EXTRA_FILES: imports/a9741.d
 TEST_OUTPUT:
 ---
-tuple(3, 4, 7, (SSS))
-tuple(3, 4, 7, (SSS))
+AliasSeq!(3, 4, 7, (SSS))
+AliasSeq!(3, 4, 7, (SSS))
 7
 SSS
-tuple("hello")
-tuple('c')
-tuple((FFF))
-tuple(10)
-tuple(20)
-tuple(30)
-tuple((Test6))
-tuple(Test7(3, "foo"))
-tuple((Test8!"foo"))
-tuple((Test9!"foo"))
-tuple(Test10(3))
-tuple(Test11(3))
-tuple(10)
-tuple(20)
-tuple()
-tuple(40)
+AliasSeq!("hello")
+AliasSeq!('c')
+AliasSeq!((FFF))
+AliasSeq!(10)
+AliasSeq!(20)
+AliasSeq!(30)
+AliasSeq!((Test6))
+AliasSeq!(Test7(3, "foo"))
+AliasSeq!((Test8!"foo"))
+AliasSeq!((Test9!"foo"))
+AliasSeq!(Test10(3))
+AliasSeq!(Test11(3))
+AliasSeq!(10)
+AliasSeq!(20)
+AliasSeq!()
+AliasSeq!(40)
 B9741
-tuple((A9741))
-tuple(1)
-tuple(2)
+AliasSeq!((A9741))
+AliasSeq!(1)
+AliasSeq!(2)
 ---
 
 RUN_OUTPUT:
diff --git a/gcc/testsuite/gdc.test/runnable/xtest46.d b/gcc/testsuite/gdc.test/runnable/xtest46.d
index 5017a767693..972de900203 100644
--- a/gcc/testsuite/gdc.test/runnable/xtest46.d
+++ b/gcc/testsuite/gdc.test/runnable/xtest46.d
@@ -13,17 +13,17 @@  runnable/xtest46.d(2964): Deprecation: alias this for classes/interfaces is depr
 int(int i, long j = 7L)
 long
 C10390(C10390(C10390(<recursion>)))
-tuple(height)
-tuple(get, get)
-tuple(clear)
-tuple(draw, draw)
+AliasSeq!(height)
+AliasSeq!(get, get)
+AliasSeq!(clear)
+AliasSeq!(draw, draw)
 const(int)
 string[]
 double[]
 double[]
 {}
 runnable/xtest46.d(4670): Deprecation: alias this for classes/interfaces is deprecated
-tuple("m")
+AliasSeq!("m")
 true
 TFunction1: extern (C) void function()
 ---
diff --git a/gcc/testsuite/gdc.test/runnable/xtest46_gc.d b/gcc/testsuite/gdc.test/runnable/xtest46_gc.d
index 224625c65ec..aab6227230a 100644
--- a/gcc/testsuite/gdc.test/runnable/xtest46_gc.d
+++ b/gcc/testsuite/gdc.test/runnable/xtest46_gc.d
@@ -14,17 +14,17 @@  runnable/xtest46_gc.d-mixin-33(2996): Deprecation: alias this for classes/interf
 int(int i, long j = 7L)
 long
 C10390(C10390(<recursion>))
-tuple(height)
-tuple(get, get)
-tuple(clear)
-tuple(draw, draw)
+AliasSeq!(height)
+AliasSeq!(get, get)
+AliasSeq!(clear)
+AliasSeq!(draw, draw)
 const(int)
 string[]
 double[]
 double[]
 {}
 runnable/xtest46_gc.d-mixin-33(4702): Deprecation: alias this for classes/interfaces is deprecated
-tuple("m")
+AliasSeq!("m")
 true
 TFunction1: extern (C) void function()
 ---
diff --git a/libphobos/config.h.in b/libphobos/config.h.in
index 0249849c890..6ecb3f2b1ba 100644
--- a/libphobos/config.h.in
+++ b/libphobos/config.h.in
@@ -1,14 +1,23 @@ 
 /* config.h.in.  Generated from configure.ac by autoheader.  */
 
+/* Define to enable to integrate valgrind (a memory checker) in the GC. */
+#undef ENABLE_VALGRIND_CHECKING
+
 /* Define to 1 if you have the <dlfcn.h> header file. */
 #undef HAVE_DLFCN_H
 
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
+/* Define if valgrind's memcheck.h header is installed. */
+#undef HAVE_MEMCHECK_H
+
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
+/* Define to 1 if you have the <stddef.h> header file. */
+#undef HAVE_STDDEF_H
+
 /* Define to 1 if you have the <stdint.h> header file. */
 #undef HAVE_STDINT_H
 
@@ -30,6 +39,9 @@ 
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
+/* Define if valgrind's valgrind/memcheck.h header is installed. */
+#undef HAVE_VALGRIND_MEMCHECK_H
+
 /* Define to the sub-directory in which libtool stores uninstalled libraries.
    */
 #undef LT_OBJDIR
diff --git a/libphobos/configure b/libphobos/configure
index 925c53c5f5e..d702c8f494c 100755
--- a/libphobos/configure
+++ b/libphobos/configure
@@ -1498,8 +1498,8 @@  Optional Features:
   --enable-libphobos-checking[=LIST]
                           enable expensive run-time checks. With LIST, enable
                           only specific categories of checks. Categories are:
-                          yes,no,all,none,release. Flags are: assert or other
-                          strings
+                          yes,no,all,none,release. Flags are: assert,valgrind
+                          or other strings
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
@@ -15553,16 +15553,20 @@  for check in release $ac_checking_flags
 do
 	case $check in
 	# These set all the flags to specific states
-	yes|all) RELEASE_FLAG="-fno-release" ; ASSERT_FLAG= ;;
-	no|none|release) RELEASE_FLAG="-frelease" ; ASSERT_FLAG= ;;
+	yes|all)		RELEASE_FLAG="-fno-release" ; ASSERT_FLAG= ;
+				VALGRIND_FLAG= ;;
+	no|none|release)	RELEASE_FLAG="-frelease" ; ASSERT_FLAG= ;
+				VALGRIND_FLAG= ;;
 	# These enable particular checks
-	assert) ASSERT_FLAG="-fassert" ;;
+	assert)			ASSERT_FLAG="-fassert" ;;
+	valgrind)		VALGRIND_FLAG="-fdebug=VALGRIND" ;;
 	# Accept
 	*) ;;
 	esac
 done
 IFS="$ac_save_IFS"
-CHECKING_DFLAGS="$RELEASE_FLAG $ASSERT_FLAG"
+CHECKING_DFLAGS="$RELEASE_FLAG $ASSERT_FLAG $VALGRIND_FLAG"
+
 
 
 # Add drtbegin.o/drtend.o to startfile/endfile specs in libgphobos.spec
@@ -15600,6 +15604,91 @@  fi
 
 
 
+
+  for ac_header in stddef.h stdlib.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+  ac_fn_c_check_header_mongrel "$LINENO" "valgrind.h" "ac_cv_header_valgrind_h" "$ac_includes_default"
+if test "x$ac_cv_header_valgrind_h" = xyes; then :
+  have_valgrind_h=yes
+else
+  have_valgrind_h=no
+fi
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND_DISCARD in <valgrind/memcheck.h>" >&5
+$as_echo_n "checking for VALGRIND_DISCARD in <valgrind/memcheck.h>... " >&6; }
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <valgrind/memcheck.h>
+  #ifndef VALGRIND_DISCARD
+  #error VALGRIND_DISCARD not defined
+  #endif
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  have_valgrind_memcheck_h=yes
+else
+  have_valgrind_memcheck_h=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_valgrind_memcheck_h" >&5
+$as_echo "$have_valgrind_memcheck_h" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND_DISCARD in <memcheck.h>" >&5
+$as_echo_n "checking for VALGRIND_DISCARD in <memcheck.h>... " >&6; }
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <memcheck.h>
+  #ifndef VALGRIND_DISCARD
+  #error VALGRIND_DISCARD not defined
+  #endif
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  have_memcheck_h=yes
+else
+  have_memcheck_h=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_memcheck_h" >&5
+$as_echo "$have_memcheck_h" >&6; }
+
+  if test x$VALGRIND_FLAG != x ; then
+
+$as_echo "#define ENABLE_VALGRIND_CHECKING 1" >>confdefs.h
+
+  fi
+  if test $have_valgrind_memcheck_h = yes; then
+
+$as_echo "#define HAVE_VALGRIND_MEMCHECK_H 1" >>confdefs.h
+
+  fi
+  if test $have_memcheck_h = yes; then
+
+$as_echo "#define HAVE_MEMCHECK_H 1" >>confdefs.h
+
+  fi
+
+  if test x$VALGRIND_FLAG != x; then
+    if (test $have_valgrind_h = no \
+        && test $have_memcheck_h = no \
+        && test $have_valgrind_memcheck_h = no); then
+      as_fn_error $? "*** valgrind checking requested, but
+*** Can't find valgrind/memcheck.h, memcheck.h or valgrind.h" "$LINENO" 5
+    fi
+  fi
+
+
 ac_config_files="$ac_config_files Makefile"
 
 
diff --git a/libphobos/configure.ac b/libphobos/configure.ac
index 464f4105430..3b2e6df5d5c 100644
--- a/libphobos/configure.ac
+++ b/libphobos/configure.ac
@@ -221,25 +221,29 @@  AC_ARG_ENABLE(libphobos-checking,
 		[enable expensive run-time checks.  With LIST,
 		 enable only specific categories of checks.
 		 Categories are: yes,no,all,none,release.
-		 Flags are: assert or other strings])],
+		 Flags are: assert,valgrind or other strings])],
 [ac_checking_flags="${enableval}"],[ac_checking_flags=release])
 IFS="${IFS= 	}"; ac_save_IFS="$IFS"; IFS="$IFS,"
 for check in release $ac_checking_flags
 do
 	case $check in
 	# These set all the flags to specific states
-	yes|all) RELEASE_FLAG="-fno-release" ; ASSERT_FLAG= ;;
-	no|none|release) RELEASE_FLAG="-frelease" ; ASSERT_FLAG= ;;
+	yes|all)		RELEASE_FLAG="-fno-release" ; ASSERT_FLAG= ;
+				VALGRIND_FLAG= ;;
+	no|none|release)	RELEASE_FLAG="-frelease" ; ASSERT_FLAG= ;
+				VALGRIND_FLAG= ;;
 	# These enable particular checks
-	assert) ASSERT_FLAG="-fassert" ;;
+	assert)			ASSERT_FLAG="-fassert" ;;
+	valgrind)		VALGRIND_FLAG="-fdebug=VALGRIND" ;;
 	# Accept
 	*) ;;
 	esac
 done
 IFS="$ac_save_IFS"
-CHECKING_DFLAGS="$RELEASE_FLAG $ASSERT_FLAG"
+CHECKING_DFLAGS="$RELEASE_FLAG $ASSERT_FLAG $VALGRIND_FLAG"
 AC_SUBST(CHECKING_DFLAGS)
 
+
 # Add drtbegin.o/drtend.o to startfile/endfile specs in libgphobos.spec
 if test "$DCFG_MINFO_BRACKETING" = "false"; then
     DRTSTUFF_SPEC=$srcdir/src/drtstuff.spec
@@ -269,6 +273,8 @@  AC_SUBST(WARN_DFLAGS)
 AC_CHECK_HEADER(stdio.h,:,
   [AC_MSG_ERROR([cannot find stdio.h.])])
 
+DRUNTIME_LIBRARIES_VALGRIND
+
 AC_CONFIG_FILES(Makefile)
 
 AC_CONFIG_FILES(libdruntime/gcc/config.d libdruntime/gcc/libbacktrace.d)
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index 1cff48a7b2a..308d51b55d0 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@ 
-17ccd12af386543c0b9935bf7e0a8e701b903105
+a88e1335f7ea767ef438c34998f5d1f26008c586
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 8225ba4a028..832a0524ab3 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -165,7 +165,7 @@  install-data-local:
 # Can't use wildcards here:
 # https://www.gnu.org/software/automake/manual/html_node/Wildcards.html
 
-DRUNTIME_CSOURCES = core/stdc/errno_.c
+DRUNTIME_CSOURCES = core/stdc/errno_.c etc/valgrind/valgrind_.c
 
 DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	core/builtins.d core/checkedint.d core/cpuid.d core/demangle.d \
@@ -205,11 +205,11 @@  DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	core/sync/semaphore.d core/thread/context.d core/thread/fiber.d \
 	core/thread/osthread.d core/thread/package.d core/thread/threadbase.d \
 	core/thread/threadgroup.d core/thread/types.d core/time.d \
-	core/vararg.d core/volatile.d gcc/attribute.d gcc/attributes.d \
-	gcc/backtrace.d gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \
-	gcc/sections/common.d gcc/sections/elf.d gcc/sections/macho.d \
-	gcc/sections/package.d gcc/sections/pecoff.d gcc/simd.d \
-	gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \
+	core/vararg.d core/volatile.d etc/valgrind/valgrind.d gcc/attribute.d \
+	gcc/attributes.d gcc/backtrace.d gcc/builtins.d gcc/deh.d gcc/emutls.d \
+	gcc/gthread.d gcc/sections/common.d gcc/sections/elf.d \
+	gcc/sections/macho.d gcc/sections/package.d gcc/sections/pecoff.d \
+	gcc/simd.d gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \
 	gcc/unwind/generic.d gcc/unwind/package.d gcc/unwind/pe.d object.d \
 	rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arraycat.d rt/cast_.d \
 	rt/config.d rt/critical_.d rt/deh.d rt/dmain2.d rt/ehalloc.d \
@@ -273,6 +273,7 @@  DRUNTIME_DSOURCES_LINUX = core/sys/linux/config.d \
 	core/sys/linux/dlfcn.d core/sys/linux/elf.d core/sys/linux/epoll.d \
 	core/sys/linux/err.d core/sys/linux/errno.d core/sys/linux/execinfo.d \
 	core/sys/linux/fcntl.d core/sys/linux/fs.d core/sys/linux/ifaddrs.d \
+	core/sys/linux/input.d core/sys/linux/input_event_codes.d \
 	core/sys/linux/io_uring.d core/sys/linux/link.d \
 	core/sys/linux/netinet/in_.d core/sys/linux/netinet/tcp.d \
 	core/sys/linux/perf_event.d core/sys/linux/sched.d \
@@ -284,7 +285,8 @@  DRUNTIME_DSOURCES_LINUX = core/sys/linux/config.d \
 	core/sys/linux/sys/socket.d core/sys/linux/sys/sysinfo.d \
 	core/sys/linux/sys/time.d core/sys/linux/sys/xattr.d \
 	core/sys/linux/termios.d core/sys/linux/time.d \
-	core/sys/linux/timerfd.d core/sys/linux/tipc.d core/sys/linux/unistd.d
+	core/sys/linux/timerfd.d core/sys/linux/tipc.d core/sys/linux/uinput.d \
+	core/sys/linux/unistd.d
 
 DRUNTIME_DSOURCES_NETBSD = core/sys/netbsd/dlfcn.d \
 	core/sys/netbsd/err.d core/sys/netbsd/execinfo.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 797d6435a7c..61a2a770888 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -235,12 +235,12 @@  am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
 	core/thread/osthread.lo core/thread/package.lo \
 	core/thread/threadbase.lo core/thread/threadgroup.lo \
 	core/thread/types.lo core/time.lo core/vararg.lo \
-	core/volatile.lo gcc/attribute.lo gcc/attributes.lo \
-	gcc/backtrace.lo gcc/builtins.lo gcc/deh.lo gcc/emutls.lo \
-	gcc/gthread.lo gcc/sections/common.lo gcc/sections/elf.lo \
-	gcc/sections/macho.lo gcc/sections/package.lo \
-	gcc/sections/pecoff.lo gcc/simd.lo gcc/unwind/arm.lo \
-	gcc/unwind/arm_common.lo gcc/unwind/c6x.lo \
+	core/volatile.lo etc/valgrind/valgrind.lo gcc/attribute.lo \
+	gcc/attributes.lo gcc/backtrace.lo gcc/builtins.lo gcc/deh.lo \
+	gcc/emutls.lo gcc/gthread.lo gcc/sections/common.lo \
+	gcc/sections/elf.lo gcc/sections/macho.lo \
+	gcc/sections/package.lo gcc/sections/pecoff.lo gcc/simd.lo \
+	gcc/unwind/arm.lo gcc/unwind/arm_common.lo gcc/unwind/c6x.lo \
 	gcc/unwind/generic.lo gcc/unwind/package.lo gcc/unwind/pe.lo \
 	object.lo rt/aApply.lo rt/aApplyR.lo rt/aaA.lo rt/adi.lo \
 	rt/arraycat.lo rt/cast_.lo rt/config.lo rt/critical_.lo \
@@ -248,7 +248,8 @@  am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
 	rt/lifetime.lo rt/memory.lo rt/minfo.lo rt/monitor_.lo \
 	rt/profilegc.lo rt/sections.lo rt/tlsgc.lo rt/util/typeinfo.lo \
 	rt/util/utility.lo
-am__objects_2 = core/stdc/libgdruntime_la-errno_.lo
+am__objects_2 = core/stdc/libgdruntime_la-errno_.lo \
+	etc/valgrind/libgdruntime_la-valgrind_.lo
 am__objects_3 = core/sys/elf/package.lo
 am__objects_4 = core/stdcpp/allocator.lo core/stdcpp/array.lo \
 	core/stdcpp/exception.lo core/stdcpp/memory.lo \
@@ -363,6 +364,7 @@  am__objects_19 = core/sys/linux/config.lo core/sys/linux/dlfcn.lo \
 	core/sys/linux/err.lo core/sys/linux/errno.lo \
 	core/sys/linux/execinfo.lo core/sys/linux/fcntl.lo \
 	core/sys/linux/fs.lo core/sys/linux/ifaddrs.lo \
+	core/sys/linux/input.lo core/sys/linux/input_event_codes.lo \
 	core/sys/linux/io_uring.lo core/sys/linux/link.lo \
 	core/sys/linux/netinet/in_.lo core/sys/linux/netinet/tcp.lo \
 	core/sys/linux/perf_event.lo core/sys/linux/sched.lo \
@@ -375,7 +377,7 @@  am__objects_19 = core/sys/linux/config.lo core/sys/linux/dlfcn.lo \
 	core/sys/linux/sys/time.lo core/sys/linux/sys/xattr.lo \
 	core/sys/linux/termios.lo core/sys/linux/time.lo \
 	core/sys/linux/timerfd.lo core/sys/linux/tipc.lo \
-	core/sys/linux/unistd.lo
+	core/sys/linux/uinput.lo core/sys/linux/unistd.lo
 @DRUNTIME_OS_LINUX_TRUE@am__objects_20 = $(am__objects_19)
 am__objects_21 = core/sys/windows/accctrl.lo \
 	core/sys/windows/aclapi.lo core/sys/windows/aclui.lo \
@@ -497,7 +499,8 @@  am__objects_35 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \
 am_libgdruntime_la_OBJECTS = $(am__objects_35)
 libgdruntime_la_OBJECTS = $(am_libgdruntime_la_OBJECTS)
 am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
-am__objects_36 = core/stdc/libgdruntime_convenience_la-errno_.lo
+am__objects_36 = core/stdc/libgdruntime_convenience_la-errno_.lo \
+	etc/valgrind/libgdruntime_convenience_la-valgrind_.lo
 @DRUNTIME_OS_MINGW_TRUE@am__objects_37 = $(am__objects_21) \
 @DRUNTIME_OS_MINGW_TRUE@	config/mingw/libgdruntime_convenience_la-msvc.lo
 @DRUNTIME_CPU_AARCH64_TRUE@am__objects_38 = config/aarch64/libgdruntime_convenience_la-switchcontext.lo
@@ -836,7 +839,7 @@  libgdruntime_convenience_la_LINK = $(libgdruntime_la_LINK)
 # https://gist.github.com/jpf91/8ad1dbc9902d6ad876313f134c6527d1
 # Can't use wildcards here:
 # https://www.gnu.org/software/automake/manual/html_node/Wildcards.html
-DRUNTIME_CSOURCES = core/stdc/errno_.c
+DRUNTIME_CSOURCES = core/stdc/errno_.c etc/valgrind/valgrind_.c
 DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	core/builtins.d core/checkedint.d core/cpuid.d core/demangle.d \
 	core/exception.d core/factory.d core/gc/config.d core/gc/gcinterface.d \
@@ -875,11 +878,11 @@  DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	core/sync/semaphore.d core/thread/context.d core/thread/fiber.d \
 	core/thread/osthread.d core/thread/package.d core/thread/threadbase.d \
 	core/thread/threadgroup.d core/thread/types.d core/time.d \
-	core/vararg.d core/volatile.d gcc/attribute.d gcc/attributes.d \
-	gcc/backtrace.d gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \
-	gcc/sections/common.d gcc/sections/elf.d gcc/sections/macho.d \
-	gcc/sections/package.d gcc/sections/pecoff.d gcc/simd.d \
-	gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \
+	core/vararg.d core/volatile.d etc/valgrind/valgrind.d gcc/attribute.d \
+	gcc/attributes.d gcc/backtrace.d gcc/builtins.d gcc/deh.d gcc/emutls.d \
+	gcc/gthread.d gcc/sections/common.d gcc/sections/elf.d \
+	gcc/sections/macho.d gcc/sections/package.d gcc/sections/pecoff.d \
+	gcc/simd.d gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \
 	gcc/unwind/generic.d gcc/unwind/package.d gcc/unwind/pe.d object.d \
 	rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arraycat.d rt/cast_.d \
 	rt/config.d rt/critical_.d rt/deh.d rt/dmain2.d rt/ehalloc.d \
@@ -942,6 +945,7 @@  DRUNTIME_DSOURCES_LINUX = core/sys/linux/config.d \
 	core/sys/linux/dlfcn.d core/sys/linux/elf.d core/sys/linux/epoll.d \
 	core/sys/linux/err.d core/sys/linux/errno.d core/sys/linux/execinfo.d \
 	core/sys/linux/fcntl.d core/sys/linux/fs.d core/sys/linux/ifaddrs.d \
+	core/sys/linux/input.d core/sys/linux/input_event_codes.d \
 	core/sys/linux/io_uring.d core/sys/linux/link.d \
 	core/sys/linux/netinet/in_.d core/sys/linux/netinet/tcp.d \
 	core/sys/linux/perf_event.d core/sys/linux/sched.d \
@@ -953,7 +957,8 @@  DRUNTIME_DSOURCES_LINUX = core/sys/linux/config.d \
 	core/sys/linux/sys/socket.d core/sys/linux/sys/sysinfo.d \
 	core/sys/linux/sys/time.d core/sys/linux/sys/xattr.d \
 	core/sys/linux/termios.d core/sys/linux/time.d \
-	core/sys/linux/timerfd.d core/sys/linux/tipc.d core/sys/linux/unistd.d
+	core/sys/linux/timerfd.d core/sys/linux/tipc.d core/sys/linux/uinput.d \
+	core/sys/linux/unistd.d
 
 DRUNTIME_DSOURCES_NETBSD = core/sys/netbsd/dlfcn.d \
 	core/sys/netbsd/err.d core/sys/netbsd/execinfo.d \
@@ -1331,6 +1336,10 @@  core/thread/types.lo: core/thread/$(am__dirstamp)
 core/time.lo: core/$(am__dirstamp)
 core/vararg.lo: core/$(am__dirstamp)
 core/volatile.lo: core/$(am__dirstamp)
+etc/valgrind/$(am__dirstamp):
+	@$(MKDIR_P) etc/valgrind
+	@: > etc/valgrind/$(am__dirstamp)
+etc/valgrind/valgrind.lo: etc/valgrind/$(am__dirstamp)
 gcc/$(am__dirstamp):
 	@$(MKDIR_P) gcc
 	@: > gcc/$(am__dirstamp)
@@ -1387,6 +1396,8 @@  rt/util/$(am__dirstamp):
 rt/util/typeinfo.lo: rt/util/$(am__dirstamp)
 rt/util/utility.lo: rt/util/$(am__dirstamp)
 core/stdc/libgdruntime_la-errno_.lo: core/stdc/$(am__dirstamp)
+etc/valgrind/libgdruntime_la-valgrind_.lo:  \
+	etc/valgrind/$(am__dirstamp)
 core/sys/elf/$(am__dirstamp):
 	@$(MKDIR_P) core/sys/elf
 	@: > core/sys/elf/$(am__dirstamp)
@@ -1668,6 +1679,8 @@  core/sys/linux/execinfo.lo: core/sys/linux/$(am__dirstamp)
 core/sys/linux/fcntl.lo: core/sys/linux/$(am__dirstamp)
 core/sys/linux/fs.lo: core/sys/linux/$(am__dirstamp)
 core/sys/linux/ifaddrs.lo: core/sys/linux/$(am__dirstamp)
+core/sys/linux/input.lo: core/sys/linux/$(am__dirstamp)
+core/sys/linux/input_event_codes.lo: core/sys/linux/$(am__dirstamp)
 core/sys/linux/io_uring.lo: core/sys/linux/$(am__dirstamp)
 core/sys/linux/link.lo: core/sys/linux/$(am__dirstamp)
 core/sys/linux/netinet/$(am__dirstamp):
@@ -1698,6 +1711,7 @@  core/sys/linux/termios.lo: core/sys/linux/$(am__dirstamp)
 core/sys/linux/time.lo: core/sys/linux/$(am__dirstamp)
 core/sys/linux/timerfd.lo: core/sys/linux/$(am__dirstamp)
 core/sys/linux/tipc.lo: core/sys/linux/$(am__dirstamp)
+core/sys/linux/uinput.lo: core/sys/linux/$(am__dirstamp)
 core/sys/linux/unistd.lo: core/sys/linux/$(am__dirstamp)
 core/sys/windows/$(am__dirstamp):
 	@$(MKDIR_P) core/sys/windows
@@ -1951,6 +1965,8 @@  libgdruntime.la: $(libgdruntime_la_OBJECTS) $(libgdruntime_la_DEPENDENCIES) $(EX
 	$(AM_V_GEN)$(libgdruntime_la_LINK) -rpath $(toolexeclibdir) $(libgdruntime_la_OBJECTS) $(libgdruntime_la_LIBADD) $(LIBS)
 core/stdc/libgdruntime_convenience_la-errno_.lo:  \
 	core/stdc/$(am__dirstamp)
+etc/valgrind/libgdruntime_convenience_la-valgrind_.lo:  \
+	etc/valgrind/$(am__dirstamp)
 config/mingw/libgdruntime_convenience_la-msvc.lo:  \
 	config/mingw/$(am__dirstamp)
 config/aarch64/libgdruntime_convenience_la-switchcontext.lo:  \
@@ -2077,6 +2093,8 @@  mostlyclean-compile:
 	-rm -f core/sys/windows/stdc/*.lo
 	-rm -f core/thread/*.$(OBJEXT)
 	-rm -f core/thread/*.lo
+	-rm -f etc/valgrind/*.$(OBJEXT)
+	-rm -f etc/valgrind/*.lo
 	-rm -f gcc/*.$(OBJEXT)
 	-rm -f gcc/*.lo
 	-rm -f gcc/sections/*.$(OBJEXT)
@@ -2160,12 +2178,18 @@  config/s390/libgdruntime_convenience_la-get_tls_offset.lo: config/s390/get_tls_o
 core/stdc/libgdruntime_la-errno_.lo: core/stdc/errno_.c
 	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o core/stdc/libgdruntime_la-errno_.lo `test -f 'core/stdc/errno_.c' || echo '$(srcdir)/'`core/stdc/errno_.c
 
+etc/valgrind/libgdruntime_la-valgrind_.lo: etc/valgrind/valgrind_.c
+	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o etc/valgrind/libgdruntime_la-valgrind_.lo `test -f 'etc/valgrind/valgrind_.c' || echo '$(srcdir)/'`etc/valgrind/valgrind_.c
+
 config/mingw/libgdruntime_la-msvc.lo: config/mingw/msvc.c
 	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o config/mingw/libgdruntime_la-msvc.lo `test -f 'config/mingw/msvc.c' || echo '$(srcdir)/'`config/mingw/msvc.c
 
 core/stdc/libgdruntime_convenience_la-errno_.lo: core/stdc/errno_.c
 	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_convenience_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o core/stdc/libgdruntime_convenience_la-errno_.lo `test -f 'core/stdc/errno_.c' || echo '$(srcdir)/'`core/stdc/errno_.c
 
+etc/valgrind/libgdruntime_convenience_la-valgrind_.lo: etc/valgrind/valgrind_.c
+	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_convenience_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o etc/valgrind/libgdruntime_convenience_la-valgrind_.lo `test -f 'etc/valgrind/valgrind_.c' || echo '$(srcdir)/'`etc/valgrind/valgrind_.c
+
 config/mingw/libgdruntime_convenience_la-msvc.lo: config/mingw/msvc.c
 	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_convenience_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o config/mingw/libgdruntime_convenience_la-msvc.lo `test -f 'config/mingw/msvc.c' || echo '$(srcdir)/'`config/mingw/msvc.c
 
@@ -2225,6 +2249,7 @@  clean-libtool:
 	-rm -rf core/sys/windows/.libs core/sys/windows/_libs
 	-rm -rf core/sys/windows/stdc/.libs core/sys/windows/stdc/_libs
 	-rm -rf core/thread/.libs core/thread/_libs
+	-rm -rf etc/valgrind/.libs etc/valgrind/_libs
 	-rm -rf gcc/.libs gcc/_libs
 	-rm -rf gcc/sections/.libs gcc/sections/_libs
 	-rm -rf gcc/unwind/.libs gcc/unwind/_libs
@@ -2387,6 +2412,7 @@  distclean-generic:
 	-rm -f core/sys/windows/$(am__dirstamp)
 	-rm -f core/sys/windows/stdc/$(am__dirstamp)
 	-rm -f core/thread/$(am__dirstamp)
+	-rm -f etc/valgrind/$(am__dirstamp)
 	-rm -f gcc/$(am__dirstamp)
 	-rm -f gcc/sections/$(am__dirstamp)
 	-rm -f gcc/unwind/$(am__dirstamp)
diff --git a/libphobos/libdruntime/core/atomic.d b/libphobos/libdruntime/core/atomic.d
index 5a7d00c38db..ff7f7abf0c2 100644
--- a/libphobos/libdruntime/core/atomic.d
+++ b/libphobos/libdruntime/core/atomic.d
@@ -85,7 +85,7 @@  enum MemoryOrder
  * Returns:
  *  The value of 'val'.
  */
-T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(ref return scope const T val) pure nothrow @nogc @trusted
+T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(auto ref return scope const T val) pure nothrow @nogc @trusted
     if (!is(T == shared U, U) && !is(T == shared inout U, U) && !is(T == shared const U, U))
 {
     static if (__traits(isFloating, T))
@@ -99,7 +99,7 @@  T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(ref return scope const T val)
 }
 
 /// Ditto
-T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(ref return scope shared const T val) pure nothrow @nogc @trusted
+T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(auto ref return scope shared const T val) pure nothrow @nogc @trusted
     if (!hasUnsharedIndirections!T)
 {
     import core.internal.traits : hasUnsharedIndirections;
@@ -109,7 +109,7 @@  T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(ref return scope shared const
 }
 
 /// Ditto
-TailShared!T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(ref shared const T val) pure nothrow @nogc @trusted
+TailShared!T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(auto ref shared const T val) pure nothrow @nogc @trusted
     if (hasUnsharedIndirections!T)
 {
     // HACK: DEPRECATE THIS FUNCTION, IT IS INVALID TO DO ATOMIC LOAD OF SHARED CLASS
@@ -1203,7 +1203,7 @@  version (CoreUnittest)
         }
     }
 
-    @betterC pure nothrow @nogc @safe unittest // issue 16651
+    @betterC pure nothrow @nogc @safe unittest // https://issues.dlang.org/show_bug.cgi?id=16651
     {
         shared ulong a = 2;
         uint b = 1;
@@ -1216,7 +1216,7 @@  version (CoreUnittest)
         assert(c == 1);
     }
 
-    pure nothrow @safe unittest // issue 16230
+    pure nothrow @safe unittest // https://issues.dlang.org/show_bug.cgi?id=16230
     {
         shared int i;
         static assert(is(typeof(atomicLoad(i)) == int));
diff --git a/libphobos/libdruntime/core/internal/array/concatenation.d b/libphobos/libdruntime/core/internal/array/concatenation.d
index ff777a6b3ab..4a05b50fcff 100644
--- a/libphobos/libdruntime/core/internal/array/concatenation.d
+++ b/libphobos/libdruntime/core/internal/array/concatenation.d
@@ -19,6 +19,7 @@  module core.internal.array.concatenation;
  */
 Tret _d_arraycatnTX(Tret, Tarr...)(auto ref Tarr froms) @trusted
 {
+    import core.internal.array.capacity : _d_arraysetlengthTImpl;
     import core.internal.traits : hasElaborateCopyConstructor, Unqual;
     import core.lifetime : copyEmplace;
     import core.stdc.string : memcpy;
@@ -38,7 +39,21 @@  Tret _d_arraycatnTX(Tret, Tarr...)(auto ref Tarr froms) @trusted
 
     if (totalLen == 0)
         return res;
-    res.length = totalLen;
+
+    // We cannot use this, because it refuses to work if the array type has disabled default construction.
+    // res.length = totalLen;
+    // Call the runtime function directly instead.
+    // TODO: once `__arrayAlloc` is templated, call that instead.
+    version (D_ProfileGC)
+    {
+        // TODO: forward file, line, name from _d_arraycatnTXTrace
+        _d_arraysetlengthTImpl!(typeof(res))._d_arraysetlengthTTrace(
+            __FILE__, __LINE__, "_d_arraycatnTX", res, totalLen);
+    }
+    else
+    {
+        _d_arraysetlengthTImpl!(typeof(res))._d_arraysetlengthT(res, totalLen);
+    }
 
     /* Currently, if both a postblit and a cpctor are defined, the postblit is
      * used. If this changes, the condition below will have to be adapted.
diff --git a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
index 62ce941e393..39cd30aee16 100644
--- a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
+++ b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
@@ -26,6 +26,7 @@  module core.internal.gc.impl.conservative.gc;
 //debug = INVARIANT;            // enable invariants
 //debug = PROFILE_API;          // profile API calls for config.profile > 1
 //debug = GC_RECURSIVE_LOCK;    // check for recursive locking on the same thread
+//debug = VALGRIND;             // Valgrind memcheck integration
 
 /***************************************************/
 version = COLLECT_PARALLEL;  // parallel scanning
@@ -52,6 +53,8 @@  version (GNU) import gcc.builtins;
 debug (PRINTF_TO_FILE) import core.stdc.stdio : sprintf, fprintf, fopen, fflush, FILE;
 else                   import core.stdc.stdio : sprintf, printf; // needed to output profiling results
 
+debug (VALGRIND) import etc.valgrind.valgrind;
+
 import core.time;
 alias currTime = MonoTime.currTime;
 
@@ -90,7 +93,7 @@  private
         int rt_hasFinalizerInSegment(void* p, size_t size, uint attr, const scope void[] segment) nothrow;
 
         // Declared as an extern instead of importing core.exception
-        // to avoid inlining - see issue 13725.
+        // to avoid inlining - see https://issues.dlang.org/show_bug.cgi?id=13725.
         void onInvalidMemoryOperationError(void* pretend_sideffect = null) @trusted pure nothrow @nogc;
         void onOutOfMemoryErrorNoGC() @trusted nothrow @nogc;
 
@@ -480,6 +483,8 @@  class ConservativeGC : GC
 
         auto p = runLocked!(mallocNoSync, mallocTime, numMallocs)(size, bits, localAllocSize, ti);
 
+        invalidate(p[0 .. localAllocSize], 0xF0, true);
+
         if (!(bits & BlkAttr.NO_SCAN))
         {
             memset(p + size, 0, localAllocSize - size);
@@ -567,6 +572,9 @@  class ConservativeGC : GC
 
         auto p = runLocked!(mallocNoSync, mallocTime, numMallocs)(size, bits, localAllocSize, ti);
 
+        debug (VALGRIND) makeMemUndefined(p[0..size]);
+        invalidate((p + size)[0 .. localAllocSize - size], 0xF0, true);
+
         memset(p, 0, size);
         if (!(bits & BlkAttr.NO_SCAN))
         {
@@ -688,7 +696,7 @@  class ConservativeGC : GC
             else if (newsz < psz)
             {
                 // Shrink in place
-                debug (MEMSTOMP) memset(p + size, 0xF2, psize - size);
+                invalidate((p + size)[0 .. psize - size], 0xF2, false);
                 lpool.freePages(pagenum + newsz, psz - newsz);
                 lpool.mergeFreePageOffsets!(false, true)(pagenum + newsz, psz - newsz);
                 lpool.bPageOffsets[pagenum] = cast(uint) newsz;
@@ -704,7 +712,7 @@  class ConservativeGC : GC
                 if (freesz < newPages)
                     return doMalloc(); // free range too small
 
-                debug (MEMSTOMP) memset(p + psize, 0xF0, size - psize);
+                invalidate((p + psize)[0 .. size - psize], 0xF0, true);
                 debug (PRINTF) printFreeInfo(pool);
                 memset(&lpool.pagetable[pagenum + psz], Bins.B_PAGEPLUS, newPages);
                 lpool.bPageOffsets[pagenum] = cast(uint) newsz;
@@ -795,7 +803,7 @@  class ConservativeGC : GC
             if (freesz < minsz)
                 return 0;
             size_t sz = freesz > maxsz ? maxsz : freesz;
-            debug (MEMSTOMP) memset(pool.baseAddr + (pagenum + psz) * PAGESIZE, 0xF0, sz * PAGESIZE);
+            invalidate((pool.baseAddr + (pagenum + psz) * PAGESIZE)[0 .. sz * PAGESIZE], 0xF0, true);
             memset(lpool.pagetable + pagenum + psz, Bins.B_PAGEPLUS, sz);
             lpool.bPageOffsets[pagenum] = cast(uint) (psz + sz);
             for (auto offset = psz; offset < psz + sz; offset++)
@@ -911,7 +919,7 @@  class ConservativeGC : GC
             size_t npages = lpool.bPageOffsets[pagenum];
             auto size = npages * PAGESIZE;
             ssize = sentinel_size(q, size);
-            debug (MEMSTOMP) memset(p, 0xF2, size);
+            invalidate(p[0 .. size], 0xF2, false);
             lpool.freePages(pagenum, npages);
             lpool.mergeFreePageOffsets!(true, true)(pagenum, npages);
         }
@@ -925,13 +933,13 @@  class ConservativeGC : GC
 
             auto size = binsize[bin];
             ssize = sentinel_size(q, size);
-            debug (MEMSTOMP) memset(p, 0xF2, size);
+            invalidate(p[0 .. size], 0xF2, false);
 
             // in case the page hasn't been recovered yet, don't add the object to the free list
             if (!gcx.recoverPool[bin] || pool.binPageChain[pagenum] == Pool.PageRecovered)
             {
-                list.next = gcx.bucket[bin];
-                list.pool = pool;
+                undefinedWrite(list.next, gcx.bucket[bin]);
+                undefinedWrite(list.pool, pool);
                 gcx.bucket[bin] = list;
             }
             pool.freebits.set(biti);
@@ -1965,8 +1973,8 @@  struct Gcx
         assert(p !is null);
     L_hasBin:
         // Return next item from free list
-        bucket[bin] = (cast(List*)p).next;
-        auto pool = (cast(List*)p).pool;
+        bucket[bin] = undefinedRead((cast(List*)p).next);
+        auto pool = undefinedRead((cast(List*)p).pool);
 
         auto biti = (p - pool.baseAddr) >> pool.shiftBy;
         assert(pool.freebits.test(biti));
@@ -1976,7 +1984,7 @@  struct Gcx
         if (bits)
             pool.setBits(biti, bits);
         //debug(PRINTF) printf("\tmalloc => %p\n", p);
-        debug (MEMSTOMP) memset(p, 0xF0, alloc_size);
+        invalidate(p[0 .. alloc_size], 0xF0, true);
 
         if (ConservativeGC.isPrecise)
         {
@@ -2059,7 +2067,7 @@  struct Gcx
 
         auto p = pool.baseAddr + pn * PAGESIZE;
         debug(PRINTF) printf("Got large alloc:  %p, pt = %d, np = %d\n", p, pool.pagetable[pn], npages);
-        debug (MEMSTOMP) memset(p, 0xF1, size);
+        invalidate(p[0 .. size], 0xF1, true);
         alloc_size = npages * PAGESIZE;
         //debug(PRINTF) printf("\tp = %p\n", p);
 
@@ -2241,6 +2249,7 @@  struct Gcx
             immutable ncap = _cap ? 2 * _cap : initSize / RANGE.sizeof;
             auto p = cast(RANGE*)os_mem_map(ncap * RANGE.sizeof);
             if (p is null) onOutOfMemoryErrorNoGC();
+            debug (VALGRIND) makeMemUndefined(p[0..ncap]);
             if (_p !is null)
             {
                 p[0 .. _length] = _p[0 .. _length];
@@ -2295,7 +2304,8 @@  struct Gcx
 
         for (;;)
         {
-            auto p = *cast(void**)(rng.pbot);
+            auto p = undefinedRead(*cast(void**)(rng.pbot));
+            debug (VALGRIND) makeMemDefined((&p)[0 .. 1]);
 
             debug(MARK_PRINTF) printf("\tmark %p: %p\n", rng.pbot, p);
 
@@ -2525,6 +2535,7 @@  struct Gcx
         for (auto p = cast(void**)pbot; cast(void*)p < ptop; p++)
         {
             auto ptr = *p;
+            debug (VALGRIND) makeMemDefined((&ptr)[0 .. 1]);
             if (cast(size_t)(ptr - minAddr) < memSize)
                 toscanRoots.push(ptr);
         }
@@ -2650,7 +2661,7 @@  struct Gcx
                         pool.freepages += npages;
                         numFree += npages;
 
-                        debug (MEMSTOMP) memset(p, 0xF3, npages * PAGESIZE);
+                        invalidate(p[0 .. npages * PAGESIZE], 0xF3, false);
                         // Don't need to update searchStart here because
                         // pn is guaranteed to be greater than last time
                         // we updated it.
@@ -2765,7 +2776,7 @@  struct Gcx
                                     debug(COLLECT_PRINTF) printf("\tcollecting %p\n", p);
                                     leakDetector.log_free(q, sentinel_size(q, size));
 
-                                    debug (MEMSTOMP) memset(p, 0xF3, size);
+                                    invalidate(p[0 .. size], 0xF3, false);
                                 }
                             }
                         }
@@ -2830,11 +2841,11 @@  struct Gcx
             if (!core.bitop.bt(freebitsdata, u / 16))
                 continue;
             auto elem = cast(List *)(p + u);
-            elem.pool = &pool.base;
-            *bucketTail = elem;
+            undefinedWrite(elem.pool, &pool.base);
+            undefinedWrite(*bucketTail, elem);
             bucketTail = &elem.next;
         }
-        *bucketTail = null;
+        undefinedWrite(*bucketTail, null);
         assert(bucket[bin] !is null);
         return true;
     }
@@ -3572,6 +3583,7 @@  struct Pool
         //debug(PRINTF) printf("Pool::Pool(%u)\n", npages);
         poolsize = npages * PAGESIZE;
         baseAddr = cast(byte *)os_mem_map(poolsize);
+        version (VALGRIND) makeMemNoAccess(baseAddr[0..poolsize]);
 
         // Some of the code depends on page alignment of memory pools
         assert((cast(size_t)baseAddr & (PAGESIZE - 1)) == 0);
@@ -4275,7 +4287,7 @@  struct LargeObjectPool
             for (; pn + n < npages; ++n)
                 if (pagetable[pn + n] != Bins.B_PAGEPLUS)
                     break;
-            debug (MEMSTOMP) memset(baseAddr + pn * PAGESIZE, 0xF3, n * PAGESIZE);
+            invalidate((baseAddr + pn * PAGESIZE)[0 .. n * PAGESIZE], 0xF3, false);
             freePages(pn, n);
             mergeFreePageOffsets!(true, true)(pn, n);
         }
@@ -4394,7 +4406,7 @@  struct SmallObjectPool
                 debug(COLLECT_PRINTF) printf("\tcollecting %p\n", p);
                 //log_free(sentinel_add(p));
 
-                debug (MEMSTOMP) memset(p, 0xF3, size);
+                invalidate(p[0 .. size], 0xF3, false);
             }
 
             if (freeBits)
@@ -4431,17 +4443,17 @@  struct SmallObjectPool
         void* ptop = p + PAGESIZE - 2 * size + 1;
         for (; p < ptop; p += size)
         {
-            (cast(List *)p).next = cast(List *)(p + size);
-            (cast(List *)p).pool = &base;
+            undefinedWrite((cast(List *)p).next, cast(List *)(p + size));
+            undefinedWrite((cast(List *)p).pool, &base);
         }
-        (cast(List *)p).next = null;
-        (cast(List *)p).pool = &base;
+        undefinedWrite((cast(List *)p).next, null);
+        undefinedWrite((cast(List *)p).pool, &base);
         return first;
     }
 }
 
 debug(SENTINEL) {} else // no additional capacity with SENTINEL
-unittest // bugzilla 14467
+unittest // https://issues.dlang.org/show_bug.cgi?id=14467
 {
     int[] arr = new int[10];
     assert(arr.capacity);
@@ -4449,7 +4461,7 @@  unittest // bugzilla 14467
     assert(arr.capacity);
 }
 
-unittest // bugzilla 15353
+unittest // https://issues.dlang.org/show_bug.cgi?id=15353
 {
     import core.memory : GC;
 
@@ -4466,7 +4478,7 @@  unittest // bugzilla 15353
     GC.collect();
 }
 
-unittest // bugzilla 15822
+unittest // https://issues.dlang.org/show_bug.cgi?id=15822
 {
     import core.memory : GC;
 
@@ -4487,7 +4499,7 @@  unittest // bugzilla 15822
     GC.collect();
 }
 
-unittest // bugzilla 1180
+unittest // https://issues.dlang.org/show_bug.cgi?id=1180
 {
     import core.exception;
     try
@@ -4823,13 +4835,22 @@  debug (SENTINEL)
     {
         assert(size <= uint.max);
         *sentinel_psize(p) = cast(uint)size;
-        *sentinel_pre(p) = SENTINEL_PRE;
-        *sentinel_post(p) = SENTINEL_POST;
+        debug (VALGRIND)
+        {
+            makeMemNoAccess(sentinel_pre(p)[0..1]);
+            makeMemNoAccess(sentinel_post(p)[0..1]);
+        }
+        else
+        {
+            *sentinel_pre(p) = SENTINEL_PRE;
+            *sentinel_post(p) = SENTINEL_POST;
+        }
     }
 
 
     void sentinel_Invariant(const void *p) nothrow @nogc
     {
+        debug (VALGRIND) {} else
         debug
         {
             assert(*sentinel_pre(p) == SENTINEL_PRE);
@@ -5063,3 +5084,53 @@  unittest
         printf("unexpected pointers %p and %p\n", p.ptr, q.ptr);
     }
 }
+
+/* ============================ MEMSTOMP =============================== */
+
+/// Mark the specified memory region as uninitialized -
+/// reading from this region is an error.
+/// If writable is false, writing to it is also an error.
+pragma(inline, true)
+void invalidate(void[] mem, ubyte pattern, bool writable) nothrow @nogc
+{
+    debug (MEMSTOMP) memset(mem.ptr, pattern, mem.length);
+    debug (VALGRIND)
+    {
+        if (writable)
+            makeMemUndefined(mem);
+        else
+            makeMemNoAccess(mem);
+    }
+}
+
+/// Read memory that should otherwise be marked as unreadable
+/// (e.g. free lists overlapped with unallocated heap objects).
+pragma(inline, true)
+T undefinedRead(T)(ref T var) nothrow
+{
+    debug (VALGRIND)
+    {
+        auto varArr = (&var)[0..1];
+        disableAddrReportingInRange(varArr);
+        T result = var;
+        enableAddrReportingInRange(varArr);
+        return result;
+    }
+    else
+        return var;
+}
+
+/// Write memory that should otherwise be marked as unwritable.
+pragma(inline, true)
+void undefinedWrite(T)(ref T var, T value) nothrow
+{
+    debug (VALGRIND)
+    {
+        auto varArr = (&var)[0..1];
+        disableAddrReportingInRange(varArr);
+        var = value;
+        enableAddrReportingInRange(varArr);
+    }
+    else
+        var = value;
+}
diff --git a/libphobos/libdruntime/core/internal/gc/proxy.d b/libphobos/libdruntime/core/internal/gc/proxy.d
index 695ef061a81..abc8c6ac2ea 100644
--- a/libphobos/libdruntime/core/internal/gc/proxy.d
+++ b/libphobos/libdruntime/core/internal/gc/proxy.d
@@ -62,8 +62,9 @@  extern (C)
             {
                 import core.stdc.stdio : fprintf, stderr;
                 import core.stdc.stdlib : exit;
+                import core.atomic : atomicLoad;
 
-                fprintf(stderr, "No GC was initialized, please recheck the name of the selected GC ('%.*s').\n", cast(int)config.gc.length, config.gc.ptr);
+                fprintf(atomicLoad(stderr), "No GC was initialized, please recheck the name of the selected GC ('%.*s').\n", cast(int)config.gc.length, config.gc.ptr);
                 instanceLock.unlock();
                 exit(1);
 
@@ -97,7 +98,9 @@  extern (C)
             {
                 default:
                     import core.stdc.stdio : fprintf, stderr;
-                    fprintf(stderr, "Unknown GC cleanup method, please recheck ('%.*s').\n",
+                    import core.atomic : atomicLoad;
+
+                    fprintf(atomicLoad(stderr), "Unknown GC cleanup method, please recheck ('%.*s').\n",
                             cast(int)config.cleanup.length, config.cleanup.ptr);
                     break;
                 case "none":
diff --git a/libphobos/libdruntime/core/internal/parseoptions.d b/libphobos/libdruntime/core/internal/parseoptions.d
index ed6251f758b..ac0eb826b35 100644
--- a/libphobos/libdruntime/core/internal/parseoptions.d
+++ b/libphobos/libdruntime/core/internal/parseoptions.d
@@ -146,9 +146,11 @@  private:
 
 bool optError(const scope char[] msg, const scope char[] name, const(char)[] errName)
 {
+    import core.atomic : atomicLoad;
+
     version (CoreUnittest) if (inUnittest) return false;
 
-    fprintf(stderr, "%.*s %.*s option '%.*s'.\n",
+    fprintf(atomicLoad(stderr), "%.*s %.*s option '%.*s'.\n",
             cast(int)msg.length, msg.ptr,
             cast(int)errName.length, errName.ptr,
             cast(int)name.length, name.ptr);
@@ -332,9 +334,11 @@  do
 
 bool parseError(const scope char[] exp, const scope char[] opt, const scope char[] got, const(char)[] errName)
 {
+    import core.atomic : atomicLoad;
+
     version (CoreUnittest) if (inUnittest) return false;
 
-    fprintf(stderr, "Expecting %.*s as argument for %.*s option '%.*s', got '%.*s' instead.\n",
+    fprintf(atomicLoad(stderr), "Expecting %.*s as argument for %.*s option '%.*s', got '%.*s' instead.\n",
             cast(int)exp.length, exp.ptr,
             cast(int)errName.length, errName.ptr,
             cast(int)opt.length, opt.ptr,
@@ -344,9 +348,11 @@  bool parseError(const scope char[] exp, const scope char[] opt, const scope char
 
 bool overflowedError(const scope char[] opt, const scope char[] got)
 {
+    import core.atomic : atomicLoad;
+
     version (CoreUnittest) if (inUnittest) return false;
 
-    fprintf(stderr, "Argument for %.*s option '%.*s' is too big.\n",
+    fprintf(atomicLoad(stderr), "Argument for %.*s option '%.*s' is too big.\n",
             cast(int)opt.length, opt.ptr,
             cast(int)got.length, got.ptr);
     return false;
diff --git a/libphobos/libdruntime/core/lifetime.d b/libphobos/libdruntime/core/lifetime.d
index ae047cb730e..89236dbf4c1 100644
--- a/libphobos/libdruntime/core/lifetime.d
+++ b/libphobos/libdruntime/core/lifetime.d
@@ -364,7 +364,7 @@  T* emplace(T, Args...)(void[] chunk, auto ref Args args)
     assert(u1.a == "hello");
 }
 
-@system unittest // bugzilla 15772
+@system unittest // https://issues.dlang.org/show_bug.cgi?id=15772
 {
     abstract class Foo {}
     class Bar: Foo {}
@@ -2322,7 +2322,7 @@  pure nothrow @nogc @system unittest
     assert(val == 1);
 }
 
-// issue 18913
+// https://issues.dlang.org/show_bug.cgi?id=18913
 @safe unittest
 {
     static struct NoCopy
@@ -2454,7 +2454,7 @@  template _d_delstructImpl(T)
     assert(outerDtors == 1);
 }
 
-// issue 25552
+// https://issues.dlang.org/show_bug.cgi?id=25552
 pure nothrow @system unittest
 {
     int i;
@@ -2478,7 +2478,7 @@  pure nothrow @system unittest
     assert(i == 2);
 }
 
-// issue 25552
+// https://issues.dlang.org/show_bug.cgi?id=25552
 @safe unittest
 {
     int i;
@@ -2527,7 +2527,7 @@  pure nothrow @system unittest
     assert(i == 6);
 }
 
-// issue 25552
+// https://issues.dlang.org/show_bug.cgi?id=25552
 @safe unittest
 {
     int i;
diff --git a/libphobos/libdruntime/core/stdc/assert_.d b/libphobos/libdruntime/core/stdc/assert_.d
index a8909e26126..d6cb8a608a0 100644
--- a/libphobos/libdruntime/core/stdc/assert_.d
+++ b/libphobos/libdruntime/core/stdc/assert_.d
@@ -59,7 +59,7 @@  else version (FreeBSD)
     /***
      * Assert failure function in the FreeBSD C library.
      */
-    noreturn __assert(const(char)* exp, const(char)* file, uint line, const(char)* exp);
+    noreturn __assert(const(char)* func, const(char)* file, uint line, const(char)* exp);
 }
 else version (NetBSD)
 {
@@ -67,6 +67,8 @@  else version (NetBSD)
      * Assert failure function in the NetBSD C library.
      */
     noreturn __assert(const(char)* file, int line, const(char)* exp);
+    ///
+    noreturn __assert13(const(char)* file, int line, const(char)* func, const(char)* exp);
 }
 else version (OpenBSD)
 {
@@ -75,14 +77,14 @@  else version (OpenBSD)
      */
     noreturn __assert(const(char)* file, int line, const(char)* exp);
     ///
-    void __assert2(const(char)* file, int line, const(char)* func, const(char)* exp);
+    noreturn __assert2(const(char)* file, int line, const(char)* func, const(char)* exp);
 }
 else version (DragonFlyBSD)
 {
     /***
      * Assert failure function in the DragonFlyBSD C library.
      */
-    noreturn __assert(const(char)* exp, const(char)* file, uint line, const(char)* exp);
+    noreturn __assert(const(char)* func, const(char)* file, uint line, const(char)* exp);
 }
 else version (CRuntime_Glibc)
 {
@@ -97,7 +99,12 @@  else version (CRuntime_Glibc)
 }
 else version (CRuntime_Bionic)
 {
+    /***
+     * Assert failure functions in the Bionic library.
+     */
     noreturn __assert(const(char)* __file, int __line, const(char)* __msg);
+    ///
+    noreturn __assert2(const(char)* __file, int __line, const(char)* __function, const(char)* __msg);
 }
 else version (CRuntime_Musl)
 {
diff --git a/libphobos/libdruntime/core/stdc/wchar_.d b/libphobos/libdruntime/core/stdc/wchar_.d
index fe5fce481cd..2d01e2634dc 100644
--- a/libphobos/libdruntime/core/stdc/wchar_.d
+++ b/libphobos/libdruntime/core/stdc/wchar_.d
@@ -17,6 +17,7 @@  module core.stdc.wchar_;
 import core.stdc.config;
 import core.stdc.stdarg; // for va_list
 import core.stdc.stdio;  // for FILE, not exposed per spec
+import core.atomic : atomicLoad;
 public import core.stdc.stddef;  // for wchar_t
 public import core.stdc.time;    // for tm
 public import core.stdc.stdint;  // for WCHAR_MIN, WCHAR_MAX
@@ -211,9 +212,9 @@  int      fputws(const scope wchar_t* s, FILE* stream);
 extern (D) @trusted
 {
     ///
-    wint_t getwchar()                     { return fgetwc(stdin);     }
+    wint_t getwchar()                     { return fgetwc(atomicLoad(stdin));     }
     ///
-    wint_t putwchar(wchar_t c)            { return fputwc(c,stdout);  }
+    wint_t putwchar(wchar_t c)            { return fputwc(c,atomicLoad(stdout));  }
 }
 
 ///
diff --git a/libphobos/libdruntime/core/sys/linux/input.d b/libphobos/libdruntime/core/sys/linux/input.d
new file mode 100644
index 00000000000..1bf356dca98
--- /dev/null
+++ b/libphobos/libdruntime/core/sys/linux/input.d
@@ -0,0 +1,236 @@ 
+module core.sys.linux.input;
+
+version (linux):
+extern(C):
+nothrow:
+
+import core.sys.linux.sys.time;
+import core.sys.posix.sys.ioctl;
+
+public import core.sys.linux.input_event_codes;
+
+struct input_event
+{
+    timeval time;
+    ushort type;
+    ushort code;
+    int value;
+}
+
+enum EV_VERSION     = 0x010001;
+
+struct input_id
+{
+    ushort bustype;
+    ushort vendor;
+    ushort product;
+    ushort version_;
+}
+
+struct input_absinfo
+{
+    int value;
+    int minimum;
+    int maximum;
+    int fuzz;
+    int flat;
+    int resolution;
+}
+
+enum INPUT_KEYMAP_BY_INDEX = (1 << 0);
+struct input_keymap_entry
+{
+    ubyte  flags;
+    ubyte  len;
+    ushort index;
+    uint keycode;
+    ubyte[32]  scancode;
+}
+
+struct input_mask
+{
+    uint type;
+    uint codes_size;
+    ulong codes_ptr;
+}
+
+enum EVIOCGVERSION       = _IOR!int('E', 0x01);
+enum EVIOCGID            = _IOR!input_id('E', 0x02);
+enum EVIOCGREP           = _IOR!(uint[2])('E', 0x03);
+enum EVIOCSREP           = _IOW!(uint[2])('E', 0x03);
+
+enum EVIOCGKEYCODE       = _IOR!(uint[2])('E', 0x04);
+enum EVIOCGKEYCODE_V2    = _IOR!input_keymap_entry('E', 0x04);
+enum EVIOCSKEYCODE       = _IOW!(uint[2])('E', 0x04);
+enum EVIOCSKEYCODE_V2    = _IOW!input_keymap_entry('E', 0x04);
+
+enum EVIOCGNAME(len)     = _IOC(_IOC_READ, 'E', 0x06, len);
+enum EVIOCGPHYS(len)     = _IOC(_IOC_READ, 'E', 0x07, len);
+enum EVIOCGUNIQ(len)     = _IOC(_IOC_READ, 'E', 0x08, len);
+enum EVIOCGPROP(len)     = _IOC(_IOC_READ, 'E', 0x09, len);
+
+enum EVIOCGMTSLOTS(len)  = _IOC(_IOC_READ, 'E', 0x0a, len);
+
+enum EVIOCGKEY(len)      = _IOC(_IOC_READ, 'E', 0x18, len);
+enum EVIOCGLED(len)      = _IOC(_IOC_READ, 'E', 0x19, len);
+enum EVIOCGSND(len)      = _IOC(_IOC_READ, 'E', 0x1a, len);
+enum EVIOCGSW(len)       = _IOC(_IOC_READ, 'E', 0x1b, len);
+
+enum EVIOCGBIT(ev,len)   = _IOC(_IOC_READ, 'E', 0x20 + (ev), len);
+enum EVIOCGABS(abs)      = _IOR!input_absinfo('E', 0x40 + (abs));
+enum EVIOCSABS(abs)      = _IOW!input_absinfo('E', 0xc0 + (abs));
+
+enum EVIOCSFF            = _IOW!ff_effect('E', 0x80);
+enum EVIOCRMFF           = _IOW!int('E', 0x81);
+enum EVIOCGEFFECTS       = _IOR!int('E', 0x84);
+
+enum EVIOCGRAB           = _IOW!int('E', 0x90);
+enum EVIOCREVOKE         = _IOW!int('E', 0x91);
+
+enum EVIOCGMASK      = _IOR!input_mask('E', 0x92);
+
+enum EVIOCSMASK      = _IOW!input_mask('E', 0x93);
+
+enum EVIOCSCLOCKID   = _IOW!int('E', 0xa0);
+
+enum ID_BUS          = 0;
+enum ID_VENDOR       = 1;
+enum ID_PRODUCT      = 2;
+enum ID_VERSION      = 3;
+
+enum BUS_PCI         = 0x01;
+enum BUS_ISAPNP      = 0x02;
+enum BUS_USB         = 0x03;
+enum BUS_HIL         = 0x04;
+enum BUS_BLUETOOTH   = 0x05;
+enum BUS_VIRTUAL     = 0x06;
+
+enum BUS_ISA         = 0x10;
+enum BUS_I8042       = 0x11;
+enum BUS_XTKBD       = 0x12;
+enum BUS_RS232       = 0x13;
+enum BUS_GAMEPORT    = 0x14;
+enum BUS_PARPORT     = 0x15;
+enum BUS_AMIGA       = 0x16;
+enum BUS_ADB         = 0x17;
+enum BUS_I2C         = 0x18;
+enum BUS_HOST        = 0x19;
+enum BUS_GSC         = 0x1A;
+enum BUS_ATARI       = 0x1B;
+enum BUS_SPI         = 0x1C;
+enum BUS_RMI         = 0x1D;
+enum BUS_CEC         = 0x1E;
+enum BUS_INTEL_ISHTP = 0x1F;
+
+enum MT_TOOL_FINGER  = 0;
+enum MT_TOOL_PEN     = 1;
+enum MT_TOOL_PALM    = 2;
+enum MT_TOOL_MAX     = 2;
+
+enum FF_STATUS_STOPPED   = 0x00;
+enum FF_STATUS_PLAYING   = 0x01;
+enum FF_STATUS_MAX       = 0x01;
+
+struct ff_replay {
+    ushort length;
+    ushort delay;
+};
+
+struct ff_trigger {
+    ushort button;
+    ushort interval;
+};
+
+struct ff_envelope {
+    ushort attack_length;
+    ushort attack_level;
+    ushort fade_length;
+    ushort fade_level;
+};
+
+struct ff_constant_effect {
+    short level;
+    ff_envelope envelope;
+};
+
+struct ff_ramp_effect {
+    short start_level;
+    short end_level;
+    ff_envelope envelope;
+};
+
+struct ff_condition_effect {
+    ushort right_saturation;
+    ushort left_saturation;
+
+    short right_coeff;
+    short left_coeff;
+
+    ushort deadband;
+    short center;
+};
+
+struct ff_periodic_effect {
+    ushort waveform;
+    ushort period;
+    short magnitude;
+    short offset;
+    ushort phase;
+
+    ff_envelope envelope;
+
+    uint custom_len;
+    short *custom_data;
+};
+
+struct ff_rumble_effect {
+    ushort strong_magnitude;
+    ushort weak_magnitude;
+};
+
+struct ff_effect {
+    ushort type;
+    short id;
+    ushort direction;
+    ff_trigger trigger;
+    ff_replay replay;
+
+    union U {
+        ff_constant_effect constant;
+        ff_ramp_effect ramp;
+        ff_periodic_effect periodic;
+        ff_condition_effect[2] condition;
+        ff_rumble_effect rumble;
+    }
+    U u;
+};
+
+enum FF_RUMBLE   = 0x50;
+enum FF_PERIODIC = 0x51;
+enum FF_CONSTANT = 0x52;
+enum FF_SPRING   = 0x53;
+enum FF_FRICTION = 0x54;
+enum FF_DAMPER   = 0x55;
+enum FF_INERTIA  = 0x56;
+enum FF_RAMP     = 0x57;
+
+enum FF_EFFECT_MIN   = FF_RUMBLE;
+enum FF_EFFECT_MAX   = FF_RAMP;
+
+enum FF_SQUARE   = 0x58;
+enum FF_TRIANGLE = 0x59;
+enum FF_SINE     = 0x5a;
+enum FF_SAW_UP   = 0x5b;
+enum FF_SAW_DOWN = 0x5c;
+enum FF_CUSTOM   = 0x5d;
+
+enum FF_WAVEFORM_MIN = FF_SQUARE;
+enum FF_WAVEFORM_MAX = FF_CUSTOM;
+
+enum FF_GAIN     = 0x60;
+enum FF_AUTOCENTER   = 0x61;
+
+enum FF_MAX_EFFECTS  = FF_GAIN;
+
+enum FF_MAX      = 0x7f;
+enum FF_CNT      = (FF_MAX+1);
diff --git a/libphobos/libdruntime/core/sys/linux/input_event_codes.d b/libphobos/libdruntime/core/sys/linux/input_event_codes.d
new file mode 100644
index 00000000000..3ebda69fd07
--- /dev/null
+++ b/libphobos/libdruntime/core/sys/linux/input_event_codes.d
@@ -0,0 +1,758 @@ 
+module core.sys.linux.input_event_codes;
+
+version (linux):
+extern(C):
+nothrow:
+
+enum INPUT_PROP_POINTER              = 0x00;
+enum INPUT_PROP_DIRECT               = 0x01;
+enum INPUT_PROP_BUTTONPAD            = 0x02;
+enum INPUT_PROP_SEMI_MT              = 0x03;
+enum INPUT_PROP_TOPBUTTONPAD         = 0x04;
+enum INPUT_PROP_POINTING_STICK       = 0x05;
+enum INPUT_PROP_ACCELEROMETER        = 0x06;
+
+enum INPUT_PROP_MAX                  = 0x1f;
+enum INPUT_PROP_CNT                  = (INPUT_PROP_MAX + 1);
+
+enum EV_SYN                  = 0x00;
+enum EV_KEY                  = 0x01;
+enum EV_REL                  = 0x02;
+enum EV_ABS                  = 0x03;
+enum EV_MSC                  = 0x04;
+enum EV_SW                   = 0x05;
+enum EV_LED                  = 0x11;
+enum EV_SND                  = 0x12;
+enum EV_REP                  = 0x14;
+enum EV_FF                   = 0x15;
+enum EV_PWR                  = 0x16;
+enum EV_FF_STATUS            = 0x17;
+enum EV_MAX                  = 0x1f;
+enum EV_CNT                  = (EV_MAX+1);
+
+enum SYN_REPORT              = 0;
+enum SYN_CONFIG              = 1;
+enum SYN_MT_REPORT           = 2;
+enum SYN_DROPPED             = 3;
+enum SYN_MAX                 = 0xf;
+enum SYN_CNT                 = (SYN_MAX+1);
+
+enum KEY_RESERVED            = 0;
+enum KEY_ESC                 = 1;
+enum KEY_1                   = 2;
+enum KEY_2                   = 3;
+enum KEY_3                   = 4;
+enum KEY_4                   = 5;
+enum KEY_5                   = 6;
+enum KEY_6                   = 7;
+enum KEY_7                   = 8;
+enum KEY_8                   = 9;
+enum KEY_9                   = 10;
+enum KEY_0                   = 11;
+enum KEY_MINUS               = 12;
+enum KEY_EQUAL               = 13;
+enum KEY_BACKSPACE           = 14;
+enum KEY_TAB                 = 15;
+enum KEY_Q                   = 16;
+enum KEY_W                   = 17;
+enum KEY_E                   = 18;
+enum KEY_R                   = 19;
+enum KEY_T                   = 20;
+enum KEY_Y                   = 21;
+enum KEY_U                   = 22;
+enum KEY_I                   = 23;
+enum KEY_O                   = 24;
+enum KEY_P                   = 25;
+enum KEY_LEFTBRACE           = 26;
+enum KEY_RIGHTBRACE          = 27;
+enum KEY_ENTER               = 28;
+enum KEY_LEFTCTRL            = 29;
+enum KEY_A                   = 30;
+enum KEY_S                   = 31;
+enum KEY_D                   = 32;
+enum KEY_F                   = 33;
+enum KEY_G                   = 34;
+enum KEY_H                   = 35;
+enum KEY_J                   = 36;
+enum KEY_K                   = 37;
+enum KEY_L                   = 38;
+enum KEY_SEMICOLON           = 39;
+enum KEY_APOSTROPHE          = 40;
+enum KEY_GRAVE               = 41;
+enum KEY_LEFTSHIFT           = 42;
+enum KEY_BACKSLASH           = 43;
+enum KEY_Z                   = 44;
+enum KEY_X                   = 45;
+enum KEY_C                   = 46;
+enum KEY_V                   = 47;
+enum KEY_B                   = 48;
+enum KEY_N                   = 49;
+enum KEY_M                   = 50;
+enum KEY_COMMA               = 51;
+enum KEY_DOT                 = 52;
+enum KEY_SLASH               = 53;
+enum KEY_RIGHTSHIFT          = 54;
+enum KEY_KPASTERISK          = 55;
+enum KEY_LEFTALT             = 56;
+enum KEY_SPACE               = 57;
+enum KEY_CAPSLOCK            = 58;
+enum KEY_F1                  = 59;
+enum KEY_F2                  = 60;
+enum KEY_F3                  = 61;
+enum KEY_F4                  = 62;
+enum KEY_F5                  = 63;
+enum KEY_F6                  = 64;
+enum KEY_F7                  = 65;
+enum KEY_F8                  = 66;
+enum KEY_F9                  = 67;
+enum KEY_F10                 = 68;
+enum KEY_NUMLOCK             = 69;
+enum KEY_SCROLLLOCK          = 70;
+enum KEY_KP7                 = 71;
+enum KEY_KP8                 = 72;
+enum KEY_KP9                 = 73;
+enum KEY_KPMINUS             = 74;
+enum KEY_KP4                 = 75;
+enum KEY_KP5                 = 76;
+enum KEY_KP6                 = 77;
+enum KEY_KPPLUS              = 78;
+enum KEY_KP1                 = 79;
+enum KEY_KP2                 = 80;
+enum KEY_KP3                 = 81;
+enum KEY_KP0                 = 82;
+enum KEY_KPDOT               = 83;
+
+enum KEY_ZENKAKUHANKAKU      = 85;
+enum KEY_102ND               = 86;
+enum KEY_F11                 = 87;
+enum KEY_F12                 = 88;
+enum KEY_RO                  = 89;
+enum KEY_KATAKANA            = 90;
+enum KEY_HIRAGANA            = 91;
+enum KEY_HENKAN              = 92;
+enum KEY_KATAKANAHIRAGANA    = 93;
+enum KEY_MUHENKAN            = 94;
+enum KEY_KPJPCOMMA           = 95;
+enum KEY_KPENTER             = 96;
+enum KEY_RIGHTCTRL           = 97;
+enum KEY_KPSLASH             = 98;
+enum KEY_SYSRQ               = 99;
+enum KEY_RIGHTALT            = 100;
+enum KEY_LINEFEED            = 101;
+enum KEY_HOME                = 102;
+enum KEY_UP                  = 103;
+enum KEY_PAGEUP              = 104;
+enum KEY_LEFT                = 105;
+enum KEY_RIGHT               = 106;
+enum KEY_END                 = 107;
+enum KEY_DOWN                = 108;
+enum KEY_PAGEDOWN            = 109;
+enum KEY_INSERT              = 110;
+enum KEY_DELETE              = 111;
+enum KEY_MACRO               = 112;
+enum KEY_MUTE                = 113;
+enum KEY_VOLUMEDOWN          = 114;
+enum KEY_VOLUMEUP            = 115;
+enum KEY_POWER               = 116;
+enum KEY_KPEQUAL             = 117;
+enum KEY_KPPLUSMINUS         = 118;
+enum KEY_PAUSE               = 119;
+enum KEY_SCALE               = 120;
+
+enum KEY_KPCOMMA             = 121;
+enum KEY_HANGEUL             = 122;
+enum KEY_HANGUEL             = KEY_HANGEUL;
+enum KEY_HANJA               = 123;
+enum KEY_YEN                 = 124;
+enum KEY_LEFTMETA            = 125;
+enum KEY_RIGHTMETA           = 126;
+enum KEY_COMPOSE             = 127;
+
+enum KEY_STOP                = 128;
+enum KEY_AGAIN               = 129;
+enum KEY_PROPS               = 130;
+enum KEY_UNDO                = 131;
+enum KEY_FRONT               = 132;
+enum KEY_COPY                = 133;
+enum KEY_OPEN                = 134;
+enum KEY_PASTE               = 135;
+enum KEY_FIND                = 136;
+enum KEY_CUT                 = 137;
+enum KEY_HELP                = 138;
+enum KEY_MENU                = 139;
+enum KEY_CALC                = 140;
+enum KEY_SETUP               = 141;
+enum KEY_SLEEP               = 142;
+enum KEY_WAKEUP              = 143;
+enum KEY_FILE                = 144;
+enum KEY_SENDFILE            = 145;
+enum KEY_DELETEFILE          = 146;
+enum KEY_XFER                = 147;
+enum KEY_PROG1               = 148;
+enum KEY_PROG2               = 149;
+enum KEY_WWW                 = 150;
+enum KEY_MSDOS               = 151;
+enum KEY_COFFEE              = 152;
+enum KEY_SCREENLOCK          = KEY_COFFEE;
+enum KEY_ROTATE_DISPLAY      = 153;
+enum KEY_DIRECTION           = KEY_ROTATE_DISPLAY;
+enum KEY_CYCLEWINDOWS        = 154;
+enum KEY_MAIL                = 155;
+enum KEY_BOOKMARKS           = 156;
+enum KEY_COMPUTER            = 157;
+enum KEY_BACK                = 158;
+enum KEY_FORWARD             = 159;
+enum KEY_CLOSECD             = 160;
+enum KEY_EJECTCD             = 161;
+enum KEY_EJECTCLOSECD        = 162;
+enum KEY_NEXTSONG            = 163;
+enum KEY_PLAYPAUSE           = 164;
+enum KEY_PREVIOUSSONG        = 165;
+enum KEY_STOPCD              = 166;
+enum KEY_RECORD              = 167;
+enum KEY_REWIND              = 168;
+enum KEY_PHONE               = 169;
+enum KEY_ISO                 = 170;
+enum KEY_CONFIG              = 171;
+enum KEY_HOMEPAGE            = 172;
+enum KEY_REFRESH             = 173;
+enum KEY_EXIT                = 174;
+enum KEY_MOVE                = 175;
+enum KEY_EDIT                = 176;
+enum KEY_SCROLLUP            = 177;
+enum KEY_SCROLLDOWN          = 178;
+enum KEY_KPLEFTPAREN         = 179;
+enum KEY_KPRIGHTPAREN        = 180;
+enum KEY_NEW                 = 181;
+enum KEY_REDO                = 182;
+
+enum KEY_F13                 = 183;
+enum KEY_F14                 = 184;
+enum KEY_F15                 = 185;
+enum KEY_F16                 = 186;
+enum KEY_F17                 = 187;
+enum KEY_F18                 = 188;
+enum KEY_F19                 = 189;
+enum KEY_F20                 = 190;
+enum KEY_F21                 = 191;
+enum KEY_F22                 = 192;
+enum KEY_F23                 = 193;
+enum KEY_F24                 = 194;
+
+enum KEY_PLAYCD              = 200;
+enum KEY_PAUSECD             = 201;
+enum KEY_PROG3               = 202;
+enum KEY_PROG4               = 203;
+enum KEY_DASHBOARD           = 204;
+enum KEY_SUSPEND             = 205;
+enum KEY_CLOSE               = 206;
+enum KEY_PLAY                = 207;
+enum KEY_FASTFORWARD         = 208;
+enum KEY_BASSBOOST           = 209;
+enum KEY_PRINT               = 210;
+enum KEY_HP                  = 211;
+enum KEY_CAMERA              = 212;
+enum KEY_SOUND               = 213;
+enum KEY_QUESTION            = 214;
+enum KEY_EMAIL               = 215;
+enum KEY_CHAT                = 216;
+enum KEY_SEARCH              = 217;
+enum KEY_CONNECT             = 218;
+enum KEY_FINANCE             = 219;
+enum KEY_SPORT               = 220;
+enum KEY_SHOP                = 221;
+enum KEY_ALTERASE            = 222;
+enum KEY_CANCEL              = 223;
+enum KEY_BRIGHTNESSDOWN      = 224;
+enum KEY_BRIGHTNESSUP        = 225;
+enum KEY_MEDIA               = 226;
+
+enum KEY_SWITCHVIDEOMODE     = 227;
+enum KEY_KBDILLUMTOGGLE      = 228;
+enum KEY_KBDILLUMDOWN        = 229;
+enum KEY_KBDILLUMUP          = 230;
+
+enum KEY_SEND                = 231;
+enum KEY_REPLY               = 232;
+enum KEY_FORWARDMAIL         = 233;
+enum KEY_SAVE                = 234;
+enum KEY_DOCUMENTS           = 235;
+
+enum KEY_BATTERY             = 236;
+
+enum KEY_BLUETOOTH           = 237;
+enum KEY_WLAN                = 238;
+enum KEY_UWB                 = 239;
+
+enum KEY_UNKNOWN             = 240;
+
+enum KEY_VIDEO_NEXT          = 241;
+enum KEY_VIDEO_PREV          = 242;
+enum KEY_BRIGHTNESS_CYCLE    = 243;
+enum KEY_BRIGHTNESS_AUTO     = 244;
+enum KEY_BRIGHTNESS_ZERO     = KEY_BRIGHTNESS_AUTO;
+enum KEY_DISPLAY_OFF         = 245;
+
+enum KEY_WWAN                = 246;
+enum KEY_WIMAX               = KEY_WWAN;
+enum KEY_RFKILL              = 247;
+
+enum KEY_MICMUTE             = 248;
+
+enum BTN_MISC                = 0x100;
+enum BTN_0                   = 0x100;
+enum BTN_1                   = 0x101;
+enum BTN_2                   = 0x102;
+enum BTN_3                   = 0x103;
+enum BTN_4                   = 0x104;
+enum BTN_5                   = 0x105;
+enum BTN_6                   = 0x106;
+enum BTN_7                   = 0x107;
+enum BTN_8                   = 0x108;
+enum BTN_9                   = 0x109;
+
+enum BTN_MOUSE               = 0x110;
+enum BTN_LEFT                = 0x110;
+enum BTN_RIGHT               = 0x111;
+enum BTN_MIDDLE              = 0x112;
+enum BTN_SIDE                = 0x113;
+enum BTN_EXTRA               = 0x114;
+enum BTN_FORWARD             = 0x115;
+enum BTN_BACK                = 0x116;
+enum BTN_TASK                = 0x117;
+
+enum BTN_JOYSTICK            = 0x120;
+enum BTN_TRIGGER             = 0x120;
+enum BTN_THUMB               = 0x121;
+enum BTN_THUMB2              = 0x122;
+enum BTN_TOP                 = 0x123;
+enum BTN_TOP2                = 0x124;
+enum BTN_PINKIE              = 0x125;
+enum BTN_BASE                = 0x126;
+enum BTN_BASE2               = 0x127;
+enum BTN_BASE3               = 0x128;
+enum BTN_BASE4               = 0x129;
+enum BTN_BASE5               = 0x12a;
+enum BTN_BASE6               = 0x12b;
+enum BTN_DEAD                = 0x12f;
+
+enum BTN_GAMEPAD             = 0x130;
+enum BTN_SOUTH               = 0x130;
+enum BTN_A                   = BTN_SOUTH;
+enum BTN_EAST                = 0x131;
+enum BTN_B                   = BTN_EAST;
+enum BTN_C                   = 0x132;
+enum BTN_NORTH               = 0x133;
+enum BTN_X                   = BTN_NORTH;
+enum BTN_WEST                = 0x134;
+enum BTN_Y                   = BTN_WEST;
+enum BTN_Z                   = 0x135;
+enum BTN_TL                  = 0x136;
+enum BTN_TR                  = 0x137;
+enum BTN_TL2                 = 0x138;
+enum BTN_TR2                 = 0x139;
+enum BTN_SELECT              = 0x13a;
+enum BTN_START               = 0x13b;
+enum BTN_MODE                = 0x13c;
+enum BTN_THUMBL              = 0x13d;
+enum BTN_THUMBR              = 0x13e;
+
+enum BTN_DIGI                = 0x140;
+enum BTN_TOOL_PEN            = 0x140;
+enum BTN_TOOL_RUBBER         = 0x141;
+enum BTN_TOOL_BRUSH          = 0x142;
+enum BTN_TOOL_PENCIL         = 0x143;
+enum BTN_TOOL_AIRBRUSH       = 0x144;
+enum BTN_TOOL_FINGER         = 0x145;
+enum BTN_TOOL_MOUSE          = 0x146;
+enum BTN_TOOL_LENS           = 0x147;
+enum BTN_TOOL_QUINTTAP       = 0x148;
+enum BTN_STYLUS3             = 0x149;
+enum BTN_TOUCH               = 0x14a;
+enum BTN_STYLUS              = 0x14b;
+enum BTN_STYLUS2             = 0x14c;
+enum BTN_TOOL_DOUBLETAP      = 0x14d;
+enum BTN_TOOL_TRIPLETAP      = 0x14e;
+enum BTN_TOOL_QUADTAP        = 0x14f;
+
+enum BTN_WHEEL               = 0x150;
+enum BTN_GEAR_DOWN           = 0x150;
+enum BTN_GEAR_UP             = 0x151;
+
+enum KEY_OK                  = 0x160;
+enum KEY_SELECT              = 0x161;
+enum KEY_GOTO                = 0x162;
+enum KEY_CLEAR               = 0x163;
+enum KEY_POWER2              = 0x164;
+enum KEY_OPTION              = 0x165;
+enum KEY_INFO                = 0x166;
+enum KEY_TIME                = 0x167;
+enum KEY_VENDOR              = 0x168;
+enum KEY_ARCHIVE             = 0x169;
+enum KEY_PROGRAM             = 0x16a;
+enum KEY_CHANNEL             = 0x16b;
+enum KEY_FAVORITES           = 0x16c;
+enum KEY_EPG                 = 0x16d;
+enum KEY_PVR                 = 0x16e;
+enum KEY_MHP                 = 0x16f;
+enum KEY_LANGUAGE            = 0x170;
+enum KEY_TITLE               = 0x171;
+enum KEY_SUBTITLE            = 0x172;
+enum KEY_ANGLE               = 0x173;
+enum KEY_ZOOM                = 0x174;
+enum KEY_MODE                = 0x175;
+enum KEY_KEYBOARD            = 0x176;
+enum KEY_SCREEN              = 0x177;
+enum KEY_PC                  = 0x178;
+enum KEY_TV                  = 0x179;
+enum KEY_TV2                 = 0x17a;
+enum KEY_VCR                 = 0x17b;
+enum KEY_VCR2                = 0x17c;
+enum KEY_SAT                 = 0x17d;
+enum KEY_SAT2                = 0x17e;
+enum KEY_CD                  = 0x17f;
+enum KEY_TAPE                = 0x180;
+enum KEY_RADIO               = 0x181;
+enum KEY_TUNER               = 0x182;
+enum KEY_PLAYER              = 0x183;
+enum KEY_TEXT                = 0x184;
+enum KEY_DVD                 = 0x185;
+enum KEY_AUX                 = 0x186;
+enum KEY_MP3                 = 0x187;
+enum KEY_AUDIO               = 0x188;
+enum KEY_VIDEO               = 0x189;
+enum KEY_DIRECTORY           = 0x18a;
+enum KEY_LIST                = 0x18b;
+enum KEY_MEMO                = 0x18c;
+enum KEY_CALENDAR            = 0x18d;
+enum KEY_RED                 = 0x18e;
+enum KEY_GREEN               = 0x18f;
+enum KEY_YELLOW              = 0x190;
+enum KEY_BLUE                = 0x191;
+enum KEY_CHANNELUP           = 0x192;
+enum KEY_CHANNELDOWN         = 0x193;
+enum KEY_FIRST               = 0x194;
+enum KEY_LAST                = 0x195;
+enum KEY_AB                  = 0x196;
+enum KEY_NEXT                = 0x197;
+enum KEY_RESTART             = 0x198;
+enum KEY_SLOW                = 0x199;
+enum KEY_SHUFFLE             = 0x19a;
+enum KEY_BREAK               = 0x19b;
+enum KEY_PREVIOUS            = 0x19c;
+enum KEY_DIGITS              = 0x19d;
+enum KEY_TEEN                = 0x19e;
+enum KEY_TWEN                = 0x19f;
+enum KEY_VIDEOPHONE          = 0x1a0;
+enum KEY_GAMES               = 0x1a1;
+enum KEY_ZOOMIN              = 0x1a2;
+enum KEY_ZOOMOUT             = 0x1a3;
+enum KEY_ZOOMRESET           = 0x1a4;
+enum KEY_WORDPROCESSOR       = 0x1a5;
+enum KEY_EDITOR              = 0x1a6;
+enum KEY_SPREADSHEET         = 0x1a7;
+enum KEY_GRAPHICSEDITOR      = 0x1a8;
+enum KEY_PRESENTATION        = 0x1a9;
+enum KEY_DATABASE            = 0x1aa;
+enum KEY_NEWS                = 0x1ab;
+enum KEY_VOICEMAIL           = 0x1ac;
+enum KEY_ADDRESSBOOK         = 0x1ad;
+enum KEY_MESSENGER           = 0x1ae;
+enum KEY_DISPLAYTOGGLE       = 0x1af;
+enum KEY_BRIGHTNESS_TOGGLE   = KEY_DISPLAYTOGGLE;
+enum KEY_SPELLCHECK          = 0x1b0;
+enum KEY_LOGOFF              = 0x1b1;
+
+enum KEY_DOLLAR              = 0x1b2;
+enum KEY_EURO                = 0x1b3;
+
+enum KEY_FRAMEBACK           = 0x1b4;
+enum KEY_FRAMEFORWARD        = 0x1b5;
+enum KEY_CONTEXT_MENU        = 0x1b6;
+enum KEY_MEDIA_REPEAT        = 0x1b7;
+enum KEY_10CHANNELSUP        = 0x1b8;
+enum KEY_10CHANNELSDOWN      = 0x1b9;
+enum KEY_IMAGES              = 0x1ba;
+
+enum KEY_DEL_EOL             = 0x1c0;
+enum KEY_DEL_EOS             = 0x1c1;
+enum KEY_INS_LINE            = 0x1c2;
+enum KEY_DEL_LINE            = 0x1c3;
+
+enum KEY_FN                  = 0x1d0;
+enum KEY_FN_ESC              = 0x1d1;
+enum KEY_FN_F1               = 0x1d2;
+enum KEY_FN_F2               = 0x1d3;
+enum KEY_FN_F3               = 0x1d4;
+enum KEY_FN_F4               = 0x1d5;
+enum KEY_FN_F5               = 0x1d6;
+enum KEY_FN_F6               = 0x1d7;
+enum KEY_FN_F7               = 0x1d8;
+enum KEY_FN_F8               = 0x1d9;
+enum KEY_FN_F9               = 0x1da;
+enum KEY_FN_F10              = 0x1db;
+enum KEY_FN_F11              = 0x1dc;
+enum KEY_FN_F12              = 0x1dd;
+enum KEY_FN_1                = 0x1de;
+enum KEY_FN_2                = 0x1df;
+enum KEY_FN_D                = 0x1e0;
+enum KEY_FN_E                = 0x1e1;
+enum KEY_FN_F                = 0x1e2;
+enum KEY_FN_S                = 0x1e3;
+enum KEY_FN_B                = 0x1e4;
+
+enum KEY_BRL_DOT1            = 0x1f1;
+enum KEY_BRL_DOT2            = 0x1f2;
+enum KEY_BRL_DOT3            = 0x1f3;
+enum KEY_BRL_DOT4            = 0x1f4;
+enum KEY_BRL_DOT5            = 0x1f5;
+enum KEY_BRL_DOT6            = 0x1f6;
+enum KEY_BRL_DOT7            = 0x1f7;
+enum KEY_BRL_DOT8            = 0x1f8;
+enum KEY_BRL_DOT9            = 0x1f9;
+enum KEY_BRL_DOT10           = 0x1fa;
+
+enum KEY_NUMERIC_0           = 0x200;
+enum KEY_NUMERIC_1           = 0x201;
+enum KEY_NUMERIC_2           = 0x202;
+enum KEY_NUMERIC_3           = 0x203;
+enum KEY_NUMERIC_4           = 0x204;
+enum KEY_NUMERIC_5           = 0x205;
+enum KEY_NUMERIC_6           = 0x206;
+enum KEY_NUMERIC_7           = 0x207;
+enum KEY_NUMERIC_8           = 0x208;
+enum KEY_NUMERIC_9           = 0x209;
+enum KEY_NUMERIC_STAR        = 0x20a;
+enum KEY_NUMERIC_POUND       = 0x20b;
+enum KEY_NUMERIC_A           = 0x20c;
+enum KEY_NUMERIC_B           = 0x20d;
+enum KEY_NUMERIC_C           = 0x20e;
+enum KEY_NUMERIC_D           = 0x20f;
+
+enum KEY_CAMERA_FOCUS        = 0x210;
+enum KEY_WPS_BUTTON          = 0x211;
+
+enum KEY_TOUCHPAD_TOGGLE     = 0x212;
+enum KEY_TOUCHPAD_ON         = 0x213;
+enum KEY_TOUCHPAD_OFF        = 0x214;
+
+enum KEY_CAMERA_ZOOMIN       = 0x215;
+enum KEY_CAMERA_ZOOMOUT      = 0x216;
+enum KEY_CAMERA_UP           = 0x217;
+enum KEY_CAMERA_DOWN         = 0x218;
+enum KEY_CAMERA_LEFT         = 0x219;
+enum KEY_CAMERA_RIGHT        = 0x21a;
+
+enum KEY_ATTENDANT_ON        = 0x21b;
+enum KEY_ATTENDANT_OFF       = 0x21c;
+enum KEY_ATTENDANT_TOGGLE    = 0x21d;
+enum KEY_LIGHTS_TOGGLE       = 0x21e;
+
+enum BTN_DPAD_UP             = 0x220;
+enum BTN_DPAD_DOWN           = 0x221;
+enum BTN_DPAD_LEFT           = 0x222;
+enum BTN_DPAD_RIGHT          = 0x223;
+
+enum KEY_ALS_TOGGLE          = 0x230;
+enum KEY_ROTATE_LOCK_TOGGLE  = 0x231;
+
+enum KEY_BUTTONCONFIG                = 0x240;
+enum KEY_TASKMANAGER         = 0x241;
+enum KEY_JOURNAL             = 0x242;
+enum KEY_CONTROLPANEL                = 0x243;
+enum KEY_APPSELECT           = 0x244;
+enum KEY_SCREENSAVER         = 0x245;
+enum KEY_VOICECOMMAND                = 0x246;
+enum KEY_ASSISTANT           = 0x247;
+
+enum KEY_BRIGHTNESS_MIN              = 0x250;
+enum KEY_BRIGHTNESS_MAX              = 0x251;
+
+enum KEY_KBDINPUTASSIST_PREV         = 0x260;
+enum KEY_KBDINPUTASSIST_NEXT         = 0x261;
+enum KEY_KBDINPUTASSIST_PREVGROUP            = 0x262;
+enum KEY_KBDINPUTASSIST_NEXTGROUP            = 0x263;
+enum KEY_KBDINPUTASSIST_ACCEPT               = 0x264;
+enum KEY_KBDINPUTASSIST_CANCEL               = 0x265;
+
+enum KEY_RIGHT_UP                    = 0x266;
+enum KEY_RIGHT_DOWN                  = 0x267;
+enum KEY_LEFT_UP                     = 0x268;
+enum KEY_LEFT_DOWN                   = 0x269;
+
+enum KEY_ROOT_MENU                   = 0x26a;
+enum KEY_MEDIA_TOP_MENU              = 0x26b;
+enum KEY_NUMERIC_11                  = 0x26c;
+enum KEY_NUMERIC_12                  = 0x26d;
+enum KEY_AUDIO_DESC                  = 0x26e;
+enum KEY_3D_MODE                     = 0x26f;
+enum KEY_NEXT_FAVORITE               = 0x270;
+enum KEY_STOP_RECORD                 = 0x271;
+enum KEY_PAUSE_RECORD                = 0x272;
+enum KEY_VOD                         = 0x273;
+enum KEY_UNMUTE                      = 0x274;
+enum KEY_FASTREVERSE                 = 0x275;
+enum KEY_SLOWREVERSE                 = 0x276;
+enum KEY_DATA                        = 0x277;
+enum KEY_ONSCREEN_KEYBOARD           = 0x278;
+
+enum BTN_TRIGGER_HAPPY               = 0x2c0;
+enum BTN_TRIGGER_HAPPY1              = 0x2c0;
+enum BTN_TRIGGER_HAPPY2              = 0x2c1;
+enum BTN_TRIGGER_HAPPY3              = 0x2c2;
+enum BTN_TRIGGER_HAPPY4              = 0x2c3;
+enum BTN_TRIGGER_HAPPY5              = 0x2c4;
+enum BTN_TRIGGER_HAPPY6              = 0x2c5;
+enum BTN_TRIGGER_HAPPY7              = 0x2c6;
+enum BTN_TRIGGER_HAPPY8              = 0x2c7;
+enum BTN_TRIGGER_HAPPY9              = 0x2c8;
+enum BTN_TRIGGER_HAPPY10             = 0x2c9;
+enum BTN_TRIGGER_HAPPY11             = 0x2ca;
+enum BTN_TRIGGER_HAPPY12             = 0x2cb;
+enum BTN_TRIGGER_HAPPY13             = 0x2cc;
+enum BTN_TRIGGER_HAPPY14             = 0x2cd;
+enum BTN_TRIGGER_HAPPY15             = 0x2ce;
+enum BTN_TRIGGER_HAPPY16             = 0x2cf;
+enum BTN_TRIGGER_HAPPY17             = 0x2d0;
+enum BTN_TRIGGER_HAPPY18             = 0x2d1;
+enum BTN_TRIGGER_HAPPY19             = 0x2d2;
+enum BTN_TRIGGER_HAPPY20             = 0x2d3;
+enum BTN_TRIGGER_HAPPY21             = 0x2d4;
+enum BTN_TRIGGER_HAPPY22             = 0x2d5;
+enum BTN_TRIGGER_HAPPY23             = 0x2d6;
+enum BTN_TRIGGER_HAPPY24             = 0x2d7;
+enum BTN_TRIGGER_HAPPY25             = 0x2d8;
+enum BTN_TRIGGER_HAPPY26             = 0x2d9;
+enum BTN_TRIGGER_HAPPY27             = 0x2da;
+enum BTN_TRIGGER_HAPPY28             = 0x2db;
+enum BTN_TRIGGER_HAPPY29             = 0x2dc;
+enum BTN_TRIGGER_HAPPY30             = 0x2dd;
+enum BTN_TRIGGER_HAPPY31             = 0x2de;
+enum BTN_TRIGGER_HAPPY32             = 0x2df;
+enum BTN_TRIGGER_HAPPY33             = 0x2e0;
+enum BTN_TRIGGER_HAPPY34             = 0x2e1;
+enum BTN_TRIGGER_HAPPY35             = 0x2e2;
+enum BTN_TRIGGER_HAPPY36             = 0x2e3;
+enum BTN_TRIGGER_HAPPY37             = 0x2e4;
+enum BTN_TRIGGER_HAPPY38             = 0x2e5;
+enum BTN_TRIGGER_HAPPY39             = 0x2e6;
+enum BTN_TRIGGER_HAPPY40             = 0x2e7;
+
+enum KEY_MIN_INTERESTING     = KEY_MUTE;
+enum KEY_MAX                 = 0x2ff;
+enum KEY_CNT                 = (KEY_MAX+1);
+
+enum REL_X                   = 0x00;
+enum REL_Y                   = 0x01;
+enum REL_Z                   = 0x02;
+enum REL_RX                  = 0x03;
+enum REL_RY                  = 0x04;
+enum REL_RZ                  = 0x05;
+enum REL_HWHEEL              = 0x06;
+enum REL_DIAL                = 0x07;
+enum REL_WHEEL               = 0x08;
+enum REL_MISC                = 0x09;
+enum REL_MAX                 = 0x0f;
+enum REL_CNT                 = (REL_MAX+1);
+
+enum ABS_X                   = 0x00;
+enum ABS_Y                   = 0x01;
+enum ABS_Z                   = 0x02;
+enum ABS_RX                  = 0x03;
+enum ABS_RY                  = 0x04;
+enum ABS_RZ                  = 0x05;
+enum ABS_THROTTLE            = 0x06;
+enum ABS_RUDDER              = 0x07;
+enum ABS_WHEEL               = 0x08;
+enum ABS_GAS                 = 0x09;
+enum ABS_BRAKE               = 0x0a;
+enum ABS_HAT0X               = 0x10;
+enum ABS_HAT0Y               = 0x11;
+enum ABS_HAT1X               = 0x12;
+enum ABS_HAT1Y               = 0x13;
+enum ABS_HAT2X               = 0x14;
+enum ABS_HAT2Y               = 0x15;
+enum ABS_HAT3X               = 0x16;
+enum ABS_HAT3Y               = 0x17;
+enum ABS_PRESSURE            = 0x18;
+enum ABS_DISTANCE            = 0x19;
+enum ABS_TILT_X              = 0x1a;
+enum ABS_TILT_Y              = 0x1b;
+enum ABS_TOOL_WIDTH          = 0x1c;
+
+enum ABS_VOLUME              = 0x20;
+
+enum ABS_MISC                = 0x28;
+
+enum ABS_MT_SLOT             = 0x2f;
+enum ABS_MT_TOUCH_MAJOR      = 0x30;
+enum ABS_MT_TOUCH_MINOR      = 0x31;
+enum ABS_MT_WIDTH_MAJOR      = 0x32;
+enum ABS_MT_WIDTH_MINOR      = 0x33;
+enum ABS_MT_ORIENTATION      = 0x34;
+enum ABS_MT_POSITION_X       = 0x35;
+enum ABS_MT_POSITION_Y       = 0x36;
+enum ABS_MT_TOOL_TYPE        = 0x37;
+enum ABS_MT_BLOB_ID          = 0x38;
+enum ABS_MT_TRACKING_ID      = 0x39;
+enum ABS_MT_PRESSURE         = 0x3a;
+enum ABS_MT_DISTANCE         = 0x3b;
+enum ABS_MT_TOOL_X           = 0x3c;
+enum ABS_MT_TOOL_Y           = 0x3d;
+
+enum ABS_MAX                 = 0x3f;
+enum ABS_CNT                 = (ABS_MAX+1);
+
+enum SW_LID                  = 0x00;
+enum SW_TABLET_MODE          = 0x01;
+enum SW_HEADPHONE_INSERT     = 0x02;
+enum SW_RFKILL_ALL           = 0x03;
+enum SW_RADIO                = SW_RFKILL_ALL;
+enum SW_MICROPHONE_INSERT    = 0x04;
+enum SW_DOCK                 = 0x05;
+enum SW_LINEOUT_INSERT       = 0x06;
+enum SW_JACK_PHYSICAL_INSERT = 0x07;
+enum SW_VIDEOOUT_INSERT      = 0x08;
+enum SW_CAMERA_LENS_COVER    = 0x09;
+enum SW_KEYPAD_SLIDE         = 0x0a;
+enum SW_FRONT_PROXIMITY      = 0x0b;
+enum SW_ROTATE_LOCK          = 0x0c;
+enum SW_LINEIN_INSERT        = 0x0d;
+enum SW_MUTE_DEVICE          = 0x0e;
+enum SW_PEN_INSERTED         = 0x0f;
+enum SW_MAX                  = 0x0f;
+enum SW_CNT                  = (SW_MAX+1);
+
+enum MSC_SERIAL              = 0x00;
+enum MSC_PULSELED            = 0x01;
+enum MSC_GESTURE             = 0x02;
+enum MSC_RAW                 = 0x03;
+enum MSC_SCAN                = 0x04;
+enum MSC_TIMESTAMP           = 0x05;
+enum MSC_MAX                 = 0x07;
+enum MSC_CNT                 = (MSC_MAX+1);
+
+enum LED_NUML                = 0x00;
+enum LED_CAPSL               = 0x01;
+enum LED_SCROLLL             = 0x02;
+enum LED_COMPOSE             = 0x03;
+enum LED_KANA                = 0x04;
+enum LED_SLEEP               = 0x05;
+enum LED_SUSPEND             = 0x06;
+enum LED_MUTE                = 0x07;
+enum LED_MISC                = 0x08;
+enum LED_MAIL                = 0x09;
+enum LED_CHARGING            = 0x0a;
+enum LED_MAX                 = 0x0f;
+enum LED_CNT                 = (LED_MAX+1);
+
+enum REP_DELAY               = 0x00;
+enum REP_PERIOD              = 0x01;
+enum REP_MAX                 = 0x01;
+enum REP_CNT                 = (REP_MAX+1);
+
+enum SND_CLICK               = 0x00;
+enum SND_BELL                = 0x01;
+enum SND_TONE                = 0x02;
+enum SND_MAX                 = 0x07;
+enum SND_CNT                 = (SND_MAX+1);
diff --git a/libphobos/libdruntime/core/sys/linux/uinput.d b/libphobos/libdruntime/core/sys/linux/uinput.d
new file mode 100644
index 00000000000..abb61f919c2
--- /dev/null
+++ b/libphobos/libdruntime/core/sys/linux/uinput.d
@@ -0,0 +1,85 @@ 
+module core.sys.linux.uinput;
+
+version (linux):
+extern(C):
+nothrow:
+
+import core.sys.posix.sys.ioctl;
+
+public import core.sys.linux.input;
+public import core.sys.linux.input_event_codes;
+
+enum UINPUT_VERSION = 5;
+enum UINPUT_MAX_NAME_SIZE = 80;
+
+struct uinput_ff_upload
+{
+    uint            request_id;
+    int             retval;
+    ff_effect       effect;
+    ff_effect       old;
+}
+
+struct uinput_ff_erase
+{
+    uint           request_id;
+    int            retval;
+    uint           effect_id;
+}
+
+enum UINPUT_IOCTL_BASE  = 'U';
+enum UI_DEV_CREATE              = _IO(UINPUT_IOCTL_BASE, 1);
+enum UI_DEV_DESTROY             = _IO(UINPUT_IOCTL_BASE, 2);
+
+struct uinput_setup
+{
+    input_id id;
+    char[UINPUT_MAX_NAME_SIZE] name;
+    uint ff_effects_max;
+}
+
+enum UI_DEV_SETUP = _IOW!uinput_setup(UINPUT_IOCTL_BASE, 3);
+
+struct uinput_abs_setup
+{
+    ushort  code;
+
+    input_absinfo absinfo;
+}
+
+enum UI_ABS_SETUP = _IOW!uinput_abs_setup(UINPUT_IOCTL_BASE, 4);
+
+enum UI_SET_EVBIT               = _IOW!int(UINPUT_IOCTL_BASE, 100);
+enum UI_SET_KEYBIT              = _IOW!int(UINPUT_IOCTL_BASE, 101);
+enum UI_SET_RELBIT              = _IOW!int(UINPUT_IOCTL_BASE, 102);
+enum UI_SET_ABSBIT              = _IOW!int(UINPUT_IOCTL_BASE, 103);
+enum UI_SET_MSCBIT              = _IOW!int(UINPUT_IOCTL_BASE, 104);
+enum UI_SET_LEDBIT              = _IOW!int(UINPUT_IOCTL_BASE, 105);
+enum UI_SET_SNDBIT              = _IOW!int(UINPUT_IOCTL_BASE, 106);
+enum UI_SET_FFBIT               = _IOW!int(UINPUT_IOCTL_BASE, 107);
+enum UI_SET_PHYS                = _IOW!(char*)(UINPUT_IOCTL_BASE, 108);
+enum UI_SET_SWBIT               = _IOW!int(UINPUT_IOCTL_BASE, 109);
+enum UI_SET_PROPBIT             = _IOW!int(UINPUT_IOCTL_BASE, 110);
+
+enum UI_BEGIN_FF_UPLOAD = _IOWR!uinput_ff_upload(UINPUT_IOCTL_BASE, 200);
+enum UI_END_FF_UPLOAD   = _IOW!uinput_ff_upload(UINPUT_IOCTL_BASE, 201);
+enum UI_BEGIN_FF_ERASE  = _IOWR!uinput_ff_erase(UINPUT_IOCTL_BASE, 202);
+enum UI_END_FF_ERASE    = _IOW!uinput_ff_erase(UINPUT_IOCTL_BASE, 203);
+
+enum UI_GET_SYSNAME(len) = _IOC(_IOC_READ, UINPUT_IOCTL_BASE, 44, len);
+
+enum UI_GET_VERSION             = _IOR!uint(UINPUT_IOCTL_BASE, 45);
+
+enum EV_UINPUT          = 0x0101;
+enum UI_FF_UPLOAD               = 1;
+enum UI_FF_ERASE                = 2;
+
+struct uinput_user_dev {
+    char[UINPUT_MAX_NAME_SIZE] name;
+    input_id id;
+    uint ff_effects_max;
+    int[ABS_CNT] absmax;
+    int[ABS_CNT] absmin;
+    int[ABS_CNT] absfuzz;
+    int[ABS_CNT] absflat;
+}
diff --git a/libphobos/libdruntime/core/sys/openbsd/unistd.d b/libphobos/libdruntime/core/sys/openbsd/unistd.d
index 0b8580fb860..4232c036049 100644
--- a/libphobos/libdruntime/core/sys/openbsd/unistd.d
+++ b/libphobos/libdruntime/core/sys/openbsd/unistd.d
@@ -12,6 +12,10 @@  extern (C):
 nothrow:
 @nogc:
 
+public import core.sys.posix.sys.types;
+
 int getentropy(void*, size_t);
+int getthrname(pid_t, char*, size_t);
 int pledge(const scope char*, const scope char*);
+int setthrname(pid_t, const scope char*);
 int unveil(const scope char*, const scope char*);
diff --git a/libphobos/libdruntime/core/sys/windows/dll.d b/libphobos/libdruntime/core/sys/windows/dll.d
index 367c1d90d93..5b02fb55801 100644
--- a/libphobos/libdruntime/core/sys/windows/dll.d
+++ b/libphobos/libdruntime/core/sys/windows/dll.d
@@ -328,6 +328,8 @@  public:
  *  first access to a __declspec(thread) variable occurs, that is."
  *
  * _tls_index is initialized by the compiler to 0, so we can use this as a test.
+ * Returns:
+ *	true for success, false for failure
  */
 bool dll_fixTLS( HINSTANCE hInstance, void* tlsstart, void* tlsend, void* tls_callbacks_a, int* tlsindex ) nothrow
 {
@@ -448,8 +450,13 @@  int dll_getRefCount( HINSTANCE hInstance ) nothrow @nogc
     return ldrMod.LoadCount;
 }
 
-// fixup TLS storage, initialize runtime and attach to threads
-// to be called from DllMain with reason DLL_PROCESS_ATTACH
+/*****************************
+ * To be called from DllMain with reason DLL_PROCESS_ATTACH
+ *
+ * fixup TLS storage, initialize runtime and attach to threads
+ * Returns:
+ *	true = success, false = failure
+ */
 bool dll_process_attach( HINSTANCE hInstance, bool attach_threads,
                          void* tlsstart, void* tlsend, void* tls_callbacks_a, int* tlsindex )
 {
@@ -480,7 +487,8 @@  bool dll_process_attach( HINSTANCE hInstance, bool attach_threads,
         }, null );
 }
 
-// same as above, but only usable if druntime is linked statically
+/** same as above, but only usable if druntime is linked statically
+ */
 bool dll_process_attach( HINSTANCE hInstance, bool attach_threads = true )
 {
     version (Win64)
@@ -495,7 +503,9 @@  bool dll_process_attach( HINSTANCE hInstance, bool attach_threads = true )
     }
 }
 
-// to be called from DllMain with reason DLL_PROCESS_DETACH
+/**
+ * to be called from DllMain with reason DLL_PROCESS_DETACH
+ */
 void dll_process_detach( HINSTANCE hInstance, bool detach_threads = true )
 {
     // notify core.thread.joinLowLevelThread that the DLL is about to be unloaded
@@ -527,7 +537,11 @@  static bool tlsCtorRun;
 static this() { tlsCtorRun = true; }
 static ~this() { tlsCtorRun = false; }
 
-// to be called from DllMain with reason DLL_THREAD_ATTACH
+/**
+ * To be called from DllMain with reason DLL_THREAD_ATTACH
+ * Returns:
+ *	true for success, false for failure
+ */
 bool dll_thread_attach( bool attach_thread = true, bool initTls = true )
 {
     // if the OS has not prepared TLS for us, don't attach to the thread
@@ -546,7 +560,11 @@  bool dll_thread_attach( bool attach_thread = true, bool initTls = true )
     return true;
 }
 
-// to be called from DllMain with reason DLL_THREAD_DETACH
+/**
+ * To be called from DllMain with reason DLL_THREAD_DETACH
+ * Returns:
+ *	true for success, false for failure
+ */
 bool dll_thread_detach( bool detach_thread = true, bool exitTls = true )
 {
     // if the OS has not prepared TLS for us, we did not attach to the thread
@@ -562,14 +580,17 @@  bool dll_thread_detach( bool detach_thread = true, bool exitTls = true )
     return true;
 }
 
-/// A simple mixin to provide a $(D DllMain) which calls the necessary
-/// runtime initialization and termination functions automatically.
-///
-/// Instead of writing a custom $(D DllMain), simply write:
-///
-/// ---
-/// mixin SimpleDllMain;
-/// ---
+/**********************************
+ * A mixin to provide a $(D DllMain) which calls the necessary
+ * D runtime initialization and termination functions automatically.
+ *
+ * Example:
+ * ---
+ * module dllmain;
+ * import core.sys.windows.dll;
+ * mixin SimpleDllMain;
+ * ---
+ */
 mixin template SimpleDllMain()
 {
     import core.sys.windows.windef : HINSTANCE, BOOL, DWORD, LPVOID;
diff --git a/libphobos/libdruntime/etc/valgrind/valgrind.d b/libphobos/libdruntime/etc/valgrind/valgrind.d
new file mode 100644
index 00000000000..21829fc23bf
--- /dev/null
+++ b/libphobos/libdruntime/etc/valgrind/valgrind.d
@@ -0,0 +1,85 @@ 
+/// D wrapper for the Valgrind client API.
+/// Note that you must include this file into your program's compilation
+/// and compile with `-debug=VALGRIND` to access the declarations below.
+module etc.valgrind.valgrind;
+
+version (StdDdoc)
+{
+    /// Mark the memory covered by `mem` as unaddressable.
+    void makeMemNoAccess (const(void)[] mem) nothrow @nogc;
+
+    /// Similarly, mark memory covered by `mem` as addressable but undefined.
+    void makeMemUndefined(const(void)[] mem) nothrow @nogc;
+
+    /// Similarly, mark memory covered by `mem` as addressable and defined.
+    void makeMemDefined  (const(void)[] mem) nothrow @nogc;
+
+    /// Get the validity data for the address range covered by `mem` and copy it
+    /// into the provided `bits` array.
+    /// Returns:
+    ///   - 0   if not running on valgrind
+    ///   - 1   success
+    ///   - 2   [previously indicated unaligned arrays;  these are now allowed]
+    ///   - 3   if any parts of `mem`/`bits` are not addressable.
+    /// The metadata is not copied in cases 0, 2 or 3 so it should be
+    /// impossible to segfault your system by using this call.
+    uint getVBits(const(void)[] mem, ubyte[] bits) nothrow @nogc;
+
+    /// Set the validity data for the address range covered by `mem`, copying it
+    /// from the provided `bits` array.
+    /// Returns:
+    ///   - 0   if not running on valgrind
+    ///   - 1   success
+    ///   - 2   [previously indicated unaligned arrays;  these are now allowed]
+    ///   - 3   if any parts of `mem`/`bits` are not addressable.
+    /// The metadata is not copied in cases 0, 2 or 3 so it should be
+    /// impossible to segfault your system by using this call.
+    uint setVBits(const(void)[] mem, ubyte[] bits) nothrow @nogc;
+
+    /// Disable and re-enable reporting of addressing errors in the
+    /// address range covered by `mem`.
+    void disableAddrReportingInRange(const(void)[] mem) nothrow @nogc;
+
+    /// ditto
+    void enableAddrReportingInRange(const(void)[] mem) nothrow @nogc;
+}
+else:
+
+debug(VALGRIND):
+
+private extern(C) nothrow @nogc
+{
+    void _d_valgrind_make_mem_noaccess (const(void)* addr, size_t len);
+    void _d_valgrind_make_mem_undefined(const(void)* addr, size_t len);
+    void _d_valgrind_make_mem_defined  (const(void)* addr, size_t len);
+    uint _d_valgrind_get_vbits(const(void)* addr, ubyte* bits, size_t len);
+    uint _d_valgrind_set_vbits(const(void)* addr, ubyte* bits, size_t len);
+    void _d_valgrind_disable_addr_reporting_in_range(const(void)* addr, size_t len);
+    void _d_valgrind_enable_addr_reporting_in_range (const(void)* addr, size_t len);
+}
+
+void makeMemNoAccess (const(void)[] mem) nothrow @nogc { _d_valgrind_make_mem_noaccess (mem.ptr, mem.length); }
+void makeMemUndefined(const(void)[] mem) nothrow @nogc { _d_valgrind_make_mem_undefined(mem.ptr, mem.length); }
+void makeMemDefined  (const(void)[] mem) nothrow @nogc { _d_valgrind_make_mem_defined  (mem.ptr, mem.length); }
+
+uint getVBits(const(void)[] mem, ubyte[] bits) nothrow @nogc
+{
+    assert(mem.length == bits.length);
+    return _d_valgrind_get_vbits(mem.ptr, bits.ptr, mem.length);
+}
+
+uint setVBits(const(void)[] mem, ubyte[] bits) nothrow @nogc
+{
+    assert(mem.length == bits.length);
+    return _d_valgrind_set_vbits(mem.ptr, bits.ptr, mem.length);
+}
+
+void disableAddrReportingInRange(const(void)[] mem) nothrow @nogc
+{
+    _d_valgrind_disable_addr_reporting_in_range(mem.ptr, mem.length);
+}
+
+void enableAddrReportingInRange(const(void)[] mem) nothrow @nogc
+{
+    _d_valgrind_enable_addr_reporting_in_range(mem.ptr, mem.length);
+}
diff --git a/libphobos/libdruntime/etc/valgrind/valgrind_.c b/libphobos/libdruntime/etc/valgrind/valgrind_.c
new file mode 100644
index 00000000000..4dc4a171f8b
--- /dev/null
+++ b/libphobos/libdruntime/etc/valgrind/valgrind_.c
@@ -0,0 +1,102 @@ 
+/**
+ * This file contains wrapper functions for macro-defined valgrind routines.
+ *
+ * Copyright: Copyright: Copyright (C) D Language Foundation 2023
+ * License: Distributed under the
+ *      $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
+ *    (See accompanying file LICENSE)
+ * Source:    $(DRUNTIMESRC etc/valgrind/valgrind.c)
+ */
+
+/* NOTE: This file has been patched from the original DMD distribution to
+ * work with the GDC compiler.
+ */
+#include "config.h"
+
+#ifdef ENABLE_VALGRIND_CHECKING
+
+#ifdef HAVE_STDDEF_H
+# include <stddef.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+
+#ifdef HAVE_VALGRIND_MEMCHECK_H
+# include <valgrind/memcheck.h>
+#elif defined HAVE_MEMCHECK_H
+# include <memcheck.h>
+#else
+# include <valgrind.h>
+#endif
+
+#ifndef VALGRIND_MAKE_MEM_NOACCESS
+# define VALGRIND_MAKE_MEM_NOACCESS VALGRIND_MAKE_NOACCESS
+#endif
+#ifndef VALGRIND_MAKE_MEM_UNDEFINED
+# define VALGRIND_MAKE_MEM_UNDEFINED VALGRIND_MAKE_WRITABLE
+#endif
+#ifndef VALGRIND_MAKE_MEM_DEFINED
+# define VALGRIND_MAKE_MEM_DEFINED VALGRIND_MAKE_READABLE
+#endif
+
+#ifndef VALGRIND_GET_VBITS
+# define VALGRIND_GET_VBITS(a,b,l) 0
+#endif
+#ifndef VALGRIND_SET_VBITS
+# define VALGRIND_SET_VBITS(a,b,l) 0
+#endif
+#ifndef VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE
+# define VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,l)
+#endif
+#ifndef VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE
+# define VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,l)
+#endif
+
+#define MAYBE_UNUSED __attribute__((unused))
+
+void _d_valgrind_make_mem_noaccess(const void* addr, size_t len)
+{
+    VALGRIND_DISCARD(VALGRIND_MAKE_MEM_NOACCESS(addr, len));
+}
+
+void _d_valgrind_make_mem_undefined(const void* addr, size_t len)
+{
+    VALGRIND_DISCARD(VALGRIND_MAKE_MEM_UNDEFINED(addr, len));
+}
+
+void _d_valgrind_make_mem_defined(const void* addr, size_t len)
+{
+    VALGRIND_DISCARD(VALGRIND_MAKE_MEM_DEFINED(addr, len));
+}
+
+unsigned _d_valgrind_get_vbits(const void* addr MAYBE_UNUSED,
+                               char* bits MAYBE_UNUSED,
+                               size_t len MAYBE_UNUSED)
+{
+    return VALGRIND_GET_VBITS(addr, bits, len);
+}
+
+unsigned _d_valgrind_set_vbits(const void* addr MAYBE_UNUSED,
+                               char* bits MAYBE_UNUSED,
+                               size_t len MAYBE_UNUSED)
+{
+    return VALGRIND_SET_VBITS(addr, bits, len);
+}
+
+void _d_valgrind_disable_addr_reporting_in_range(const void* addr MAYBE_UNUSED,
+                                                 size_t len MAYBE_UNUSED)
+{
+    VALGRIND_DISCARD(VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(addr, len));
+}
+
+void _d_valgrind_enable_addr_reporting_in_range(const void* addr MAYBE_UNUSED,
+                                                size_t len MAYBE_UNUSED)
+{
+    VALGRIND_DISCARD(VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(addr, len));
+}
+
+#endif  /* ENABLE_VALGRIND_CHECKING  */
diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d
index 337eabf64db..b0889b66386 100644
--- a/libphobos/libdruntime/object.d
+++ b/libphobos/libdruntime/object.d
@@ -289,8 +289,9 @@  if ((is(LHS : const Object) || is(LHS : const shared Object)) &&
         // If same exact type => one call to method opEquals
         if (typeid(lhs) is typeid(rhs) ||
             !__ctfe && typeid(lhs).opEquals(typeid(rhs)))
-                /* CTFE doesn't like typeid much. 'is' works, but opEquals doesn't
-                (issue 7147). But CTFE also guarantees that equal TypeInfos are
+                /* CTFE doesn't like typeid much. 'is' works, but opEquals doesn't:
+                https://issues.dlang.org/show_bug.cgi?id=7147
+                But CTFE also guarantees that equal TypeInfos are
                 always identical. So, no opEquals needed during CTFE. */
         {
             return true;
@@ -983,7 +984,7 @@  class TypeInfo_Enum : TypeInfo
 }
 
 
-@safe unittest // issue 12233
+@safe unittest // https://issues.dlang.org/show_bug.cgi?id=12233
 {
     static assert(is(typeof(TypeInfo.init) == TypeInfo));
     assert(TypeInfo.init is null);
@@ -4195,8 +4196,11 @@  void destroy(bool initialize = true, T)(T obj) if (is(T == interface))
     assert(c.s == "S");         // `c.s` is back to its inital state, `"S"`
     assert(c.a.dtorCount == 1); // `c.a`'s destructor was called
     assert(c.a.x == 10);        // `c.a.x` is back to its inital state, `10`
+}
 
-    // check C++ classes work too!
+/// C++ classes work too
+@system unittest
+{
     extern (C++) class CPP
     {
         struct Agg
@@ -4247,6 +4251,34 @@  void destroy(bool initialize = true, T)(T obj) if (is(T == interface))
     assert(i == 0);           // `i` is back to its initial state `0`
 }
 
+/// Nested struct type
+@system unittest
+{
+    int dtorCount;
+    struct A
+    {
+        int i;
+        ~this()
+        {
+            dtorCount++; // capture local variable
+        }
+    }
+    A a = A(5);
+    destroy!false(a);
+    assert(dtorCount == 1);
+    assert(a.i == 5);
+
+    destroy(a);
+    assert(dtorCount == 2);
+    assert(a.i == 0);
+
+    // the context pointer is now null
+    // restore it so the dtor can run
+    import core.lifetime : emplace;
+    emplace(&a, A(0));
+    // dtor also called here
+}
+
 @system unittest
 {
     extern(C++)
diff --git a/libphobos/libdruntime/rt/lifetime.d b/libphobos/libdruntime/rt/lifetime.d
index 40fa3e00b45..1245374ec5f 100644
--- a/libphobos/libdruntime/rt/lifetime.d
+++ b/libphobos/libdruntime/rt/lifetime.d
@@ -1307,12 +1307,19 @@  int hasArrayFinalizerInSegment(void* p, size_t size, in void[] segment) nothrow
     return cast(size_t)(cast(void*)si.xdtor - segment.ptr) < segment.length;
 }
 
+debug (VALGRIND) import etc.valgrind.valgrind;
+
 // called by the GC
 void finalize_array2(void* p, size_t size) nothrow
 {
     debug(PRINTF) printf("rt_finalize_array2(p = %p)\n", p);
 
     TypeInfo_Struct si = void;
+    debug (VALGRIND)
+    {
+        auto block = p[0..size];
+        disableAddrReportingInRange(block);
+    }
     if (size <= 256)
     {
         si = *cast(TypeInfo_Struct*)(p + size - size_t.sizeof);
@@ -1329,6 +1336,7 @@  void finalize_array2(void* p, size_t size) nothrow
         size = *cast(size_t*)p;
         p += LARGEPREFIX;
     }
+    debug (VALGRIND) enableAddrReportingInRange(block);
 
     try
     {
@@ -2373,7 +2381,7 @@  unittest
 
 unittest
 {
-    // bugzilla 13854
+    // https://issues.dlang.org/show_bug.cgi?id=13854
     auto arr = new ubyte[PAGESIZE]; // ensure page size
     auto info1 = GC.query(arr.ptr);
     assert(info1.base !is arr.ptr); // offset is required for page size or larger
@@ -2416,7 +2424,7 @@  unittest
 
 unittest
 {
-    // bugzilla 13878
+    // https://issues.dlang.org/show_bug.cgi?id=13878
     auto arr = new ubyte[1];
     auto info = GC.query(arr.ptr);
     assert(info.attr & BlkAttr.NO_SCAN); // should be NO_SCAN
diff --git a/libphobos/libdruntime/rt/minfo.d b/libphobos/libdruntime/rt/minfo.d
index 74891506364..b5c868f70bc 100644
--- a/libphobos/libdruntime/rt/minfo.d
+++ b/libphobos/libdruntime/rt/minfo.d
@@ -268,7 +268,9 @@  struct ModuleGroup
                     }
                 }
                 // trim space to what is needed.
-                edges[i] = (cast(int*)realloc(edge, int.sizeof * nEdges))[0 .. nEdges];
+                edges[i] = nEdges > 0
+                    ? (cast(int*)realloc(edge, int.sizeof * nEdges))[0 .. nEdges]
+                    : null;
             }
         }
 
diff --git a/libphobos/libdruntime/rt/util/typeinfo.d b/libphobos/libdruntime/rt/util/typeinfo.d
index 7b55693a720..730649ef481 100644
--- a/libphobos/libdruntime/rt/util/typeinfo.d
+++ b/libphobos/libdruntime/rt/util/typeinfo.d
@@ -545,7 +545,7 @@  unittest
 
 unittest
 {
-    // Original test case from issue 13073
+    // Original test case from https://issues.dlang.org/show_bug.cgi?id=13073
     uint x = 0x22_DF_FF_FF;
     uint y = 0xA2_DF_FF_FF;
     assert(!(x < y && y < x));
diff --git a/libphobos/m4/druntime/libraries.m4 b/libphobos/m4/druntime/libraries.m4
index 45a56f6f76a..8dd9c7da107 100644
--- a/libphobos/m4/druntime/libraries.m4
+++ b/libphobos/m4/druntime/libraries.m4
@@ -233,3 +233,56 @@  AC_DEFUN([DRUNTIME_LIBRARIES_UCONTEXT],
       AC_MSG_ERROR([swapcontext required but not found]))
   fi
 ])
+
+# DRUNTIME_LIBRARIES_VALGRIND
+# ------------------------------
+# Allow specifying whether to use valgrind integration in the GC, which enables
+# the D run-time to communicate which memory access operations are valid.
+# This is only required if `--enable-libphobos-checking=valgrind' was seen.
+AC_DEFUN([DRUNTIME_LIBRARIES_VALGRIND],
+[
+  AC_CHECK_HEADERS(stddef.h stdlib.h)
+
+  AC_CHECK_HEADER(valgrind.h, have_valgrind_h=yes, have_valgrind_h=no)
+
+  AC_MSG_CHECKING(for VALGRIND_DISCARD in <valgrind/memcheck.h>)
+  AC_PREPROC_IFELSE([AC_LANG_SOURCE(
+    [[#include <valgrind/memcheck.h>
+  #ifndef VALGRIND_DISCARD
+  #error VALGRIND_DISCARD not defined
+  #endif]])],
+    [have_valgrind_memcheck_h=yes],
+    [have_valgrind_memcheck_h=no])
+  AC_MSG_RESULT($have_valgrind_memcheck_h)
+  AC_MSG_CHECKING(for VALGRIND_DISCARD in <memcheck.h>)
+  AC_PREPROC_IFELSE([AC_LANG_SOURCE(
+    [[#include <memcheck.h>
+  #ifndef VALGRIND_DISCARD
+  #error VALGRIND_DISCARD not defined
+  #endif]])],
+    [have_memcheck_h=yes],
+    [have_memcheck_h=no])
+  AC_MSG_RESULT($have_memcheck_h)
+
+  if test x$VALGRIND_FLAG != x ; then
+    AC_DEFINE(ENABLE_VALGRIND_CHECKING, 1,
+        [Define to enable to integrate valgrind (a memory checker) in the GC.])
+  fi
+  if test $have_valgrind_memcheck_h = yes; then
+    AC_DEFINE(HAVE_VALGRIND_MEMCHECK_H, 1,
+        [Define if valgrind's valgrind/memcheck.h header is installed.])
+  fi
+  if test $have_memcheck_h = yes; then
+    AC_DEFINE(HAVE_MEMCHECK_H, 1,
+        [Define if valgrind's memcheck.h header is installed.])
+  fi
+
+  if test x$VALGRIND_FLAG != x; then
+    if (test $have_valgrind_h = no \
+        && test $have_memcheck_h = no \
+        && test $have_valgrind_memcheck_h = no); then
+      AC_MSG_ERROR([*** valgrind checking requested, but
+*** Can't find valgrind/memcheck.h, memcheck.h or valgrind.h])
+    fi
+  fi
+])
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE
index d3ebf74468c..e0011d7e7f7 100644
--- a/libphobos/src/MERGE
+++ b/libphobos/src/MERGE
@@ -1,4 +1,4 @@ 
-8d3800bee23db56f71ef4066f74bce057fcce256
+1921d29df25f2b44d6014c224e2018ce63ac2b71
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/phobos repository.
diff --git a/libphobos/src/std/algorithm/iteration.d b/libphobos/src/std/algorithm/iteration.d
index 55ccb512b73..39927be9bbb 100644
--- a/libphobos/src/std/algorithm/iteration.d
+++ b/libphobos/src/std/algorithm/iteration.d
@@ -2026,7 +2026,7 @@  private struct ChunkByGroup(alias eq, Range, bool eqEquivalenceAssured)
         }
     }
 
-    // Cannot be a copy constructor due to issue 22239
+    // Cannot be a copy constructor due to https://issues.dlang.org/show_bug.cgi?id=22239
     this(this) @trusted
     {
         import core.lifetime : emplace;
@@ -2128,7 +2128,7 @@  if (isForwardRange!Range)
         }();
     }
 
-    // Cannot be a copy constructor due to issue 22239
+    // Cannot be a copy constructor due to https://issues.dlang.org/show_bug.cgi?id=22239
     this(this) @trusted
     {
         import core.lifetime : emplace;
diff --git a/libphobos/src/std/algorithm/mutation.d b/libphobos/src/std/algorithm/mutation.d
index 9b1d9207b9a..61b6a5e4eff 100644
--- a/libphobos/src/std/algorithm/mutation.d
+++ b/libphobos/src/std/algorithm/mutation.d
@@ -3049,7 +3049,7 @@  if (isBlitAssignable!T && !is(typeof(lhs.proxySwap(rhs))))
     swap(b1, b2);
 }
 
-// issue 20732
+// https://issues.dlang.org/show_bug.cgi?id=20732
 @safe unittest
 {
     static struct A
diff --git a/libphobos/src/std/algorithm/searching.d b/libphobos/src/std/algorithm/searching.d
index ee318c88a0f..f061915d582 100644
--- a/libphobos/src/std/algorithm/searching.d
+++ b/libphobos/src/std/algorithm/searching.d
@@ -1282,7 +1282,7 @@  if (isInputRange!R &&
 
 @safe pure unittest
 {
-    //example from issue 19727
+    //example from https://issues.dlang.org/show_bug.cgi?id=19727
     import std.path : asRelativePath;
     string[] ext = ["abc", "def", "ghi"];
     string path = "/foo/file.def";
@@ -1315,19 +1315,12 @@  in
 }
 do
 {
-    import std.typecons : Rebindable;
+    import std.typecons : Rebindable2;
 
     alias Element = ElementType!Range;
-    Rebindable!Element seed = r.front;
+    auto seed = Rebindable2!Element(r.front);
     r.popFront();
-    static if (is(Rebindable!Element == T[], T))
-    {
-        return extremum!(map, selector)(r, seed);
-    }
-    else
-    {
-        return extremum!(map, selector)(r, seed.get);
-    }
+    return extremum!(map, selector)(r, seed.get);
 }
 
 private auto extremum(alias map, alias selector = "a < b", Range,
@@ -1337,25 +1330,24 @@  if (isInputRange!Range && !isInfinite!Range &&
     !is(CommonType!(ElementType!Range, RangeElementType) == void) &&
      is(typeof(unaryFun!map(ElementType!(Range).init))))
 {
-    import std.typecons : Rebindable;
+    import std.typecons : Rebindable2;
 
     alias mapFun = unaryFun!map;
     alias selectorFun = binaryFun!selector;
 
     alias Element = ElementType!Range;
     alias CommonElement = CommonType!(Element, RangeElementType);
-    Rebindable!CommonElement extremeElement = seedElement;
+    auto extremeElement = Rebindable2!CommonElement(seedElement);
 
     // if we only have one statement in the loop, it can be optimized a lot better
     static if (__traits(isSame, map, a => a))
     {
-
         // direct access via a random access range is faster
         static if (isRandomAccessRange!Range)
         {
             foreach (const i; 0 .. r.length)
             {
-                if (selectorFun(r[i], extremeElement))
+                if (selectorFun(r[i], extremeElement.get))
                 {
                     extremeElement = r[i];
                 }
@@ -1365,7 +1357,7 @@  if (isInputRange!Range && !isInfinite!Range &&
         {
             while (!r.empty)
             {
-                if (selectorFun(r.front, extremeElement))
+                if (selectorFun(r.front, extremeElement.get))
                 {
                     extremeElement = r.front;
                 }
@@ -1376,7 +1368,7 @@  if (isInputRange!Range && !isInfinite!Range &&
     else
     {
         alias MapType = Unqual!(typeof(mapFun(CommonElement.init)));
-        MapType extremeElementMapped = mapFun(extremeElement);
+        MapType extremeElementMapped = mapFun(extremeElement.get);
 
         // direct access via a random access range is faster
         static if (isRandomAccessRange!Range)
@@ -1405,15 +1397,7 @@  if (isInputRange!Range && !isInfinite!Range &&
             }
         }
     }
-    // Rebindable is an alias to T for arrays
-    static if (is(typeof(extremeElement) == T[], T))
-    {
-        return extremeElement;
-    }
-    else
-    {
-        return extremeElement.get;
-    }
+    return extremeElement.get;
 }
 
 private auto extremum(alias selector = "a < b", Range)(Range r)
@@ -2309,7 +2293,7 @@  private R1 simpleMindedFind(alias pred, R1, R2)(R1 haystack, scope R2 needle)
     @safe:
         string _impl;
 
-        // This is what triggers issue 7992.
+        // This is what triggers https://issues.dlang.org/show_bug.cgi?id=7992.
         @property size_t length() const { return _impl.length; }
         @property void length(size_t len) { _impl.length = len; }
 
@@ -2322,7 +2306,7 @@  private R1 simpleMindedFind(alias pred, R1, R2)(R1 haystack, scope R2 needle)
         @property CustomString save() { return this; }
     }
 
-    // If issue 7992 occurs, this will throw an exception from calling
+    // If https://issues.dlang.org/show_bug.cgi?id=7992 occurs, this will throw an exception from calling
     // popFront() on an empty range.
     auto r = find(CustomString("a"), CustomString("b"));
     assert(r.empty);
@@ -3880,6 +3864,14 @@  if (isInputRange!Range && !isInfinite!Range &&
     assert(arr.maxElement!"a.val".val == 1);
 }
 
+// https://issues.dlang.org/show_bug.cgi?id=23993
+@safe unittest
+{
+    import std.bigint : BigInt;
+
+    assert([BigInt(2), BigInt(3)].maxElement == BigInt(3));
+}
+
 // minPos
 /**
 Computes a subrange of `range` starting at the first occurrence of `range`'s
diff --git a/libphobos/src/std/complex.d b/libphobos/src/std/complex.d
index 3b860fe476b..347e351c26a 100644
--- a/libphobos/src/std/complex.d
+++ b/libphobos/src/std/complex.d
@@ -1066,7 +1066,7 @@  Complex!T asin(T)(Complex!T z)  @safe pure nothrow @nogc
 {
     import std.math.operations : isClose;
     import std.math.constants : PI;
-    version (DigitalMars) {} else // Disabled because of issue 21376
+    version (DigitalMars) {} else // Disabled because of https://issues.dlang.org/show_bug.cgi?id=21376
     assert(isClose(asin(complex(0.5f)), float(PI) / 6));
 }
 
@@ -1092,7 +1092,7 @@  Complex!T acos(T)(Complex!T z)  @safe pure nothrow @nogc
 {
     import std.math.operations : isClose;
     import std.math.constants : PI;
-    version (DigitalMars) {} else // Disabled because of issue 21376
+    version (DigitalMars) {} else // Disabled because of https://issues.dlang.org/show_bug.cgi?id=21376
     assert(isClose(acos(complex(0.5f)), float(PI) / 3));
 }
 
diff --git a/libphobos/src/std/container/array.d b/libphobos/src/std/container/array.d
index f5efe6d1f2a..0d6be93a1c1 100644
--- a/libphobos/src/std/container/array.d
+++ b/libphobos/src/std/container/array.d
@@ -1566,7 +1566,7 @@  if (!is(immutable T == immutable bool))
     r2[0 .. 0] += 0;
 }
 
-// Test issue 11194
+// Test https://issues.dlang.org/show_bug.cgi?id=11194
 @system unittest
 {
     static struct S {
diff --git a/libphobos/src/std/conv.d b/libphobos/src/std/conv.d
index 89d4e5eafa2..aabcd784229 100644
--- a/libphobos/src/std/conv.d
+++ b/libphobos/src/std/conv.d
@@ -209,14 +209,14 @@  template to(T)
         return toImpl!T(args);
     }
 
-    // Fix issue 6175
+    // Fix https://issues.dlang.org/show_bug.cgi?id=6175
     T to(S)(ref S arg)
         if (isStaticArray!S)
     {
         return toImpl!T(arg);
     }
 
-    // Fix issue 16108
+    // Fix https://issues.dlang.org/show_bug.cgi?id=16108
     T to(S)(ref S arg)
         if (isAggregateType!S && !isCopyable!S)
     {
@@ -423,7 +423,7 @@  template to(T)
     assert(c == "abcx");
 }
 
-// Tests for issue 6175
+// Tests for https://issues.dlang.org/show_bug.cgi?id=6175
 @safe pure nothrow unittest
 {
     char[9] sarr = "blablabla";
@@ -432,7 +432,7 @@  template to(T)
     assert(sarr.length == darr.length);
 }
 
-// Tests for issue 7348
+// Tests for https://issues.dlang.org/show_bug.cgi?id=7348
 @safe pure /+nothrow+/ unittest
 {
     assert(to!string(null) == "null");
@@ -454,7 +454,7 @@  template to(T)
     assert(text("a", s) == "aS");
 }
 
-// Tests for issue 11390
+// Tests for https://issues.dlang.org/show_bug.cgi?id=11390
 @safe pure /+nothrow+/ unittest
 {
     const(typeof(null)) ctn;
@@ -463,7 +463,7 @@  template to(T)
     assert(to!string(itn) == "null");
 }
 
-// Tests for issue 8729: do NOT skip leading WS
+// Tests for https://issues.dlang.org/show_bug.cgi?id=8729: do NOT skip leading WS
 @safe pure unittest
 {
     import std.exception;
@@ -1370,7 +1370,7 @@  if (is (T == immutable) && isExactSomeString!T && is(S == enum))
     S2 s2;
     assert(to!string(s2) == "S2(42, 43.5)");
 
-    // Test for issue 8080
+    // Test for https://issues.dlang.org/show_bug.cgi?id=8080
     struct S8080
     {
         short[4] data;
@@ -1972,7 +1972,7 @@  $(UL
 private T toImpl(T, S)(S value)
 if (isInputRange!S && isSomeChar!(ElementEncodingType!S) &&
     !isExactSomeString!T && is(typeof(parse!T(value))) &&
-    // issue 20539
+    // https://issues.dlang.org/show_bug.cgi?id=20539
     !(is(T == enum) && is(typeof(value == OriginalType!T.init)) && !isSomeString!(OriginalType!T)))
 {
     scope(success)
@@ -5560,7 +5560,7 @@  private bool isHexLiteral(String)(scope const String hexData)
     static assert( ("5A 01A C FF de 1b"d).isHexLiteral);
     static assert( ("0123456789abcdefABCDEF"d).isHexLiteral);
     static assert( (" 012 34 5 6789 abcd ef\rAB\nCDEF"d).isHexLiteral);
-    // library version allows what's pointed by issue 10454
+    // library version allows what's pointed by https://issues.dlang.org/show_bug.cgi?id=10454
     static assert( ("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").isHexLiteral);
 }
 
@@ -5931,7 +5931,7 @@  if ((radix == 2 || radix == 8 || radix == 10 || radix == 16) &&
     }
 }
 
-@safe unittest // opSlice (issue 16192)
+@safe unittest // opSlice (https://issues.dlang.org/show_bug.cgi?id=16192)
 {
     import std.meta : AliasSeq;
 
@@ -5959,7 +5959,7 @@  if ((radix == 2 || radix == 8 || radix == 10 || radix == 16) &&
         for (; !r.empty; r.popFront(), ++i)
         {
             assert(original[i .. original.length].tupleof == r.tupleof);
-                // tupleof is used to work around issue 16216.
+                // tupleof is used to work around https://issues.dlang.org/show_bug.cgi?id=16216.
         }
 
         // opSlice vs popBack
diff --git a/libphobos/src/std/exception.d b/libphobos/src/std/exception.d
index 6ffc0f7750a..1d93d351d99 100644
--- a/libphobos/src/std/exception.d
+++ b/libphobos/src/std/exception.d
@@ -1035,7 +1035,7 @@  Params:
 
 Bugs:
     The function is explicitly annotated `@nogc` because inference could fail,
-    see $(LINK2 https://issues.dlang.org/show_bug.cgi?id=17084, issue 17084).
+    see $(LINK2 https://issues.dlang.org/show_bug.cgi?id=17084, Bugzilla issue 17084).
 
 Returns: `true` if `source`'s representation embeds a pointer
 that points to `target`'s representation or somewhere inside
diff --git a/libphobos/src/std/experimental/allocator/building_blocks/kernighan_ritchie.d b/libphobos/src/std/experimental/allocator/building_blocks/kernighan_ritchie.d
index 65226e7f4cb..6883d33adae 100644
--- a/libphobos/src/std/experimental/allocator/building_blocks/kernighan_ritchie.d
+++ b/libphobos/src/std/experimental/allocator/building_blocks/kernighan_ritchie.d
@@ -827,7 +827,7 @@  version (StdUnittest)
 
     // Both sequences must work on either system
 
-    // A sequence of allocs which generates the error described in issue 16564
+    // A sequence of allocs which generates the error described in https://issues.dlang.org/show_bug.cgi?id=16564
     // that is a gap at the end of buf from the perspective of the allocator
 
     // for 64 bit systems (leftover balance = 8 bytes < 16)
diff --git a/libphobos/src/std/format/internal/floats.d b/libphobos/src/std/format/internal/floats.d
index 632bf7674a6..afe0bfa3cb5 100644
--- a/libphobos/src/std/format/internal/floats.d
+++ b/libphobos/src/std/format/internal/floats.d
@@ -1449,7 +1449,7 @@  if (is(T == float) || is(T == double)
         assert(printFloat(-0.1L, f) == "-1.000000e-01");
         assert(printFloat(10.0L, f) == "1.000000e+01");
         assert(printFloat(-10.0L, f) == "-1.000000e+01");
-        version (Windows) {} // issue 20972
+        version (Windows) {} // https://issues.dlang.org/show_bug.cgi?id=20972
         else
         {
             assert(printFloat(1e4000L, f) == "1.000000e+4000");
@@ -1472,7 +1472,7 @@  if (is(T == float) || is(T == double)
     {
         // log2 is broken for x87-reals on some computers in CTFE
         // the following tests excludes these computers from the tests
-        // (issue 21757)
+        // (https://issues.dlang.org/show_bug.cgi?id=21757)
         enum test = cast(int) log2(3.05e2312L);
         static if (real.mant_dig == 64 && test == 7681)
         {
@@ -2120,7 +2120,7 @@  if (is(T == float) || is(T == double)
         assert(printFloat(-0.1L, f) == "-0.100000");
         assert(printFloat(10.0L, f) == "10.000000");
         assert(printFloat(-10.0L, f) == "-10.000000");
-        version (Windows) {} // issue 20972
+        version (Windows) {} // https://issues.dlang.org/show_bug.cgi?id=20972
         else
         {
             auto result1 = printFloat(1e4000L, f);
@@ -2145,7 +2145,7 @@  if (is(T == float) || is(T == double)
     {
         // log2 is broken for x87-reals on some computers in CTFE
         // the following tests excludes these computers from the tests
-        // (issue 21757)
+        // (https://issues.dlang.org/show_bug.cgi?id=21757)
         enum test = cast(int) log2(3.05e2312L);
         static if (real.mant_dig == 64 && test == 7681)
         {
@@ -2803,7 +2803,7 @@  if (is(T == float) || is(T == double)
         assert(printFloat(-0.1L, f) == "-0.1");
         assert(printFloat(10.0L, f) == "10");
         assert(printFloat(-10.0L, f) == "-10");
-        version (Windows) {} // issue 20972
+        version (Windows) {} // https://issues.dlang.org/show_bug.cgi?id=20972
         else
         {
             assert(printFloat(1e4000L, f) == "1e+4000");
@@ -2826,7 +2826,7 @@  if (is(T == float) || is(T == double)
     {
         // log2 is broken for x87-reals on some computers in CTFE
         // the following tests excludes these computers from the tests
-        // (issue 21757)
+        // (https://issues.dlang.org/show_bug.cgi?id=21757)
         enum test = cast(int) log2(3.05e2312L);
         static if (real.mant_dig == 64 && test == 7681)
         {
diff --git a/libphobos/src/std/format/internal/write.d b/libphobos/src/std/format/internal/write.d
index 7f127c09847..8eb70eaa268 100644
--- a/libphobos/src/std/format/internal/write.d
+++ b/libphobos/src/std/format/internal/write.d
@@ -738,7 +738,7 @@  if (is(FloatingPointTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
         assert(FloatingPointControl.rounding == FloatingPointControl.roundToNearest);
     }
 
-    // issue 20320
+    // https://issues.dlang.org/show_bug.cgi?id=20320
     real a = 0.16;
     real b = 0.016;
     assert(format("%.1f", a) == "0.2");
@@ -749,7 +749,7 @@  if (is(FloatingPointTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
     assert(format("%.1f", a1) == "0.2");
     assert(format("%.2f", b1) == "0.02");
 
-    // issue 9889
+    // https://issues.dlang.org/show_bug.cgi?id=9889
     assert(format("%.1f", 0.09) == "0.1");
     assert(format("%.1f", -0.09) == "-0.1");
     assert(format("%.1f", 0.095) == "0.1");
@@ -907,7 +907,7 @@  if (is(FloatingPointTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
 
     // log2 is broken for x87-reals on some computers in CTFE
     // the following test excludes these computers from the test
-    // (issue 21757)
+    // (https://issues.dlang.org/show_bug.cgi?id=21757)
     enum test = cast(int) log2(3.05e2312L);
     static if (real.mant_dig == 64 && test == 7681) // 80 bit reals
     {
@@ -3334,7 +3334,7 @@  if (isSomeString!T1 && isSomeString!T2 && isSomeString!T3 && isSomeString!T4)
     long fractsWidth = fracts.length; // TODO: does not take graphemes into account
     long suffixWidth;
 
-    // TODO: remove this workaround which hides issue 21815
+    // TODO: remove this workaround which hides https://issues.dlang.org/show_bug.cgi?id=21815
     if (f.width > 0)
     {
         prefixWidth = getWidth(prefix);
diff --git a/libphobos/src/std/math/operations.d b/libphobos/src/std/math/operations.d
index f2e18005e25..4bf19ee3da9 100644
--- a/libphobos/src/std/math/operations.d
+++ b/libphobos/src/std/math/operations.d
@@ -1287,11 +1287,12 @@  bool isClose(T, U, V = CommonType!(FloatingPointBaseType!T,FloatingPointBaseType
         // two numbers
         if (lhs == rhs) return true;
 
-        static if (is(typeof(lhs.infinity)) && is(typeof(rhs.infinity)))
-        {
-            if (lhs == lhs.infinity || rhs == rhs.infinity ||
-                lhs == -lhs.infinity || rhs == -rhs.infinity) return false;
-        }
+        static if (is(typeof(lhs.infinity)))
+            if (lhs == lhs.infinity || lhs == -lhs.infinity)
+                 return false;
+        static if (is(typeof(rhs.infinity)))
+            if (rhs == rhs.infinity || rhs == -rhs.infinity)
+                return false;
 
         import std.math.algebraic : abs;
 
@@ -1406,6 +1407,8 @@  bool isClose(T, U, V = CommonType!(FloatingPointBaseType!T,FloatingPointBaseType
     assert(!isClose(1,real.nan));
     assert(!isClose(real.nan,real.max));
     assert(!isClose(real.nan,real.nan));
+
+    assert(!isClose(-double.infinity, 1));
 }
 
 @safe pure nothrow @nogc unittest
@@ -1950,7 +1953,7 @@  if (isFloatingPoint!T)
 
     // log2 is broken for x87-reals on some computers in CTFE
     // the following test excludes these computers from the test
-    // (issue 21757)
+    // (https://issues.dlang.org/show_bug.cgi?id=21757)
     enum test = cast(int) log2(3.05e2312L);
     static if (F.realFormat == RealFormat.ieeeExtended && test == 7681)
     {
diff --git a/libphobos/src/std/path.d b/libphobos/src/std/path.d
index e81f2b6b855..449235a6820 100644
--- a/libphobos/src/std/path.d
+++ b/libphobos/src/std/path.d
@@ -1595,7 +1595,7 @@  if (isSomeChar!C)
 
 @safe unittest
 {
-    // Test for issue 7397
+    // Test for https://issues.dlang.org/show_bug.cgi?id=7397
     string[] ary = ["a", "b"];
     version (Posix)
     {
@@ -1875,7 +1875,7 @@  if (isSomeChar!C)
 
 @safe unittest
 {
-    // Test for issue 7397
+    // Test for https://issues.dlang.org/show_bug.cgi?id=7397
     string[] ary = ["a", "b"];
     version (Posix)
     {
@@ -2745,7 +2745,7 @@  else version (Posix)
     See_Also:
         $(LREF asAbsolutePath) which does not allocate
 */
-string absolutePath(string path, lazy string base = getcwd())
+string absolutePath(return scope const string path, lazy string base = getcwd())
     @safe pure
 {
     import std.array : array;
@@ -2792,6 +2792,19 @@  string absolutePath(string path, lazy string base = getcwd())
     assertThrown(absolutePath("bar", "foo"));
 }
 
+// Ensure that we can call absolute path with scope paramaters
+@safe unittest
+{
+    string testAbsPath(scope const string path, scope const string base) {
+        return absolutePath(path, base);
+    }
+
+    version (Posix)
+        assert(testAbsPath("some/file", "/foo/bar")  == "/foo/bar/some/file");
+    version (Windows)
+        assert(testAbsPath(`some\file`, `c:\foo\bar`)    == `c:\foo\bar\some\file`);
+}
+
 /** Transforms `path` into an absolute path.
 
     The following algorithm is used:
@@ -3559,7 +3572,8 @@  if (isConvertibleToString!Range)
     assert(!globMatch("foo.bar", "[gh]???bar"));
     assert(!globMatch("foo.bar"w, "[!fg]*bar"w));
     assert(!globMatch("foo.bar"d, "[fg]???baz"d));
-    assert(!globMatch("foo.di", "*.d")); // test issue 6634: triggered bad assertion
+    // https://issues.dlang.org/show_bug.cgi?id=6634
+    assert(!globMatch("foo.di", "*.d")); // triggered bad assertion
 
     assert(globMatch("foo.bar", "{foo,bif}.bar"));
     assert(globMatch("bif.bar"w, "{foo,bif}.bar"w));
diff --git a/libphobos/src/std/random.d b/libphobos/src/std/random.d
index 066ed1713e2..87e63f3f6ee 100644
--- a/libphobos/src/std/random.d
+++ b/libphobos/src/std/random.d
@@ -2842,7 +2842,7 @@  auto ref choice(Range)(ref Range range)
            "Choice did not return a valid element from the given Range");
 }
 
-@safe unittest // issue 18631
+@safe unittest // https://issues.dlang.org/show_bug.cgi?id=18631
 {
     auto rng = MinstdRand0(42);
     const a = [0,1,2];
@@ -2855,7 +2855,7 @@  auto ref choice(Range)(ref Range range)
     auto z1 = choice(cast(const)[1, 2, 3], rng);
 }
 
-@safe unittest // Ref range (issue 18631 PR)
+@safe unittest // Ref range (https://issues.dlang.org/show_bug.cgi?id=18631 PR)
 {
     struct TestRange
     {
diff --git a/libphobos/src/std/range/package.d b/libphobos/src/std/range/package.d
index d37c6416434..191ec32cf4b 100644
--- a/libphobos/src/std/range/package.d
+++ b/libphobos/src/std/range/package.d
@@ -3902,24 +3902,17 @@  Returns:
 struct Repeat(T)
 {
 private:
-    //Store a non-qualified T when possible: This is to make Repeat assignable
-    static if ((is(T == class) || is(T == interface)) && (is(T == const) || is(T == immutable)))
-    {
-        import std.typecons : Rebindable;
-        alias UT = Rebindable!T;
-    }
-    else static if (is(T : Unqual!T) && is(Unqual!T : T))
-        alias UT = Unqual!T;
-    else
-        alias UT = T;
-    UT _value;
+    import std.typecons : Rebindable2;
+
+    // Store a rebindable T to make Repeat assignable.
+    Rebindable2!T _value;
 
 public:
     /// Range primitives
-    @property inout(T) front() inout { return _value; }
+    @property inout(T) front() inout { return _value.get; }
 
     /// ditto
-    @property inout(T) back() inout { return _value; }
+    @property inout(T) back() inout { return _value.get; }
 
     /// ditto
     enum bool empty = false;
@@ -3934,7 +3927,7 @@  public:
     @property auto save() inout { return this; }
 
     /// ditto
-    inout(T) opIndex(size_t) inout { return _value; }
+    inout(T) opIndex(size_t) inout { return _value.get; }
 
     /// ditto
     auto opSlice(size_t i, size_t j)
@@ -3959,7 +3952,12 @@  public:
 }
 
 /// Ditto
-Repeat!T repeat(T)(T value) { return Repeat!T(value); }
+Repeat!T repeat(T)(T value)
+{
+    import std.typecons : Rebindable2;
+
+    return Repeat!T(Rebindable2!T(value));
+}
 
 ///
 pure @safe nothrow unittest
@@ -9144,7 +9142,7 @@  public:
         {
             static if (needsEndTracker)
             {
-                if (poppedElems < windowSize)
+                if (nextSource.empty)
                     hasShownPartialBefore = true;
             }
             else
@@ -10124,6 +10122,15 @@  public:
     assert("ab cd".splitter(' ').slide!(No.withPartial)(2).equal!equal([["ab", "cd"]]));
 }
 
+// https://issues.dlang.org/show_bug.cgi?id=23976
+@safe unittest
+{
+    import std.algorithm.comparison : equal;
+    import std.algorithm.iteration : splitter;
+
+    assert("1<2".splitter('<').slide(2).equal!equal([["1", "2"]]));
+}
+
 private struct OnlyResult(Values...)
 if (Values.length > 1)
 {
@@ -10339,7 +10346,7 @@  if (!is(CommonType!Values == void))
 /// ditto
 auto only()()
 {
-    // cannot use noreturn due to issue 22383
+    // cannot use noreturn due to https://issues.dlang.org/show_bug.cgi?id=22383
     struct EmptyElementType {}
     EmptyElementType[] result;
     return result;
diff --git a/libphobos/src/std/regex/internal/ir.d b/libphobos/src/std/regex/internal/ir.d
index ec0cb66631e..3b38f9c9fbc 100644
--- a/libphobos/src/std/regex/internal/ir.d
+++ b/libphobos/src/std/regex/internal/ir.d
@@ -49,10 +49,29 @@  CharMatcher[CodepointSet] matcherCache;
     }
 }
 
-@property ref wordMatcher()()
+// Force pure because that is needed
+// Templated so that we don't pull in std.uni wordCharacter unnecessarily.
+@property ref wordMatcher()() pure
 {
-    static immutable CharMatcher matcher = CharMatcher(wordCharacter);
-    return matcher;
+    static auto actual()
+    {
+        static CharMatcher matcher;
+        static bool haveMatcher;
+
+        if (!haveMatcher)
+        {
+            matcher = CharMatcher(wordCharacter);
+            haveMatcher = true;
+        }
+
+        return &matcher;
+    }
+
+    // WORKAROUND: if the compiler won't memoize the output of the function for us,
+    //  we'll do it with pure and there will be casts and it'll be happy about it.
+    // This is unfortunately needed to make std.regex as a whole faster to import & use
+    //  in build times ~500ms.
+    return *(cast(immutable(CharMatcher)* function() @safe nothrow @nogc pure)&actual)();
 }
 
 // some special Unicode white space characters
diff --git a/libphobos/src/std/signals.d b/libphobos/src/std/signals.d
index e5dc67eb83d..97004d52ddd 100644
--- a/libphobos/src/std/signals.d
+++ b/libphobos/src/std/signals.d
@@ -624,7 +624,7 @@  void linkin() { }
     a.value6 = 46;
 }
 
-// Triggers bug from issue 15341
+// Triggers bug from https://issues.dlang.org/show_bug.cgi?id=15341
 @system unittest
 {
     class Observer
@@ -666,7 +666,7 @@  version (none) // Disabled because of https://issues.dlang.org/show_bug.cgi?id=5
     }
 }
 
-// Triggers bug from issue 16249
+// Triggers bug from https://issues.dlang.org/show_bug.cgi?id=16249
 @system unittest
 {
     class myLINE
diff --git a/libphobos/src/std/stdio.d b/libphobos/src/std/stdio.d
index 5ed685fe7fc..19ce9880b89 100644
--- a/libphobos/src/std/stdio.d
+++ b/libphobos/src/std/stdio.d
@@ -34,9 +34,17 @@  $(TR $(TD Misc) $(TD
 ))
 ))
 
-Standard I/O functions that extend $(B core.stdc.stdio).  $(B core.stdc.stdio)
+Standard I/O functions that extend $(LINK2 https://dlang.org/phobos/core_stdc_stdio.html, core.stdc.stdio).  $(B core.stdc.stdio)
 is $(D_PARAM public)ally imported when importing $(B std.stdio).
 
+There are three layers of I/O:
+$(OL
+$(LI The lowest layer is the operating system layer. The two main schemes are Windows and Posix.)
+$(LI C's $(TT stdio.h) which unifies the two operating system schemes.)
+$(LI $(TT std.stdio), this module, unifies the various $(TT stdio.h) implementations into
+a high level package for D programs.)
+)
+
 Source: $(PHOBOSSRC std/stdio.d)
 Copyright: Copyright The D Language Foundation 2007-.
 License:   $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
@@ -48,6 +56,55 @@  CSTDIO=$(HTTP cplusplus.com/reference/cstdio/$1/, $1)
  */
 module std.stdio;
 
+/*
+# Glossary
+
+The three layers have many terms for their data structures and types.
+Here we try to bring some sanity to them for the intrepid code spelunker.
+
+## Windows
+
+Handle
+
+        A Windows handle is an opaque object of type HANDLE.
+        The `HANDLE` for standard devices can be retrieved with
+        Windows `GetStdHandle()`.
+
+## Posix
+
+file descriptor, aka fileno, aka fildes
+
+        An int from 0..`FOPEN_MAX`, which is an index into some internal data
+        structure.
+        0 is for `stdin`, 1 for `stdout`, 2 for `stderr`.
+        Negative values usually indicate an error.
+
+## stdio.h
+
+`FILE`
+
+        A struct that encapsulates the C library's view of the operating system
+        files. A `FILE` should only be referred to via a pointer.
+
+`fileno`
+
+        A field of `FILE` which is the Posix file descriptor for Posix systems, and
+        and an index into an array of file `HANDLE`s for Windows.
+        This array is how Posix behavior is emulated on Windows.
+        For Digital Mars C, that array is `__osfhnd[]`, and is initialized
+        at program start by the C runtime library.
+        In this module, they are typed as `fileno_t`.
+
+`stdin`, `stdout`, `stderr`
+
+        Global pointers to `FILE` representing standard input, output, and error streams.
+        Being global means there are synchronization issues when multiple threads
+        are doing I/O on the same streams.
+
+## std.stdio
+
+*/
+
 import core.stdc.stddef : wchar_t;
 public import core.stdc.stdio;
 import std.algorithm.mutation : copy;
@@ -129,6 +186,10 @@  else version (Solaris)
 {
     version = GENERIC_IO;
 }
+else
+{
+    static assert(0, "unsupported operating system");
+}
 
 // Character type used for operating system filesystem APIs
 version (Windows)
@@ -140,6 +201,7 @@  else
     private alias FSChar = char;
 }
 
+private alias fileno_t = int;   // file descriptor, fildes, fileno
 
 version (Windows)
 {
@@ -203,7 +265,7 @@  version (DIGITAL_MARS_STDIO)
     // @@@DEPRECATED_2.107@@@
     deprecated("internal function _fileno was unintentionally available from "
                ~ "std.stdio and will be removed afer 2.107")
-    int _fileno(FILE* f) { return f._file; }
+    fileno_t _fileno(FILE* f) { return f._file; }
 }
 else version (MICROSOFT_STDIO)
 {
@@ -550,7 +612,7 @@  Throws: `ErrnoException` if the file could not be opened.
                                 stdioOpenmode, "'")),
                 name);
 
-        // MSVCRT workaround (issue 14422)
+        // MSVCRT workaround (https://issues.dlang.org/show_bug.cgi?id=14422)
         version (MICROSOFT_STDIO)
         {
             setAppendWin(stdioOpenmode);
@@ -708,7 +770,7 @@  Throws: `ErrnoException` in case of error.
         {
             auto handle = _p.handle;
             _p.handle = null;
-            // fclose disassociates the FILE* even in case of error (issue 19751)
+            // fclose disassociates the FILE* even in case of error (https://issues.dlang.org/show_bug.cgi?id=19751)
             errnoEnforce(.fclose(handle) == 0,
                     "Could not close file `"~_name~"'");
         }
@@ -1140,7 +1202,7 @@  Throws: `ErrnoException` if the file is not opened or the call to `fread` fails.
         enforce(isOpen, "Attempting to read from an unopened file");
         version (Windows)
         {
-            immutable fd = .fileno(_p.handle);
+            immutable fileno_t fd = .fileno(_p.handle);
             immutable mode = .__setmode(fd, _O_BINARY);
             scope(exit) .__setmode(fd, mode);
             version (DIGITAL_MARS_STDIO)
@@ -1230,7 +1292,7 @@  Throws: `ErrnoException` if the file is not opened or if the call to `fwrite` fa
 
         version (Windows)
         {
-            immutable fd = .fileno(_p.handle);
+            immutable fileno_t fd = .fileno(_p.handle);
             immutable oldMode = .__setmode(fd, _O_BINARY);
 
             if (oldMode != _O_BINARY)
@@ -2287,7 +2349,7 @@  Returns the `FILE*` corresponding to this object.
 /**
 Returns the file number corresponding to this object.
  */
-    @property int fileno() const @trusted
+    @property fileno_t fileno() const @trusted
     {
         import std.exception : enforce;
 
@@ -3108,10 +3170,13 @@  is empty, throws an `Exception`. In case of an I/O error throws
                 // "wide-oriented" for us.
                 immutable int mode = __setmode(f.fileno, _O_TEXT);
                     // Set some arbitrary mode to obtain the previous one.
-                __setmode(f.fileno, mode); // Restore previous mode.
-                if (mode & (_O_WTEXT | _O_U16TEXT | _O_U8TEXT))
+                if (mode != -1) // __setmode() succeeded
                 {
-                    orientation_ = 1; // wide
+                    __setmode(f.fileno, mode); // Restore previous mode.
+                    if (mode & (_O_WTEXT | _O_U16TEXT | _O_U8TEXT))
+                    {
+                        orientation_ = 1; // wide
+                    }
                 }
             }
             else
@@ -3336,7 +3401,8 @@  is empty, throws an `Exception`. In case of an I/O error throws
 
         version (Windows)
         {
-            int fd, oldMode;
+            fileno_t fd;
+            int oldMode;
             version (DIGITAL_MARS_STDIO)
                 ubyte oldInfo;
         }
@@ -3795,7 +3861,7 @@  void main()
     assert(std.file.readText!string(deleteme) == "y");
 }
 
-@safe unittest // issue 18801
+@safe unittest // https://issues.dlang.org/show_bug.cgi?id=18801
 {
     static import std.file;
     import std.string : stripLeft;
diff --git a/libphobos/src/std/traits.d b/libphobos/src/std/traits.d
index 689f0aef809..4dc569df297 100644
--- a/libphobos/src/std/traits.d
+++ b/libphobos/src/std/traits.d
@@ -5337,7 +5337,7 @@  package template isBlitAssignable(T)
         enum isBlitAssignable = isBlitAssignable!(OriginalType!T);
     }
     else static if (isStaticArray!T && is(T == E[n], E, size_t n))
-    // Workaround for issue 11499 : isStaticArray!T should not be necessary.
+    // Workaround for https://issues.dlang.org/show_bug.cgi?id=11499 : isStaticArray!T should not be necessary.
     {
         enum isBlitAssignable = isBlitAssignable!E;
     }
@@ -8877,7 +8877,9 @@  template getSymbolsByUDA(alias symbol, alias attribute)
         @Attr void c();
     }
 
-    static assert(getSymbolsByUDA!(A, Attr).stringof == "tuple(a, a, c)");
+    alias ola = __traits(getOverloads, A, "a");
+    static assert(__traits(isSame, getSymbolsByUDA!(A, Attr),
+        AliasSeq!(ola[0], ola[1], A.c)));
 }
 
 // getSymbolsByUDA no longer works on modules
diff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d
index 0748d5251e0..67a1ede8148 100644
--- a/libphobos/src/std/typecons.d
+++ b/libphobos/src/std/typecons.d
@@ -2955,6 +2955,140 @@  Rebindable!T rebindable(T)(Rebindable!T obj)
     assert(rebindable(pr3341_aa)[321] == 543);
 }
 
+package(std) struct Rebindable2(T)
+{
+private:
+    static if (isAssignable!(typeof(cast() T.init)))
+    {
+        enum useQualifierCast = true;
+
+        typeof(cast() T.init) data;
+    }
+    else
+    {
+        enum useQualifierCast = false;
+
+        align(T.alignof)
+        static struct Payload
+        {
+            static if (hasIndirections!T)
+            {
+                void[T.sizeof] data;
+            }
+            else
+            {
+                ubyte[T.sizeof] data;
+            }
+        }
+
+        Payload data;
+    }
+
+public:
+
+    static if (!__traits(compiles, { T value; }))
+    {
+        @disable this();
+    }
+
+    /**
+     * Constructs a `Rebindable2` from a given value.
+     */
+    this(T value) @trusted
+    {
+        static if (useQualifierCast)
+        {
+            this.data = cast() value;
+        }
+        else
+        {
+            set(value);
+        }
+    }
+
+    /**
+     * Overwrites the currently stored value with `value`.
+     */
+    void opAssign(this This)(T value) @trusted
+    {
+        clear;
+        set(value);
+    }
+
+    /**
+     * Returns the value currently stored in the `Rebindable2`.
+     */
+    T get(this This)() @property @trusted
+    {
+        static if (useQualifierCast)
+        {
+            return cast(T) this.data;
+        }
+        else
+        {
+            return *cast(T*) &this.data;
+        }
+    }
+
+    /// Ditto
+    inout(T) get() inout @property @trusted
+    {
+        static if (useQualifierCast)
+        {
+            return cast(inout(T)) this.data;
+        }
+        else
+        {
+            return *cast(inout(T)*) &this.data;
+        }
+    }
+
+    static if (!useQualifierCast)
+    {
+        ~this() @trusted
+        {
+            clear;
+        }
+    }
+
+private:
+
+    void set(this This)(T value)
+    {
+        static if (useQualifierCast)
+        {
+            this.data = cast() value;
+        }
+        else
+        {
+            // As we're escaping a copy of `value`, deliberately leak a copy:
+            static union DontCallDestructor
+            {
+                T value;
+            }
+            DontCallDestructor copy = DontCallDestructor(value);
+            this.data = *cast(Payload*) &copy;
+        }
+    }
+
+    void clear(this This)()
+    {
+        // work around reinterpreting cast being impossible in CTFE
+        if (__ctfe)
+        {
+            return;
+        }
+
+        // call possible struct destructors
+        .destroy!(No.initialize)(*cast(T*) &this.data);
+    }
+}
+
+package(std) Rebindable2!T rebindable2(T)(T value)
+{
+    return Rebindable2!T(value);
+}
+
 /**
     Similar to `Rebindable!(T)` but strips all qualifiers from the reference as
     opposed to just constness / immutability. Primary intended use case is with
diff --git a/libphobos/src/std/uni/package.d b/libphobos/src/std/uni/package.d
index e2a0de73535..6ab6ba0f631 100644
--- a/libphobos/src/std/uni/package.d
+++ b/libphobos/src/std/uni/package.d
@@ -8592,7 +8592,7 @@  public:
     Decomposes a Hangul syllable. If `ch` is not a composed syllable
     then this function returns $(LREF Grapheme) containing only `ch` as is.
 */
-Grapheme decomposeHangul(dchar ch) @safe
+Grapheme decomposeHangul(dchar ch) nothrow pure @safe
 {
     immutable idxS = cast(int) ch - jamoSBase;
     if (idxS < 0 || idxS >= jamoSCount) return Grapheme(ch);
@@ -8709,7 +8709,15 @@  enum {
     In cases where the string in question is already normalized,
     it is returned unmodified and no memory allocation happens.
 +/
-inout(C)[] normalize(NormalizationForm norm=NFC, C)(return scope inout(C)[] input)
+/*
+    WARNING: @trusted lambda inside - handle with same care as @trusted
+        functions
+
+    Despite being a template, the attributes do no harm since this doesn't work
+    with user-defined range or character types anyway.
+*/
+pure @safe inout(C)[] normalize(NormalizationForm norm=NFC, C)
+    (return scope inout(C)[] input)
 {
     import std.algorithm.mutation : SwapStrategy;
     import std.algorithm.sorting : sort;
@@ -8790,20 +8798,24 @@  inout(C)[] normalize(NormalizationForm norm=NFC, C)(return scope inout(C)[] inpu
         // reset variables
         decomposed.length = 0;
         () @trusted {
-            decomposed.assumeSafeAppend();
+            // assumeSafeAppend isn't considered pure as of writing, hence the
+            // cast. It isn't pure in the sense that the elements after
+            // the array in question are affected, but we don't use those
+            // making the call pure for our purposes.
+            (cast(void delegate() pure nothrow) {decomposed.assumeSafeAppend();})();
             ccc.length = 0;
-            ccc.assumeSafeAppend();
+            (cast(void delegate() pure nothrow) {ccc.assumeSafeAppend();})();
         } ();
         input = input[anchors[1]..$];
         // and move on
         anchors = splitNormalized!norm(input);
-    }while (anchors[0] != input.length);
+    } while (anchors[0] != input.length);
     app.put(input[0 .. anchors[0]]);
     return () @trusted inout { return cast(inout(C)[]) app.data; } ();
 }
 
 ///
-@safe unittest
+@safe pure unittest
 {
     // any encoding works
     wstring greet = "Hello world";
@@ -8817,7 +8829,7 @@  inout(C)[] normalize(NormalizationForm norm=NFC, C)(return scope inout(C)[] inpu
     assert(normalize!NFKD("ϓ") == "\u03A5\u0301");
 }
 
-@safe unittest
+@safe pure unittest
 {
     import std.conv : text;
 
@@ -8825,18 +8837,9 @@  inout(C)[] normalize(NormalizationForm norm=NFC, C)(return scope inout(C)[] inpu
     assert(normalize!NFKD("2¹⁰") == "210", normalize!NFKD("2¹⁰"));
     assert(normalize!NFD("Äffin") == "A\u0308ffin");
 
-    // check example
-
-    // any encoding works
-    wstring greet = "Hello world";
+    // test with dstring
+    dstring greet = "Hello world";
     assert(normalize(greet) is greet); // the same exact slice
-
-    // An example of a character with all 4 forms being different:
-    // Greek upsilon with acute and hook symbol (code point 0x03D3)
-    assert(normalize!NFC("ϓ") == "\u03D3");
-    assert(normalize!NFD("ϓ") == "\u03D2\u0301");
-    assert(normalize!NFKC("ϓ") == "\u038E");
-    assert(normalize!NFKD("ϓ") == "\u03A5\u0301");
 }
 
 // canonically recompose given slice of code points, works in-place and mutates data