public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r11-7978] d: Merge upstream dmd 3b808e838, druntime 483bc129, phobos f89dc217a
@ 2021-04-03 23:27 Iain Buclaw
  0 siblings, 0 replies; only message in thread
From: Iain Buclaw @ 2021-04-03 23:27 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:5a0aa603b2452dca48ad86d97d4b918187d259fc

commit r11-7978-g5a0aa603b2452dca48ad86d97d4b918187d259fc
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Fri Apr 2 13:29:22 2021 +0200

    d: Merge upstream dmd 3b808e838, druntime 483bc129, phobos f89dc217a
    
    D front-end changes:
    
     - Explicit package visibility attribute is now always applied to
       introducing scopes.
    
     - Added `__traits(totype, string)' to convert mangled type string to an
       existing type.
    
     - Printf-like and scanf-like functions are now detected by prefixing
       them with `pragma(printf)' for printf-like functions or
       `pragma(scanf)' for scanf-like functions.
    
     - Added `__c_wchar_t', `__c_complex_float', `__c_complex_double', and
       `__c_complex_real' types for interfacing with C and C++.
    
     - Template alias parameters can now be instantiated with basic types,
       such as `int` or `void function()`.
    
     - Mixins can now be used as types in the form `mixin(string) var'.
    
     - Mixin expressions can take an argument list, same as `pragma(msg)'.
    
     - Implement DIP1034, add `typeof(*null)' types to represent `noreturn'.
    
     - `pragma(msg)' can print expressions of type `void'.
    
     - It is now an error to use private variables selectively imported from
       other modules.  Due to a bug, some imported private members were
       visible from other modules, violating the specification.
    
     - Added new syntax to declare an alias to a function type using the
       `alias' syntax based on the assignment operator.
    
     - Function literals can now return a value by reference.
    
    Phobos changes:
    
     - Synchronize C bindings with the latest port fixes in upstream druntime.
    
     - Added alias for a `noreturn' type in object.d
    
     - Make use of the new `pragma(printf)' and `pragma(scanf)' pragmas, fix
       all code that got flagged as being incorrect.
    
     - Fixed code that relied on bugs in the D import package system.
    
    Reviewed-on: https://github.com/dlang/dmd/pull/12339
                 https://github.com/dlang/druntime/pull/3422
                 https://github.com/dlang/phobos/pull/7932
    
    gcc/d/ChangeLog:
    
            * dmd/MERGE: Merge upstream dmd 3b808e838.
            * Make-lang.in (D_FRONTEND_OBJS): Add d/chkformat.o.
            * d-codegen.cc (build_struct_literal): Handle special enums.
            * d-convert.cc (convert_expr): Handle noreturn type.
            (convert_for_condition): Likewise.
            * d-target.cc (Target::_init): Set type for wchar_t.
            (TargetCPP::derivedClassOffset): New method.
            (Target::libraryObjectMonitors): New method.
            * decl.cc (get_symbol_decl): Set TREE_THIS_VOLATILE for functions of
            type noreturn.
            * toir.cc (IRVisitor::visit (ReturnStatement *)): Handle returning
            noreturn types.
            * types.cc (TypeVisitor::visit (TypeNoreturn *)): New method.
            (TypeVisitor::visit (TypeEnum *)): Handle special enums.
    
    libphobos/ChangeLog:
    
            * libdruntime/MERGE: Merge upstream druntime 483bc129.
            * libdruntime/Makefile.am (DRUNTIME_DSOURCES_DARWIN): Add
            core/sys/darwin/fcntl.d.
            (DRUNTIME_DSOURCES_OPENBSD): Add core/sys/openbsd/unistd.d.
            (DRUNTIME_DSOURCES_WINDOWS): Add core/sys/windows/stdc/malloc.d.
            * libdruntime/Makefile.in: Regenerate.
            * src/MERGE: Merge upstream phobos f89dc217a.
            * src/Makefile.am (PHOBOS_DSOURCES): Add std/regex/internal/tests2.d.
            * src/Makefile.in: Regenerate.
            * testsuite/libphobos.exceptions/chain.d: Fix format arguments.
            * testsuite/libphobos.exceptions/line_trace.d: Likewise.

Diff:
---
 gcc/d/Make-lang.in                                 |    1 +
 gcc/d/d-codegen.cc                                 |    8 +
 gcc/d/d-convert.cc                                 |   14 +-
 gcc/d/d-target.cc                                  |   28 +
 gcc/d/decl.cc                                      |    4 +
 gcc/d/dmd/MERGE                                    |    2 +-
 gcc/d/dmd/attrib.c                                 |   39 +-
 gcc/d/dmd/attrib.h                                 |    4 +-
 gcc/d/dmd/blockexit.c                              |    2 +
 gcc/d/dmd/chkformat.c                              |  975 +++++++++
 gcc/d/dmd/cppmangle.c                              |   18 +-
 gcc/d/dmd/ctfeexpr.c                               |    2 +-
 gcc/d/dmd/dcast.c                                  |    5 +-
 gcc/d/dmd/dclass.c                                 |   20 +-
 gcc/d/dmd/declaration.h                            |    4 +-
 gcc/d/dmd/denum.c                                  |   19 +-
 gcc/d/dmd/dimport.c                                |   80 +-
 gcc/d/dmd/dmangle.c                                |   37 +-
 gcc/d/dmd/dmodule.c                                |   33 +-
 gcc/d/dmd/dscope.c                                 |    6 +-
 gcc/d/dmd/dsymbol.c                                |   32 +-
 gcc/d/dmd/dsymbol.h                                |    3 +-
 gcc/d/dmd/dsymbolsem.c                             |  139 +-
 gcc/d/dmd/dtemplate.c                              |  210 +-
 gcc/d/dmd/expression.c                             | 2218 ++------------------
 gcc/d/dmd/expression.h                             |    9 +-
 gcc/d/dmd/expressionsem.c                          | 2091 +++++++++++++++++-
 gcc/d/dmd/func.c                                   |   18 +-
 gcc/d/dmd/hdrgen.c                                 |   57 +-
 gcc/d/dmd/hdrgen.h                                 |    1 +
 gcc/d/dmd/idgen.c                                  |    8 +-
 gcc/d/dmd/import.h                                 |    1 +
 gcc/d/dmd/module.h                                 |    1 +
 gcc/d/dmd/mtype.c                                  |  282 ++-
 gcc/d/dmd/mtype.h                                  |   38 +-
 gcc/d/dmd/parse.c                                  |  217 +-
 gcc/d/dmd/parse.h                                  |    1 +
 gcc/d/dmd/scope.h                                  |    4 +
 gcc/d/dmd/semantic2.c                              |   20 +
 gcc/d/dmd/semantic3.c                              |   34 +-
 gcc/d/dmd/statement.c                              |   36 +-
 gcc/d/dmd/statement.h                              |    3 +-
 gcc/d/dmd/statementsem.c                           |    2 +-
 gcc/d/dmd/target.h                                 |    4 +
 gcc/d/dmd/template.h                               |    1 +
 gcc/d/dmd/templateparamsem.c                       |    2 +-
 gcc/d/dmd/traits.c                                 |  103 +-
 gcc/d/dmd/typesem.c                                |   77 +-
 gcc/d/dmd/visitor.h                                |    4 +
 gcc/d/toir.cc                                      |    7 +
 gcc/d/types.cc                                     |   47 +-
 gcc/testsuite/gdc.test/compilable/bug20796.d       |    2 +
 gcc/testsuite/gdc.test/compilable/cppmangle.d      |   18 +
 gcc/testsuite/gdc.test/compilable/ddocunittest.d   |    1 +
 .../extra-files/serenity7190/core/Controller.d     |    8 +-
 .../gdc.test/compilable/extra-files/test20280a.d   |   12 +
 gcc/testsuite/gdc.test/compilable/fix21585.d       |   24 +
 gcc/testsuite/gdc.test/compilable/fix21647.d       |   30 +
 gcc/testsuite/gdc.test/compilable/ice10598.d       |    3 -
 .../gdc.test/compilable/imports/issue21614a.d      |   22 +
 .../gdc.test/compilable/imports/pkg20537/package.d |    0
 .../gdc.test/compilable/imports/test17991a/a.d     |    0
 .../compilable/imports/test17991a/package.d        |    0
 .../gdc.test/compilable/imports/test20151a/b/c/c.d |    0
 .../gdc.test/compilable/imports/test20530a.d       |    0
 .../gdc.test/compilable/imports/test21501b.d       |    7 +
 .../gdc.test/compilable/imports/test21501c.d       |    4 +
 gcc/testsuite/gdc.test/compilable/issue16020.d     |   39 +
 gcc/testsuite/gdc.test/compilable/issue21614.d     |   10 +
 gcc/testsuite/gdc.test/compilable/issue21726.d     |    2 +
 gcc/testsuite/gdc.test/compilable/mixintype.d      |   55 +
 gcc/testsuite/gdc.test/compilable/mixintype2.d     |   68 +
 gcc/testsuite/gdc.test/compilable/noreturn1.d      |   21 +
 .../compilable/protection/issue20796/package.d     |    5 +
 .../protection/issue21726/format/package.d         |    7 +
 .../compilable/protection/issue21726/package.d     |    1 +
 .../compilable/protection/issue21726/typecons.d    |    6 +
 gcc/testsuite/gdc.test/compilable/test16002.d      |    3 +
 gcc/testsuite/gdc.test/compilable/test17991.d      |    3 +
 gcc/testsuite/gdc.test/compilable/test19292.d      |   15 +
 gcc/testsuite/gdc.test/compilable/test20151a.d     |    3 +
 gcc/testsuite/gdc.test/compilable/test20280.d      |    8 +
 gcc/testsuite/gdc.test/compilable/test20530.d      |   46 +
 gcc/testsuite/gdc.test/compilable/test20537.d      |   10 +
 gcc/testsuite/gdc.test/compilable/test20692.d      |   18 +
 gcc/testsuite/gdc.test/compilable/test21501a.d     |   19 +
 gcc/testsuite/gdc.test/compilable/test9029.d       |   39 +
 gcc/testsuite/gdc.test/fail_compilation/bug15613.d |   18 +
 gcc/testsuite/gdc.test/fail_compilation/bug16165.d |   18 +
 gcc/testsuite/gdc.test/fail_compilation/bug9631.d  |  100 +
 .../gdc.test/fail_compilation/chkformat.d          |  139 ++
 .../gdc.test/fail_compilation/cppmangle.d          |    2 +-
 .../gdc.test/fail_compilation/diag11819b.d         |    2 +-
 .../gdc.test/fail_compilation/diag13082.d          |    6 +-
 .../gdc.test/fail_compilation/diag16271.d          |   12 +
 gcc/testsuite/gdc.test/fail_compilation/diag8101.d |   47 +-
 .../gdc.test/fail_compilation/diag8101b.d          |   17 +-
 gcc/testsuite/gdc.test/fail_compilation/diag9420.d |    3 +-
 .../gdc.test/fail_compilation/fail11038.d          |   17 +
 .../gdc.test/fail_compilation/fail11445.d          |    2 +-
 .../gdc.test/fail_compilation/fail15361.d          |    8 +
 .../gdc.test/fail_compilation/fail15896.d          |   18 +
 .../gdc.test/fail_compilation/fail17630.d          |   15 +
 .../gdc.test/fail_compilation/fail18219.d          |   20 +
 .../gdc.test/fail_compilation/fail19107.d          |   21 +
 gcc/testsuite/gdc.test/fail_compilation/fail263.d  |    3 +-
 gcc/testsuite/gdc.test/fail_compilation/fail3.d    |    3 +-
 gcc/testsuite/gdc.test/fail_compilation/fail322.d  |    7 +-
 gcc/testsuite/gdc.test/fail_compilation/fail332.d  |   45 +-
 gcc/testsuite/gdc.test/fail_compilation/fail347.d  |    2 +-
 gcc/testsuite/gdc.test/fail_compilation/fail53.d   |    3 +-
 gcc/testsuite/gdc.test/fail_compilation/fail55.d   |    3 +-
 gcc/testsuite/gdc.test/fail_compilation/fail79.d   |    2 +-
 gcc/testsuite/gdc.test/fail_compilation/fail99.d   |    3 +-
 gcc/testsuite/gdc.test/fail_compilation/fix21585.d |   19 +
 gcc/testsuite/gdc.test/fail_compilation/format.d   |   44 +
 gcc/testsuite/gdc.test/fail_compilation/ice10598.d |   10 +
 gcc/testsuite/gdc.test/fail_compilation/ice10922.d |    3 +-
 gcc/testsuite/gdc.test/fail_compilation/ice12497.d |   18 -
 gcc/testsuite/gdc.test/fail_compilation/ice12501.d |    8 +-
 gcc/testsuite/gdc.test/fail_compilation/ice14907.d |   22 +
 gcc/testsuite/gdc.test/fail_compilation/ice14923.d |    5 +-
 gcc/testsuite/gdc.test/fail_compilation/ice8255.d  |    5 +-
 gcc/testsuite/gdc.test/fail_compilation/ice9540.d  |    5 +-
 .../gdc.test/fail_compilation/imports/a17630.d     |    3 +
 .../gdc.test/fail_compilation/imports/a18219.d     |    6 +
 .../gdc.test/fail_compilation/imports/b17630.d     |    3 +
 .../gdc.test/fail_compilation/imports/b18219.d     |   15 +
 .../imports/ice10598a.d                            |    0
 .../imports/ice10598b.d                            |    0
 .../gdc.test/fail_compilation/imports/imp15896.d   |    4 +
 .../gdc.test/fail_compilation/imports/test21651b.d |    3 +
 .../gdc.test/fail_compilation/issue16020.d         |   13 +
 .../gdc.test/fail_compilation/mixintype2.d         |   16 +
 .../gdc.test/fail_compilation/test16002.d          |   15 -
 .../gdc.test/fail_compilation/test21651.d          |   11 +
 .../gdc.test/fail_compilation/warn12809.d          |   41 +
 gcc/testsuite/gdc.test/runnable/funclit.d          |   61 +
 gcc/testsuite/gdc.test/runnable/mangle.d           |    6 +
 gcc/testsuite/gdc.test/runnable/noreturn1.d        |   74 +
 gcc/testsuite/gdc.test/runnable_cxx/cppa.d         |   29 +-
 .../gdc.test/runnable_cxx/extra-files/cppb.cpp     |    4 +
 .../runnable_cxx/extra-files/test21515.cpp         |   82 +
 gcc/testsuite/gdc.test/runnable_cxx/test21515.d    |  104 +
 libphobos/libdruntime/MERGE                        |    2 +-
 libphobos/libdruntime/Makefile.am                  |   58 +-
 libphobos/libdruntime/Makefile.in                  |  105 +-
 libphobos/libdruntime/core/stdc/complex.d          |   70 +-
 libphobos/libdruntime/core/stdc/config.d           |   43 +
 libphobos/libdruntime/core/stdc/errno.d            |   16 +-
 libphobos/libdruntime/core/stdc/math.d             |  400 ++--
 libphobos/libdruntime/core/stdc/stdio.d            |   61 +-
 libphobos/libdruntime/core/stdc/stdlib.d           |    6 +-
 libphobos/libdruntime/core/stdc/tgmath.d           |  653 +++---
 libphobos/libdruntime/core/stdc/wchar_.d           |    9 +-
 libphobos/libdruntime/core/sys/darwin/fcntl.d      |   20 +
 libphobos/libdruntime/core/sys/linux/epoll.d       |   88 +-
 libphobos/libdruntime/core/sys/openbsd/string.d    |    2 +
 libphobos/libdruntime/core/sys/openbsd/unistd.d    |   17 +
 libphobos/libdruntime/core/sys/posix/config.d      |    1 +
 libphobos/libdruntime/core/sys/posix/dlfcn.d       |   11 +-
 libphobos/libdruntime/core/sys/posix/signal.d      |   14 +-
 libphobos/libdruntime/core/sys/posix/unistd.d      |   48 +
 libphobos/libdruntime/core/sys/windows/com.d       |   20 +-
 libphobos/libdruntime/core/sys/windows/dll.d       |   12 +-
 .../libdruntime/core/sys/windows/stdc/malloc.d     |   26 +
 libphobos/libdruntime/gc/impl/conservative/gc.d    |    4 +-
 libphobos/libdruntime/object.d                     |    7 +-
 libphobos/src/MERGE                                |    2 +-
 libphobos/src/Makefile.am                          |   12 +-
 libphobos/src/Makefile.in                          |   14 +-
 libphobos/src/std/algorithm/iteration.d            |    8 +-
 libphobos/src/std/algorithm/searching.d            |    4 +-
 libphobos/src/std/container/rbtree.d               |    4 +-
 libphobos/src/std/conv.d                           |    2 +-
 libphobos/src/std/datetime/systime.d               |    4 +-
 libphobos/src/std/experimental/logger/nulllogger.d |    2 +-
 libphobos/src/std/experimental/typecons.d          |    6 +-
 libphobos/src/std/file.d                           |    5 +-
 libphobos/src/std/format.d                         |    4 +-
 libphobos/src/std/internal/math/biguintcore.d      |    4 +-
 libphobos/src/std/math.d                           |    4 +-
 libphobos/src/std/parallelism.d                    |    4 +-
 libphobos/src/std/range/package.d                  |    1 -
 libphobos/src/std/regex/internal/tests.d           |  653 +-----
 libphobos/src/std/regex/internal/tests2.d          |  662 ++++++
 libphobos/src/std/socket.d                         |    2 +-
 libphobos/src/std/typecons.d                       |   10 +-
 libphobos/src/std/zip.d                            |    6 +-
 libphobos/testsuite/libphobos.exceptions/chain.d   |    4 +-
 .../testsuite/libphobos.exceptions/line_trace.d    |    2 +-
 191 files changed, 7657 insertions(+), 4100 deletions(-)

diff --git a/gcc/d/Make-lang.in b/gcc/d/Make-lang.in
index 75857d81ec7..b3c77a08f46 100644
--- a/gcc/d/Make-lang.in
+++ b/gcc/d/Make-lang.in
@@ -64,6 +64,7 @@ D_FRONTEND_OBJS = \
 	d/blockexit.o \
 	d/canthrow.o \
 	d/checkedint.o \
+	d/chkformat.o \
 	d/clone.o \
 	d/cond.o \
 	d/constfold.o \
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 5e6f240cb90..608abcd94f5 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -1153,6 +1153,14 @@ build_struct_literal (tree type, vec <constructor_elt, va_gc> *init)
   if (vec_safe_is_empty (init))
     return build_constructor (type, NULL);
 
+  /* Struct literals can be seen for special enums representing `_Complex',
+     make sure to reinterpret the literal as the correct type.  */
+  if (COMPLEX_FLOAT_TYPE_P (type))
+    {
+      gcc_assert (vec_safe_length (init) == 2);
+      return build_complex (type, (*init)[0].value, (*init)[1].value);
+    }
+
   vec <constructor_elt, va_gc> *ve = NULL;
   HOST_WIDE_INT offset = 0;
   bool constant_p = true;
diff --git a/gcc/d/d-convert.cc b/gcc/d/d-convert.cc
index f407a46da6e..3073edaae9f 100644
--- a/gcc/d/d-convert.cc
+++ b/gcc/d/d-convert.cc
@@ -559,7 +559,9 @@ convert_expr (tree exp, Type *etype, Type *totype)
       break;
 
     case Tnull:
-      /* Casting from typeof(null) is represented as all zeros.  */
+    case Tnoreturn:
+      /* Casting from `typeof(null)' for `null' expressions, or `typeof(*null)'
+	 for `noreturn' expressions is represented as all zeros.  */
       result = build_typeof_null_value (totype);
 
       /* Make sure the expression is still evaluated if necessary.  */
@@ -742,6 +744,16 @@ convert_for_condition (tree expr, Type *type)
 	break;
       }
 
+    case Tnoreturn:
+      /* Front-end allows conditionals that never return, represent the
+	 conditional result value as all zeros.  */
+      result = build_zero_cst (d_bool_type);
+
+      /* Make sure the expression is still evaluated if necessary.  */
+      if (TREE_SIDE_EFFECTS (expr))
+	result = compound_expr (expr, result);
+      break;
+
     default:
       result = expr;
       break;
diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc
index d50fcef22e2..a1dc2ee286f 100644
--- a/gcc/d/d-target.cc
+++ b/gcc/d/d-target.cc
@@ -164,6 +164,15 @@ Target::_init (const Param &)
   this->c.longsize = int_size_in_bytes (long_integer_type_node);
   this->c.long_doublesize = int_size_in_bytes (long_double_type_node);
 
+  /* Define what type to use for wchar_t.  We don't want to support wide
+     characters less than "short" in D.  */
+  if (WCHAR_TYPE_SIZE == 32)
+    this->c.twchar_t = Type::basic[Tdchar];
+  else if (WCHAR_TYPE_SIZE == 16)
+    this->c.twchar_t = Type::basic[Twchar];
+  else
+    sorry ("D does not support wide characters on this target.");
+
   /* Set-up target C++ ABI.  */
   this->cpp.reverseOverloads = false;
   this->cpp.exceptions = true;
@@ -417,6 +426,15 @@ TargetCPP::fundamentalType (const Type *, bool &)
   return false;
 }
 
+/* Get the starting offset position for fields of an `extern(C++)` class
+   that is derived from the given BASE_CLASS.  */
+
+unsigned
+TargetCPP::derivedClassOffset(ClassDeclaration *base_class)
+{
+  return base_class->structsize;
+}
+
 /* Return the default system linkage for the target.  */
 
 LINK
@@ -517,3 +535,13 @@ Target::getTargetInfo (const char *key, const Loc &loc)
 
   return NULL;
 }
+
+/**
+ * Returns true if the implementation for object monitors is always defined
+ * in the D runtime library (rt/monitor_.d).  */
+
+bool
+Target::libraryObjectMonitors (FuncDeclaration *, Statement *)
+{
+  return true;
+}
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index 042abbfc48a..0ec19345272 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -1277,6 +1277,10 @@ get_symbol_decl (Declaration *decl)
       if (decl->storage_class & STCfinal)
 	DECL_FINAL_P (decl->csym) = 1;
 
+      /* Function is of type `noreturn' or `typeof(*null)'.  */
+      if (fd->type->nextOf ()->ty == Tnoreturn)
+	TREE_THIS_VOLATILE (decl->csym) = 1;
+
       /* Check whether this function is expanded by the frontend.  */
       DECL_INTRINSIC_CODE (decl->csym) = INTRINSIC_NONE;
       maybe_set_intrinsic (fd);
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 78b454c1c64..86475c80d35 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-a3c9bf422e7ff54d45846b8c577ee82da4234db1
+3b808e838bb00f527eb4ed5281cd985756237b8f
 
 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/attrib.c b/gcc/d/dmd/attrib.c
index 56b8ce816be..a808b8a6c3f 100644
--- a/gcc/d/dmd/attrib.c
+++ b/gcc/d/dmd/attrib.c
@@ -80,8 +80,8 @@ Scope *AttribDeclaration::createNewScope(Scope *sc,
     if (stc != sc->stc ||
         linkage != sc->linkage ||
         cppmangle != sc->cppmangle ||
-        !protection.isSubsetOf(sc->protection) ||
         explicitProtection != sc->explicitProtection ||
+        !(protection == sc->protection) ||
         aligndecl != sc->aligndecl ||
         inlining != sc->inlining)
     {
@@ -552,10 +552,21 @@ void ProtDeclaration::addMember(Scope *sc, ScopeDsymbol *sds)
     if (protection.kind == Prot::package_ && protection.pkg && sc->_module)
     {
         Module *m = sc->_module;
-        Package* pkg = m->parent ? m->parent->isPackage() : NULL;
-        if (!pkg || !protection.pkg->isAncestorPackageOf(pkg))
-            error("does not bind to one of ancestor packages of module `%s`",
-               m->toPrettyChars(true));
+
+        // While isAncestorPackageOf does an equality check, the fix for issue 17441 adds a check to see if
+        // each package's .isModule() properites are equal.
+        //
+        // Properties generated from `package(foo)` i.e. protection.pkg have .isModule() == null.
+        // This breaks package declarations of the package in question if they are declared in
+        // the same package.d file, which _do_ have a module associated with them, and hence a non-null
+        // isModule()
+        if (!m->isPackage() || !protection.pkg->ident->equals(m->isPackage()->ident))
+        {
+            Package* pkg = m->parent ? m->parent->isPackage() : NULL;
+            if (!pkg || !protection.pkg->isAncestorPackageOf(pkg))
+                error("does not bind to one of ancestor packages of module `%s`",
+                      m->toPrettyChars(true));
+        }
     }
 
     return AttribDeclaration::addMember(sc, sds);
@@ -795,6 +806,18 @@ Scope *PragmaDeclaration::newScope(Scope *sc)
             sc->protection, sc->explicitProtection, sc->aligndecl,
             inlining);
     }
+    if (ident == Id::printf || ident == Id::scanf)
+    {
+        Scope *sc2 = sc->push();
+
+        if (ident == Id::printf)
+            // Override previous setting, never let both be set
+            sc2->flags = (sc2->flags & ~SCOPEscanf) | SCOPEprintf;
+        else
+            sc2->flags = (sc2->flags & ~SCOPEprintf) | SCOPEscanf;
+
+        return sc2;
+    }
     return sc;
 }
 
@@ -1164,12 +1187,12 @@ void ForwardingAttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sds)
 
 // These are mixin declarations, like mixin("int x");
 
-CompileDeclaration::CompileDeclaration(Loc loc, Expression *exp)
+CompileDeclaration::CompileDeclaration(Loc loc, Expressions *exps)
     : AttribDeclaration(NULL)
 {
     //printf("CompileDeclaration(loc = %d)\n", loc.linnum);
     this->loc = loc;
-    this->exp = exp;
+    this->exps = exps;
     this->scopesym = NULL;
     this->compiled = false;
 }
@@ -1177,7 +1200,7 @@ CompileDeclaration::CompileDeclaration(Loc loc, Expression *exp)
 Dsymbol *CompileDeclaration::syntaxCopy(Dsymbol *)
 {
     //printf("CompileDeclaration::syntaxCopy('%s')\n", toChars());
-    return new CompileDeclaration(loc, exp->syntaxCopy());
+    return new CompileDeclaration(loc, Expression::arraySyntaxCopy(exps));
 }
 
 void CompileDeclaration::addMember(Scope *, ScopeDsymbol *sds)
diff --git a/gcc/d/dmd/attrib.h b/gcc/d/dmd/attrib.h
index 74364176128..174d3c1ad5b 100644
--- a/gcc/d/dmd/attrib.h
+++ b/gcc/d/dmd/attrib.h
@@ -234,12 +234,12 @@ public:
 class CompileDeclaration : public AttribDeclaration
 {
 public:
-    Expression *exp;
+    Expressions *exps;
 
     ScopeDsymbol *scopesym;
     bool compiled;
 
-    CompileDeclaration(Loc loc, Expression *exp);
+    CompileDeclaration(Loc loc, Expressions *exps);
     Dsymbol *syntaxCopy(Dsymbol *s);
     void addMember(Scope *sc, ScopeDsymbol *sds);
     void setScope(Scope *sc);
diff --git a/gcc/d/dmd/blockexit.c b/gcc/d/dmd/blockexit.c
index 44e3cc13bd3..1895d36fb1e 100644
--- a/gcc/d/dmd/blockexit.c
+++ b/gcc/d/dmd/blockexit.c
@@ -62,6 +62,8 @@ int blockExit(Statement *s, FuncDeclaration *func, bool mustNotThrow)
                         return;
                     }
                 }
+                if (s->exp->type->toBasetype()->isTypeNoreturn())
+                    result = BEhalt;
                 if (canThrow(s->exp, func, mustNotThrow))
                     result |= BEthrow;
             }
diff --git a/gcc/d/dmd/chkformat.c b/gcc/d/dmd/chkformat.c
new file mode 100644
index 00000000000..d00b658ca00
--- /dev/null
+++ b/gcc/d/dmd/chkformat.c
@@ -0,0 +1,975 @@
+
+/* Compiler implementation of the D programming language
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
+ * written by Walter Bright
+ * http://www.digitalmars.com
+ * Distributed under the Boost Software License, Version 1.0.
+ * http://www.boost.org/LICENSE_1_0.txt
+ */
+
+// Check the arguments to `printf` and `scanf` against the `format` string.
+
+#include "root/dsystem.h"
+#include "root/dcompat.h"
+
+#include "arraytypes.h"
+#include "cond.h"
+#include "errors.h"
+#include "expression.h"
+#include "globals.h"
+#include "identifier.h"
+#include "mtype.h"
+#include "target.h"
+
+
+/* Different kinds of formatting specifications, variations we don't
+   care about are merged. (Like we don't care about the difference between
+   f, e, g, a, etc.)
+
+   For `scanf`, every format is a pointer.
+ */
+enum Format
+{
+    Format_d,          // int
+    Format_hhd,        // signed char
+    Format_hd,         // short int
+    Format_ld,         // long int
+    Format_lld,        // long long int
+    Format_jd,         // intmax_t
+    Format_zd,         // size_t
+    Format_td,         // ptrdiff_t
+    Format_u,          // unsigned int
+    Format_hhu,        // unsigned char
+    Format_hu,         // unsigned short int
+    Format_lu,         // unsigned long int
+    Format_llu,        // unsigned long long int
+    Format_ju,         // uintmax_t
+    Format_g,          // float (scanf) / double (printf)
+    Format_lg,         // double (scanf)
+    Format_Lg,         // long double (both)
+    Format_s,          // char string (both)
+    Format_ls,         // wchar_t string (both)
+    Format_c,          // char (printf)
+    Format_lc,         // wint_t (printf)
+    Format_p,          // pointer
+    Format_n,          // pointer to int
+    Format_hhn,        // pointer to signed char
+    Format_hn,         // pointer to short
+    Format_ln,         // pointer to long int
+    Format_lln,        // pointer to long long int
+    Format_jn,         // pointer to intmax_t
+    Format_zn,         // pointer to size_t
+    Format_tn,         // pointer to ptrdiff_t
+    Format_GNU_a,      // GNU ext. : address to a string with no maximum size (scanf)
+    Format_GNU_m,      // GNU ext. : string corresponding to the error code in errno (printf) / length modifier (scanf)
+    Format_percent,    // %% (i.e. no argument)
+    Format_error,      // invalid format specification
+};
+
+/**************************************
+ * Parse the *length specifier* and the *specifier* of the following form:
+ * `[length]specifier`
+ *
+ * Params:
+ *      format = format string
+ *      idx = index of of start of format specifier,
+ *          which gets updated to index past the end of it,
+ *          even if `Format_error` is returned
+ *      genSpecifier = Generic specifier. For instance, it will be set to `d` if the
+ *           format is `hdd`.
+ * Returns:
+ *      Format
+ */
+static Format parseGenericFormatSpecifier(const char *format,
+            size_t &idx, char &genSpecifier, bool useGNUExts =
+            findCondition(global.versionids, Identifier::idPool("CRuntime_Glibc")))
+{
+    genSpecifier = 0;
+
+    const size_t length = strlen(format);
+
+    /* Read the `length modifier`
+     */
+    const char lm = format[idx];
+    bool lm1= false;        // if jztL
+    bool lm2= false;        // if `hh` or `ll`
+    if (lm == 'j' ||
+        lm == 'z' ||
+        lm == 't' ||
+        lm == 'L')
+    {
+        ++idx;
+        if (idx == length)
+            return Format_error;
+        lm1 = true;
+    }
+    else if (lm == 'h' || lm == 'l')
+    {
+        ++idx;
+        if (idx == length)
+            return Format_error;
+        lm2 = lm == format[idx];
+        if (lm2)
+        {
+            ++idx;
+            if (idx == length)
+                return Format_error;
+        }
+    }
+
+    /* Read the `specifier`
+     */
+    Format specifier;
+    const char sc = format[idx];
+    genSpecifier = sc;
+    switch (sc)
+    {
+        case 'd':
+        case 'i':
+            if (lm == 'L')
+                specifier = Format_error;
+            else
+                specifier = lm == 'h' && lm2 ? Format_hhd :
+                            lm == 'h'        ? Format_hd  :
+                            lm == 'l' && lm2 ? Format_lld :
+                            lm == 'l'        ? Format_ld  :
+                            lm == 'j'        ? Format_jd  :
+                            lm == 'z'        ? Format_zd  :
+                            lm == 't'        ? Format_td  :
+                                               Format_d;
+            break;
+
+        case 'u':
+        case 'o':
+        case 'x':
+        case 'X':
+            if (lm == 'L')
+                specifier = Format_error;
+            else
+                specifier = lm == 'h' && lm2 ? Format_hhu :
+                            lm == 'h'        ? Format_hu  :
+                            lm == 'l' && lm2 ? Format_llu :
+                            lm == 'l'        ? Format_lu  :
+                            lm == 'j'        ? Format_ju  :
+                            lm == 'z'        ? Format_zd  :
+                            lm == 't'        ? Format_td  :
+                                               Format_u;
+            break;
+
+        case 'a':
+            if (useGNUExts)
+            {
+                // https://www.gnu.org/software/libc/manual/html_node/Dynamic-String-Input.html
+                specifier = Format_GNU_a;
+                break;
+            }
+            /* fall through */
+
+        case 'f':
+        case 'F':
+        case 'e':
+        case 'E':
+        case 'g':
+        case 'G':
+        case 'A':
+            if (lm == 'L')
+                specifier = Format_Lg;
+            else if (lm1 || lm2 || lm == 'h')
+                specifier = Format_error;
+            else
+                specifier = lm == 'l' ? Format_lg : Format_g;
+            break;
+
+        case 'c':
+            if (lm1 || lm2 || lm == 'h')
+                specifier = Format_error;
+            else
+                specifier = lm == 'l' ? Format_lc : Format_c;
+            break;
+
+        case 's':
+            if (lm1 || lm2 || lm == 'h')
+                specifier = Format_error;
+            else
+                specifier = lm == 'l' ? Format_ls : Format_s;
+            break;
+
+        case 'p':
+            if (lm1 || lm2 || lm == 'h' || lm == 'l')
+                specifier = Format_error;
+            else
+                specifier = Format_p;
+            break;
+
+        case 'n':
+            if (lm == 'L')
+                specifier = Format_error;
+            else
+                specifier = lm == 'l' && lm2 ? Format_lln :
+                            lm == 'l'        ? Format_ln  :
+                            lm == 'h' && lm2 ? Format_hhn :
+                            lm == 'h'        ? Format_hn  :
+                            lm == 'j'        ? Format_jn  :
+                            lm == 'z'        ? Format_zn  :
+                            lm == 't'        ? Format_tn  :
+                                               Format_n;
+            break;
+
+        case 'm':
+            if (useGNUExts)
+            {
+                // http://www.gnu.org/software/libc/manual/html_node/Other-Output-Conversions.html
+                specifier = Format_GNU_m;
+                break;
+            }
+            goto Ldefault;
+
+        default:
+        Ldefault:
+            specifier = Format_error;
+            break;
+    }
+
+    ++idx;
+    return specifier; // success
+}
+
+Format formatError(size_t &idx, size_t i)
+{
+    idx = i;
+    return Format_error;
+}
+
+/**************************************
+ * Parse the *format specifier* which is of the form:
+ *
+ * `%[*][width][length]specifier`
+ *
+ * Params:
+ *      format = format string
+ *      idx = index of `%` of start of format specifier,
+ *          which gets updated to index past the end of it,
+ *          even if `Format_error` is returned
+ *      asterisk = set if there is a `*` sub-specifier
+ * Returns:
+ *      Format
+ */
+static Format parseScanfFormatSpecifier(const char *format, size_t &idx,
+                bool &asterisk)
+{
+    asterisk = false;
+
+    size_t i = idx;
+    assert(format[i] == '%');
+    const size_t length = strlen(format);
+
+    ++i;
+    if (i == length)
+        return formatError(idx, i);
+
+    if (format[i] == '%')
+    {
+        idx = i + 1;
+        return Format_percent;
+    }
+
+    // * sub-specifier
+    if (format[i] == '*')
+    {
+        ++i;
+        if (i == length)
+            return formatError(idx, i);
+        asterisk = true;
+    }
+
+    // fieldWidth
+    while (isdigit(format[i]))
+    {
+        i++;
+        if (i == length)
+            return formatError(idx, i);
+    }
+
+    /* Read the scanset
+     * A scanset can be anything, so we just check that it is paired
+     */
+    if (format[i] == '[')
+    {
+        while (i < length)
+        {
+            if (format[i] == ']')
+                break;
+            ++i;
+        }
+
+        // no `]` found
+        if (i == length)
+            return formatError(idx, i);
+
+        ++i;
+        // no specifier after `]`
+        // it could be mixed with the one above, but then idx won't have the right index
+        if (i == length)
+            return formatError(idx, i);
+    }
+
+    /* Read the specifier
+     */
+    char genSpec;
+    Format specifier = parseGenericFormatSpecifier(format, i, genSpec);
+    if (specifier == Format_error)
+        return formatError(idx, i);
+
+    idx = i;
+    return specifier;  // success
+}
+
+/**************************************
+ * Parse the *format specifier* which is of the form:
+ *
+ * `%[flags][field width][.precision][length modifier]specifier`
+ *
+ * Params:
+ *      format = format string
+ *      idx = index of `%` of start of format specifier,
+ *          which gets updated to index past the end of it,
+ *          even if `Format_error` is returned
+ *      widthStar = set if * for width
+ *      precisionStar = set if * for precision
+ * Returns:
+ *      Format
+ */
+static Format parsePrintfFormatSpecifier(const char *format, size_t &idx,
+                bool &widthStar, bool &precisionStar)
+{
+    widthStar = false;
+    precisionStar = false;
+
+    size_t i = idx;
+    assert(format[i] == '%');
+    const size_t format_length = strlen(format);
+    const size_t length = format_length;
+    bool hash = false;
+    bool zero = false;
+    bool flags = false;
+    bool width = false;
+    bool precision = false;
+
+    ++i;
+    if (i == length)
+        return formatError(idx, i);
+
+    if (format[i] == '%')
+    {
+        idx = i + 1;
+        return Format_percent;
+    }
+
+    /* Read the `flags`
+     */
+    while (1)
+    {
+        const char c = format[i];
+        if (c == '-' ||
+            c == '+' ||
+            c == ' ')
+        {
+            flags = true;
+        }
+        else if (c == '#')
+        {
+            hash = true;
+        }
+        else if (c == '0')
+        {
+            zero = true;
+        }
+        else
+            break;
+        ++i;
+        if (i == length)
+            return formatError(idx, i);
+    }
+
+    /* Read the `field width`
+     */
+    {
+        const char c = format[i];
+        if (c == '*')
+        {
+            width = true;
+            widthStar = true;
+            ++i;
+            if (i == length)
+                return formatError(idx, i);
+        }
+        else if ('1' <= c && c <= '9')
+        {
+            width = true;
+            ++i;
+            if (i == length)
+                return formatError(idx, i);
+            while ('0' <= format[i] && format[i] <= '9')
+            {
+               ++i;
+               if (i == length)
+                    return formatError(idx, i);
+            }
+        }
+    }
+
+    /* Read the `precision`
+     */
+    if (format[i] == '.')
+    {
+        precision = true;
+        ++i;
+        if (i == length)
+            return formatError(idx, i);
+        const char c = format[i];
+        if (c == '*')
+        {
+            precisionStar = true;
+            ++i;
+            if (i == length)
+                return formatError(idx, i);
+        }
+        else if ('0' <= c && c <= '9')
+        {
+            ++i;
+            if (i == length)
+                return formatError(idx, i);
+            while ('0' <= format[i] && format[i] <= '9')
+            {
+               ++i;
+               if (i == length)
+                    return formatError(idx, i);
+            }
+        }
+    }
+
+    /* Read the specifier
+     */
+    char genSpec;
+    Format specifier = parseGenericFormatSpecifier(format, i, genSpec);
+    if (specifier == Format_error)
+        return formatError(idx, i);
+
+    switch (genSpec)
+    {
+        case 'c':
+        case 's':
+            if (hash || zero)
+                return formatError(idx, i);
+            break;
+
+        case 'd':
+        case 'i':
+            if (hash)
+                return formatError(idx, i);
+            break;
+
+        case 'n':
+            if (hash || zero || precision || width || flags)
+                return formatError(idx, i);
+            break;
+
+        default:
+            break;
+    }
+
+    idx = i;
+    return specifier;  // success
+}
+
+/*******************************************/
+
+static Expression *getNextPrintfArg(const Loc &loc, Expressions &args, size_t &n,
+                size_t gnu_m_count, bool &skip)
+{
+    if (n == args.length)
+    {
+        if (args.length < (n + 1) - gnu_m_count)
+            deprecation(loc, "more format specifiers than %d arguments", (int)n);
+        else
+            skip = true;
+        return NULL;
+    }
+    return args[n++];
+}
+
+static void errorPrintfFormat(const char *prefix, DString &slice, Expression *arg,
+                const char *texpect, Type *tactual)
+{
+    deprecation(arg->loc, "%sargument `%s` for format specification `\"%.*s\"` must be `%s`, not `%s`",
+                prefix ? prefix : "", arg->toChars(), (int)slice.length, slice.ptr, texpect, tactual->toChars());
+}
+
+/******************************************
+ * Check that arguments to a printf format string are compatible
+ * with that string. Issue errors for incompatibilities.
+ *
+ * Follows the C99 specification for printf.
+ *
+ * Takes a generous, rather than strict, view of compatiblity.
+ * For example, an unsigned value can be formatted with a signed specifier.
+ *
+ * Diagnosed incompatibilities are:
+ *
+ * 1. incompatible sizes which will cause argument misalignment
+ * 2. deferencing arguments that are not pointers
+ * 3. insufficient number of arguments
+ * 4. struct arguments
+ * 5. array and slice arguments
+ * 6. non-pointer arguments to `s` specifier
+ * 7. non-standard formats
+ * 8. undefined behavior per C99
+ *
+ * Per the C Standard, extra arguments are ignored.
+ *
+ * No attempt is made to fix the arguments or the format string.
+ *
+ * Params:
+ *      loc = location for error messages
+ *      format = format string
+ *      args = arguments to match with format string
+ *      isVa_list = if a "v" function (format check only)
+ *
+ * Returns:
+ *      `true` if errors occurred
+ * References:
+ * C99 7.19.6.1
+ * http://www.cplusplus.com/reference/cstdio/printf/
+ */
+bool checkPrintfFormat(const Loc &loc, const char *format, Expressions &args, bool isVa_list)
+{
+    //printf("checkPrintFormat('%s')\n", format);
+    size_t n = 0;             // index in args
+    size_t gnu_m_count = 0;   // number of Format_GNU_m
+    const size_t format_length = strlen(format);
+    for (size_t i = 0; i < format_length;)
+    {
+        if (format[i] != '%')
+        {
+            ++i;
+            continue;
+        }
+        bool widthStar = false;
+        bool precisionStar = false;
+        size_t j = i;
+        const Format fmt = parsePrintfFormatSpecifier(format, j, widthStar, precisionStar);
+        DString slice = DString(j - i, format + i);
+        i = j;
+
+        if (fmt == Format_percent)
+            continue;                   // "%%", no arguments
+
+        if (isVa_list)
+        {
+            // format check only
+            if (fmt == Format_error)
+                deprecation(loc, "format specifier `\"%.*s\"` is invalid", (int)slice.length, slice.ptr);
+            continue;
+        }
+
+        if (fmt == Format_GNU_m)
+            ++gnu_m_count;
+
+        if (widthStar)
+        {
+            bool skip = false;
+            Expression *e = getNextPrintfArg(loc, args, n, gnu_m_count, skip);
+            if (skip)
+                continue;
+            if (!e)
+                return true;
+            Type *t = e->type->toBasetype();
+            if (t->ty != Tint32 && t->ty != Tuns32)
+                errorPrintfFormat("width ", slice, e, "int", t);
+        }
+
+        if (precisionStar)
+        {
+            bool skip = false;
+            Expression *e = getNextPrintfArg(loc, args, n, gnu_m_count, skip);
+            if (skip)
+                continue;
+            if (!e)
+                return true;
+            Type *t = e->type->toBasetype();
+            if (t->ty != Tint32 && t->ty != Tuns32)
+                errorPrintfFormat("precision ", slice, e, "int", t);
+        }
+
+        bool skip = false;
+        Expression *e = getNextPrintfArg(loc, args, n, gnu_m_count, skip);
+        if (skip)
+            continue;
+        if (!e)
+            return true;
+        Type *t = e->type->toBasetype();
+        Type *tnext = t->nextOf();
+        const unsigned c_longsize = target.c.longsize;
+        const bool is64bit = global.params.is64bit;
+
+        // Types which are promoted to int are allowed.
+        // Spec: C99 6.5.2.2.7
+        switch (fmt)
+        {
+            case Format_u:      // unsigned int
+            case Format_d:      // int
+                if (t->ty != Tint32 && t->ty != Tuns32)
+                    errorPrintfFormat(NULL, slice, e, "int", t);
+                break;
+
+            case Format_hhu:    // unsigned char
+            case Format_hhd:    // signed char
+                if (t->ty != Tint32 && t->ty != Tuns32 && t->ty != Tint8 && t->ty != Tuns8)
+                    errorPrintfFormat(NULL, slice, e, "byte", t);
+                break;
+
+            case Format_hu:     // unsigned short int
+            case Format_hd:     // short int
+                if (t->ty != Tint32 && t->ty != Tuns32 && t->ty != Tint16 && t->ty != Tuns16)
+                    errorPrintfFormat(NULL, slice, e, "short", t);
+                break;
+
+            case Format_lu:     // unsigned long int
+            case Format_ld:     // long int
+                if (!(t->isintegral() && t->size() == c_longsize))
+                    errorPrintfFormat(NULL, slice, e, (c_longsize == 4 ? "int" : "long"), t);
+                break;
+
+            case Format_llu:    // unsigned long long int
+            case Format_lld:    // long long int
+                if (t->ty != Tint64 && t->ty != Tuns64)
+                    errorPrintfFormat(NULL, slice, e, "long", t);
+                break;
+
+            case Format_ju:     // uintmax_t
+            case Format_jd:     // intmax_t
+                if (t->ty != Tint64 && t->ty != Tuns64)
+                    errorPrintfFormat(NULL, slice, e, "core.stdc.stdint.intmax_t", t);
+                break;
+
+            case Format_zd:     // size_t
+                if (!(t->isintegral() && t->size() == (is64bit ? 8 : 4)))
+                    errorPrintfFormat(NULL, slice, e, "size_t", t);
+                break;
+
+            case Format_td:     // ptrdiff_t
+                if (!(t->isintegral() && t->size() == (is64bit ? 8 : 4)))
+                    errorPrintfFormat(NULL, slice, e, "ptrdiff_t", t);
+                break;
+
+            case Format_GNU_a:  // Format_GNU_a is only for scanf
+            case Format_lg:
+            case Format_g:      // double
+                if (t->ty != Tfloat64 && t->ty != Timaginary64)
+                    errorPrintfFormat(NULL, slice, e, "double", t);
+                break;
+
+            case Format_Lg:     // long double
+                if (t->ty != Tfloat80 && t->ty != Timaginary80)
+                    errorPrintfFormat(NULL, slice, e, "real", t);
+                break;
+
+            case Format_p:      // pointer
+                if (t->ty != Tpointer && t->ty != Tnull && t->ty != Tclass && t->ty != Tdelegate && t->ty != Taarray)
+                    errorPrintfFormat(NULL, slice, e, "void*", t);
+                break;
+
+            case Format_n:      // pointer to int
+                if (!(t->ty == Tpointer && tnext->ty == Tint32))
+                    errorPrintfFormat(NULL, slice, e, "int*", t);
+                break;
+
+            case Format_ln:     // pointer to long int
+                if (!(t->ty == Tpointer && tnext->isintegral() && tnext->size() == c_longsize))
+                    errorPrintfFormat(NULL, slice, e, (c_longsize == 4 ? "int*" : "long*"), t);
+                break;
+
+            case Format_lln:    // pointer to long long int
+                if (!(t->ty == Tpointer && tnext->ty == Tint64))
+                    errorPrintfFormat(NULL, slice, e, "long*", t);
+                break;
+
+            case Format_hn:     // pointer to short
+                if (!(t->ty == Tpointer && tnext->ty == Tint16))
+                    errorPrintfFormat(NULL, slice, e, "short*", t);
+                break;
+
+            case Format_hhn:    // pointer to signed char
+                if (!(t->ty == Tpointer && tnext->ty == Tint16))
+                    errorPrintfFormat(NULL, slice, e, "byte*", t);
+                break;
+
+            case Format_jn:     // pointer to intmax_t
+                if (!(t->ty == Tpointer && tnext->ty == Tint64))
+                    errorPrintfFormat(NULL, slice, e, "core.stdc.stdint.intmax_t*", t);
+                break;
+
+            case Format_zn:     // pointer to size_t
+                if (!(t->ty == Tpointer && tnext->ty == (is64bit ? Tuns64 : Tuns32)))
+                    errorPrintfFormat(NULL, slice, e, "size_t*", t);
+                break;
+
+            case Format_tn:     // pointer to ptrdiff_t
+                if (!(t->ty == Tpointer && tnext->ty == (is64bit ? Tint64 : Tint32)))
+                    errorPrintfFormat(NULL, slice, e, "ptrdiff_t*", t);
+                break;
+
+            case Format_c:      // char
+                if (t->ty != Tint32 && t->ty != Tuns32)
+                    errorPrintfFormat(NULL, slice, e, "char", t);
+                break;
+
+            case Format_lc:     // wint_t
+                if (t->ty != Tint32 && t->ty != Tuns32)
+                    errorPrintfFormat(NULL, slice, e, "wchar_t", t);
+                break;
+
+            case Format_s:      // pointer to char string
+                if (!(t->ty == Tpointer && (tnext->ty == Tchar || tnext->ty == Tint8 || tnext->ty == Tuns8)))
+                    errorPrintfFormat(NULL, slice, e, "char*", t);
+                break;
+
+            case Format_ls:     // pointer to wchar_t string
+            {
+                if (!(t->ty == Tpointer && tnext == target.c.twchar_t))
+                    errorPrintfFormat(NULL, slice, e, "wchar_t*", t);
+                break;
+            }
+            case Format_error:
+                deprecation(loc, "format specifier `\"%.*s\"` is invalid", (int)slice.length, slice.ptr);
+                break;
+
+            case Format_GNU_m:
+                break;  // not assert(0) because it may go through it if there are extra arguments
+
+            case Format_percent:
+            default:
+                assert(0);
+        }
+    }
+    return false;
+}
+
+/*******************************************/
+
+static Expression *getNextScanfArg(const Loc &loc, Expressions &args, size_t &n, bool asterisk)
+{
+    if (n == args.length)
+    {
+        if (!asterisk)
+            deprecation(loc, "more format specifiers than %d arguments", (int)n);
+        return NULL;
+    }
+    return args[n++];
+}
+
+static void errorScanfFormat(const char *prefix, DString &slice,
+                Expression *arg, const char *texpect, Type *tactual)
+{
+    deprecation(arg->loc, "%sargument `%s` for format specification `\"%.*s\"` must be `%s`, not `%s`",
+                prefix ? prefix : "", arg->toChars(), (int)slice.length, slice.ptr, texpect, tactual->toChars());
+}
+
+/******************************************
+ * Check that arguments to a scanf format string are compatible
+ * with that string. Issue errors for incompatibilities.
+ *
+ * Follows the C99 specification for scanf.
+ *
+ * Takes a generous, rather than strict, view of compatiblity.
+ * For example, an unsigned value can be formatted with a signed specifier.
+ *
+ * Diagnosed incompatibilities are:
+ *
+ * 1. incompatible sizes which will cause argument misalignment
+ * 2. deferencing arguments that are not pointers
+ * 3. insufficient number of arguments
+ * 4. struct arguments
+ * 5. array and slice arguments
+ * 6. non-standard formats
+ * 7. undefined behavior per C99
+ *
+ * Per the C Standard, extra arguments are ignored.
+ *
+ * No attempt is made to fix the arguments or the format string.
+ *
+ * Params:
+ *      loc = location for error messages
+ *      format = format string
+ *      args = arguments to match with format string
+ *      isVa_list = if a "v" function (format check only)
+ *
+ * Returns:
+ *      `true` if errors occurred
+ * References:
+ * C99 7.19.6.2
+ * http://www.cplusplus.com/reference/cstdio/scanf/
+ */
+bool checkScanfFormat(const Loc &loc, const char *format, Expressions &args, bool isVa_list)
+{
+    size_t n = 0;
+    const size_t format_length = strlen(format);
+    for (size_t i = 0; i < format_length;)
+    {
+        if (format[i] != '%')
+        {
+            ++i;
+            continue;
+        }
+        bool asterisk = false;
+        size_t j = i;
+        const Format fmt = parseScanfFormatSpecifier(format, j, asterisk);
+        DString slice = DString(j - i, format + i);
+        i = j;
+
+        if (fmt == Format_percent || asterisk)
+            continue;   // "%%", "%*": no arguments
+
+        if (isVa_list)
+        {
+            // format check only
+            if (fmt == Format_error)
+                deprecation(loc, "format specifier `\"%.*s\"` is invalid", (int)slice.length, slice.ptr);
+            continue;
+        }
+
+        Expression *e = getNextScanfArg(loc, args, n, asterisk);
+        if (!e)
+            return true;
+
+        Type *t = e->type->toBasetype();
+        Type *tnext = t->nextOf();
+        const unsigned c_longsize = target.c.longsize;
+        const bool is64bit = global.params.is64bit;
+
+        switch (fmt)
+        {
+            case Format_n:
+            case Format_d:      // pointer to int
+                if (!(t->ty == Tpointer && tnext->ty == Tint32))
+                    errorScanfFormat(NULL, slice, e, "int*", t);
+                break;
+
+            case Format_hhn:
+            case Format_hhd:    // pointer to signed char
+                if (!(t->ty == Tpointer && tnext->ty == Tint16))
+                    errorScanfFormat(NULL, slice, e, "byte*", t);
+                break;
+
+            case Format_hn:
+            case Format_hd:     // pointer to short
+                if (!(t->ty == Tpointer && tnext->ty == Tint16))
+                    errorScanfFormat(NULL, slice, e, "short*", t);
+                break;
+
+            case Format_ln:
+            case Format_ld:     // pointer to long int
+                if (!(t->ty == Tpointer && tnext->isintegral() && tnext->size() == c_longsize))
+                    errorScanfFormat(NULL, slice, e, (c_longsize == 4 ? "int*" : "long*"), t);
+                break;
+
+            case Format_lln:
+            case Format_lld:    // pointer to long long int
+                if (!(t->ty == Tpointer && tnext->ty == Tint64))
+                    errorScanfFormat(NULL, slice, e, "long*", t);
+                break;
+
+            case Format_jn:
+            case Format_jd:     // pointer to intmax_t
+                if (!(t->ty == Tpointer && tnext->ty == Tint64))
+                    errorScanfFormat(NULL, slice, e, "core.stdc.stdint.intmax_t*", t);
+                break;
+
+            case Format_zn:
+            case Format_zd:     // pointer to size_t
+                if (!(t->ty == Tpointer && tnext->ty == (is64bit ? Tuns64 : Tuns32)))
+                    errorScanfFormat(NULL, slice, e, "size_t*", t);
+                break;
+
+            case Format_tn:
+            case Format_td:     // pointer to ptrdiff_t
+                if (!(t->ty == Tpointer && tnext->ty == (is64bit ? Tint64 : Tint32)))
+                    errorScanfFormat(NULL, slice, e, "ptrdiff_t*", t);
+                break;
+
+            case Format_u:      // pointer to unsigned int
+                if (!(t->ty == Tpointer && tnext->ty == Tuns32))
+                    errorScanfFormat(NULL, slice, e, "uint*", t);
+                break;
+
+            case Format_hhu:    // pointer to unsigned char
+                if (!(t->ty == Tpointer && tnext->ty == Tuns8))
+                    errorScanfFormat(NULL, slice, e, "ubyte*", t);
+                break;
+
+            case Format_hu:     // pointer to unsigned short int
+                if (!(t->ty == Tpointer && tnext->ty == Tuns16))
+                    errorScanfFormat(NULL, slice, e, "ushort*", t);
+                break;
+
+            case Format_lu:     // pointer to unsigned long int
+                if (!(t->ty == Tpointer && tnext->ty == (is64bit ? Tuns64 : Tuns32)))
+                    errorScanfFormat(NULL, slice, e, (c_longsize == 4 ? "uint*" : "ulong*"), t);
+                break;
+
+            case Format_llu:    // pointer to unsigned long long int
+                if (!(t->ty == Tpointer && tnext->ty == Tuns64))
+                    errorScanfFormat(NULL, slice, e, "ulong*", t);
+                break;
+
+            case Format_ju:     // pointer to uintmax_t
+                if (!(t->ty == Tpointer && tnext->ty == (is64bit ? Tuns64 : Tuns32)))
+                    errorScanfFormat(NULL, slice, e, "ulong*", t);
+                break;
+
+            case Format_g:      // pointer to float
+                if (!(t->ty == Tpointer && tnext->ty == Tfloat32))
+                    errorScanfFormat(NULL, slice, e, "float*", t);
+                break;
+
+            case Format_lg:     // pointer to double
+                if (!(t->ty == Tpointer && tnext->ty == Tfloat64))
+                    errorScanfFormat(NULL, slice, e, "double*", t);
+                break;
+
+            case Format_Lg:     // pointer to long double
+                if (!(t->ty == Tpointer && tnext->ty == Tfloat80))
+                    errorScanfFormat(NULL, slice, e, "real*", t);
+                break;
+
+            case Format_GNU_a:
+            case Format_GNU_m:
+            case Format_c:
+            case Format_s:      // pointer to char string
+                if (!(t->ty == Tpointer && (tnext->ty == Tchar || tnext->ty == Tint8 || tnext->ty == Tuns8)))
+                    errorScanfFormat(NULL, slice, e, "char*", t);
+                break;
+
+            case Format_lc:
+            case Format_ls:     // pointer to wchar_t string
+            {
+                if (!(t->ty == Tpointer && tnext == target.c.twchar_t))
+                    errorScanfFormat(NULL, slice, e, "wchar_t*", t);
+                break;
+            }
+            case Format_p:      // double pointer
+                if (!(t->ty == Tpointer && tnext->ty == Tpointer))
+                    errorScanfFormat(NULL, slice, e, "void**", t);
+                break;
+
+            case Format_error:
+                deprecation(loc, "format specifier `\"%.*s\"` is invalid", (int)slice.length, slice.ptr);
+                break;
+
+            case Format_percent:
+            default:
+                assert(0);
+        }
+    }
+    return false;
+}
diff --git a/gcc/d/dmd/cppmangle.c b/gcc/d/dmd/cppmangle.c
index a0e0b5fb993..baf64c5653e 100644
--- a/gcc/d/dmd/cppmangle.c
+++ b/gcc/d/dmd/cppmangle.c
@@ -806,6 +806,14 @@ public:
         writeBasicType(t, 'D', 'n');
     }
 
+    void visit(TypeNoreturn *t)
+    {
+        if (t->isImmutable() || t->isShared())
+            return error(t);
+
+        writeBasicType(t, 0, 'v');      // mangle like `void`
+    }
+
     void visit(TypeBasic *t)
     {
         if (t->isImmutable() || t->isShared())
@@ -1012,7 +1020,7 @@ public:
         if (t->isImmutable() || t->isShared())
             return error(t);
 
-        /* __c_(u)long(long) get special mangling
+        /* __c_(u)long(long) and others get special mangling
          */
         Identifier *id = t->sym->ident;
         //printf("enum id = '%s'\n", id->toChars());
@@ -1020,10 +1028,18 @@ public:
             return writeBasicType(t, 0, 'l');
         else if (id == Id::__c_ulong)
             return writeBasicType(t, 0, 'm');
+        else if (id == Id::__c_wchar_t)
+            return writeBasicType(t, 0, 'w');
         else if (id == Id::__c_longlong)
             return writeBasicType(t, 0, 'x');
         else if (id == Id::__c_ulonglong)
             return writeBasicType(t, 0, 'y');
+        else if (id == Id::__c_complex_float)
+            return writeBasicType(t, 'C', 'f');
+        else if (id == Id::__c_complex_double)
+            return writeBasicType(t, 'C', 'd');
+        else if (id == Id::__c_complex_real)
+            return writeBasicType(t, 'C', 'e');
 
         doSymbol(t);
     }
diff --git a/gcc/d/dmd/ctfeexpr.c b/gcc/d/dmd/ctfeexpr.c
index 1d669e595e5..a8e97833ad0 100644
--- a/gcc/d/dmd/ctfeexpr.c
+++ b/gcc/d/dmd/ctfeexpr.c
@@ -162,7 +162,7 @@ const char *CTFEExp::toChars()
     switch (op)
     {
         case TOKcantexp:    return "<cant>";
-        case TOKvoidexp:    return "<void>";
+        case TOKvoidexp:    return "cast(void)0";
         case TOKbreak:      return "<break>";
         case TOKcontinue:   return "<continue>";
         case TOKgoto:       return "<goto>";
diff --git a/gcc/d/dmd/dcast.c b/gcc/d/dmd/dcast.c
index 61e28fe8d13..4dd648bcc48 100644
--- a/gcc/d/dmd/dcast.c
+++ b/gcc/d/dmd/dcast.c
@@ -26,6 +26,7 @@
 FuncDeclaration *isFuncAddress(Expression *e, bool *hasOverloads = NULL);
 bool isCommutative(TOK op);
 MOD MODmerge(MOD mod1, MOD mod2);
+void toAutoQualChars(const char **result, Type *t1, Type *t2);
 
 /* ==================== implicitCast ====================== */
 
@@ -90,8 +91,10 @@ Expression *implicitCastTo(Expression *e, Scope *sc, Type *t)
                     //printf("type %p ty %d deco %p\n", type, type->ty, type->deco);
                     //type = type->semantic(loc, sc);
                     //printf("type %s t %s\n", type->deco, t->deco);
+                    const char *ts[2];
+                    toAutoQualChars(ts, e->type, t);
                     e->error("cannot implicitly convert expression (%s) of type %s to %s",
-                        e->toChars(), e->type->toChars(), t->toChars());
+                        e->toChars(), ts[0], ts[1]);
                 }
             }
             result = new ErrorExp();
diff --git a/gcc/d/dmd/dclass.c b/gcc/d/dmd/dclass.c
index c7dbbbea5d3..3f33014da9f 100644
--- a/gcc/d/dmd/dclass.c
+++ b/gcc/d/dmd/dclass.c
@@ -277,15 +277,10 @@ Scope *ClassDeclaration::newScope(Scope *sc)
     Scope *sc2 = AggregateDeclaration::newScope(sc);
     if (isCOMclass())
     {
-        if (global.params.isWindows)
-            sc2->linkage = LINKwindows;
-        else
-        {
-            /* This enables us to use COM objects under Linux and
-             * work with things like XPCOM
-             */
-            sc2->linkage = LINKc;
-        }
+        /* This enables us to use COM objects under Linux and
+         * work with things like XPCOM
+         */
+        sc2->linkage = target.systemLinkage();
     }
     return sc2;
 }
@@ -491,9 +486,10 @@ void ClassDeclaration::finalizeSize()
         assert(baseClass->sizeok == SIZEOKdone);
 
         alignsize = baseClass->alignsize;
-        structsize = baseClass->structsize;
-        if (isCPPclass() && global.params.isWindows)
-            structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
+        if (classKind == ClassKind::cpp)
+            structsize = target.cpp.derivedClassOffset(baseClass);
+        else
+            structsize = baseClass->structsize;
     }
     else if (isInterfaceDeclaration())
     {
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index 81b563f4b0f..55c814288e0 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -118,7 +118,7 @@ struct Match
     FuncDeclaration *anyf;      // pick a func, any func, to use for error recovery
 };
 
-void functionResolve(Match *m, Dsymbol *fd, Loc loc, Scope *sc, Objects *tiargs, Type *tthis, Expressions *fargs);
+void functionResolve(Match *m, Dsymbol *fd, Loc loc, Scope *sc, Objects *tiargs, Type *tthis, Expressions *fargs, const char **pMessage = NULL);
 int overloadApply(Dsymbol *fstart, void *param, int (*fp)(void *, Dsymbol *));
 void aliasSemantic(AliasDeclaration *ds, Scope *sc);
 
@@ -551,6 +551,8 @@ void builtin_init();
 #define FUNCFLAGreturnInprocess 0x10    // working on inferring 'return' for parameters
 #define FUNCFLAGinlineScanned   0x20    // function has been scanned for inline possibilities
 #define FUNCFLAGinferScope      0x40    // infer 'scope' for parameters
+#define FUNCFLAGprintf          0x200   // is a printf-like function
+#define FUNCFLAGscanf           0x400   // is a scanf-like function
 
 class FuncDeclaration : public Declaration
 {
diff --git a/gcc/d/dmd/denum.c b/gcc/d/dmd/denum.c
index ca1d3bb771c..bfd3b7274f4 100644
--- a/gcc/d/dmd/denum.c
+++ b/gcc/d/dmd/denum.c
@@ -22,6 +22,19 @@
 #include "declaration.h"
 #include "init.h"
 
+bool isSpecialEnumIdent(const Identifier *ident)
+{
+    return  ident == Id::__c_long ||
+            ident == Id::__c_ulong ||
+            ident == Id::__c_longlong ||
+            ident == Id::__c_ulonglong ||
+            ident == Id::__c_long_double ||
+            ident == Id::__c_wchar_t ||
+            ident == Id::__c_complex_float ||
+            ident == Id::__c_complex_double ||
+            ident == Id::__c_complex_real;
+}
+
 /********************************* EnumDeclaration ****************************/
 
 EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype)
@@ -187,11 +200,7 @@ Lerrors:
  */
 bool EnumDeclaration::isSpecial() const
 {
-    return (ident == Id::__c_long ||
-            ident == Id::__c_ulong ||
-            ident == Id::__c_longlong ||
-            ident == Id::__c_ulonglong ||
-            ident == Id::__c_long_double) && memtype;
+    return isSpecialEnumIdent(ident) && memtype;
 }
 
 Expression *EnumDeclaration::getDefaultValue(Loc loc)
diff --git a/gcc/d/dmd/dimport.c b/gcc/d/dmd/dimport.c
index 0d93ed80e58..7b63a186552 100644
--- a/gcc/d/dmd/dimport.c
+++ b/gcc/d/dmd/dimport.c
@@ -161,37 +161,75 @@ void Import::load(Scope *sc)
     if (mod && !mod->importedFrom)
         mod->importedFrom = sc ? sc->_module->importedFrom : Module::rootModule;
     if (!pkg)
-        pkg = mod;
+    {
+        if (mod && mod->isPackageFile)
+        {
+            // one level depth package.d file (import pkg; ./pkg/package.d)
+            // it's necessary to use the wrapping Package already created
+            pkg = mod->pkg;
+        }
+        else
+            pkg = mod;
+    }
 
     //printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
 }
 
 void Import::importAll(Scope *sc)
 {
-    if (!mod)
+    if (mod) return; // Already done
+    load(sc);
+    if (!mod) return; // Failed
+
+    if (sc->stc & STCstatic)
+        isstatic = true;
+    mod->importAll(NULL);
+    if (mod->md && mod->md->isdeprecated)
     {
-        load(sc);
-        if (mod)                // if successfully loaded module
-        {
-            mod->importAll(NULL);
-
-            if (mod->md && mod->md->isdeprecated)
-            {
-                Expression *msg = mod->md->msg;
-                if (StringExp *se = msg ? msg->toStringExp() : NULL)
-                    mod->deprecation(loc, "is deprecated - %s", se->string);
-                else
-                    mod->deprecation(loc, "is deprecated");
-            }
+        Expression *msg = mod->md->msg;
+        if (StringExp *se = msg ? msg->toStringExp() : NULL)
+            mod->deprecation(loc, "is deprecated - %s", se->string);
+        else
+            mod->deprecation(loc, "is deprecated");
+    }
+    if (sc->explicitProtection)
+        protection = sc->protection;
+    if (!isstatic && !aliasId && !names.length)
+        sc->scopesym->importScope(mod, protection);
+    // Enable access to pkgs/mod as soon as posible, because compiler
+    // can traverse them before the import gets semantic (Issue: 21501)
+    if (!aliasId && !names.length)
+        addPackageAccess(sc->scopesym);
+}
 
-            if (sc->explicitProtection)
-                protection = sc->protection;
-            if (!isstatic && !aliasId && !names.length)
-            {
-                sc->scopesym->importScope(mod, protection);
-            }
+/*******************************
+ * Mark the imported packages as accessible from the current
+ * scope. This access check is necessary when using FQN b/c
+ * we're using a single global package tree.
+ * https://issues.dlang.org/show_bug.cgi?id=313
+ */
+void Import::addPackageAccess(ScopeDsymbol *scopesym)
+{
+    //printf("Import::addPackageAccess('%s') %p\n", toPrettyChars(), this);
+    if (packages)
+    {
+        // import a.b.c.d;
+        Package *p = pkg; // a
+        scopesym->addAccessiblePackage(p, protection);
+        for (size_t i = 1; i < packages->length; i++) // [b, c]
+        {
+            Identifier *id = (*packages)[i];
+            p = (Package *) p->symtab->lookup(id);
+            // https://issues.dlang.org/show_bug.cgi?id=17991
+            // An import of truly empty file/package can happen
+            // https://issues.dlang.org/show_bug.cgi?id=20151
+            // Package in the path conflicts with a module name
+            if (p == NULL)
+                return;
+            scopesym->addAccessiblePackage(p, protection);
         }
     }
+    scopesym->addAccessiblePackage(mod, protection); // d
 }
 
 Dsymbol *Import::toAlias()
diff --git a/gcc/d/dmd/dmangle.c b/gcc/d/dmd/dmangle.c
index 303ae617874..83f4c18bee8 100644
--- a/gcc/d/dmd/dmangle.c
+++ b/gcc/d/dmd/dmangle.c
@@ -82,6 +82,8 @@ void initTypeMangle()
     mangleChar[Treturn] = "@";
     mangleChar[Tvector] = "@";
     mangleChar[Ttraits] = "@";
+    mangleChar[Tmixin] = "@";
+    mangleChar[Tnoreturn] = "@";    // becomes 'Nn'
 
     mangleChar[Tnull] = "n";    // same as TypeNone
 
@@ -150,7 +152,7 @@ public:
     *  using upper case letters for all digits but the last digit which uses
     *  a lower case letter.
     * The decoder has to look up the referenced position to determine
-    *  whether the back reference is an identifer (starts with a digit)
+    *  whether the back reference is an identifier (starts with a digit)
     *  or a type (starts with a letter).
     *
     * Params:
@@ -414,6 +416,11 @@ public:
         visit((Type *)t);
     }
 
+    void visit(TypeNoreturn *)
+    {
+        buf->writestring("Nn");
+    }
+
     ////////////////////////////////////////////////////////////////////////////
 
     void mangleDecl(Declaration *sthis)
@@ -1085,3 +1092,31 @@ void mangleToBuffer(TemplateInstance *ti, OutBuffer *buf)
     Mangler v(buf);
     v.mangleTemplateInstance(ti);
 }
+
+/**********************************************
+ * Convert a string representing a type (the deco) and
+ * return its equivalent Type.
+ * Params:
+ *      deco = string containing the deco
+ * Returns:
+ *      null for failed to convert
+ *      Type for succeeded
+ */
+
+Type *decoToType(const char *deco)
+{
+    if (!deco)
+        return NULL;
+
+    //printf("decoToType(): %s\n", deco)
+    if (StringValue *sv = Type::stringtable.lookup(deco, strlen(deco)))
+    {
+        if (sv->ptrvalue)
+        {
+            Type *t = (Type *)sv->ptrvalue;
+            assert(t->deco);
+            return t;
+        }
+    }
+    return NULL;
+}
diff --git a/gcc/d/dmd/dmodule.c b/gcc/d/dmd/dmodule.c
index ed01858f06b..472b2b9e7f8 100644
--- a/gcc/d/dmd/dmodule.c
+++ b/gcc/d/dmd/dmodule.c
@@ -52,6 +52,7 @@ Module::Module(const char *filename, Identifier *ident, int doDocComment, int do
     members = NULL;
     isDocFile = 0;
     isPackageFile = false;
+    pkg = NULL;
     needmoduleinfo = 0;
     selfimports = 0;
     rootimports = 0;
@@ -685,15 +686,27 @@ Module *Module::parse()
          *
          * To avoid the conflict:
          * 1. If preceding package name insertion had occurred by Package::resolve,
-         *    later package.d loading will change Package::isPkgMod to PKGmodule and set Package::mod.
+         *    reuse the previous wrapping 'Package' if it exists
          * 2. Otherwise, 'package.d' wrapped by 'Package' is inserted to the internal tree in here.
+         *
+         * Then change Package::isPkgMod to PKGmodule and set Package::mod.
+         *
+         * Note that the 'wrapping Package' is the Package that contains package.d and other submodules,
+         * the one inserted to the symbol table.
          */
-        Package *p = new Package(ident);
+        Dsymbol *ps = dst->lookup(ident);
+        Package *p = ps ? ps->isPackage() : NULL;
+        if (p == NULL)
+        {
+            p = new Package(ident);
+            p->tag = this->tag; // reuse the same package tag
+            p->symtab = new DsymbolTable();
+        }
+        this->tag= p->tag; // reuse the 'older' package tag
+        this->pkg = p;
         p->parent = this->parent;
         p->isPkgMod = PKGmodule;
         p->mod = this;
-        p->tag = this->tag; // reuse the same package tag
-        p->symtab = new DsymbolTable();
         s = p;
     }
     if (!dst->insert(s))
@@ -720,15 +733,9 @@ Module *Module::parse()
         }
         else if (Package *pkg = prev->isPackage())
         {
-            if (pkg->isPkgMod == PKGunknown && isPackageFile)
-            {
-                /* If the previous inserted Package is not yet determined as package.d,
-                 * link it to the actual module.
-                 */
-                pkg->isPkgMod = PKGmodule;
-                pkg->mod = this;
-                pkg->tag = this->tag; // reuse the same package tag
-            }
+            // 'package.d' loaded after a previous 'Package' insertion
+            if (isPackageFile)
+                amodules.push(this); // Add to global array of all modules
             else
                 error(md ? md->loc : loc, "from file %s conflicts with package name %s",
                     srcname, pkg->toChars());
diff --git a/gcc/d/dmd/dscope.c b/gcc/d/dmd/dscope.c
index 65e6734b035..e56f3936ee0 100644
--- a/gcc/d/dmd/dscope.c
+++ b/gcc/d/dmd/dscope.c
@@ -24,6 +24,7 @@
 #include "aggregate.h"
 #include "module.h"
 #include "id.h"
+#include "target.h"
 #include "template.h"
 
 Scope *Scope::freelist = NULL;
@@ -155,7 +156,8 @@ Scope *Scope::push()
     s->nofree = 0;
     s->fieldinit = saveFieldInit();
     s->flags = (flags & (SCOPEcontract | SCOPEdebug | SCOPEctfe | SCOPEcompile | SCOPEconstraint |
-                         SCOPEnoaccesscheck | SCOPEignoresymbolvisibility));
+                         SCOPEnoaccesscheck | SCOPEignoresymbolvisibility |
+                         SCOPEprintf | SCOPEscanf));
     s->lastdc = NULL;
 
     assert(this != s);
@@ -637,7 +639,7 @@ const char *Scope::search_correct_C(Identifier *ident)
     else if (ident == Id::C_unsigned)
         tok = TOKuns32;
     else if (ident == Id::C_wchar_t)
-        tok = global.params.isWindows ? TOKwchar : TOKdchar;
+        tok = target.c.twchar_t->ty == Twchar ? TOKwchar : TOKdchar;
     else
         return NULL;
     return Token::toChars(tok);
diff --git a/gcc/d/dmd/dsymbol.c b/gcc/d/dmd/dsymbol.c
index 89c55576a55..f0c1cf6d93c 100644
--- a/gcc/d/dmd/dsymbol.c
+++ b/gcc/d/dmd/dsymbol.c
@@ -515,7 +515,7 @@ Dsymbol *Dsymbol::search_correct(Identifier *ident)
  * Returns:
  *      symbol found, NULL if not
  */
-Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, RootObject *id)
+Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, RootObject *id, int flags)
 {
     //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
     Dsymbol *s = toAlias();
@@ -533,7 +533,7 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, RootObject *id)
     switch (id->dyncast())
     {
         case DYNCAST_IDENTIFIER:
-            sm = s->search(loc, (Identifier *)id);
+            sm = s->search(loc, (Identifier *)id, flags);
             break;
 
         case DYNCAST_DSYMBOL:
@@ -1801,31 +1801,3 @@ bool Prot::operator==(const Prot& other) const
     }
     return false;
 }
-
-/**
- * Checks if parent defines different access restrictions than this one.
- *
- * Params:
- *  parent = protection attribute for scope that hosts this one
- *
- * Returns:
- *  'true' if parent is already more restrictive than this one and thus
- *  no differentiation is needed.
- */
-bool Prot::isSubsetOf(const Prot& parent) const
-{
-    if (this->kind != parent.kind)
-        return false;
-
-    if (this->kind == Prot::package_)
-    {
-        if (!this->pkg)
-            return true;
-        if (!parent.pkg)
-            return false;
-        if (parent.pkg->isAncestorPackageOf(this->pkg))
-            return true;
-    }
-
-    return true;
-}
diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h
index 1ddfe06e6a1..4aabb5d3c6c 100644
--- a/gcc/d/dmd/dsymbol.h
+++ b/gcc/d/dmd/dsymbol.h
@@ -107,7 +107,6 @@ struct Prot
 
     bool isMoreRestrictiveThan(const Prot other) const;
     bool operator==(const Prot& other) const;
-    bool isSubsetOf(const Prot& other) const;
 };
 
 // in hdrgen.c
@@ -207,7 +206,7 @@ public:
     virtual void importAll(Scope *sc);
     virtual Dsymbol *search(const Loc &loc, Identifier *ident, int flags = IgnoreNone);
     Dsymbol *search_correct(Identifier *id);
-    Dsymbol *searchX(Loc loc, Scope *sc, RootObject *id);
+    Dsymbol *searchX(Loc loc, Scope *sc, RootObject *id, int flags);
     virtual bool overloadInsert(Dsymbol *s);
     virtual d_uns64 size(Loc loc);
     virtual bool isforwardRef();
diff --git a/gcc/d/dmd/dsymbolsem.c b/gcc/d/dmd/dsymbolsem.c
index 5d5c9fca769..26e23e98587 100644
--- a/gcc/d/dmd/dsymbolsem.c
+++ b/gcc/d/dmd/dsymbolsem.c
@@ -42,6 +42,8 @@ VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e);
 Initializer *inferType(Initializer *init, Scope *sc);
 void MODtoBuffer(OutBuffer *buf, MOD mod);
 bool reliesOnTident(Type *t, TemplateParameters *tparams = NULL, size_t iStart = 0);
+bool expressionsToString(OutBuffer &buf, Scope *sc, Expressions *exps);
+bool symbolIsVisible(Scope *sc, Dsymbol *s);
 Objc *objc();
 
 static unsigned setMangleOverride(Dsymbol *s, char *sym)
@@ -1098,22 +1100,7 @@ public:
                     scopesym->importScope(imp->mod, imp->protection);
                 }
 
-                // Mark the imported packages as accessible from the current
-                // scope. This access check is necessary when using FQN b/c
-                // we're using a single global package tree. See Bugzilla 313.
-                if (imp->packages)
-                {
-                    // import a.b.c.d;
-                    Package *p = imp->pkg; // a
-                    scopesym->addAccessiblePackage(p, imp->protection);
-                    for (size_t i = 1; i < imp->packages->length; i++) // [b, c]
-                    {
-                        Identifier *id = (*imp->packages)[i];
-                        p = (Package *) p->symtab->lookup(id);
-                        scopesym->addAccessiblePackage(p, imp->protection);
-                    }
-                }
-                scopesym->addAccessiblePackage(imp->mod, imp->protection); // d
+                imp->addPackageAccess(scopesym);
             }
 
             dsymbolSemantic(imp->mod, NULL);
@@ -1130,8 +1117,12 @@ public:
             {
                 AliasDeclaration *ad = imp->aliasdecls[i];
                 //printf("\tImport %s alias %s = %s, scope = %p\n", toPrettyChars(), imp->aliases[i]->toChars(), imp->names[i]->toChars(), ad->_scope);
-                if (imp->mod->search(imp->loc, imp->names[i]))
+                Dsymbol *sym = imp->mod->search(imp->loc, imp->names[i], IgnorePrivateImports);
+                if (sym)
                 {
+                    if (!symbolIsVisible(sc, sym))
+                        imp->mod->error(imp->loc, "member `%s` is not visible from module `%s`",
+                            imp->names[i]->toChars(), sc->_module->toChars());
                     dsymbolSemantic(ad, sc);
                     // If the import declaration is in non-root module,
                     // analysis of the aliased symbol is deferred.
@@ -1141,7 +1132,7 @@ public:
                 {
                     Dsymbol *s = imp->mod->search_correct(imp->names[i]);
                     if (s)
-                        imp->mod->error(imp->loc, "import `%s` not found, did you mean %s `%s`?", imp->names[i]->toChars(), s->kind(), s->toChars());
+                        imp->mod->error(imp->loc, "import `%s` not found, did you mean %s `%s`?", imp->names[i]->toChars(), s->kind(), s->toPrettyChars());
                     else
                         imp->mod->error(imp->loc, "import `%s` not found", imp->names[i]->toChars());
                     ad->type = Type::terror;
@@ -1312,8 +1303,6 @@ public:
                     e = expressionSemantic(e, sc);
                     e = resolveProperties(sc, e);
                     sc = sc->endCTFE();
-
-                    // pragma(msg) is allowed to contain types as well as expressions
                     e = ctfeInterpretForPragmaMsg(e);
                     if (e->op == TOKerror)
                     {
@@ -1458,6 +1447,12 @@ public:
                 }
             }
         }
+        else if (pd->ident == Id::printf || pd->ident == Id::scanf)
+        {
+            if (pd->args && pd->args->length != 0)
+                pd->error("takes no argument");
+            goto Ldecl;
+        }
         else if (global.params.ignoreUnsupportedPragmas)
         {
             if (global.params.verbose)
@@ -1547,13 +1542,14 @@ public:
     Dsymbols *compileIt(CompileDeclaration *cd)
     {
         //printf("CompileDeclaration::compileIt(loc = %d) %s\n", cd->loc.linnum, cd->exp->toChars());
-        StringExp *se = semanticString(sc, cd->exp, "argument to mixin");
-        if (!se)
+        OutBuffer buf;
+        if (expressionsToString(buf, sc, cd->exps))
             return NULL;
-        se = se->toUTF8(sc);
 
         unsigned errors = global.errors;
-        Parser p(cd->loc, sc->_module, (utf8_t *)se->string, se->len, 0);
+        const size_t len = buf.length();
+        const char *str = buf.extractChars();
+        Parser p(cd->loc, sc->_module, (const utf8_t *)str, len, false);
         p.nextToken();
 
         Dsymbols *d = p.parseDeclDefs(0);
@@ -1562,7 +1558,7 @@ public:
 
         if (p.token.value != TOKeof)
         {
-            cd->exp->error("incomplete mixin declaration (%s)", se->toChars());
+            cd->error("incomplete mixin declaration (%s)", str);
             return NULL;
         }
         return d;
@@ -1637,7 +1633,7 @@ public:
         Scope *sc = m->_scope;                  // see if already got one from importAll()
         if (!sc)
         {
-            Scope::createGlobal(m);      // create root scope
+            sc = Scope::createGlobal(m);      // create root scope
         }
 
         //printf("Module = %p, linkage = %d\n", sc->scopesym, sc->linkage);
@@ -1735,7 +1731,7 @@ public:
                     // memtype is forward referenced, so try again later
                     ed->_scope = scx ? scx : sc->copy();
                     ed->_scope->setNoFree();
-                    ed->_scope->_module->addDeferredSemantic(ed);
+                    Module::addDeferredSemantic(ed);
                     Module::dprogress = dprogress_save;
                     //printf("\tdeferring %s\n", ed->toChars());
                     ed->semanticRun = PASSinit;
@@ -2233,7 +2229,7 @@ public:
                 //printf("forward reference - deferring\n");
                 tm->_scope = scx ? scx : sc->copy();
                 tm->_scope->setNoFree();
-                tm->_scope->_module->addDeferredSemantic(tm);
+                Module::addDeferredSemantic(tm);
                 return;
             }
 
@@ -2457,6 +2453,23 @@ public:
         ns->semanticRun = PASSsemanticdone;
     }
 
+
+private:
+    static bool isPointerToChar(Parameter *p)
+    {
+        if (TypePointer *tptr = p->type->isTypePointer())
+        {
+            return tptr->next->ty == Tchar;
+        }
+        return false;
+    }
+
+    static bool isVa_list(Parameter *p, FuncDeclaration *funcdecl, Scope *sc)
+    {
+        return p->type->equals(target.va_listType(funcdecl->loc, sc));
+    }
+
+public:
     void funcDeclarationSemantic(FuncDeclaration *funcdecl)
     {
         TypeFunction *f;
@@ -2771,6 +2784,45 @@ public:
         if (funcdecl->isAbstract() && funcdecl->isFinalFunc())
             funcdecl->error("cannot be both final and abstract");
 
+        if (const unsigned pors = sc->flags & (SCOPEprintf | SCOPEscanf))
+        {
+            /* printf/scanf-like functions must be of the form:
+             *    extern (C/C++) T printf([parameters...], const(char)* format, ...);
+             * or:
+             *    extern (C/C++) T vprintf([parameters...], const(char)* format, va_list);
+             */
+            const size_t nparams = f->parameterList.length();
+            if ((f->linkage == LINKc || f->linkage == LINKcpp) &&
+
+                ((f->parameterList.varargs == VARARGvariadic &&
+                  nparams >= 1 &&
+                  isPointerToChar(f->parameterList[nparams - 1])) ||
+                 (f->parameterList.varargs == VARARGnone &&
+                  nparams >= 2 &&
+                  isPointerToChar(f->parameterList[nparams - 2]) &&
+                  isVa_list(f->parameterList[nparams - 1], funcdecl, sc))
+                )
+               )
+            {
+                funcdecl->flags |= (pors == SCOPEprintf) ? FUNCFLAGprintf : FUNCFLAGscanf;
+            }
+            else
+            {
+                const char *p = (pors == SCOPEprintf ? Id::printf : Id::scanf)->toChars();
+                if (f->parameterList.varargs == VARARGvariadic)
+                {
+                    funcdecl->error("`pragma(%s)` functions must be `extern(C) %s %s([parameters...], const(char)*, ...)`"
+                                    " not `%s`",
+                        p, f->next->toChars(), funcdecl->toChars(), funcdecl->type->toChars());
+                }
+                else
+                {
+                    funcdecl->error("`pragma(%s)` functions must be `extern(C) %s %s([parameters...], const(char)*, va_list)`",
+                        p, f->next->toChars(), funcdecl->toChars());
+                }
+            }
+        }
+
         id = parent->isInterfaceDeclaration();
         if (id)
         {
@@ -3831,7 +3883,7 @@ public:
 
             sd->_scope = scx ? scx : sc->copy();
             sd->_scope->setNoFree();
-            sd->_scope->_module->addDeferredSemantic(sd);
+            Module::addDeferredSemantic(sd);
 
             //printf("\tdeferring %s\n", sd->toChars());
             return;
@@ -4079,7 +4131,7 @@ public:
                 {
                     //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
                     if (tc->sym->_scope)
-                        tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
+                        Module::addDeferredSemantic(tc->sym);
                     cldec->baseok = BASEOKnone;
                 }
              L7: ;
@@ -4131,7 +4183,7 @@ public:
                 {
                     //printf("\ttry later, forward reference of base %s\n", tc->sym->toChars());
                     if (tc->sym->_scope)
-                        tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
+                        Module::addDeferredSemantic(tc->sym);
                     cldec->baseok = BASEOKnone;
                 }
                 i++;
@@ -4141,7 +4193,7 @@ public:
                 // Forward referencee of one or more bases, try again later
                 cldec->_scope = scx ? scx : sc->copy();
                 cldec->_scope->setNoFree();
-                cldec->_scope->_module->addDeferredSemantic(cldec);
+                Module::addDeferredSemantic(cldec);
                 //printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, cldec->toChars());
                 return;
             }
@@ -4254,8 +4306,8 @@ public:
                 cldec->_scope = scx ? scx : sc->copy();
                 cldec->_scope->setNoFree();
                 if (tc->sym->_scope)
-                    tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
-                cldec->_scope->_module->addDeferredSemantic(cldec);
+                    Module::addDeferredSemantic(tc->sym);
+                Module::addDeferredSemantic(cldec);
                 //printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, cldec->toChars());
                 return;
             }
@@ -4359,7 +4411,7 @@ public:
 
             cldec->_scope = scx ? scx : sc->copy();
             cldec->_scope->setNoFree();
-            cldec->_scope->_module->addDeferredSemantic(cldec);
+            Module::addDeferredSemantic(cldec);
             //printf("\tdeferring %s\n", cldec->toChars());
             return;
         }
@@ -4628,7 +4680,7 @@ public:
                 {
                     //printf("\ttry later, forward reference of base %s\n", tc->sym->toChars());
                     if (tc->sym->_scope)
-                        tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
+                        Module::addDeferredSemantic(tc->sym);
                     idec->baseok = BASEOKnone;
                 }
                 i++;
@@ -4638,7 +4690,7 @@ public:
                 // Forward referencee of one or more bases, try again later
                 idec->_scope = scx ? scx : sc->copy();
                 idec->_scope->setNoFree();
-                idec->_scope->_module->addDeferredSemantic(idec);
+                Module::addDeferredSemantic(idec);
                 return;
             }
             idec->baseok = BASEOKdone;
@@ -4682,8 +4734,8 @@ public:
                 idec->_scope = scx ? scx : sc->copy();
                 idec->_scope->setNoFree();
                 if (tc->sym->_scope)
-                    tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
-                idec->_scope->_module->addDeferredSemantic(idec);
+                    Module::addDeferredSemantic(tc->sym);
+                Module::addDeferredSemantic(idec);
                 return;
             }
         }
@@ -5335,6 +5387,7 @@ void aliasSemantic(AliasDeclaration *ds, Scope *sc)
     ds->userAttribDecl = sc->userAttribDecl;
 
     // TypeTraits needs to know if it's located in an AliasDeclaration
+    const unsigned oldflags = sc->flags;
     sc->flags |= SCOPEalias;
 
     if (ds->aliassym)
@@ -5345,7 +5398,7 @@ void aliasSemantic(AliasDeclaration *ds, Scope *sc)
         {
             if (fd && fd->semanticRun >= PASSsemanticdone)
             {
-                sc->flags &= ~SCOPEalias;
+                sc->flags = oldflags;
                 return;
             }
 
@@ -5361,13 +5414,13 @@ void aliasSemantic(AliasDeclaration *ds, Scope *sc)
                 ds->aliassym = NULL;
                 ds->type = Type::terror;
             }
-            sc->flags &= ~SCOPEalias;
+            sc->flags = oldflags;
             return;
         }
 
         if (ds->aliassym->isTemplateInstance())
             dsymbolSemantic(ds->aliassym, sc);
-        sc->flags &= ~SCOPEalias;
+        sc->flags = oldflags;
         return;
     }
     ds->inuse = 1;
@@ -5472,7 +5525,7 @@ void aliasSemantic(AliasDeclaration *ds, Scope *sc)
         if (!ds->overloadInsert(sx))
             ScopeDsymbol::multiplyDefined(Loc(), sx, ds);
     }
-    sc->flags &= ~SCOPEalias;
+    sc->flags = oldflags;
 }
 
 
diff --git a/gcc/d/dmd/dtemplate.c b/gcc/d/dmd/dtemplate.c
index b868e9ad388..208b064aafb 100644
--- a/gcc/d/dmd/dtemplate.c
+++ b/gcc/d/dmd/dtemplate.c
@@ -156,17 +156,14 @@ Dsymbol *getDsymbol(RootObject *oarg)
     if (ea)
     {
         // Try to convert Expression to symbol
-        if (ea->op == TOKvar)
-            sa = ((VarExp *)ea)->var;
-        else if (ea->op == TOKfunction)
-        {
-            if (((FuncExp *)ea)->td)
-                sa = ((FuncExp *)ea)->td;
-            else
-                sa = ((FuncExp *)ea)->fd;
-        }
-        else if (ea->op == TOKtemplate)
-            sa = ((TemplateExp *)ea)->td;
+        if (VarExp *ve = ea->isVarExp())
+            sa = ve->var;
+        else if (FuncExp *fe = ea->isFuncExp())
+            sa = fe->td ? (Dsymbol *)fe->td : (Dsymbol *)fe->fd;
+        else if (TemplateExp *te = ea->isTemplateExp())
+            sa = te->td;
+        else if (ScopeExp *se = ea->isScopeExp())
+            sa = se->sds;
         else
             sa = NULL;
     }
@@ -536,6 +533,7 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
     this->isstatic = true;
     this->previous = NULL;
     this->protection = Prot(Prot::undefined);
+    this->inuse = 0;
     this->instances = NULL;
 
     // Compute in advance for Ddoc's use
@@ -770,7 +768,9 @@ MATCH TemplateDeclaration::matchWithInstance(Scope *sc, TemplateInstance *ti,
         Declaration *sparam;
 
         //printf("\targument [%d]\n", i);
+        inuse++;
         m2 = tp->matchArg(ti->loc, paramscope, ti->tiargs, i, parameters, dedtypes, &sparam);
+        inuse--;
         //printf("\tm2 = %d\n", m2);
 
         if (m2 == MATCHnomatch)
@@ -1397,7 +1397,9 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(
                         }
                         else
                         {
+                            inuse++;
                             oded = tparam->defaultArg(instLoc, paramscope);
+                            inuse--;
                             if (oded)
                                 (*dedargs)[i] = declareParameter(paramscope, tparam, oded);
                         }
@@ -1771,7 +1773,9 @@ Lmatch:
             }
             else
             {
+                inuse++;
                 oded = tparam->defaultArg(instLoc, paramscope);
+                inuse--;
                 if (!oded)
                 {
                     // if tuple parameter and
@@ -1997,18 +2001,19 @@ bool TemplateDeclaration::isOverloadable()
 /*************************************************
  * Given function arguments, figure out which template function
  * to expand, and return matching result.
- * Input:
- *      m               matching result
- *      dstart          the root of overloaded function templates
- *      loc             instantiation location
- *      sc              instantiation scope
- *      tiargs          initial list of template arguments
- *      tthis           if !NULL, the 'this' pointer argument
- *      fargs           arguments to function
+ * Params:
+ *      m           = matching result
+ *      dstart      = the root of overloaded function templates
+ *      loc         = instantiation location
+ *      sc          = instantiation scope
+ *      tiargs      = initial list of template arguments
+ *      tthis       = if !NULL, the 'this' pointer argument
+ *      fargs       = arguments to function
+ *      pMessage    = address to store error message, or null
  */
 
 void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
-        Objects *tiargs, Type *tthis, Expressions *fargs)
+    Objects *tiargs, Type *tthis, Expressions *fargs, const char **pMessage)
 {
     struct ParamDeduce
     {
@@ -2018,6 +2023,7 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
         Type *tthis;
         Objects *tiargs;
         Expressions *fargs;
+        const char **pMessage;
         // result
         Match *m;
         int property;   // 0: unintialized
@@ -2093,7 +2099,7 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
                 else
                     return 0;   // MATCHnomatch
             }
-            MATCH mfa = tf->callMatch(tthis_fd, fargs);
+            MATCH mfa = tf->callMatch(tthis_fd, fargs, 0, pMessage);
             //printf("test1: mfa = %d\n", mfa);
             if (mfa > MATCHnomatch)
             {
@@ -2180,8 +2186,12 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
         int applyTemplate(TemplateDeclaration *td)
         {
             //printf("applyTemplate()\n");
-            // skip duplicates
-            if (td == td_best)
+            if (td->inuse)
+            {
+                td->error(loc, "recursive template expansion");
+                return 1;
+            }
+            if (td == td_best)  // skip duplicates
                 return 0;
 
             if (!sc)
@@ -2431,6 +2441,7 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
     p.tthis  = tthis;
     p.tiargs = tiargs;
     p.fargs  = fargs;
+    p.pMessage = pMessage;
 
     // result
     p.m          = m;
@@ -5165,6 +5176,16 @@ MATCH TemplateAliasParameter::matchArg(Scope *sc, RootObject *oarg,
              *  template X(T) {}        // T => sa
              */
         }
+        else if (ta && ta->ty != Tident)
+        {
+            /* Match any type that's not a TypeIdentifier to alias parameters,
+             * but prefer type parameter.
+             * template X(alias a) { }  // a == ta
+             *
+             * TypeIdentifiers are excluded because they might be not yet resolved aliases.
+             */
+            m = MATCHconvert;
+        }
         else
             goto Lnomatch;
     }
@@ -5485,12 +5506,15 @@ RootObject *TemplateValueParameter::defaultArg(Loc instLoc, Scope *sc)
     if (e)
     {
         e = e->syntaxCopy();
+        unsigned olderrs = global.errors;
         if ((e = expressionSemantic(e, sc)) == NULL)
             return NULL;
         if ((e = resolveProperties(sc, e)) == NULL)
             return NULL;
         e = e->resolveLoc(instLoc, sc);     // use the instantiated loc
         e = e->optimize(WANTvalue);
+        if (global.errors != olderrs)
+            e = new ErrorExp();
     }
     return e;
 }
@@ -6049,6 +6073,7 @@ bool TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
         if (ta)
         {
             //printf("type %s\n", ta->toChars());
+
             // It might really be an Expression or an Alias
             ta->resolve(loc, sc, &ea, &ta, &sa, (flags & 1) != 0);
             if (ea) goto Lexpr;
@@ -6270,6 +6295,7 @@ bool TemplateInstance::findBestMatch(Scope *sc, Expressions *fargs)
     }
 
     unsigned errs = global.errors;
+    TemplateDeclaration *td_last = NULL;
 
   struct ParamBest
   {
@@ -6291,7 +6317,11 @@ bool TemplateInstance::findBestMatch(Scope *sc, Expressions *fargs)
         TemplateDeclaration *td = s->isTemplateDeclaration();
         if (!td)
             return 0;
-
+        if (td->inuse)
+        {
+            td->error(ti->loc, "recursive template expansion");
+            return 1;
+        }
         if (td == td_best)          // skip duplicates
             return 0;
 
@@ -6349,8 +6379,6 @@ bool TemplateInstance::findBestMatch(Scope *sc, Expressions *fargs)
     /* Since there can be multiple TemplateDeclaration's with the same
      * name, look for the best match.
      */
-    TemplateDeclaration *td_last = NULL;
-
     OverloadSet *tovers = tempdecl->isOverloadSet();
     size_t overs_dim = tovers ? tovers->a.length : 1;
     for (size_t oi = 0; oi < overs_dim; oi++)
@@ -6359,7 +6387,9 @@ bool TemplateInstance::findBestMatch(Scope *sc, Expressions *fargs)
         p.td_best  = NULL;
         p.td_ambig = NULL;
         p.m_best   = MATCHnomatch;
-        overloadApply(tovers ? tovers->a[oi] : tempdecl, &p, &ParamBest::fp);
+
+        Dsymbol *dstart = tovers ? tovers->a[oi] : tempdecl;
+        overloadApply(dstart, &p, &ParamBest::fp);
 
         if (p.td_ambig)
         {
@@ -6481,8 +6511,11 @@ bool TemplateInstance::needsTypeInference(Scope *sc, int flag)
     {
         TemplateDeclaration *td = s->isTemplateDeclaration();
         if (!td)
-        {
             return 0;
+        if (td->inuse)
+        {
+            td->error(ti->loc, "recursive template expansion");
+            return 1;
         }
 
         /* If any of the overloaded template declarations need inference,
@@ -7128,6 +7161,68 @@ void unSpeculative(Scope *sc, RootObject *o)
         unSpeculative(sc, ti);
 }
 
+/**
+    Returns: true if the instances' innards are discardable.
+
+    The idea of this function is to see if the template instantiation
+    can be 100% replaced with its eponymous member. All other members
+    can be discarded, even in the compiler to free memory (for example,
+    the template could be expanded in a region allocator, deemed trivial,
+    the end result copied back out independently and the entire region freed),
+    and can be elided entirely from the binary.
+
+    The current implementation affects code that generally looks like:
+
+    ---
+    template foo(args...) {
+        some_basic_type_or_string helper() { .... }
+        enum foo = helper();
+    }
+    ---
+
+    since it was the easiest starting point of implementation but it can and
+    should be expanded more later.
+*/
+static bool isDiscardable(TemplateInstance *ti)
+{
+    if (ti->aliasdecl == NULL)
+        return false;
+
+    VarDeclaration *v = ti->aliasdecl->isVarDeclaration();
+    if (v == NULL)
+        return false;
+
+    if (!(v->storage_class & STCmanifest))
+        return false;
+
+    // Currently only doing basic types here because it is the easiest proof-of-concept
+    // implementation with minimal risk of side effects, but it could likely be
+    // expanded to any type that already exists outside this particular instance.
+    if (!(v->type->equals(Type::tstring) || (v->type->isTypeBasic() != NULL)))
+        return false;
+
+    // Static ctors and dtors, even in an eponymous enum template, are still run,
+    // so if any of them are in here, we'd better not assume it is trivial lest
+    // we break useful code
+    for (size_t i = 0; i < ti->members->length; i++)
+    {
+        Dsymbol *member = (*ti->members)[i];
+        if (member->hasStaticCtorOrDtor())
+            return false;
+        if (member->isStaticDtorDeclaration())
+            return false;
+        if (member->isStaticCtorDeclaration())
+            return false;
+    }
+
+    // but if it passes through this gauntlet... it should be fine. D code will
+    // see only the eponymous member, outside stuff can never access it, even through
+    // reflection; the outside world ought to be none the wiser. Even dmd should be
+    // able to simply free the memory of everything except the final result.
+
+    return true;
+}
+
 /***********************************************
  * Returns true if this is not instantiated in non-root module, and
  * is a part of non-speculative instantiatiation.
@@ -7137,38 +7232,6 @@ void unSpeculative(Scope *sc, RootObject *o)
  */
 bool TemplateInstance::needsCodegen()
 {
-    // Now -allInst is just for the backward compatibility.
-    if (global.params.allInst)
-    {
-        //printf("%s minst = %s, enclosing (%s)->isNonRoot = %d\n",
-        //    toPrettyChars(), minst ? minst->toChars() : NULL,
-        //    enclosing ? enclosing->toPrettyChars() : NULL, enclosing && enclosing->inNonRoot());
-        if (enclosing)
-        {
-            // Bugzilla 14588: If the captured context is not a function
-            // (e.g. class), the instance layout determination is guaranteed,
-            // because the semantic/semantic2 pass will be executed
-            // even for non-root instances.
-            if (!enclosing->isFuncDeclaration())
-                return true;
-
-            // Bugzilla 14834: If the captured context is a function,
-            // this excessive instantiation may cause ODR violation, because
-            // -allInst and others doesn't guarantee the semantic3 execution
-            // for that function.
-
-            // If the enclosing is also an instantiated function,
-            // we have to rely on the ancestor's needsCodegen() result.
-            if (TemplateInstance *ti = enclosing->isInstantiated())
-                return ti->needsCodegen();
-
-            // Bugzilla 13415: If and only if the enclosing scope needs codegen,
-            // this nested templates would also need code generation.
-            return !enclosing->inNonRoot();
-        }
-        return true;
-    }
-
     if (!minst)
     {
         // If this is a speculative instantiation,
@@ -7185,6 +7248,10 @@ bool TemplateInstance::needsCodegen()
         if (tinst && tinst->needsCodegen())
         {
             minst = tinst->minst;   // cache result
+            if (global.params.allInst && minst)
+            {
+                return true;
+            }
             assert(minst);
             assert(minst->isRoot() || minst->rootImports());
             return true;
@@ -7192,6 +7259,10 @@ bool TemplateInstance::needsCodegen()
         if (tnext && (tnext->needsCodegen() || tnext->minst))
         {
             minst = tnext->minst;   // cache result
+            if (global.params.allInst && minst)
+            {
+                return true;
+            }
             assert(minst);
             return minst->isRoot() || minst->rootImports();
         }
@@ -7200,6 +7271,16 @@ bool TemplateInstance::needsCodegen()
         return false;
     }
 
+    if (global.params.allInst)
+    {
+        return true;
+    }
+
+    if (isDiscardable(this))
+    {
+        return false;
+    }
+
     /* Even when this is reached to the codegen pass,
      * a non-root nested template should not generate code,
      * due to avoid ODR violation.
@@ -7221,14 +7302,7 @@ bool TemplateInstance::needsCodegen()
         return false;
     }
 
-    /* The issue is that if the importee is compiled with a different -debug
-     * setting than the importer, the importer may believe it exists
-     * in the compiled importee when it does not, when the instantiation
-     * is behind a conditional debug declaration.
-     */
-    // workaround for Bugzilla 11239
-    if (global.params.useUnitTests ||
-        global.params.debuglevel)
+    if (global.params.useUnitTests)
     {
         // Prefer instantiations from root modules, to maximize link-ability.
         if (minst->isRoot())
diff --git a/gcc/d/dmd/expression.c b/gcc/d/dmd/expression.c
index c90392d16a2..2592b38d961 100644
--- a/gcc/d/dmd/expression.c
+++ b/gcc/d/dmd/expression.c
@@ -43,110 +43,10 @@ VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e);
 Expression *extractSideEffect(Scope *sc, const char *name, Expression **e0, Expression *e, bool alwaysCopy = false);
 char *MODtoChars(MOD mod);
 bool MODimplicitConv(MOD modfrom, MOD modto);
-MOD MODmerge(MOD mod1, MOD mod2);
 void MODMatchToBuffer(OutBuffer *buf, unsigned char lhsMod, unsigned char rhsMod);
 Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads);
 bool checkUnsafeAccess(Scope *sc, Expression *e, bool readonly, bool printmsg);
-
-/*************************************************************
- * Given var, we need to get the
- * right 'this' pointer if var is in an outer class, but our
- * existing 'this' pointer is in an inner class.
- * Input:
- *      e1      existing 'this'
- *      ad      struct or class we need the correct 'this' for
- *      var     the specific member of ad we're accessing
- */
-
-Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad,
-        Expression *e1, Declaration *var, int flag = 0)
-{
-    //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1->toChars(), ad->toChars(), var->toChars());
- L1:
-    Type *t = e1->type->toBasetype();
-    //printf("e1->type = %s, var->type = %s\n", e1->type->toChars(), var->type->toChars());
-
-    /* If e1 is not the 'this' pointer for ad
-     */
-    if (ad &&
-        !(t->ty == Tpointer && t->nextOf()->ty == Tstruct &&
-          ((TypeStruct *)t->nextOf())->sym == ad)
-        &&
-        !(t->ty == Tstruct &&
-          ((TypeStruct *)t)->sym == ad)
-       )
-    {
-        ClassDeclaration *cd = ad->isClassDeclaration();
-        ClassDeclaration *tcd = t->isClassHandle();
-
-        /* e1 is the right this if ad is a base class of e1
-         */
-        if (!cd || !tcd ||
-            !(tcd == cd || cd->isBaseOf(tcd, NULL))
-           )
-        {
-            /* Only classes can be inner classes with an 'outer'
-             * member pointing to the enclosing class instance
-             */
-            if (tcd && tcd->isNested())
-            {
-                /* e1 is the 'this' pointer for an inner class: tcd.
-                 * Rewrite it as the 'this' pointer for the outer class.
-                 */
-
-                e1 = new DotVarExp(loc, e1, tcd->vthis);
-                e1->type = tcd->vthis->type;
-                e1->type = e1->type->addMod(t->mod);
-                // Do not call checkNestedRef()
-                //e1 = expressionSemantic(e1, sc);
-
-                // Skip up over nested functions, and get the enclosing
-                // class type.
-                int n = 0;
-                Dsymbol *s;
-                for (s = tcd->toParent();
-                     s && s->isFuncDeclaration();
-                     s = s->toParent())
-                {
-                    FuncDeclaration *f = s->isFuncDeclaration();
-                    if (f->vthis)
-                    {
-                        //printf("rewriting e1 to %s's this\n", f->toChars());
-                        n++;
-                        e1 = new VarExp(loc, f->vthis);
-                    }
-                    else
-                    {
-                        e1->error("need `this` of type %s to access member %s"
-                                  " from static function %s",
-                            ad->toChars(), var->toChars(), f->toChars());
-                        e1 = new ErrorExp();
-                        return e1;
-                    }
-                }
-                if (s && s->isClassDeclaration())
-                {
-                    e1->type = s->isClassDeclaration()->type;
-                    e1->type = e1->type->addMod(t->mod);
-                    if (n > 1)
-                        e1 = expressionSemantic(e1, sc);
-                }
-                else
-                    e1 = expressionSemantic(e1, sc);
-                goto L1;
-            }
-
-            /* Can't find a path from e1 to ad
-             */
-            if (flag)
-                return NULL;
-            e1->error("this for %s needs to be type %s not type %s",
-                var->toChars(), ad->toChars(), t->toChars());
-            return new ErrorExp();
-        }
-    }
-    return e1;
-}
+void toAutoQualChars(const char **result, Type *t1, Type *t2);
 
 /*****************************************
  * Determine if 'this' is available.
@@ -230,817 +130,112 @@ bool isNeedThisScope(Scope *sc, Declaration *d)
     return true;
 }
 
-/***************************************
- * Pull out any properties.
+/******************************
+ * check e is exp.opDispatch!(tiargs) or not
+ * It's used to switch to UFCS the semantic analysis path
  */
 
-Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL)
+bool isDotOpDispatch(Expression *e)
 {
-    //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", Token::toChars(e1->op), e1->toChars(), e2 ? e2->toChars() : NULL);
-    Loc loc = e1->loc;
-
-    OverloadSet *os;
-    Dsymbol *s;
-    Objects *tiargs;
-    Type *tthis;
-    if (e1->op == TOKdot)
-    {
-        DotExp *de = (DotExp *)e1;
-        if (de->e2->op == TOKoverloadset)
-        {
-            tiargs = NULL;
-            tthis  = de->e1->type;
-            os = ((OverExp *)de->e2)->vars;
-            goto Los;
-        }
-    }
-    else if (e1->op == TOKoverloadset)
-    {
-        tiargs = NULL;
-        tthis  = NULL;
-        os = ((OverExp *)e1)->vars;
-    Los:
-        assert(os);
-        FuncDeclaration *fd = NULL;
-        if (e2)
-        {
-            e2 = expressionSemantic(e2, sc);
-            if (e2->op == TOKerror)
-                return new ErrorExp();
-            e2 = resolveProperties(sc, e2);
+    return e->op == TOKdotti &&
+           ((DotTemplateInstanceExp *)e)->ti->name == Id::opDispatch;
+}
 
-            Expressions a;
-            a.push(e2);
+/****************************************
+ * Expand tuples.
+ * Input:
+ *      exps    aray of Expressions
+ * Output:
+ *      exps    rewritten in place
+ */
 
-            for (size_t i = 0; i < os->a.length; i++)
-            {
-                FuncDeclaration *f = resolveFuncCall(loc, sc, os->a[i], tiargs, tthis, &a, 1);
-                if (f)
-                {
-                    if (f->errors)
-                        return new ErrorExp();
-                    fd = f;
-                    assert(fd->type->ty == Tfunction);
-                }
-            }
-            if (fd)
-            {
-                Expression *e = new CallExp(loc, e1, e2);
-                return expressionSemantic(e, sc);
-            }
-        }
-        {
-            for (size_t i = 0; i < os->a.length; i++)
-            {
-                FuncDeclaration *f = resolveFuncCall(loc, sc, os->a[i], tiargs, tthis, NULL, 1);
-                if (f)
-                {
-                    if (f->errors)
-                        return new ErrorExp();
-                    fd = f;
-                    assert(fd->type->ty == Tfunction);
-                    TypeFunction *tf = (TypeFunction *)fd->type;
-                    if (!tf->isref && e2)
-                        goto Leproplvalue;
-                }
-            }
-            if (fd)
-            {
-                Expression *e = new CallExp(loc, e1);
-                if (e2)
-                    e = new AssignExp(loc, e, e2);
-                return expressionSemantic(e, sc);
-            }
-        }
-        if (e2)
-            goto Leprop;
-    }
-    else if (e1->op == TOKdotti)
-    {
-        DotTemplateInstanceExp* dti = (DotTemplateInstanceExp *)e1;
-        if (!dti->findTempDecl(sc))
-            goto Leprop;
-        if (!dti->ti->semanticTiargs(sc))
-            goto Leprop;
-        tiargs = dti->ti->tiargs;
-        tthis  = dti->e1->type;
-        if ((os = dti->ti->tempdecl->isOverloadSet()) != NULL)
-            goto Los;
-        if ((s = dti->ti->tempdecl) != NULL)
-            goto Lfd;
-    }
-    else if (e1->op == TOKdottd)
-    {
-        DotTemplateExp *dte = (DotTemplateExp *)e1;
-        s      = dte->td;
-        tiargs = NULL;
-        tthis  = dte->e1->type;
-        goto Lfd;
-    }
-    else if (e1->op == TOKscope)
-    {
-        s = ((ScopeExp *)e1)->sds;
-        TemplateInstance *ti = s->isTemplateInstance();
-        if (ti && !ti->semanticRun && ti->tempdecl)
-        {
-            //assert(ti->needsTypeInference(sc));
-            if (!ti->semanticTiargs(sc))
-                goto Leprop;
-            tiargs = ti->tiargs;
-            tthis  = NULL;
-            if ((os = ti->tempdecl->isOverloadSet()) != NULL)
-                goto Los;
-            if ((s = ti->tempdecl) != NULL)
-                goto Lfd;
-        }
-    }
-    else if (e1->op == TOKtemplate)
-    {
-        s      = ((TemplateExp *)e1)->td;
-        tiargs = NULL;
-        tthis  = NULL;
-        goto Lfd;
-    }
-    else if (e1->op == TOKdotvar && e1->type && e1->type->toBasetype()->ty == Tfunction)
-    {
-        DotVarExp *dve = (DotVarExp *)e1;
-        s      = dve->var->isFuncDeclaration();
-        tiargs = NULL;
-        tthis  = dve->e1->type;
-        goto Lfd;
-    }
-    else if (e1->op == TOKvar && e1->type && e1->type->toBasetype()->ty == Tfunction)
+void expandTuples(Expressions *exps)
+{
+    //printf("expandTuples()\n");
+    if (exps)
     {
-        s      = ((VarExp *)e1)->var->isFuncDeclaration();
-        tiargs = NULL;
-        tthis  = NULL;
-    Lfd:
-        assert(s);
-        if (e2)
+        for (size_t i = 0; i < exps->length; i++)
         {
-            e2 = expressionSemantic(e2, sc);
-            if (e2->op == TOKerror)
-                return new ErrorExp();
-            e2 = resolveProperties(sc, e2);
-
-            Expressions a;
-            a.push(e2);
+            Expression *arg = (*exps)[i];
+            if (!arg)
+                continue;
 
-            FuncDeclaration *fd = resolveFuncCall(loc, sc, s, tiargs, tthis, &a, 1);
-            if (fd && fd->type)
-            {
-                if (fd->errors)
-                    return new ErrorExp();
-                assert(fd->type->ty == Tfunction);
-                Expression *e = new CallExp(loc, e1, e2);
-                return expressionSemantic(e, sc);
-            }
-        }
-        {
-            FuncDeclaration *fd = resolveFuncCall(loc, sc, s, tiargs, tthis, NULL, 1);
-            if (fd && fd->type)
+            // Look for tuple with 0 members
+            if (arg->op == TOKtype)
             {
-                if (fd->errors)
-                    return new ErrorExp();
-                assert(fd->type->ty == Tfunction);
-                TypeFunction *tf = (TypeFunction *)fd->type;
-                if (!e2 || tf->isref)
+                TypeExp *e = (TypeExp *)arg;
+                if (e->type->toBasetype()->ty == Ttuple)
                 {
-                    Expression *e = new CallExp(loc, e1);
-                    if (e2)
-                        e = new AssignExp(loc, e, e2);
-                    return expressionSemantic(e, sc);
-                }
-            }
-        }
-        if (FuncDeclaration *fd = s->isFuncDeclaration())
-        {
-            // Keep better diagnostic message for invalid property usage of functions
-            assert(fd->type->ty == Tfunction);
-            Expression *e = new CallExp(loc, e1, e2);
-            return expressionSemantic(e, sc);
-        }
-        if (e2)
-            goto Leprop;
-    }
-    if (e1->op == TOKvar)
-    {
-        VarExp *ve = (VarExp *)e1;
-        VarDeclaration *v = ve->var->isVarDeclaration();
-        if (v && ve->checkPurity(sc, v))
-            return new ErrorExp();
-    }
-    if (e2)
-        return NULL;
-
-    if (e1->type &&
-        e1->op != TOKtype)      // function type is not a property
-    {
-        /* Look for e1 being a lazy parameter; rewrite as delegate call
-         */
-        if (e1->op == TOKvar)
-        {
-            VarExp *ve = (VarExp *)e1;
+                    TypeTuple *tt = (TypeTuple *)e->type->toBasetype();
 
-            if (ve->var->storage_class & STClazy)
-            {
-                Expression *e = new CallExp(loc, e1);
-                return expressionSemantic(e, sc);
+                    if (!tt->arguments || tt->arguments->length == 0)
+                    {
+                        exps->remove(i);
+                        if (i == exps->length)
+                            return;
+                        i--;
+                        continue;
+                    }
+                }
             }
-        }
-        else if (e1->op == TOKdotvar)
-        {
-            // Check for reading overlapped pointer field in @safe code.
-            if (checkUnsafeAccess(sc, e1, true, true))
-                return new ErrorExp();
-        }
-        else if (e1->op == TOKdot)
-        {
-            e1->error("expression has no value");
-            return new ErrorExp();
-        }
-        else if (e1->op == TOKcall)
-        {
-            CallExp *ce = (CallExp *)e1;
-            // Check for reading overlapped pointer field in @safe code.
-            if (checkUnsafeAccess(sc, ce->e1, true, true))
-                return new ErrorExp();
-        }
-    }
-
-    if (!e1->type)
-    {
-        error(loc, "cannot resolve type for %s", e1->toChars());
-        e1 = new ErrorExp();
-    }
-    return e1;
-
-Leprop:
-    error(loc, "not a property %s", e1->toChars());
-    return new ErrorExp();
-
-Leproplvalue:
-    error(loc, "%s is not an lvalue", e1->toChars());
-    return new ErrorExp();
-}
-
-Expression *resolveProperties(Scope *sc, Expression *e)
-{
-    //printf("resolveProperties(%s)\n", e->toChars());
-
-    e = resolvePropertiesX(sc, e);
-    if (e->checkRightThis(sc))
-        return new ErrorExp();
-    return e;
-}
-
-/******************************
- * Check the tail CallExp is really property function call.
- */
-static bool checkPropertyCall(Expression *e)
-{
-    while (e->op == TOKcomma)
-        e = ((CommaExp *)e)->e2;
 
-    if (e->op == TOKcall)
-    {
-        CallExp *ce = (CallExp *)e;
-        TypeFunction *tf;
-        if (ce->f)
-        {
-            tf = (TypeFunction *)ce->f->type;
-            /* If a forward reference to ce->f, try to resolve it
-             */
-            if (!tf->deco && ce->f->semanticRun < PASSsemanticdone)
+            // Inline expand all the tuples
+            while (arg->op == TOKtuple)
             {
-                dsymbolSemantic(ce->f, NULL);
-                tf = (TypeFunction *)ce->f->type;
+                TupleExp *te = (TupleExp *)arg;
+                exps->remove(i);                // remove arg
+                exps->insert(i, te->exps);      // replace with tuple contents
+                if (i == exps->length)
+                    return;             // empty tuple, no more arguments
+                (*exps)[i] = Expression::combine(te->e0, (*exps)[i]);
+                arg = (*exps)[i];
             }
         }
-        else if (ce->e1->type->ty == Tfunction)
-            tf = (TypeFunction *)ce->e1->type;
-        else if (ce->e1->type->ty == Tdelegate)
-            tf = (TypeFunction *)ce->e1->type->nextOf();
-        else if (ce->e1->type->ty == Tpointer && ce->e1->type->nextOf()->ty == Tfunction)
-            tf = (TypeFunction *)ce->e1->type->nextOf();
-        else
-            assert(0);
     }
-    return false;
 }
 
-/******************************
- * If e1 is a property function (template), resolve it.
+/****************************************
+ * Expand alias this tuples.
  */
 
-Expression *resolvePropertiesOnly(Scope *sc, Expression *e1)
+TupleDeclaration *isAliasThisTuple(Expression *e)
 {
-    //printf("e1 = %s %s\n", Token::toChars(e1->op), e1->toChars());
-    OverloadSet *os;
-    FuncDeclaration *fd;
-    TemplateDeclaration *td;
+    if (!e->type)
+        return NULL;
 
-    if (e1->op == TOKdot)
-    {
-        DotExp *de = (DotExp *)e1;
-        if (de->e2->op == TOKoverloadset)
-        {
-            os = ((OverExp *)de->e2)->vars;
-            goto Los;
-        }
-    }
-    else if (e1->op == TOKoverloadset)
-    {
-        os = ((OverExp *)e1)->vars;
-    Los:
-        assert(os);
-        for (size_t i = 0; i < os->a.length; i++)
-        {
-            Dsymbol *s = os->a[i];
-            fd = s->isFuncDeclaration();
-            td = s->isTemplateDeclaration();
-            if (fd)
-            {
-                if (((TypeFunction *)fd->type)->isproperty)
-                    return resolveProperties(sc, e1);
-            }
-            else if (td && td->onemember &&
-                     (fd = td->onemember->isFuncDeclaration()) != NULL)
-            {
-                if (((TypeFunction *)fd->type)->isproperty ||
-                    (fd->storage_class2 & STCproperty) ||
-                    (td->_scope->stc & STCproperty))
-                {
-                    return resolveProperties(sc, e1);
-                }
-            }
-        }
-    }
-    else if (e1->op == TOKdotti)
-    {
-        DotTemplateInstanceExp* dti = (DotTemplateInstanceExp *)e1;
-        if (dti->ti->tempdecl && (td = dti->ti->tempdecl->isTemplateDeclaration()) != NULL)
-            goto Ltd;
-    }
-    else if (e1->op == TOKdottd)
-    {
-        td = ((DotTemplateExp *)e1)->td;
-        goto Ltd;
-    }
-    else if (e1->op == TOKscope)
-    {
-        Dsymbol *s = ((ScopeExp *)e1)->sds;
-        TemplateInstance *ti = s->isTemplateInstance();
-        if (ti && !ti->semanticRun && ti->tempdecl)
-        {
-            if ((td = ti->tempdecl->isTemplateDeclaration()) != NULL)
-                goto Ltd;
-        }
-    }
-    else if (e1->op == TOKtemplate)
+    Type *t = e->type->toBasetype();
+Lagain:
+    if (Dsymbol *s = t->toDsymbol(NULL))
     {
-        td = ((TemplateExp *)e1)->td;
-    Ltd:
-        assert(td);
-        if (td->onemember &&
-            (fd = td->onemember->isFuncDeclaration()) != NULL)
+        AggregateDeclaration *ad = s->isAggregateDeclaration();
+        if (ad)
         {
-            if (((TypeFunction *)fd->type)->isproperty ||
-                (fd->storage_class2 & STCproperty) ||
-                (td->_scope->stc & STCproperty))
+            s = ad->aliasthis;
+            if (s && s->isVarDeclaration())
             {
-                return resolveProperties(sc, e1);
+                TupleDeclaration *td = s->isVarDeclaration()->toAlias()->isTupleDeclaration();
+                if (td && td->isexp)
+                    return td;
             }
-        }
-    }
-    else if (e1->op == TOKdotvar && e1->type->ty == Tfunction)
-    {
-        DotVarExp *dve = (DotVarExp *)e1;
-        fd = dve->var->isFuncDeclaration();
-        goto Lfd;
-    }
-    else if (e1->op == TOKvar && e1->type->ty == Tfunction &&
-        (sc->intypeof || !((VarExp *)e1)->var->needThis()))
-    {
-        fd = ((VarExp *)e1)->var->isFuncDeclaration();
-    Lfd:
-        assert(fd);
-        if (((TypeFunction *)fd->type)->isproperty)
-            return resolveProperties(sc, e1);
-    }
-    return e1;
-}
-
-
-// TODO: merge with Scope::search::searchScopes()
-static Dsymbol *searchScopes(Scope *sc, Loc loc, Identifier *ident, int flags)
-{
-    Dsymbol *s = NULL;
-    for (Scope *scx = sc; scx; scx = scx->enclosing)
-    {
-        if (!scx->scopesym)
-            continue;
-        if (scx->scopesym->isModule())
-            flags |= SearchUnqualifiedModule;    // tell Module.search() that SearchLocalsOnly is to be obeyed
-        s = scx->scopesym->search(loc, ident, flags);
-        if (s)
-        {
-            // overload set contains only module scope symbols.
-            if (s->isOverloadSet())
-                break;
-            // selective/renamed imports also be picked up
-            if (AliasDeclaration *ad = s->isAliasDeclaration())
+            if (Type *att = t->aliasthisOf())
             {
-                if (ad->_import)
-                    break;
+                t = att;
+                goto Lagain;
             }
-            // See only module scope symbols for UFCS target.
-            Dsymbol *p = s->toParent2();
-            if (p && p->isModule())
-                break;
         }
-        s = NULL;
-
-        // Stop when we hit a module, but keep going if that is not just under the global scope
-        if (scx->scopesym->isModule() && !(scx->enclosing && !scx->enclosing->enclosing))
-            break;
     }
-    return s;
+    return NULL;
 }
 
-/******************************
- * Find symbol in accordance with the UFCS name look up rule
- */
-
-static Expression *searchUFCS(Scope *sc, UnaExp *ue, Identifier *ident)
+int expandAliasThisTuples(Expressions *exps, size_t starti)
 {
-    //printf("searchUFCS(ident = %s)\n", ident->toChars());
-    Loc loc = ue->loc;
-    int flags = 0;
-    Dsymbol *s = NULL;
-
-    if (sc->flags & SCOPEignoresymbolvisibility)
-        flags |= IgnoreSymbolVisibility;
-
-    // First look in local scopes
-    s = searchScopes(sc, loc, ident, flags | SearchLocalsOnly);
-    if (!s)
-    {
-        // Second look in imported modules
-        s = searchScopes(sc, loc, ident, flags | SearchImportsOnly);
-    }
-
-    if (!s)
-        return ue->e1->type->Type::getProperty(loc, ident, 0);
+    if (!exps || exps->length == 0)
+        return -1;
 
-    FuncDeclaration *f = s->isFuncDeclaration();
-    if (f)
+    for (size_t u = starti; u < exps->length; u++)
     {
-        TemplateDeclaration *td = getFuncTemplateDecl(f);
-        if (td)
-        {
-            if (td->overroot)
-                td = td->overroot;
-            s = td;
-        }
-    }
-
-    if (ue->op == TOKdotti)
-    {
-        DotTemplateInstanceExp *dti = (DotTemplateInstanceExp *)ue;
-        TemplateInstance *ti = new TemplateInstance(loc, s->ident);
-        ti->tiargs = dti->ti->tiargs;   // for better diagnostic message
-        if (!ti->updateTempDecl(sc, s))
-            return new ErrorExp();
-        return new ScopeExp(loc, ti);
-    }
-    else
-    {
-        //printf("-searchUFCS() %s\n", s->toChars());
-        return new DsymbolExp(loc, s);
-    }
-}
-
-/******************************
- * check e is exp.opDispatch!(tiargs) or not
- * It's used to switch to UFCS the semantic analysis path
- */
-
-bool isDotOpDispatch(Expression *e)
-{
-    return e->op == TOKdotti &&
-           ((DotTemplateInstanceExp *)e)->ti->name == Id::opDispatch;
-}
-
-/******************************
- * Pull out callable entity with UFCS.
- */
-
-Expression *resolveUFCS(Scope *sc, CallExp *ce)
-{
-    Loc loc = ce->loc;
-    Expression *eleft;
-    Expression *e;
-
-    if (ce->e1->op == TOKdotid)
-    {
-        DotIdExp *die = (DotIdExp *)ce->e1;
-        Identifier *ident = die->ident;
-
-        Expression *ex = semanticX(die, sc);
-        if (ex != die)
-        {
-            ce->e1 = ex;
-            return NULL;
-        }
-        eleft = die->e1;
-
-        Type *t = eleft->type->toBasetype();
-        if (t->ty == Tarray || t->ty == Tsarray ||
-            t->ty == Tnull  || (t->isTypeBasic() && t->ty != Tvoid))
-        {
-            /* Built-in types and arrays have no callable properties, so do shortcut.
-             * It is necessary in: e.init()
-             */
-        }
-        else if (t->ty == Taarray)
-        {
-            if (ident == Id::remove)
-            {
-                /* Transform:
-                 *  aa.remove(arg) into delete aa[arg]
-                 */
-                if (!ce->arguments || ce->arguments->length != 1)
-                {
-                    ce->error("expected key as argument to aa.remove()");
-                    return new ErrorExp();
-                }
-                if (!eleft->type->isMutable())
-                {
-                    ce->error("cannot remove key from %s associative array %s",
-                            MODtoChars(t->mod), eleft->toChars());
-                    return new ErrorExp();
-                }
-                Expression *key = (*ce->arguments)[0];
-                key = expressionSemantic(key, sc);
-                key = resolveProperties(sc, key);
-
-                TypeAArray *taa = (TypeAArray *)t;
-                key = key->implicitCastTo(sc, taa->index);
-
-                if (key->checkValue())
-                    return new ErrorExp();
-
-                semanticTypeInfo(sc, taa->index);
-
-                return new RemoveExp(loc, eleft, key);
-            }
-        }
-        else
-        {
-            if (Expression *ey = semanticY(die, sc, 1))
-            {
-                if (ey->op == TOKerror)
-                    return ey;
-                ce->e1 = ey;
-                if (isDotOpDispatch(ey))
-                {
-                    unsigned errors = global.startGagging();
-                    e = expressionSemantic(ce->syntaxCopy(), sc);
-                    if (!global.endGagging(errors))
-                        return e;
-                    /* fall down to UFCS */
-                }
-                else
-                    return NULL;
-            }
-        }
-        e = searchUFCS(sc, die, ident);
-    }
-    else if (ce->e1->op == TOKdotti)
-    {
-        DotTemplateInstanceExp *dti = (DotTemplateInstanceExp *)ce->e1;
-        if (Expression *ey = semanticY(dti, sc, 1))
-        {
-            ce->e1 = ey;
-            return NULL;
-        }
-        eleft = dti->e1;
-        e = searchUFCS(sc, dti, dti->ti->name);
-    }
-    else
-        return NULL;
-
-    // Rewrite
-    ce->e1 = e;
-    if (!ce->arguments)
-        ce->arguments = new Expressions();
-    ce->arguments->shift(eleft);
-
-    return NULL;
-}
-
-/******************************
- * Pull out property with UFCS.
- */
-
-Expression *resolveUFCSProperties(Scope *sc, Expression *e1, Expression *e2 = NULL)
-{
-    Loc loc = e1->loc;
-    Expression *eleft;
-    Expression *e;
-
-    if (e1->op == TOKdotid)
-    {
-        DotIdExp *die = (DotIdExp *)e1;
-        eleft = die->e1;
-        e = searchUFCS(sc, die, die->ident);
-    }
-    else if (e1->op == TOKdotti)
-    {
-        DotTemplateInstanceExp *dti;
-        dti = (DotTemplateInstanceExp *)e1;
-        eleft = dti->e1;
-        e = searchUFCS(sc, dti, dti->ti->name);
-    }
-    else
-        return NULL;
-
-    if (e == NULL)
-        return NULL;
-
-    // Rewrite
-    if (e2)
-    {
-        // run semantic without gagging
-        e2 = expressionSemantic(e2, sc);
-
-        /* f(e1) = e2
-         */
-        Expression *ex = e->copy();
-        Expressions *a1 = new Expressions();
-        a1->setDim(1);
-        (*a1)[0] = eleft;
-        ex = new CallExp(loc, ex, a1);
-        ex = trySemantic(ex, sc);
-
-        /* f(e1, e2)
-         */
-        Expressions *a2 = new Expressions();
-        a2->setDim(2);
-        (*a2)[0] = eleft;
-        (*a2)[1] = e2;
-        e = new CallExp(loc, e, a2);
-        if (ex)
-        {   // if fallback setter exists, gag errors
-            e = trySemantic(e, sc);
-            if (!e)
-            {   checkPropertyCall(ex);
-                ex = new AssignExp(loc, ex, e2);
-                return expressionSemantic(ex, sc);
-            }
-        }
-        else
-        {   // strict setter prints errors if fails
-            e = expressionSemantic(e, sc);
-        }
-        checkPropertyCall(e);
-        return e;
-    }
-    else
-    {
-        /* f(e1)
-         */
-        Expressions *arguments = new Expressions();
-        arguments->setDim(1);
-        (*arguments)[0] = eleft;
-        e = new CallExp(loc, e, arguments);
-        e = expressionSemantic(e, sc);
-        checkPropertyCall(e);
-        return expressionSemantic(e, sc);
-    }
-}
-
-/******************************
- * Perform semantic() on an array of Expressions.
- */
-
-bool arrayExpressionSemantic(Expressions *exps, Scope *sc, bool preserveErrors)
-{
-    bool err = false;
-    if (exps)
-    {
-        for (size_t i = 0; i < exps->length; i++)
-        {
-            Expression *e = (*exps)[i];
-            if (e)
-            {
-                e = expressionSemantic(e, sc);
-                if (e->op == TOKerror)
-                    err = true;
-                if (preserveErrors || e->op != TOKerror)
-                    (*exps)[i] = e;
-            }
-        }
-    }
-    return err;
-}
-
-/****************************************
- * Expand tuples.
- * Input:
- *      exps    aray of Expressions
- * Output:
- *      exps    rewritten in place
- */
-
-void expandTuples(Expressions *exps)
-{
-    //printf("expandTuples()\n");
-    if (exps)
-    {
-        for (size_t i = 0; i < exps->length; i++)
-        {
-            Expression *arg = (*exps)[i];
-            if (!arg)
-                continue;
-
-            // Look for tuple with 0 members
-            if (arg->op == TOKtype)
-            {
-                TypeExp *e = (TypeExp *)arg;
-                if (e->type->toBasetype()->ty == Ttuple)
-                {
-                    TypeTuple *tt = (TypeTuple *)e->type->toBasetype();
-
-                    if (!tt->arguments || tt->arguments->length == 0)
-                    {
-                        exps->remove(i);
-                        if (i == exps->length)
-                            return;
-                        i--;
-                        continue;
-                    }
-                }
-            }
-
-            // Inline expand all the tuples
-            while (arg->op == TOKtuple)
-            {
-                TupleExp *te = (TupleExp *)arg;
-                exps->remove(i);                // remove arg
-                exps->insert(i, te->exps);      // replace with tuple contents
-                if (i == exps->length)
-                    return;             // empty tuple, no more arguments
-                (*exps)[i] = Expression::combine(te->e0, (*exps)[i]);
-                arg = (*exps)[i];
-            }
-        }
-    }
-}
-
-/****************************************
- * Expand alias this tuples.
- */
-
-TupleDeclaration *isAliasThisTuple(Expression *e)
-{
-    if (!e->type)
-        return NULL;
-
-    Type *t = e->type->toBasetype();
-Lagain:
-    if (Dsymbol *s = t->toDsymbol(NULL))
-    {
-        AggregateDeclaration *ad = s->isAggregateDeclaration();
-        if (ad)
-        {
-            s = ad->aliasthis;
-            if (s && s->isVarDeclaration())
-            {
-                TupleDeclaration *td = s->isVarDeclaration()->toAlias()->isTupleDeclaration();
-                if (td && td->isexp)
-                    return td;
-            }
-            if (Type *att = t->aliasthisOf())
-            {
-                t = att;
-                goto Lagain;
-            }
-        }
-    }
-    return NULL;
-}
-
-int expandAliasThisTuples(Expressions *exps, size_t starti)
-{
-    if (!exps || exps->length == 0)
-        return -1;
-
-    for (size_t u = starti; u < exps->length; u++)
-    {
-        Expression *exp = (*exps)[u];
-        TupleDeclaration *td = isAliasThisTuple(exp);
+        Expression *exp = (*exps)[u];
+        TupleDeclaration *td = isAliasThisTuple(exp);
         if (td)
         {
             exps->remove(u);
@@ -1061,907 +256,130 @@ int expandAliasThisTuples(Expressions *exps, size_t starti)
         }
     }
 
-    return -1;
-}
-
-/****************************************
- * The common type is determined by applying ?: to each pair.
- * Output:
- *      exps[]  properties resolved, implicitly cast to common type, rewritten in place
- *      *pt     if pt is not NULL, set to the common type
- * Returns:
- *      true    a semantic error was detected
- */
-
-bool arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt)
-{
-    /* Still have a problem with:
-     *  ubyte[][] = [ cast(ubyte[])"hello", [1]];
-     * which works if the array literal is initialized top down with the ubyte[][]
-     * type, but fails with this function doing bottom up typing.
-     */
-    //printf("arrayExpressionToCommonType()\n");
-    IntegerExp integerexp(0);
-    CondExp condexp(Loc(), &integerexp, NULL, NULL);
-
-    Type *t0 = NULL;
-    Expression *e0 = NULL;      // dead-store to prevent spurious warning
-    size_t j0 = ~0;             // dead-store to prevent spurious warning
-    bool foundType = false;
-
-    for (size_t i = 0; i < exps->length; i++)
-    {
-        Expression *e = (*exps)[i];
-        if (!e)
-            continue;
-
-        e = resolveProperties(sc, e);
-        if (!e->type)
-        {
-            e->error("%s has no value", e->toChars());
-            t0 = Type::terror;
-            continue;
-        }
-        if (e->op == TOKtype)
-        {
-            foundType = true;   // do not break immediately, there might be more errors
-            e->checkValue();    // report an error "type T has no value"
-            t0 = Type::terror;
-            continue;
-        }
-        if (e->type->ty == Tvoid)
-        {
-            // void expressions do not concur to the determination of the common
-            // type.
-            continue;
-        }
-        if (checkNonAssignmentArrayOp(e))
-        {
-            t0 = Type::terror;
-            continue;
-        }
-
-        e = doCopyOrMove(sc, e);
-
-        if (!foundType && t0 && !t0->equals(e->type))
-        {
-            /* This applies ?: to merge the types. It's backwards;
-             * ?: should call this function to merge types.
-             */
-            condexp.type = NULL;
-            condexp.e1 = e0;
-            condexp.e2 = e;
-            condexp.loc = e->loc;
-            Expression *ex = expressionSemantic(&condexp, sc);
-            if (ex->op == TOKerror)
-                e = ex;
-            else
-            {
-                (*exps)[j0] = condexp.e1;
-                e = condexp.e2;
-            }
-        }
-        j0 = i;
-        e0 = e;
-        t0 = e->type;
-        if (e->op != TOKerror)
-            (*exps)[i] = e;
-    }
-
-    if (!t0)
-        t0 = Type::tvoid;               // [] is typed as void[]
-    else if (t0->ty != Terror)
-    {
-        for (size_t i = 0; i < exps->length; i++)
-        {
-            Expression *e = (*exps)[i];
-            if (!e)
-                continue;
-
-            e = e->implicitCastTo(sc, t0);
-            //assert(e->op != TOKerror);
-            if (e->op == TOKerror)
-            {
-                /* Bugzilla 13024: a workaround for the bug in typeMerge -
-                 * it should paint e1 and e2 by deduced common type,
-                 * but doesn't in this particular case.
-                 */
-                t0 = Type::terror;
-                break;
-            }
-            (*exps)[i] = e;
-        }
-    }
-    if (pt)
-        *pt = t0;
-
-    return (t0 == Type::terror);
-}
-
-/****************************************
- * Get TemplateDeclaration enclosing FuncDeclaration.
- */
-
-TemplateDeclaration *getFuncTemplateDecl(Dsymbol *s)
-{
-    FuncDeclaration *f = s->isFuncDeclaration();
-    if (f && f->parent)
-    {
-        TemplateInstance *ti = f->parent->isTemplateInstance();
-        if (ti && !ti->isTemplateMixin() &&
-            ti->tempdecl && ((TemplateDeclaration *)ti->tempdecl)->onemember &&
-            ti->tempdecl->ident == f->ident)
-        {
-            return (TemplateDeclaration *)ti->tempdecl;
-        }
-    }
-    return NULL;
-}
-
-/************************************************
- * If we want the value of this expression, but do not want to call
- * the destructor on it.
- */
-
-Expression *valueNoDtor(Expression *e)
-{
-    if (e->op == TOKcall)
-    {
-        /* The struct value returned from the function is transferred
-         * so do not call the destructor on it.
-         * Recognize:
-         *       ((S _ctmp = S.init), _ctmp).this(...)
-         * and make sure the destructor is not called on _ctmp
-         * BUG: if e is a CommaExp, we should go down the right side.
-         */
-        CallExp *ce = (CallExp *)e;
-        if (ce->e1->op == TOKdotvar)
-        {
-            DotVarExp *dve = (DotVarExp *)ce->e1;
-            if (dve->var->isCtorDeclaration())
-            {
-                // It's a constructor call
-                if (dve->e1->op == TOKcomma)
-                {
-                    CommaExp *comma = (CommaExp *)dve->e1;
-                    if (comma->e2->op == TOKvar)
-                    {
-                        VarExp *ve = (VarExp *)comma->e2;
-                        VarDeclaration *ctmp = ve->var->isVarDeclaration();
-                        if (ctmp)
-                        {
-                            ctmp->storage_class |= STCnodtor;
-                            assert(!ce->isLvalue());
-                        }
-                    }
-                }
-            }
-        }
-    }
-    else if (e->op == TOKvar)
-    {
-        VarDeclaration *vtmp = ((VarExp *)e)->var->isVarDeclaration();
-        if (vtmp && vtmp->storage_class & STCrvalue)
-        {
-            vtmp->storage_class |= STCnodtor;
-        }
-    }
-    return e;
-}
-
-/********************************************
- * Issue an error if default construction is disabled for type t.
- * Default construction is required for arrays and 'out' parameters.
- * Returns:
- *      true    an error was issued
- */
-bool checkDefCtor(Loc loc, Type *t)
-{
-    t = t->baseElemOf();
-    if (t->ty == Tstruct)
-    {
-        StructDeclaration *sd = ((TypeStruct *)t)->sym;
-        if (sd->noDefaultCtor)
-        {
-            sd->error(loc, "default construction is disabled");
-            return true;
-        }
-    }
-    return false;
-}
-
-/*********************************************
- * If e is an instance of a struct, and that struct has a copy constructor,
- * rewrite e as:
- *    (tmp = e),tmp
- * Input:
- *      sc      just used to specify the scope of created temporary variable
- */
-Expression *callCpCtor(Scope *sc, Expression *e)
-{
-    Type *tv = e->type->baseElemOf();
-    if (tv->ty == Tstruct)
-    {
-        StructDeclaration *sd = ((TypeStruct *)tv)->sym;
-        if (sd->postblit)
-        {
-            /* Create a variable tmp, and replace the argument e with:
-             *      (tmp = e),tmp
-             * and let AssignExp() handle the construction.
-             * This is not the most efficent, ideally tmp would be constructed
-             * directly onto the stack.
-             */
-            VarDeclaration *tmp = copyToTemp(STCrvalue, "__copytmp", e);
-            tmp->storage_class |= STCnodtor;
-            dsymbolSemantic(tmp, sc);
-            Expression *de = new DeclarationExp(e->loc, tmp);
-            Expression *ve = new VarExp(e->loc, tmp);
-            de->type = Type::tvoid;
-            ve->type = e->type;
-            e = Expression::combine(de, ve);
-        }
-    }
-    return e;
-}
-
-/************************************************
- * Handle the postblit call on lvalue, or the move of rvalue.
- */
-Expression *doCopyOrMove(Scope *sc, Expression *e)
-{
-    if (e->op == TOKquestion)
-    {
-        CondExp *ce = (CondExp *)e;
-        ce->e1 = doCopyOrMove(sc, ce->e1);
-        ce->e2 = doCopyOrMove(sc, ce->e2);
-    }
-    else
-    {
-        e = e->isLvalue() ? callCpCtor(sc, e) : valueNoDtor(e);
-    }
-    return e;
-}
-
-/****************************************
- * Now that we know the exact type of the function we're calling,
- * the arguments[] need to be adjusted:
- *      1. implicitly convert argument to the corresponding parameter type
- *      2. add default arguments for any missing arguments
- *      3. do default promotions on arguments corresponding to ...
- *      4. add hidden _arguments[] argument
- *      5. call copy constructor for struct value arguments
- * Input:
- *      tf      type of the function
- *      fd      the function being called, NULL if called indirectly
- * Output:
- *      *prettype return type of function
- *      *peprefix expression to execute before arguments[] are evaluated, NULL if none
- * Returns:
- *      true    errors happened
- */
-
-bool functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
-        Type *tthis, Expressions *arguments, FuncDeclaration *fd, Type **prettype, Expression **peprefix)
-{
-    //printf("functionParameters()\n");
-    assert(arguments);
-    assert(fd || tf->next);
-    size_t nargs = arguments ? arguments->length : 0;
-    size_t nparams = tf->parameterList.length();
-    unsigned olderrors = global.errors;
-    bool err = false;
-    *prettype = Type::terror;
-    Expression *eprefix = NULL;
-    *peprefix = NULL;
-
-    if (nargs > nparams && tf->parameterList.varargs == VARARGnone)
-    {
-        error(loc, "expected %llu arguments, not %llu for non-variadic function type %s", (ulonglong)nparams, (ulonglong)nargs, tf->toChars());
-        return true;
-    }
-
-    // If inferring return type, and semantic3() needs to be run if not already run
-    if (!tf->next && fd->inferRetType)
-    {
-        fd->functionSemantic();
-    }
-    else if (fd && fd->parent)
-    {
-        TemplateInstance *ti = fd->parent->isTemplateInstance();
-        if (ti && ti->tempdecl)
-        {
-            fd->functionSemantic3();
-        }
-    }
-    bool isCtorCall = fd && fd->needThis() && fd->isCtorDeclaration();
-
-    size_t n = (nargs > nparams) ? nargs : nparams;   // n = max(nargs, nparams)
-
-    /* If the function return type has wildcards in it, we'll need to figure out the actual type
-     * based on the actual argument types.
-     */
-    MOD wildmatch = 0;
-    if (tthis && tf->isWild() && !isCtorCall)
-    {
-        Type *t = tthis;
-        if (t->isImmutable())
-            wildmatch = MODimmutable;
-        else if (t->isWildConst())
-            wildmatch = MODwildconst;
-        else if (t->isWild())
-            wildmatch = MODwild;
-        else if (t->isConst())
-            wildmatch = MODconst;
-        else
-            wildmatch = MODmutable;
-    }
-
-    int done = 0;
-    for (size_t i = 0; i < n; i++)
-    {
-        Expression *arg;
-
-        if (i < nargs)
-            arg = (*arguments)[i];
-        else
-            arg = NULL;
-
-        if (i < nparams)
-        {
-            Parameter *p = tf->parameterList[i];
-
-            if (!arg)
-            {
-                if (!p->defaultArg)
-                {
-                    if (tf->parameterList.varargs == VARARGtypesafe && i + 1 == nparams)
-                        goto L2;
-                    error(loc, "expected %llu function arguments, not %llu", (ulonglong)nparams, (ulonglong)nargs);
-                    return true;
-                }
-                arg = p->defaultArg;
-                arg = inlineCopy(arg, sc);
-                // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__
-                arg = arg->resolveLoc(loc, sc);
-                arguments->push(arg);
-                nargs++;
-            }
-
-            if (tf->parameterList.varargs == VARARGtypesafe && i + 1 == nparams)
-            {
-                //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars());
-                {
-                    MATCH m;
-                    if ((m = arg->implicitConvTo(p->type)) > MATCHnomatch)
-                    {
-                        if (p->type->nextOf() && arg->implicitConvTo(p->type->nextOf()) >= m)
-                            goto L2;
-                        else if (nargs != nparams)
-                        {   error(loc, "expected %llu function arguments, not %llu", (ulonglong)nparams, (ulonglong)nargs);
-                            return true;
-                        }
-                        goto L1;
-                    }
-                }
-             L2:
-                Type *tb = p->type->toBasetype();
-                Type *tret = p->isLazyArray();
-                switch (tb->ty)
-                {
-                    case Tsarray:
-                    case Tarray:
-                    {
-                        /* Create a static array variable v of type arg->type:
-                         *  T[dim] __arrayArg = [ arguments[i], ..., arguments[nargs-1] ];
-                         *
-                         * The array literal in the initializer of the hidden variable
-                         * is now optimized. See Bugzilla 2356.
-                         */
-                        Type *tbn = ((TypeArray *)tb)->next;
-
-                        Expressions *elements = new Expressions();
-                        elements->setDim(nargs - i);
-                        for (size_t u = 0; u < elements->length; u++)
-                        {
-                            Expression *a = (*arguments)[i + u];
-                            if (tret && a->implicitConvTo(tret))
-                            {
-                                a = a->implicitCastTo(sc, tret);
-                                a = a->optimize(WANTvalue);
-                                a = toDelegate(a, a->type, sc);
-                            }
-                            else
-                                a = a->implicitCastTo(sc, tbn);
-                            (*elements)[u] = a;
-                        }
-                        // Bugzilla 14395: Convert to a static array literal, or its slice.
-                        arg = new ArrayLiteralExp(loc, tbn->sarrayOf(nargs - i), elements);
-                        if (tb->ty == Tarray)
-                        {
-                            arg = new SliceExp(loc, arg, NULL, NULL);
-                            arg->type = p->type;
-                        }
-                        break;
-                    }
-                    case Tclass:
-                    {
-                        /* Set arg to be:
-                         *      new Tclass(arg0, arg1, ..., argn)
-                         */
-                        Expressions *args = new Expressions();
-                        args->setDim(nargs - i);
-                        for (size_t u = i; u < nargs; u++)
-                            (*args)[u - i] = (*arguments)[u];
-                        arg = new NewExp(loc, NULL, NULL, p->type, args);
-                        break;
-                    }
-                    default:
-                        if (!arg)
-                        {
-                            error(loc, "not enough arguments");
-                            return true;
-                        }
-                        break;
-                }
-                arg = expressionSemantic(arg, sc);
-                //printf("\targ = '%s'\n", arg->toChars());
-                arguments->setDim(i + 1);
-                (*arguments)[i] =  arg;
-                nargs = i + 1;
-                done = 1;
-            }
-
-        L1:
-            if (!(p->storageClass & STClazy && p->type->ty == Tvoid))
-            {
-                bool isRef = (p->storageClass & (STCref | STCout)) != 0;
-                if (unsigned char wm = arg->type->deduceWild(p->type, isRef))
-                {
-                    if (wildmatch)
-                        wildmatch = MODmerge(wildmatch, wm);
-                    else
-                        wildmatch = wm;
-                    //printf("[%d] p = %s, a = %s, wm = %d, wildmatch = %d\n", i, p->type->toChars(), arg->type->toChars(), wm, wildmatch);
-                }
-            }
-        }
-        if (done)
-            break;
-    }
-    if ((wildmatch == MODmutable || wildmatch == MODimmutable) &&
-        tf->next->hasWild() &&
-        (tf->isref || !tf->next->implicitConvTo(tf->next->immutableOf())))
-    {
-        if (fd)
-        {
-            /* If the called function may return the reference to
-             * outer inout data, it should be rejected.
-             *
-             * void foo(ref inout(int) x) {
-             *   ref inout(int) bar(inout(int)) { return x; }
-             *   struct S { ref inout(int) bar() inout { return x; } }
-             *   bar(int.init) = 1;  // bad!
-             *   S().bar() = 1;      // bad!
-             * }
-             */
-            Dsymbol *s = NULL;
-            if (fd->isThis() || fd->isNested())
-                s = fd->toParent2();
-            for (; s; s = s->toParent2())
-            {
-                if (AggregateDeclaration *ad = s->isAggregateDeclaration())
-                {
-                    if (ad->isNested())
-                        continue;
-                    break;
-                }
-                if (FuncDeclaration *ff = s->isFuncDeclaration())
-                {
-                    if (((TypeFunction *)ff->type)->iswild)
-                        goto Linouterr;
-
-                    if (ff->isNested() || ff->isThis())
-                        continue;
-                }
-                break;
-            }
-        }
-        else if (tf->isWild())
-        {
-        Linouterr:
-            const char *s = wildmatch == MODmutable ? "mutable" : MODtoChars(wildmatch);
-            error(loc, "modify inout to %s is not allowed inside inout function", s);
-            return true;
-        }
-    }
-
-    assert(nargs >= nparams);
-    for (size_t i = 0; i < nargs; i++)
-    {
-        Expression *arg = (*arguments)[i];
-        assert(arg);
-        if (i < nparams)
-        {
-            Parameter *p = tf->parameterList[i];
-
-            if (!(p->storageClass & STClazy && p->type->ty == Tvoid))
-            {
-                Type *tprm = p->type;
-                if (p->type->hasWild())
-                    tprm = p->type->substWildTo(wildmatch);
-                if (!tprm->equals(arg->type))
-                {
-                    //printf("arg->type = %s, p->type = %s\n", arg->type->toChars(), p->type->toChars());
-                    arg = arg->implicitCastTo(sc, tprm);
-                    arg = arg->optimize(WANTvalue, (p->storageClass & (STCref | STCout)) != 0);
-                }
-            }
-            if (p->storageClass & STCref)
-            {
-                arg = arg->toLvalue(sc, arg);
-
-                // Look for mutable misaligned pointer, etc., in @safe mode
-                err |= checkUnsafeAccess(sc, arg, false, true);
-            }
-            else if (p->storageClass & STCout)
-            {
-                Type *t = arg->type;
-                if (!t->isMutable() || !t->isAssignable())  // check blit assignable
-                {
-                    arg->error("cannot modify struct %s with immutable members", arg->toChars());
-                    err = true;
-                }
-                else
-                {
-                    // Look for misaligned pointer, etc., in @safe mode
-                    err |= checkUnsafeAccess(sc, arg, false, true);
-                    err |= checkDefCtor(arg->loc, t);   // t must be default constructible
-                }
-                arg = arg->toLvalue(sc, arg);
-            }
-            else if (p->storageClass & STClazy)
-            {
-                // Convert lazy argument to a delegate
-                if (p->type->ty == Tvoid)
-                    arg = toDelegate(arg, p->type, sc);
-                else
-                    arg = toDelegate(arg, arg->type, sc);
-            }
-
-            //printf("arg: %s\n", arg->toChars());
-            //printf("type: %s\n", arg->type->toChars());
-            if (tf->parameterEscapes(p))
-            {
-                /* Argument value can escape from the called function.
-                 * Check arg to see if it matters.
-                 */
-                if (global.params.vsafe)
-                    err |= checkParamArgumentEscape(sc, fd, p->ident, arg, false);
-            }
-            else
-            {
-                /* Argument value cannot escape from the called function.
-                 */
-                Expression *a = arg;
-                if (a->op == TOKcast)
-                    a = ((CastExp *)a)->e1;
-
-                if (a->op == TOKfunction)
-                {
-                    /* Function literals can only appear once, so if this
-                     * appearance was scoped, there cannot be any others.
-                     */
-                    FuncExp *fe = (FuncExp *)a;
-                    fe->fd->tookAddressOf = 0;
-                }
-                else if (a->op == TOKdelegate)
-                {
-                    /* For passing a delegate to a scoped parameter,
-                     * this doesn't count as taking the address of it.
-                     * We only worry about 'escaping' references to the function.
-                     */
-                    DelegateExp *de = (DelegateExp *)a;
-                    if (de->e1->op == TOKvar)
-                    {   VarExp *ve = (VarExp *)de->e1;
-                        FuncDeclaration *f = ve->var->isFuncDeclaration();
-                        if (f)
-                        {   f->tookAddressOf--;
-                            //printf("tookAddressOf = %d\n", f->tookAddressOf);
-                        }
-                    }
-                }
-            }
-            arg = arg->optimize(WANTvalue, (p->storageClass & (STCref | STCout)) != 0);
-        }
-        else
-        {
-            // These will be the trailing ... arguments
-
-            // If not D linkage, do promotions
-            if (tf->linkage != LINKd)
-            {
-                // Promote bytes, words, etc., to ints
-                arg = integralPromotions(arg, sc);
-
-                // Promote floats to doubles
-                switch (arg->type->ty)
-                {
-                    case Tfloat32:
-                        arg = arg->castTo(sc, Type::tfloat64);
-                        break;
-
-                    case Timaginary32:
-                        arg = arg->castTo(sc, Type::timaginary64);
-                        break;
-                }
-
-                if (tf->parameterList.varargs == VARARGvariadic)
-                {
-                    const char *p = tf->linkage == LINKc ? "extern(C)" : "extern(C++)";
-                    if (arg->type->ty == Tarray)
-                    {
-                        arg->error("cannot pass dynamic arrays to %s vararg functions", p);
-                        err = true;
-                    }
-                    if (arg->type->ty == Tsarray)
-                    {
-                        arg->error("cannot pass static arrays to %s vararg functions", p);
-                        err = true;
-                    }
-                }
-            }
-
-            // Do not allow types that need destructors
-            if (arg->type->needsDestruction())
-            {
-                arg->error("cannot pass types that need destruction as variadic arguments");
-                err = true;
-            }
-
-            // Convert static arrays to dynamic arrays
-            // BUG: I don't think this is right for D2
-            Type *tb = arg->type->toBasetype();
-            if (tb->ty == Tsarray)
-            {
-                TypeSArray *ts = (TypeSArray *)tb;
-                Type *ta = ts->next->arrayOf();
-                if (ts->size(arg->loc) == 0)
-                    arg = new NullExp(arg->loc, ta);
-                else
-                    arg = arg->castTo(sc, ta);
-            }
-            if (tb->ty == Tstruct)
-            {
-                //arg = callCpCtor(sc, arg);
-            }
-
-            // Give error for overloaded function addresses
-            if (arg->op == TOKsymoff)
-            {   SymOffExp *se = (SymOffExp *)arg;
-                if (se->hasOverloads &&
-                    !se->var->isFuncDeclaration()->isUnique())
-                {   arg->error("function %s is overloaded", arg->toChars());
-                    err = true;
-                }
-            }
-            if (arg->checkValue())
-                err = true;
-            arg = arg->optimize(WANTvalue);
-        }
-        (*arguments)[i] = arg;
-    }
-
-    /* Remaining problems:
-     * 1. order of evaluation - some function push L-to-R, others R-to-L. Until we resolve what array assignment does (which is
-     *    implemented by calling a function) we'll defer this for now.
-     * 2. value structs (or static arrays of them) that need to be copy constructed
-     * 3. value structs (or static arrays of them) that have destructors, and subsequent arguments that may throw before the
-     *    function gets called (functions normally destroy their parameters)
-     * 2 and 3 are handled by doing the argument construction in 'eprefix' so that if a later argument throws, they are cleaned
-     * up properly. Pushing arguments on the stack then cannot fail.
-     */
-    if (1)
-    {
-        /* TODO: tackle problem 1)
-         */
-        const bool leftToRight = true; // TODO: something like !fd.isArrayOp
-        if (!leftToRight)
-            assert(nargs == nparams); // no variadics for RTL order, as they would probably be evaluated LTR and so add complexity
+    return -1;
+}
 
-        const ptrdiff_t start = (leftToRight ? 0 : (ptrdiff_t)nargs - 1);
-        const ptrdiff_t end = (leftToRight ? (ptrdiff_t)nargs : -1);
-        const ptrdiff_t step = (leftToRight ? 1 : -1);
+/****************************************
+ * Get TemplateDeclaration enclosing FuncDeclaration.
+ */
 
-        /* Compute indices of last throwing argument and first arg needing destruction.
-         * Used to not set up destructors unless an arg needs destruction on a throw
-         * in a later argument.
-         */
-        ptrdiff_t lastthrow = -1;
-        ptrdiff_t firstdtor = -1;
-        for (ptrdiff_t i = start; i != end; i += step)
+TemplateDeclaration *getFuncTemplateDecl(Dsymbol *s)
+{
+    FuncDeclaration *f = s->isFuncDeclaration();
+    if (f && f->parent)
+    {
+        TemplateInstance *ti = f->parent->isTemplateInstance();
+        if (ti && !ti->isTemplateMixin() &&
+            ti->tempdecl && ((TemplateDeclaration *)ti->tempdecl)->onemember &&
+            ti->tempdecl->ident == f->ident)
         {
-            Expression *arg = (*arguments)[i];
-            if (canThrow(arg, sc->func, false))
-                lastthrow = i;
-            if (firstdtor == -1 && arg->type->needsDestruction())
-            {
-                Parameter *p = (i >= (ptrdiff_t)nparams ? NULL : tf->parameterList[i]);
-                if (!(p && (p->storageClass & (STClazy | STCref | STCout))))
-                    firstdtor = i;
-            }
+            return (TemplateDeclaration *)ti->tempdecl;
         }
+    }
+    return NULL;
+}
 
-        /* Does problem 3) apply to this call?
-         */
-        const bool needsPrefix = (firstdtor >= 0 && lastthrow >= 0
-            && (lastthrow - firstdtor) * step > 0);
+/************************************************
+ * If we want the value of this expression, but do not want to call
+ * the destructor on it.
+ */
 
-        /* If so, initialize 'eprefix' by declaring the gate
+Expression *valueNoDtor(Expression *e)
+{
+    if (e->op == TOKcall)
+    {
+        /* The struct value returned from the function is transferred
+         * so do not call the destructor on it.
+         * Recognize:
+         *       ((S _ctmp = S.init), _ctmp).this(...)
+         * and make sure the destructor is not called on _ctmp
+         * BUG: if e is a CommaExp, we should go down the right side.
          */
-        VarDeclaration *gate = NULL;
-        if (needsPrefix)
-        {
-            // eprefix => bool __gate [= false]
-            Identifier *idtmp = Identifier::generateId("__gate");
-            gate = new VarDeclaration(loc, Type::tbool, idtmp, NULL);
-            gate->storage_class |= STCtemp | STCctfe | STCvolatile;
-            dsymbolSemantic(gate, sc);
-
-            Expression *ae = new DeclarationExp(loc, gate);
-            eprefix = expressionSemantic(ae, sc);
-        }
-
-        for (ptrdiff_t i = start; i != end; i += step)
+        CallExp *ce = (CallExp *)e;
+        if (ce->e1->op == TOKdotvar)
         {
-            Expression *arg = (*arguments)[i];
-
-            Parameter *parameter = (i >= (ptrdiff_t)nparams ? NULL : tf->parameterList[i]);
-            const bool isRef = (parameter && (parameter->storageClass & (STCref | STCout)));
-            const bool isLazy = (parameter && (parameter->storageClass & STClazy));
-
-            /* Skip lazy parameters
-             */
-            if (isLazy)
-                continue;
-
-            /* Do we have a gate? Then we have a prefix and we're not yet past the last throwing arg.
-             * Declare a temporary variable for this arg and append that declaration to 'eprefix',
-             * which will implicitly take care of potential problem 2) for this arg.
-             * 'eprefix' will therefore finally contain all args up to and including the last
-             * potentially throwing arg, excluding all lazy parameters.
-             */
-            if (gate)
+            DotVarExp *dve = (DotVarExp *)ce->e1;
+            if (dve->var->isCtorDeclaration())
             {
-                const bool needsDtor = (!isRef && arg->type->needsDestruction() && i != lastthrow);
-
-                /* Declare temporary 'auto __pfx = arg' (needsDtor) or 'auto __pfy = arg' (!needsDtor)
-                 */
-                VarDeclaration *tmp = copyToTemp(0,
-                    needsDtor ? "__pfx" : "__pfy",
-                    !isRef ? arg : arg->addressOf());
-                dsymbolSemantic(tmp, sc);
-
-                /* Modify the destructor so it only runs if gate==false, i.e.,
-                 * only if there was a throw while constructing the args
-                 */
-                if (!needsDtor)
+                // It's a constructor call
+                if (dve->e1->op == TOKcomma)
                 {
-                    if (tmp->edtor)
+                    CommaExp *comma = (CommaExp *)dve->e1;
+                    if (comma->e2->op == TOKvar)
                     {
-                        assert(i == lastthrow);
-                        tmp->edtor = NULL;
+                        VarExp *ve = (VarExp *)comma->e2;
+                        VarDeclaration *ctmp = ve->var->isVarDeclaration();
+                        if (ctmp)
+                        {
+                            ctmp->storage_class |= STCnodtor;
+                            assert(!ce->isLvalue());
+                        }
                     }
                 }
-                else
-                {
-                    // edtor => (__gate || edtor)
-                    assert(tmp->edtor);
-                    Expression *e = tmp->edtor;
-                    e = new LogicalExp(e->loc, TOKoror, new VarExp(e->loc, gate), e);
-                    tmp->edtor = expressionSemantic(e, sc);
-                    //printf("edtor: %s\n", tmp->edtor->toChars());
-                }
-
-                // eprefix => (eprefix, auto __pfx/y = arg)
-                DeclarationExp *ae = new DeclarationExp(loc, tmp);
-                eprefix = Expression::combine(eprefix, expressionSemantic(ae, sc));
-
-                // arg => __pfx/y
-                arg = new VarExp(loc, tmp);
-                arg = expressionSemantic(arg, sc);
-                if (isRef)
-                {
-                    arg = new PtrExp(loc, arg);
-                    arg = expressionSemantic(arg, sc);
-                }
-
-                /* Last throwing arg? Then finalize eprefix => (eprefix, gate = true),
-                 * i.e., disable the dtors right after constructing the last throwing arg.
-                 * From now on, the callee will take care of destructing the args because
-                 * the args are implicitly moved into function parameters.
-                 *
-                 * Set gate to null to let the next iterations know they don't need to
-                 * append to eprefix anymore.
-                 */
-                if (i == lastthrow)
-                {
-                    Expression *e = new AssignExp(gate->loc, new VarExp(gate->loc, gate), new IntegerExp(gate->loc, 1, Type::tbool));
-                    eprefix = Expression::combine(eprefix, expressionSemantic(e, sc));
-                    gate = NULL;
-                }
-            }
-            else
-            {
-                /* No gate, no prefix to append to.
-                 * Handle problem 2) by calling the copy constructor for value structs
-                 * (or static arrays of them) if appropriate.
-                 */
-                Type *tv = arg->type->baseElemOf();
-                if (!isRef && tv->ty == Tstruct)
-                    arg = doCopyOrMove(sc, arg);
             }
-
-            (*arguments)[i] = arg;
         }
     }
-    //if (eprefix) printf("eprefix: %s\n", eprefix->toChars());
-
-    // If D linkage and variadic, add _arguments[] as first argument
-    if (tf->isDstyleVariadic())
+    else if (e->op == TOKvar)
     {
-        assert(arguments->length >= nparams);
-
-        Parameters *args = new Parameters;
-        args->setDim(arguments->length - nparams);
-        for (size_t i = 0; i < arguments->length - nparams; i++)
+        VarDeclaration *vtmp = ((VarExp *)e)->var->isVarDeclaration();
+        if (vtmp && vtmp->storage_class & STCrvalue)
         {
-            Parameter *arg = new Parameter(STCin, (*arguments)[nparams + i]->type, NULL, NULL, NULL);
-            (*args)[i] = arg;
+            vtmp->storage_class |= STCnodtor;
         }
-
-        TypeTuple *tup = new TypeTuple(args);
-        Expression *e = new TypeidExp(loc, tup);
-        e = expressionSemantic(e, sc);
-        arguments->insert(0, e);
     }
+    return e;
+}
 
-    Type *tret = tf->next;
-    if (isCtorCall)
+/*********************************************
+ * If e is an instance of a struct, and that struct has a copy constructor,
+ * rewrite e as:
+ *    (tmp = e),tmp
+ * Input:
+ *      sc      just used to specify the scope of created temporary variable
+ */
+Expression *callCpCtor(Scope *sc, Expression *e)
+{
+    Type *tv = e->type->baseElemOf();
+    if (tv->ty == Tstruct)
     {
-        //printf("[%s] fd = %s %s, %d %d %d\n", loc.toChars(), fd->toChars(), fd->type->toChars(),
-        //    wildmatch, tf->isWild(), fd->isolateReturn());
-        if (!tthis)
-        {
-            assert(sc->intypeof || global.errors);
-            tthis = fd->isThis()->type->addMod(fd->type->mod);
-        }
-        if (tf->isWild() && !fd->isolateReturn())
+        StructDeclaration *sd = ((TypeStruct *)tv)->sym;
+        if (sd->postblit)
         {
-            if (wildmatch)
-                tret = tret->substWildTo(wildmatch);
-            int offset;
-            if (!tret->implicitConvTo(tthis) &&
-                !(MODimplicitConv(tret->mod, tthis->mod) && tret->isBaseOf(tthis, &offset) && offset == 0))
-            {
-                const char* s1 = tret ->isNaked() ? " mutable" : tret ->modToChars();
-                const char* s2 = tthis->isNaked() ? " mutable" : tthis->modToChars();
-                ::error(loc, "inout constructor %s creates%s object, not%s",
-                        fd->toPrettyChars(), s1, s2);
-                err = true;
-            }
+            /* Create a variable tmp, and replace the argument e with:
+             *      (tmp = e),tmp
+             * and let AssignExp() handle the construction.
+             * This is not the most efficent, ideally tmp would be constructed
+             * directly onto the stack.
+             */
+            VarDeclaration *tmp = copyToTemp(STCrvalue, "__copytmp", e);
+            tmp->storage_class |= STCnodtor;
+            dsymbolSemantic(tmp, sc);
+            Expression *de = new DeclarationExp(e->loc, tmp);
+            Expression *ve = new VarExp(e->loc, tmp);
+            de->type = Type::tvoid;
+            ve->type = e->type;
+            e = Expression::combine(de, ve);
         }
-        tret = tthis;
     }
-    else if (wildmatch && tret)
+    return e;
+}
+
+/************************************************
+ * Handle the postblit call on lvalue, or the move of rvalue.
+ */
+Expression *doCopyOrMove(Scope *sc, Expression *e)
+{
+    if (e->op == TOKquestion)
+    {
+        CondExp *ce = (CondExp *)e;
+        ce->e1 = doCopyOrMove(sc, ce->e1);
+        ce->e2 = doCopyOrMove(sc, ce->e2);
+    }
+    else
     {
-        /* Adjust function return type based on wildmatch
-         */
-        //printf("wildmatch = x%x, tret = %s\n", wildmatch, tret->toChars());
-        tret = tret->substWildTo(wildmatch);
+        e = e->isLvalue() ? callCpCtor(sc, e) : valueNoDtor(e);
     }
-    *prettype = tret;
-    *peprefix = eprefix;
-    return (err || olderrors != global.errors);
+    return e;
 }
 
 /******************************** Expression **************************/
@@ -5288,8 +3706,10 @@ MATCH FuncExp::matchType(Type *to, Scope *sc, FuncExp **presult, int flag)
     }
     else if (!flag)
     {
+        const char *ts[2];
+        toAutoQualChars(ts, tx, to);
         error("cannot implicitly convert expression (%s) of type %s to %s",
-                toChars(), tx->toChars(), to->toChars());
+                toChars(), ts[0], ts[1]);
     }
     return m;
 }
@@ -5644,11 +4064,17 @@ Expression *BinExp::incompatibleTypes()
         error("incompatible types for ((%s) %s (%s)): cannot use `%s` with types",
             e1->toChars(), Token::toChars(thisOp), e2->toChars(), Token::toChars(op));
     }
+    else if (e1->type->equals(e2->type))
+    {
+        error("incompatible types for ((%s) %s (%s)): both operands are of type `%s`",
+            e1->toChars(), Token::toChars(thisOp), e2->toChars(), e1->type->toChars());
+    }
     else
     {
+        const char *ts[2];
+        toAutoQualChars(ts, e1->type, e2->type);
         error("incompatible types for ((%s) %s (%s)): `%s` and `%s`",
-            e1->toChars(), Token::toChars(thisOp), e2->toChars(),
-            e1->type->toChars(), e2->type->toChars());
+            e1->toChars(), Token::toChars(thisOp), e2->toChars(), ts[0], ts[1]);
     }
     return new ErrorExp();
 }
@@ -5693,9 +4119,36 @@ Expression *BinAssignExp::modifiableLvalue(Scope *sc, Expression *)
 
 /************************************************************/
 
-CompileExp::CompileExp(Loc loc, Expression *e)
-        : UnaExp(loc, TOKmixin, sizeof(CompileExp), e)
+CompileExp::CompileExp(Loc loc, Expressions *exps)
+    : Expression(loc, TOKmixin, sizeof(CompileExp))
+{
+    this->exps = exps;
+}
+
+Expression *CompileExp::syntaxCopy()
+{
+    return new CompileExp(loc, arraySyntaxCopy(exps));
+}
+
+bool CompileExp::equals(RootObject *o)
 {
+    if (this == o)
+        return true;
+    if (o && o->dyncast() == DYNCAST_EXPRESSION && ((Expression *)o)->op == TOKmixin)
+    {
+        CompileExp *ce = (CompileExp *)o;
+        if (exps->length != ce->exps->length)
+            return false;
+        for (size_t i = 0; i < exps->length; i++)
+        {
+            Expression *e1 = (*exps)[i];
+            Expression *e2 = (*ce->exps)[i];
+            if (e1 != e2 && (!e1 || !e2 || !e1->equals(e2)))
+                return false;
+        }
+        return true;
+    }
+    return false;
 }
 
 /************************************************************/
@@ -6362,64 +4815,6 @@ ArrayLengthExp::ArrayLengthExp(Loc loc, Expression *e1)
 {
 }
 
-Expression *opAssignToOp(Loc loc, TOK op, Expression *e1, Expression *e2)
-{   Expression *e;
-
-    switch (op)
-    {
-        case TOKaddass:   e = new AddExp(loc, e1, e2);  break;
-        case TOKminass:   e = new MinExp(loc, e1, e2);  break;
-        case TOKmulass:   e = new MulExp(loc, e1, e2);  break;
-        case TOKdivass:   e = new DivExp(loc, e1, e2);  break;
-        case TOKmodass:   e = new ModExp(loc, e1, e2);  break;
-        case TOKandass:   e = new AndExp(loc, e1, e2);  break;
-        case TOKorass:    e = new OrExp (loc, e1, e2);  break;
-        case TOKxorass:   e = new XorExp(loc, e1, e2);  break;
-        case TOKshlass:   e = new ShlExp(loc, e1, e2);  break;
-        case TOKshrass:   e = new ShrExp(loc, e1, e2);  break;
-        case TOKushrass:  e = new UshrExp(loc, e1, e2); break;
-        default:        assert(0);
-    }
-    return e;
-}
-
-/*********************
- * Rewrite:
- *    array.length op= e2
- * as:
- *    array.length = array.length op e2
- * or:
- *    auto tmp = &array;
- *    (*tmp).length = (*tmp).length op e2
- */
-
-Expression *ArrayLengthExp::rewriteOpAssign(BinExp *exp)
-{
-    Expression *e;
-
-    assert(exp->e1->op == TOKarraylength);
-    ArrayLengthExp *ale = (ArrayLengthExp *)exp->e1;
-    if (ale->e1->op == TOKvar)
-    {
-        e = opAssignToOp(exp->loc, exp->op, ale, exp->e2);
-        e = new AssignExp(exp->loc, ale->syntaxCopy(), e);
-    }
-    else
-    {
-        /*    auto tmp = &array;
-         *    (*tmp).length = (*tmp).length op e2
-         */
-        VarDeclaration *tmp = copyToTemp(0, "__arraylength", new AddrExp(ale->loc, ale->e1));
-
-        Expression *e1 = new ArrayLengthExp(ale->loc, new PtrExp(ale->loc, new VarExp(ale->loc, tmp)));
-        Expression *elvalue = e1->syntaxCopy();
-        e = opAssignToOp(exp->loc, exp->op, e1, exp->e2);
-        e = new AssignExp(exp->loc, elvalue, e);
-        e = new CommaExp(exp->loc, new DeclarationExp(ale->loc, tmp), e);
-    }
-    return e;
-}
-
 /*********************** IntervalExp ********************************/
 
 // Mainly just a placeholder
@@ -7248,203 +5643,6 @@ Expression *PrettyFuncInitExp::resolveLoc(Loc loc, Scope *sc)
     return e;
 }
 
-/****************************************************************/
-
-Expression *extractOpDollarSideEffect(Scope *sc, UnaExp *ue)
-{
-    Expression *e0;
-    Expression *e1 = Expression::extractLast(ue->e1, &e0);
-    // Bugzilla 12585: Extract the side effect part if ue->e1 is comma.
-
-    if (!isTrivialExp(e1))
-    {
-        /* Even if opDollar is needed, 'e1' should be evaluate only once. So
-         * Rewrite:
-         *      e1.opIndex( ... use of $ ... )
-         *      e1.opSlice( ... use of $ ... )
-         * as:
-         *      (ref __dop = e1, __dop).opIndex( ... __dop.opDollar ...)
-         *      (ref __dop = e1, __dop).opSlice( ... __dop.opDollar ...)
-         */
-        e1 = extractSideEffect(sc, "__dop", &e0, e1, false);
-        assert(e1->op == TOKvar);
-        VarExp *ve = (VarExp *)e1;
-        ve->var->storage_class |= STCexptemp;     // lifetime limited to expression
-    }
-    ue->e1 = e1;
-    return e0;
-}
-
-/**************************************
- * Runs semantic on ae->arguments. Declares temporary variables
- * if '$' was used.
- */
-Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, Expression **pe0)
-{
-    assert(!ae->lengthVar);
-
-    *pe0 = NULL;
-
-    AggregateDeclaration *ad = isAggregate(ae->e1->type);
-    Dsymbol *slice = search_function(ad, Id::slice);
-    //printf("slice = %s %s\n", slice->kind(), slice->toChars());
-
-    for (size_t i = 0; i < ae->arguments->length; i++)
-    {
-        if (i == 0)
-            *pe0 = extractOpDollarSideEffect(sc, ae);
-
-        Expression *e = (*ae->arguments)[i];
-        if (e->op == TOKinterval && !(slice && slice->isTemplateDeclaration()))
-        {
-        Lfallback:
-            if (ae->arguments->length == 1)
-                return NULL;
-            ae->error("multi-dimensional slicing requires template opSlice");
-            return new ErrorExp();
-        }
-        //printf("[%d] e = %s\n", i, e->toChars());
-
-        // Create scope for '$' variable for this dimension
-        ArrayScopeSymbol *sym = new ArrayScopeSymbol(sc, ae);
-        sym->loc = ae->loc;
-        sym->parent = sc->scopesym;
-        sc = sc->push(sym);
-        ae->lengthVar = NULL;       // Create it only if required
-        ae->currentDimension = i;   // Dimension for $, if required
-
-        e = expressionSemantic(e, sc);
-        e = resolveProperties(sc, e);
-
-        if (ae->lengthVar && sc->func)
-        {
-            // If $ was used, declare it now
-            Expression *de = new DeclarationExp(ae->loc, ae->lengthVar);
-            de = expressionSemantic(de, sc);
-            *pe0 = Expression::combine(*pe0, de);
-        }
-        sc = sc->pop();
-
-        if (e->op == TOKinterval)
-        {
-            IntervalExp *ie = (IntervalExp *)e;
-
-            Objects *tiargs = new Objects();
-            Expression *edim = new IntegerExp(ae->loc, i, Type::tsize_t);
-            edim = expressionSemantic(edim, sc);
-            tiargs->push(edim);
-
-            Expressions *fargs = new Expressions();
-            fargs->push(ie->lwr);
-            fargs->push(ie->upr);
-
-            unsigned xerrors = global.startGagging();
-            sc = sc->push();
-            FuncDeclaration *fslice = resolveFuncCall(ae->loc, sc, slice, tiargs, ae->e1->type, fargs, 1);
-            sc = sc->pop();
-            global.endGagging(xerrors);
-            if (!fslice)
-                goto Lfallback;
-
-            e = new DotTemplateInstanceExp(ae->loc, ae->e1, slice->ident, tiargs);
-            e = new CallExp(ae->loc, e, fargs);
-            e = expressionSemantic(e, sc);
-        }
-
-        if (!e->type)
-        {
-            ae->error("%s has no value", e->toChars());
-            e = new ErrorExp();
-        }
-        if (e->op == TOKerror)
-            return e;
-
-        (*ae->arguments)[i] = e;
-    }
-
-    return ae;
-}
-
-/***********************************************************
- * Resolve `exp` as a compile-time known string.
- * Params:
- *  sc  = scope
- *  exp = Expression which expected as a string
- *  s   = What the string is expected for, will be used in error diagnostic.
- * Returns:
- *  String literal, or `null` if error happens.
- */
-StringExp *semanticString(Scope *sc, Expression *exp, const char *s)
-{
-    sc = sc->startCTFE();
-    exp = expressionSemantic(exp, sc);
-    exp = resolveProperties(sc, exp);
-    sc = sc->endCTFE();
-
-    if (exp->op == TOKerror)
-        return NULL;
-
-    Expression *e = exp;
-    if (exp->type->isString())
-    {
-        e = e->ctfeInterpret();
-        if (e->op == TOKerror)
-            return NULL;
-    }
-
-    StringExp *se = e->toStringExp();
-    if (!se)
-    {
-        exp->error("string expected for %s, not (%s) of type %s",
-            s, exp->toChars(), exp->type->toChars());
-        return NULL;
-    }
-    return se;
-}
-
-/**************************************
- * Runs semantic on se->lwr and se->upr. Declares a temporary variable
- * if '$' was used.
- */
-Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, IntervalExp *ie, Expression **pe0)
-{
-    //assert(!ae->lengthVar);
-    if (!ie)
-        return ae;
-
-    VarDeclaration *lengthVar = ae->lengthVar;
-
-    // create scope for '$'
-    ArrayScopeSymbol *sym = new ArrayScopeSymbol(sc, ae);
-    sym->loc = ae->loc;
-    sym->parent = sc->scopesym;
-    sc = sc->push(sym);
-
-    for (size_t i = 0; i < 2; ++i)
-    {
-        Expression *e = i == 0 ? ie->lwr : ie->upr;
-        e = expressionSemantic(e, sc);
-        e = resolveProperties(sc, e);
-        if (!e->type)
-        {
-            ae->error("%s has no value", e->toChars());
-            return new ErrorExp();
-        }
-        (i == 0 ? ie->lwr : ie->upr) = e;
-    }
-
-    if (lengthVar != ae->lengthVar && sc->func)
-    {
-        // If $ was used, declare it now
-        Expression *de = new DeclarationExp(ae->loc, ae->lengthVar);
-        de = expressionSemantic(de, sc);
-        *pe0 = Expression::combine(*pe0, de);
-    }
-    sc = sc->pop();
-
-    return ae;
-}
-
 Expression *BinExp::reorderSettingAAElem(Scope *sc)
 {
     BinExp *be = this;
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index f0ae2805df4..2ed8fac373e 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -883,10 +883,14 @@ public:
 
 /****************************************************************/
 
-class CompileExp : public UnaExp
+class CompileExp : public Expression
 {
 public:
-    CompileExp(Loc loc, Expression *e);
+    Expressions *exps;
+
+    CompileExp(Loc loc, Expressions *exps);
+    Expression *syntaxCopy();
+    bool equals(RootObject *o);
     void accept(Visitor *v) { v->visit(this); }
 };
 
@@ -1124,7 +1128,6 @@ class ArrayLengthExp : public UnaExp
 public:
     ArrayLengthExp(Loc loc, Expression *e1);
 
-    static Expression *rewriteOpAssign(BinExp *exp);
     void accept(Visitor *v) { v->visit(this); }
 };
 
diff --git a/gcc/d/dmd/expressionsem.c b/gcc/d/dmd/expressionsem.c
index 7cccd956966..4a37d0fcba2 100644
--- a/gcc/d/dmd/expressionsem.c
+++ b/gcc/d/dmd/expressionsem.c
@@ -47,26 +47,1252 @@ bool symbolIsVisible(Scope *sc, Dsymbol *s);
 VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e);
 Expression *extractSideEffect(Scope *sc, const char *name, Expression **e0, Expression *e, bool alwaysCopy = false);
 Type *getTypeInfoType(Loc loc, Type *t, Scope *sc);
+char *MODtoChars(MOD mod);
 bool MODimplicitConv(MOD modfrom, MOD modto);
+MOD MODmerge(MOD mod1, MOD mod2);
 MATCH MODmethodConv(MOD modfrom, MOD modto);
 void MODMatchToBuffer(OutBuffer *buf, unsigned char lhsMod, unsigned char rhsMod);
 
 void unSpeculative(Scope *sc, RootObject *o);
-bool arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt);
-bool checkDefCtor(Loc loc, Type *t);
 bool isDotOpDispatch(Expression *e);
-bool functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Type *tthis, Expressions *arguments, FuncDeclaration *fd, Type **prettype, Expression **peprefix);
-Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad, Expression *e1, Declaration *var, int flag = 0);
 bool isNeedThisScope(Scope *sc, Declaration *d);
-Expression *resolveUFCS(Scope *sc, CallExp *ce);
 bool checkUnsafeAccess(Scope *sc, Expression *e, bool readonly, bool printmsg);
 bool isSafeCast(Expression *e, Type *tfrom, Type *tto);
 FuncDeclaration *isFuncAddress(Expression *e, bool *hasOverloads = NULL);
 Expression *callCpCtor(Scope *sc, Expression *e);
 
 Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads);
-Expression *resolveUFCSProperties(Scope *sc, Expression *e1, Expression *e2 = NULL);
-Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL);
+
+bool checkPrintfFormat(const Loc &loc, const char *format, Expressions &args, bool isVa_list);
+bool checkScanfFormat(const Loc &loc, const char *format, Expressions &args, bool isVa_list);
+
+/********************************************************
+ * Perform semantic analysis and CTFE on expressions to produce
+ * a string.
+ * Params:
+ *      buf = append generated string to buffer
+ *      sc = context
+ *      exps = array of Expressions
+ * Returns:
+ *      true on error
+ */
+bool expressionsToString(OutBuffer &buf, Scope *sc, Expressions *exps)
+{
+    if (!exps)
+        return false;
+
+    for (size_t i = 0; i < exps->length; i++)
+    {
+        Expression *ex = (*exps)[i];
+        if (!ex)
+            continue;
+        Scope *sc2 = sc->startCTFE();
+        Expression *e2 = expressionSemantic(ex, sc2);
+        Expression *e3 = resolveProperties(sc2, e2);
+        sc2->endCTFE();
+
+        // allowed to contain types as well as expressions
+        Expression *e4 = ctfeInterpretForPragmaMsg(e3);
+        if (!e4 || e4->op == TOKerror)
+            return true;
+
+        // expand tuple
+        if (TupleExp *te = e4->isTupleExp())
+        {
+            if (expressionsToString(buf, sc, te->exps))
+                return true;
+            continue;
+        }
+        // char literals exp `.toStringExp` return `null` but we cant override it
+        // because in most contexts we don't want the conversion to succeed.
+        IntegerExp *ie = e4->isIntegerExp();
+        const TY ty = (ie && ie->type) ? ie->type->ty : (TY)Terror;
+        if (ty == Tchar || ty == Twchar || ty == Tdchar)
+        {
+            TypeSArray *tsa = new TypeSArray(ie->type, new IntegerExp(ex->loc, 1, Type::tint32));
+            e4 = new ArrayLiteralExp(ex->loc, tsa, ie);
+        }
+
+        if (StringExp *se = e4->toStringExp())
+            buf.writestring(se->toUTF8(sc)->toPtr());
+        else
+            buf.writestring(e4->toChars());
+    }
+    return false;
+}
+
+/***********************************************************
+ * Resolve `exp` as a compile-time known string.
+ * Params:
+ *  sc  = scope
+ *  exp = Expression which expected as a string
+ *  s   = What the string is expected for, will be used in error diagnostic.
+ * Returns:
+ *  String literal, or `null` if error happens.
+ */
+StringExp *semanticString(Scope *sc, Expression *exp, const char *s)
+{
+    sc = sc->startCTFE();
+    exp = expressionSemantic(exp, sc);
+    exp = resolveProperties(sc, exp);
+    sc = sc->endCTFE();
+
+    if (exp->op == TOKerror)
+        return NULL;
+
+    Expression *e = exp;
+    if (exp->type->isString())
+    {
+        e = e->ctfeInterpret();
+        if (e->op == TOKerror)
+            return NULL;
+    }
+
+    StringExp *se = e->toStringExp();
+    if (!se)
+    {
+        exp->error("string expected for %s, not (%s) of type %s",
+            s, exp->toChars(), exp->type->toChars());
+        return NULL;
+    }
+    return se;
+}
+
+/****************************************************************/
+
+static Expression *extractOpDollarSideEffect(Scope *sc, UnaExp *ue)
+{
+    Expression *e0;
+    Expression *e1 = Expression::extractLast(ue->e1, &e0);
+    // Bugzilla 12585: Extract the side effect part if ue->e1 is comma.
+
+    if (!isTrivialExp(e1))
+    {
+        /* Even if opDollar is needed, 'e1' should be evaluate only once. So
+         * Rewrite:
+         *      e1.opIndex( ... use of $ ... )
+         *      e1.opSlice( ... use of $ ... )
+         * as:
+         *      (ref __dop = e1, __dop).opIndex( ... __dop.opDollar ...)
+         *      (ref __dop = e1, __dop).opSlice( ... __dop.opDollar ...)
+         */
+        e1 = extractSideEffect(sc, "__dop", &e0, e1, false);
+        assert(e1->op == TOKvar);
+        VarExp *ve = (VarExp *)e1;
+        ve->var->storage_class |= STCexptemp;     // lifetime limited to expression
+    }
+    ue->e1 = e1;
+    return e0;
+}
+
+/**************************************
+ * Runs semantic on ae->arguments. Declares temporary variables
+ * if '$' was used.
+ */
+Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, Expression **pe0)
+{
+    assert(!ae->lengthVar);
+
+    *pe0 = NULL;
+
+    AggregateDeclaration *ad = isAggregate(ae->e1->type);
+    Dsymbol *slice = search_function(ad, Id::slice);
+    //printf("slice = %s %s\n", slice->kind(), slice->toChars());
+
+    for (size_t i = 0; i < ae->arguments->length; i++)
+    {
+        if (i == 0)
+            *pe0 = extractOpDollarSideEffect(sc, ae);
+
+        Expression *e = (*ae->arguments)[i];
+        if (e->op == TOKinterval && !(slice && slice->isTemplateDeclaration()))
+        {
+        Lfallback:
+            if (ae->arguments->length == 1)
+                return NULL;
+            ae->error("multi-dimensional slicing requires template opSlice");
+            return new ErrorExp();
+        }
+        //printf("[%d] e = %s\n", i, e->toChars());
+
+        // Create scope for '$' variable for this dimension
+        ArrayScopeSymbol *sym = new ArrayScopeSymbol(sc, ae);
+        sym->loc = ae->loc;
+        sym->parent = sc->scopesym;
+        sc = sc->push(sym);
+        ae->lengthVar = NULL;       // Create it only if required
+        ae->currentDimension = i;   // Dimension for $, if required
+
+        e = expressionSemantic(e, sc);
+        e = resolveProperties(sc, e);
+
+        if (ae->lengthVar && sc->func)
+        {
+            // If $ was used, declare it now
+            Expression *de = new DeclarationExp(ae->loc, ae->lengthVar);
+            de = expressionSemantic(de, sc);
+            *pe0 = Expression::combine(*pe0, de);
+        }
+        sc = sc->pop();
+
+        if (e->op == TOKinterval)
+        {
+            IntervalExp *ie = (IntervalExp *)e;
+
+            Objects *tiargs = new Objects();
+            Expression *edim = new IntegerExp(ae->loc, i, Type::tsize_t);
+            edim = expressionSemantic(edim, sc);
+            tiargs->push(edim);
+
+            Expressions *fargs = new Expressions();
+            fargs->push(ie->lwr);
+            fargs->push(ie->upr);
+
+            unsigned xerrors = global.startGagging();
+            sc = sc->push();
+            FuncDeclaration *fslice = resolveFuncCall(ae->loc, sc, slice, tiargs, ae->e1->type, fargs, 1);
+            sc = sc->pop();
+            global.endGagging(xerrors);
+            if (!fslice)
+                goto Lfallback;
+
+            e = new DotTemplateInstanceExp(ae->loc, ae->e1, slice->ident, tiargs);
+            e = new CallExp(ae->loc, e, fargs);
+            e = expressionSemantic(e, sc);
+        }
+
+        if (!e->type)
+        {
+            ae->error("%s has no value", e->toChars());
+            e = new ErrorExp();
+        }
+        if (e->op == TOKerror)
+            return e;
+
+        (*ae->arguments)[i] = e;
+    }
+
+    return ae;
+}
+
+/**************************************
+ * Runs semantic on se->lwr and se->upr. Declares a temporary variable
+ * if '$' was used.
+ */
+Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, IntervalExp *ie, Expression **pe0)
+{
+    //assert(!ae->lengthVar);
+    if (!ie)
+        return ae;
+
+    VarDeclaration *lengthVar = ae->lengthVar;
+
+    // create scope for '$'
+    ArrayScopeSymbol *sym = new ArrayScopeSymbol(sc, ae);
+    sym->loc = ae->loc;
+    sym->parent = sc->scopesym;
+    sc = sc->push(sym);
+
+    for (size_t i = 0; i < 2; ++i)
+    {
+        Expression *e = i == 0 ? ie->lwr : ie->upr;
+        e = expressionSemantic(e, sc);
+        e = resolveProperties(sc, e);
+        if (!e->type)
+        {
+            ae->error("%s has no value", e->toChars());
+            return new ErrorExp();
+        }
+        (i == 0 ? ie->lwr : ie->upr) = e;
+    }
+
+    if (lengthVar != ae->lengthVar && sc->func)
+    {
+        // If $ was used, declare it now
+        Expression *de = new DeclarationExp(ae->loc, ae->lengthVar);
+        de = expressionSemantic(de, sc);
+        *pe0 = Expression::combine(*pe0, de);
+    }
+    sc = sc->pop();
+
+    return ae;
+}
+
+/******************************
+ * Perform semantic() on an array of Expressions.
+ */
+
+bool arrayExpressionSemantic(Expressions *exps, Scope *sc, bool preserveErrors)
+{
+    bool err = false;
+    if (exps)
+    {
+        for (size_t i = 0; i < exps->length; i++)
+        {
+            Expression *e = (*exps)[i];
+            if (e)
+            {
+                e = expressionSemantic(e, sc);
+                if (e->op == TOKerror)
+                    err = true;
+                if (preserveErrors || e->op != TOKerror)
+                    (*exps)[i] = e;
+            }
+        }
+    }
+    return err;
+}
+
+/******************************
+ * Check the tail CallExp is really property function call.
+ */
+static bool checkPropertyCall(Expression *e)
+{
+    while (e->op == TOKcomma)
+        e = ((CommaExp *)e)->e2;
+
+    if (e->op == TOKcall)
+    {
+        CallExp *ce = (CallExp *)e;
+        TypeFunction *tf;
+        if (ce->f)
+        {
+            tf = (TypeFunction *)ce->f->type;
+            /* If a forward reference to ce->f, try to resolve it
+             */
+            if (!tf->deco && ce->f->semanticRun < PASSsemanticdone)
+            {
+                dsymbolSemantic(ce->f, NULL);
+                tf = (TypeFunction *)ce->f->type;
+            }
+        }
+        else if (ce->e1->type->ty == Tfunction)
+            tf = (TypeFunction *)ce->e1->type;
+        else if (ce->e1->type->ty == Tdelegate)
+            tf = (TypeFunction *)ce->e1->type->nextOf();
+        else if (ce->e1->type->ty == Tpointer && ce->e1->type->nextOf()->ty == Tfunction)
+            tf = (TypeFunction *)ce->e1->type->nextOf();
+        else
+            assert(0);
+    }
+    return false;
+}
+
+// TODO: merge with Scope::search::searchScopes()
+static Dsymbol *searchScopes(Scope *sc, Loc loc, Identifier *ident, int flags)
+{
+    Dsymbol *s = NULL;
+    for (Scope *scx = sc; scx; scx = scx->enclosing)
+    {
+        if (!scx->scopesym)
+            continue;
+        if (scx->scopesym->isModule())
+            flags |= SearchUnqualifiedModule;    // tell Module.search() that SearchLocalsOnly is to be obeyed
+        s = scx->scopesym->search(loc, ident, flags);
+        if (s)
+        {
+            // overload set contains only module scope symbols.
+            if (s->isOverloadSet())
+                break;
+            // selective/renamed imports also be picked up
+            if (AliasDeclaration *ad = s->isAliasDeclaration())
+            {
+                if (ad->_import)
+                    break;
+            }
+            // See only module scope symbols for UFCS target.
+            Dsymbol *p = s->toParent2();
+            if (p && p->isModule())
+                break;
+        }
+        s = NULL;
+
+        // Stop when we hit a module, but keep going if that is not just under the global scope
+        if (scx->scopesym->isModule() && !(scx->enclosing && !scx->enclosing->enclosing))
+            break;
+    }
+    return s;
+}
+
+/******************************
+ * Find symbol in accordance with the UFCS name look up rule
+ */
+
+static Expression *searchUFCS(Scope *sc, UnaExp *ue, Identifier *ident)
+{
+    //printf("searchUFCS(ident = %s)\n", ident->toChars());
+    Loc loc = ue->loc;
+    int flags = 0;
+    Dsymbol *s = NULL;
+
+    if (sc->flags & SCOPEignoresymbolvisibility)
+        flags |= IgnoreSymbolVisibility;
+
+    // First look in local scopes
+    s = searchScopes(sc, loc, ident, flags | SearchLocalsOnly);
+    if (!s)
+    {
+        // Second look in imported modules
+        s = searchScopes(sc, loc, ident, flags | SearchImportsOnly);
+    }
+
+    if (!s)
+        return ue->e1->type->Type::getProperty(loc, ident, 0);
+
+    FuncDeclaration *f = s->isFuncDeclaration();
+    if (f)
+    {
+        TemplateDeclaration *td = getFuncTemplateDecl(f);
+        if (td)
+        {
+            if (td->overroot)
+                td = td->overroot;
+            s = td;
+        }
+    }
+
+    if (ue->op == TOKdotti)
+    {
+        DotTemplateInstanceExp *dti = (DotTemplateInstanceExp *)ue;
+        TemplateInstance *ti = new TemplateInstance(loc, s->ident);
+        ti->tiargs = dti->ti->tiargs;   // for better diagnostic message
+        if (!ti->updateTempDecl(sc, s))
+            return new ErrorExp();
+        return new ScopeExp(loc, ti);
+    }
+    else
+    {
+        //printf("-searchUFCS() %s\n", s->toChars());
+        return new DsymbolExp(loc, s);
+    }
+}
+
+/******************************
+ * Pull out callable entity with UFCS.
+ */
+
+static Expression *resolveUFCS(Scope *sc, CallExp *ce)
+{
+    Loc loc = ce->loc;
+    Expression *eleft;
+    Expression *e;
+
+    if (ce->e1->op == TOKdotid)
+    {
+        DotIdExp *die = (DotIdExp *)ce->e1;
+        Identifier *ident = die->ident;
+
+        Expression *ex = semanticX(die, sc);
+        if (ex != die)
+        {
+            ce->e1 = ex;
+            return NULL;
+        }
+        eleft = die->e1;
+
+        Type *t = eleft->type->toBasetype();
+        if (t->ty == Tarray || t->ty == Tsarray ||
+            t->ty == Tnull  || (t->isTypeBasic() && t->ty != Tvoid))
+        {
+            /* Built-in types and arrays have no callable properties, so do shortcut.
+             * It is necessary in: e.init()
+             */
+        }
+        else if (t->ty == Taarray)
+        {
+            if (ident == Id::remove)
+            {
+                /* Transform:
+                 *  aa.remove(arg) into delete aa[arg]
+                 */
+                if (!ce->arguments || ce->arguments->length != 1)
+                {
+                    ce->error("expected key as argument to aa.remove()");
+                    return new ErrorExp();
+                }
+                if (!eleft->type->isMutable())
+                {
+                    ce->error("cannot remove key from %s associative array %s",
+                            MODtoChars(t->mod), eleft->toChars());
+                    return new ErrorExp();
+                }
+                Expression *key = (*ce->arguments)[0];
+                key = expressionSemantic(key, sc);
+                key = resolveProperties(sc, key);
+
+                TypeAArray *taa = (TypeAArray *)t;
+                key = key->implicitCastTo(sc, taa->index);
+
+                if (key->checkValue())
+                    return new ErrorExp();
+
+                semanticTypeInfo(sc, taa->index);
+
+                return new RemoveExp(loc, eleft, key);
+            }
+        }
+        else
+        {
+            if (Expression *ey = semanticY(die, sc, 1))
+            {
+                if (ey->op == TOKerror)
+                    return ey;
+                ce->e1 = ey;
+                if (isDotOpDispatch(ey))
+                {
+                    unsigned errors = global.startGagging();
+                    e = expressionSemantic(ce->syntaxCopy(), sc);
+                    if (!global.endGagging(errors))
+                        return e;
+                    /* fall down to UFCS */
+                }
+                else
+                    return NULL;
+            }
+        }
+        e = searchUFCS(sc, die, ident);
+    }
+    else if (ce->e1->op == TOKdotti)
+    {
+        DotTemplateInstanceExp *dti = (DotTemplateInstanceExp *)ce->e1;
+        if (Expression *ey = semanticY(dti, sc, 1))
+        {
+            ce->e1 = ey;
+            return NULL;
+        }
+        eleft = dti->e1;
+        e = searchUFCS(sc, dti, dti->ti->name);
+    }
+    else
+        return NULL;
+
+    // Rewrite
+    ce->e1 = e;
+    if (!ce->arguments)
+        ce->arguments = new Expressions();
+    ce->arguments->shift(eleft);
+
+    return NULL;
+}
+
+/******************************
+ * Pull out property with UFCS.
+ */
+
+static Expression *resolveUFCSProperties(Scope *sc, Expression *e1, Expression *e2 = NULL)
+{
+    Loc loc = e1->loc;
+    Expression *eleft;
+    Expression *e;
+
+    if (e1->op == TOKdotid)
+    {
+        DotIdExp *die = (DotIdExp *)e1;
+        eleft = die->e1;
+        e = searchUFCS(sc, die, die->ident);
+    }
+    else if (e1->op == TOKdotti)
+    {
+        DotTemplateInstanceExp *dti;
+        dti = (DotTemplateInstanceExp *)e1;
+        eleft = dti->e1;
+        e = searchUFCS(sc, dti, dti->ti->name);
+    }
+    else
+        return NULL;
+
+    if (e == NULL)
+        return NULL;
+
+    // Rewrite
+    if (e2)
+    {
+        // run semantic without gagging
+        e2 = expressionSemantic(e2, sc);
+
+        /* f(e1) = e2
+         */
+        Expression *ex = e->copy();
+        Expressions *a1 = new Expressions();
+        a1->setDim(1);
+        (*a1)[0] = eleft;
+        ex = new CallExp(loc, ex, a1);
+        ex = trySemantic(ex, sc);
+
+        /* f(e1, e2)
+         */
+        Expressions *a2 = new Expressions();
+        a2->setDim(2);
+        (*a2)[0] = eleft;
+        (*a2)[1] = e2;
+        e = new CallExp(loc, e, a2);
+        if (ex)
+        {   // if fallback setter exists, gag errors
+            e = trySemantic(e, sc);
+            if (!e)
+            {   checkPropertyCall(ex);
+                ex = new AssignExp(loc, ex, e2);
+                return expressionSemantic(ex, sc);
+            }
+        }
+        else
+        {   // strict setter prints errors if fails
+            e = expressionSemantic(e, sc);
+        }
+        checkPropertyCall(e);
+        return e;
+    }
+    else
+    {
+        /* f(e1)
+         */
+        Expressions *arguments = new Expressions();
+        arguments->setDim(1);
+        (*arguments)[0] = eleft;
+        e = new CallExp(loc, e, arguments);
+        e = expressionSemantic(e, sc);
+        checkPropertyCall(e);
+        return expressionSemantic(e, sc);
+    }
+}
+
+/******************************
+ * If e1 is a property function (template), resolve it.
+ */
+
+Expression *resolvePropertiesOnly(Scope *sc, Expression *e1)
+{
+    //printf("e1 = %s %s\n", Token::toChars(e1->op), e1->toChars());
+    OverloadSet *os;
+    FuncDeclaration *fd;
+    TemplateDeclaration *td;
+
+    if (e1->op == TOKdot)
+    {
+        DotExp *de = (DotExp *)e1;
+        if (de->e2->op == TOKoverloadset)
+        {
+            os = ((OverExp *)de->e2)->vars;
+            goto Los;
+        }
+    }
+    else if (e1->op == TOKoverloadset)
+    {
+        os = ((OverExp *)e1)->vars;
+    Los:
+        assert(os);
+        for (size_t i = 0; i < os->a.length; i++)
+        {
+            Dsymbol *s = os->a[i];
+            fd = s->isFuncDeclaration();
+            td = s->isTemplateDeclaration();
+            if (fd)
+            {
+                if (((TypeFunction *)fd->type)->isproperty)
+                    return resolveProperties(sc, e1);
+            }
+            else if (td && td->onemember &&
+                     (fd = td->onemember->isFuncDeclaration()) != NULL)
+            {
+                if (((TypeFunction *)fd->type)->isproperty ||
+                    (fd->storage_class2 & STCproperty) ||
+                    (td->_scope->stc & STCproperty))
+                {
+                    return resolveProperties(sc, e1);
+                }
+            }
+        }
+    }
+    else if (e1->op == TOKdotti)
+    {
+        DotTemplateInstanceExp* dti = (DotTemplateInstanceExp *)e1;
+        if (dti->ti->tempdecl && (td = dti->ti->tempdecl->isTemplateDeclaration()) != NULL)
+            goto Ltd;
+    }
+    else if (e1->op == TOKdottd)
+    {
+        td = ((DotTemplateExp *)e1)->td;
+        goto Ltd;
+    }
+    else if (e1->op == TOKscope)
+    {
+        Dsymbol *s = ((ScopeExp *)e1)->sds;
+        TemplateInstance *ti = s->isTemplateInstance();
+        if (ti && !ti->semanticRun && ti->tempdecl)
+        {
+            if ((td = ti->tempdecl->isTemplateDeclaration()) != NULL)
+                goto Ltd;
+        }
+    }
+    else if (e1->op == TOKtemplate)
+    {
+        td = ((TemplateExp *)e1)->td;
+    Ltd:
+        assert(td);
+        if (td->onemember &&
+            (fd = td->onemember->isFuncDeclaration()) != NULL)
+        {
+            if (((TypeFunction *)fd->type)->isproperty ||
+                (fd->storage_class2 & STCproperty) ||
+                (td->_scope->stc & STCproperty))
+            {
+                return resolveProperties(sc, e1);
+            }
+        }
+    }
+    else if (e1->op == TOKdotvar && e1->type->ty == Tfunction)
+    {
+        DotVarExp *dve = (DotVarExp *)e1;
+        fd = dve->var->isFuncDeclaration();
+        goto Lfd;
+    }
+    else if (e1->op == TOKvar && e1->type->ty == Tfunction &&
+        (sc->intypeof || !((VarExp *)e1)->var->needThis()))
+    {
+        fd = ((VarExp *)e1)->var->isFuncDeclaration();
+    Lfd:
+        assert(fd);
+        if (((TypeFunction *)fd->type)->isproperty)
+            return resolveProperties(sc, e1);
+    }
+    return e1;
+}
+
+/*************************************************************
+ * Given var, we need to get the
+ * right 'this' pointer if var is in an outer class, but our
+ * existing 'this' pointer is in an inner class.
+ * Input:
+ *      e1      existing 'this'
+ *      ad      struct or class we need the correct 'this' for
+ *      var     the specific member of ad we're accessing
+ */
+
+static Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad,
+        Expression *e1, Declaration *var, int flag = 0)
+{
+    //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1->toChars(), ad->toChars(), var->toChars());
+ L1:
+    Type *t = e1->type->toBasetype();
+    //printf("e1->type = %s, var->type = %s\n", e1->type->toChars(), var->type->toChars());
+
+    /* If e1 is not the 'this' pointer for ad
+     */
+    if (ad &&
+        !(t->ty == Tpointer && t->nextOf()->ty == Tstruct &&
+          ((TypeStruct *)t->nextOf())->sym == ad)
+        &&
+        !(t->ty == Tstruct &&
+          ((TypeStruct *)t)->sym == ad)
+       )
+    {
+        ClassDeclaration *cd = ad->isClassDeclaration();
+        ClassDeclaration *tcd = t->isClassHandle();
+
+        /* e1 is the right this if ad is a base class of e1
+         */
+        if (!cd || !tcd ||
+            !(tcd == cd || cd->isBaseOf(tcd, NULL))
+           )
+        {
+            /* Only classes can be inner classes with an 'outer'
+             * member pointing to the enclosing class instance
+             */
+            if (tcd && tcd->isNested())
+            {
+                /* e1 is the 'this' pointer for an inner class: tcd.
+                 * Rewrite it as the 'this' pointer for the outer class.
+                 */
+
+                e1 = new DotVarExp(loc, e1, tcd->vthis);
+                e1->type = tcd->vthis->type;
+                e1->type = e1->type->addMod(t->mod);
+                // Do not call checkNestedRef()
+                //e1 = expressionSemantic(e1, sc);
+
+                // Skip up over nested functions, and get the enclosing
+                // class type.
+                int n = 0;
+                Dsymbol *s;
+                for (s = tcd->toParent();
+                     s && s->isFuncDeclaration();
+                     s = s->toParent())
+                {
+                    FuncDeclaration *f = s->isFuncDeclaration();
+                    if (f->vthis)
+                    {
+                        //printf("rewriting e1 to %s's this\n", f->toChars());
+                        n++;
+                        e1 = new VarExp(loc, f->vthis);
+                    }
+                    else
+                    {
+                        e1->error("need `this` of type %s to access member %s"
+                                  " from static function %s",
+                            ad->toChars(), var->toChars(), f->toChars());
+                        e1 = new ErrorExp();
+                        return e1;
+                    }
+                }
+                if (s && s->isClassDeclaration())
+                {
+                    e1->type = s->isClassDeclaration()->type;
+                    e1->type = e1->type->addMod(t->mod);
+                    if (n > 1)
+                        e1 = expressionSemantic(e1, sc);
+                }
+                else
+                    e1 = expressionSemantic(e1, sc);
+                goto L1;
+            }
+
+            /* Can't find a path from e1 to ad
+             */
+            if (flag)
+                return NULL;
+            e1->error("this for %s needs to be type %s not type %s",
+                var->toChars(), ad->toChars(), t->toChars());
+            return new ErrorExp();
+        }
+    }
+    return e1;
+}
+
+/***************************************
+ * Pull out any properties.
+ */
+
+static Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL)
+{
+    //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", Token::toChars(e1->op), e1->toChars(), e2 ? e2->toChars() : NULL);
+    Loc loc = e1->loc;
+
+    OverloadSet *os;
+    Dsymbol *s;
+    Objects *tiargs;
+    Type *tthis;
+    if (e1->op == TOKdot)
+    {
+        DotExp *de = (DotExp *)e1;
+        if (de->e2->op == TOKoverloadset)
+        {
+            tiargs = NULL;
+            tthis  = de->e1->type;
+            os = ((OverExp *)de->e2)->vars;
+            goto Los;
+        }
+    }
+    else if (e1->op == TOKoverloadset)
+    {
+        tiargs = NULL;
+        tthis  = NULL;
+        os = ((OverExp *)e1)->vars;
+    Los:
+        assert(os);
+        FuncDeclaration *fd = NULL;
+        if (e2)
+        {
+            e2 = expressionSemantic(e2, sc);
+            if (e2->op == TOKerror)
+                return new ErrorExp();
+            e2 = resolveProperties(sc, e2);
+
+            Expressions a;
+            a.push(e2);
+
+            for (size_t i = 0; i < os->a.length; i++)
+            {
+                FuncDeclaration *f = resolveFuncCall(loc, sc, os->a[i], tiargs, tthis, &a, 1);
+                if (f)
+                {
+                    if (f->errors)
+                        return new ErrorExp();
+                    fd = f;
+                    assert(fd->type->ty == Tfunction);
+                }
+            }
+            if (fd)
+            {
+                Expression *e = new CallExp(loc, e1, e2);
+                return expressionSemantic(e, sc);
+            }
+        }
+        {
+            for (size_t i = 0; i < os->a.length; i++)
+            {
+                FuncDeclaration *f = resolveFuncCall(loc, sc, os->a[i], tiargs, tthis, NULL, 1);
+                if (f)
+                {
+                    if (f->errors)
+                        return new ErrorExp();
+                    fd = f;
+                    assert(fd->type->ty == Tfunction);
+                    TypeFunction *tf = (TypeFunction *)fd->type;
+                    if (!tf->isref && e2)
+                        goto Leproplvalue;
+                }
+            }
+            if (fd)
+            {
+                Expression *e = new CallExp(loc, e1);
+                if (e2)
+                    e = new AssignExp(loc, e, e2);
+                return expressionSemantic(e, sc);
+            }
+        }
+        if (e2)
+            goto Leprop;
+    }
+    else if (e1->op == TOKdotti)
+    {
+        DotTemplateInstanceExp* dti = (DotTemplateInstanceExp *)e1;
+        if (!dti->findTempDecl(sc))
+            goto Leprop;
+        if (!dti->ti->semanticTiargs(sc))
+            goto Leprop;
+        tiargs = dti->ti->tiargs;
+        tthis  = dti->e1->type;
+        if ((os = dti->ti->tempdecl->isOverloadSet()) != NULL)
+            goto Los;
+        if ((s = dti->ti->tempdecl) != NULL)
+            goto Lfd;
+    }
+    else if (e1->op == TOKdottd)
+    {
+        DotTemplateExp *dte = (DotTemplateExp *)e1;
+        s      = dte->td;
+        tiargs = NULL;
+        tthis  = dte->e1->type;
+        goto Lfd;
+    }
+    else if (e1->op == TOKscope)
+    {
+        s = ((ScopeExp *)e1)->sds;
+        TemplateInstance *ti = s->isTemplateInstance();
+        if (ti && !ti->semanticRun && ti->tempdecl)
+        {
+            //assert(ti->needsTypeInference(sc));
+            if (!ti->semanticTiargs(sc))
+                goto Leprop;
+            tiargs = ti->tiargs;
+            tthis  = NULL;
+            if ((os = ti->tempdecl->isOverloadSet()) != NULL)
+                goto Los;
+            if ((s = ti->tempdecl) != NULL)
+                goto Lfd;
+        }
+    }
+    else if (e1->op == TOKtemplate)
+    {
+        s      = ((TemplateExp *)e1)->td;
+        tiargs = NULL;
+        tthis  = NULL;
+        goto Lfd;
+    }
+    else if (e1->op == TOKdotvar && e1->type && e1->type->toBasetype()->ty == Tfunction)
+    {
+        DotVarExp *dve = (DotVarExp *)e1;
+        s      = dve->var->isFuncDeclaration();
+        tiargs = NULL;
+        tthis  = dve->e1->type;
+        goto Lfd;
+    }
+    else if (e1->op == TOKvar && e1->type && e1->type->toBasetype()->ty == Tfunction)
+    {
+        s      = ((VarExp *)e1)->var->isFuncDeclaration();
+        tiargs = NULL;
+        tthis  = NULL;
+    Lfd:
+        assert(s);
+        if (e2)
+        {
+            e2 = expressionSemantic(e2, sc);
+            if (e2->op == TOKerror)
+                return new ErrorExp();
+            e2 = resolveProperties(sc, e2);
+
+            Expressions a;
+            a.push(e2);
+
+            FuncDeclaration *fd = resolveFuncCall(loc, sc, s, tiargs, tthis, &a, 1);
+            if (fd && fd->type)
+            {
+                if (fd->errors)
+                    return new ErrorExp();
+                assert(fd->type->ty == Tfunction);
+                Expression *e = new CallExp(loc, e1, e2);
+                return expressionSemantic(e, sc);
+            }
+        }
+        {
+            FuncDeclaration *fd = resolveFuncCall(loc, sc, s, tiargs, tthis, NULL, 1);
+            if (fd && fd->type)
+            {
+                if (fd->errors)
+                    return new ErrorExp();
+                assert(fd->type->ty == Tfunction);
+                TypeFunction *tf = (TypeFunction *)fd->type;
+                if (!e2 || tf->isref)
+                {
+                    Expression *e = new CallExp(loc, e1);
+                    if (e2)
+                        e = new AssignExp(loc, e, e2);
+                    return expressionSemantic(e, sc);
+                }
+            }
+        }
+        if (FuncDeclaration *fd = s->isFuncDeclaration())
+        {
+            // Keep better diagnostic message for invalid property usage of functions
+            assert(fd->type->ty == Tfunction);
+            Expression *e = new CallExp(loc, e1, e2);
+            return expressionSemantic(e, sc);
+        }
+        if (e2)
+            goto Leprop;
+    }
+    if (e1->op == TOKvar)
+    {
+        VarExp *ve = (VarExp *)e1;
+        VarDeclaration *v = ve->var->isVarDeclaration();
+        if (v && ve->checkPurity(sc, v))
+            return new ErrorExp();
+    }
+    if (e2)
+        return NULL;
+
+    if (e1->type &&
+        e1->op != TOKtype)      // function type is not a property
+    {
+        /* Look for e1 being a lazy parameter; rewrite as delegate call
+         */
+        if (e1->op == TOKvar)
+        {
+            VarExp *ve = (VarExp *)e1;
+
+            if (ve->var->storage_class & STClazy)
+            {
+                Expression *e = new CallExp(loc, e1);
+                return expressionSemantic(e, sc);
+            }
+        }
+        else if (e1->op == TOKdotvar)
+        {
+            // Check for reading overlapped pointer field in @safe code.
+            if (checkUnsafeAccess(sc, e1, true, true))
+                return new ErrorExp();
+        }
+        else if (e1->op == TOKdot)
+        {
+            e1->error("expression has no value");
+            return new ErrorExp();
+        }
+        else if (e1->op == TOKcall)
+        {
+            CallExp *ce = (CallExp *)e1;
+            // Check for reading overlapped pointer field in @safe code.
+            if (checkUnsafeAccess(sc, ce->e1, true, true))
+                return new ErrorExp();
+        }
+    }
+
+    if (!e1->type)
+    {
+        error(loc, "cannot resolve type for %s", e1->toChars());
+        e1 = new ErrorExp();
+    }
+    return e1;
+
+Leprop:
+    error(loc, "not a property %s", e1->toChars());
+    return new ErrorExp();
+
+Leproplvalue:
+    error(loc, "%s is not an lvalue", e1->toChars());
+    return new ErrorExp();
+}
+
+Expression *resolveProperties(Scope *sc, Expression *e)
+{
+    //printf("resolveProperties(%s)\n", e->toChars());
+
+    e = resolvePropertiesX(sc, e);
+    if (e->checkRightThis(sc))
+        return new ErrorExp();
+    return e;
+}
+
+/****************************************
+ * The common type is determined by applying ?: to each pair.
+ * Output:
+ *      exps[]  properties resolved, implicitly cast to common type, rewritten in place
+ *      *pt     if pt is not NULL, set to the common type
+ * Returns:
+ *      true    a semantic error was detected
+ */
+
+static bool arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt)
+{
+    /* Still have a problem with:
+     *  ubyte[][] = [ cast(ubyte[])"hello", [1]];
+     * which works if the array literal is initialized top down with the ubyte[][]
+     * type, but fails with this function doing bottom up typing.
+     */
+    //printf("arrayExpressionToCommonType()\n");
+    IntegerExp integerexp(0);
+    CondExp condexp(Loc(), &integerexp, NULL, NULL);
+
+    Type *t0 = NULL;
+    Expression *e0 = NULL;      // dead-store to prevent spurious warning
+    size_t j0 = ~0;             // dead-store to prevent spurious warning
+    bool foundType = false;
+
+    for (size_t i = 0; i < exps->length; i++)
+    {
+        Expression *e = (*exps)[i];
+        if (!e)
+            continue;
+
+        e = resolveProperties(sc, e);
+        if (!e->type)
+        {
+            e->error("%s has no value", e->toChars());
+            t0 = Type::terror;
+            continue;
+        }
+        if (e->op == TOKtype)
+        {
+            foundType = true;   // do not break immediately, there might be more errors
+            e->checkValue();    // report an error "type T has no value"
+            t0 = Type::terror;
+            continue;
+        }
+        if (e->type->ty == Tvoid)
+        {
+            // void expressions do not concur to the determination of the common
+            // type.
+            continue;
+        }
+        if (checkNonAssignmentArrayOp(e))
+        {
+            t0 = Type::terror;
+            continue;
+        }
+
+        e = doCopyOrMove(sc, e);
+
+        if (!foundType && t0 && !t0->equals(e->type))
+        {
+            /* This applies ?: to merge the types. It's backwards;
+             * ?: should call this function to merge types.
+             */
+            condexp.type = NULL;
+            condexp.e1 = e0;
+            condexp.e2 = e;
+            condexp.loc = e->loc;
+            Expression *ex = expressionSemantic(&condexp, sc);
+            if (ex->op == TOKerror)
+                e = ex;
+            else
+            {
+                (*exps)[j0] = condexp.e1;
+                e = condexp.e2;
+            }
+        }
+        j0 = i;
+        e0 = e;
+        t0 = e->type;
+        if (e->op != TOKerror)
+            (*exps)[i] = e;
+    }
+
+    if (!t0)
+        t0 = Type::tvoid;               // [] is typed as void[]
+    else if (t0->ty != Terror)
+    {
+        for (size_t i = 0; i < exps->length; i++)
+        {
+            Expression *e = (*exps)[i];
+            if (!e)
+                continue;
+
+            e = e->implicitCastTo(sc, t0);
+            //assert(e->op != TOKerror);
+            if (e->op == TOKerror)
+            {
+                /* Bugzilla 13024: a workaround for the bug in typeMerge -
+                 * it should paint e1 and e2 by deduced common type,
+                 * but doesn't in this particular case.
+                 */
+                t0 = Type::terror;
+                break;
+            }
+            (*exps)[i] = e;
+        }
+    }
+    if (pt)
+        *pt = t0;
+
+    return (t0 == Type::terror);
+}
+
+static Expression *opAssignToOp(Loc loc, TOK op, Expression *e1, Expression *e2)
+{   Expression *e;
+
+    switch (op)
+    {
+        case TOKaddass:   e = new AddExp(loc, e1, e2);  break;
+        case TOKminass:   e = new MinExp(loc, e1, e2);  break;
+        case TOKmulass:   e = new MulExp(loc, e1, e2);  break;
+        case TOKdivass:   e = new DivExp(loc, e1, e2);  break;
+        case TOKmodass:   e = new ModExp(loc, e1, e2);  break;
+        case TOKandass:   e = new AndExp(loc, e1, e2);  break;
+        case TOKorass:    e = new OrExp (loc, e1, e2);  break;
+        case TOKxorass:   e = new XorExp(loc, e1, e2);  break;
+        case TOKshlass:   e = new ShlExp(loc, e1, e2);  break;
+        case TOKshrass:   e = new ShrExp(loc, e1, e2);  break;
+        case TOKushrass:  e = new UshrExp(loc, e1, e2); break;
+        default:        assert(0);
+    }
+    return e;
+}
+
+/*********************
+ * Rewrite:
+ *    array.length op= e2
+ * as:
+ *    array.length = array.length op e2
+ * or:
+ *    auto tmp = &array;
+ *    (*tmp).length = (*tmp).length op e2
+ */
+
+static Expression *rewriteOpAssign(BinExp *exp)
+{
+    Expression *e;
+
+    assert(exp->e1->op == TOKarraylength);
+    ArrayLengthExp *ale = (ArrayLengthExp *)exp->e1;
+    if (ale->e1->op == TOKvar)
+    {
+        e = opAssignToOp(exp->loc, exp->op, ale, exp->e2);
+        e = new AssignExp(exp->loc, ale->syntaxCopy(), e);
+    }
+    else
+    {
+        /*    auto tmp = &array;
+         *    (*tmp).length = (*tmp).length op e2
+         */
+        VarDeclaration *tmp = copyToTemp(0, "__arraylength", new AddrExp(ale->loc, ale->e1));
+
+        Expression *e1 = new ArrayLengthExp(ale->loc, new PtrExp(ale->loc, new VarExp(ale->loc, tmp)));
+        Expression *elvalue = e1->syntaxCopy();
+        e = opAssignToOp(exp->loc, exp->op, e1, exp->e2);
+        e = new AssignExp(exp->loc, elvalue, e);
+        e = new CommaExp(exp->loc, new DeclarationExp(ale->loc, tmp), e);
+    }
+    return e;
+}
 
 /****************************************
  * Preprocess arguments to function.
@@ -76,39 +1302,728 @@ Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL)
  *      true    a semantic error occurred
  */
 
-static bool preFunctionParameters(Scope *sc, Expressions *exps)
-{
-    bool err = false;
-    if (exps)
+static bool preFunctionParameters(Scope *sc, Expressions *exps)
+{
+    bool err = false;
+    if (exps)
+    {
+        expandTuples(exps);
+
+        for (size_t i = 0; i < exps->length; i++)
+        {
+            Expression *arg = (*exps)[i];
+
+            arg = resolveProperties(sc, arg);
+            if (arg->op == TOKtype)
+            {
+                arg->error("cannot pass type %s as a function argument", arg->toChars());
+                arg = new ErrorExp();
+                err = true;
+            }
+            else if (arg->type->toBasetype()->ty == Tfunction)
+            {
+                arg->error("cannot pass type %s as a function argument", arg->toChars());
+                arg = new ErrorExp();
+                err = true;
+            }
+            else if (checkNonAssignmentArrayOp(arg))
+            {
+                arg = new ErrorExp();
+                err = true;
+            }
+            (*exps)[i] = arg;
+        }
+    }
+    return err;
+}
+
+/********************************************
+ * Issue an error if default construction is disabled for type t.
+ * Default construction is required for arrays and 'out' parameters.
+ * Returns:
+ *      true    an error was issued
+ */
+static bool checkDefCtor(Loc loc, Type *t)
+{
+    t = t->baseElemOf();
+    if (t->ty == Tstruct)
+    {
+        StructDeclaration *sd = ((TypeStruct *)t)->sym;
+        if (sd->noDefaultCtor)
+        {
+            sd->error(loc, "default construction is disabled");
+            return true;
+        }
+    }
+    return false;
+}
+
+/****************************************
+ * Now that we know the exact type of the function we're calling,
+ * the arguments[] need to be adjusted:
+ *      1. implicitly convert argument to the corresponding parameter type
+ *      2. add default arguments for any missing arguments
+ *      3. do default promotions on arguments corresponding to ...
+ *      4. add hidden _arguments[] argument
+ *      5. call copy constructor for struct value arguments
+ * Input:
+ *      tf      type of the function
+ *      fd      the function being called, NULL if called indirectly
+ * Output:
+ *      *prettype return type of function
+ *      *peprefix expression to execute before arguments[] are evaluated, NULL if none
+ * Returns:
+ *      true    errors happened
+ */
+
+static bool functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
+        Type *tthis, Expressions *arguments, FuncDeclaration *fd, Type **prettype, Expression **peprefix)
+{
+    //printf("functionParameters()\n");
+    assert(arguments);
+    assert(fd || tf->next);
+    size_t nargs = arguments ? arguments->length : 0;
+    size_t nparams = tf->parameterList.length();
+    unsigned olderrors = global.errors;
+    bool err = false;
+    *prettype = Type::terror;
+    Expression *eprefix = NULL;
+    *peprefix = NULL;
+
+    if (nargs > nparams && tf->parameterList.varargs == VARARGnone)
+    {
+        error(loc, "expected %llu arguments, not %llu for non-variadic function type %s", (ulonglong)nparams, (ulonglong)nargs, tf->toChars());
+        return true;
+    }
+
+    // If inferring return type, and semantic3() needs to be run if not already run
+    if (!tf->next && fd->inferRetType)
+    {
+        fd->functionSemantic();
+    }
+    else if (fd && fd->parent)
+    {
+        TemplateInstance *ti = fd->parent->isTemplateInstance();
+        if (ti && ti->tempdecl)
+        {
+            fd->functionSemantic3();
+        }
+    }
+    bool isCtorCall = fd && fd->needThis() && fd->isCtorDeclaration();
+
+    size_t n = (nargs > nparams) ? nargs : nparams;   // n = max(nargs, nparams)
+
+    /* If the function return type has wildcards in it, we'll need to figure out the actual type
+     * based on the actual argument types.
+     */
+    MOD wildmatch = 0;
+    if (tthis && tf->isWild() && !isCtorCall)
+    {
+        Type *t = tthis;
+        if (t->isImmutable())
+            wildmatch = MODimmutable;
+        else if (t->isWildConst())
+            wildmatch = MODwildconst;
+        else if (t->isWild())
+            wildmatch = MODwild;
+        else if (t->isConst())
+            wildmatch = MODconst;
+        else
+            wildmatch = MODmutable;
+    }
+
+    int done = 0;
+    for (size_t i = 0; i < n; i++)
+    {
+        Expression *arg;
+
+        if (i < nargs)
+            arg = (*arguments)[i];
+        else
+            arg = NULL;
+
+        if (i < nparams)
+        {
+            Parameter *p = tf->parameterList[i];
+
+            if (!arg)
+            {
+                if (!p->defaultArg)
+                {
+                    if (tf->parameterList.varargs == VARARGtypesafe && i + 1 == nparams)
+                        goto L2;
+                    error(loc, "expected %llu function arguments, not %llu", (ulonglong)nparams, (ulonglong)nargs);
+                    return true;
+                }
+                arg = p->defaultArg;
+                arg = inlineCopy(arg, sc);
+                // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__
+                arg = arg->resolveLoc(loc, sc);
+                arguments->push(arg);
+                nargs++;
+            }
+
+            if (tf->parameterList.varargs == VARARGtypesafe && i + 1 == nparams)
+            {
+                //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars());
+                {
+                    MATCH m;
+                    if ((m = arg->implicitConvTo(p->type)) > MATCHnomatch)
+                    {
+                        if (p->type->nextOf() && arg->implicitConvTo(p->type->nextOf()) >= m)
+                            goto L2;
+                        else if (nargs != nparams)
+                        {   error(loc, "expected %llu function arguments, not %llu", (ulonglong)nparams, (ulonglong)nargs);
+                            return true;
+                        }
+                        goto L1;
+                    }
+                }
+             L2:
+                Type *tb = p->type->toBasetype();
+                Type *tret = p->isLazyArray();
+                switch (tb->ty)
+                {
+                    case Tsarray:
+                    case Tarray:
+                    {
+                        /* Create a static array variable v of type arg->type:
+                         *  T[dim] __arrayArg = [ arguments[i], ..., arguments[nargs-1] ];
+                         *
+                         * The array literal in the initializer of the hidden variable
+                         * is now optimized. See Bugzilla 2356.
+                         */
+                        Type *tbn = ((TypeArray *)tb)->next;
+
+                        Expressions *elements = new Expressions();
+                        elements->setDim(nargs - i);
+                        for (size_t u = 0; u < elements->length; u++)
+                        {
+                            Expression *a = (*arguments)[i + u];
+                            if (tret && a->implicitConvTo(tret))
+                            {
+                                a = a->implicitCastTo(sc, tret);
+                                a = a->optimize(WANTvalue);
+                                a = toDelegate(a, a->type, sc);
+                            }
+                            else
+                                a = a->implicitCastTo(sc, tbn);
+                            (*elements)[u] = a;
+                        }
+                        // Bugzilla 14395: Convert to a static array literal, or its slice.
+                        arg = new ArrayLiteralExp(loc, tbn->sarrayOf(nargs - i), elements);
+                        if (tb->ty == Tarray)
+                        {
+                            arg = new SliceExp(loc, arg, NULL, NULL);
+                            arg->type = p->type;
+                        }
+                        break;
+                    }
+                    case Tclass:
+                    {
+                        /* Set arg to be:
+                         *      new Tclass(arg0, arg1, ..., argn)
+                         */
+                        Expressions *args = new Expressions();
+                        args->setDim(nargs - i);
+                        for (size_t u = i; u < nargs; u++)
+                            (*args)[u - i] = (*arguments)[u];
+                        arg = new NewExp(loc, NULL, NULL, p->type, args);
+                        break;
+                    }
+                    default:
+                        if (!arg)
+                        {
+                            error(loc, "not enough arguments");
+                            return true;
+                        }
+                        break;
+                }
+                arg = expressionSemantic(arg, sc);
+                //printf("\targ = '%s'\n", arg->toChars());
+                arguments->setDim(i + 1);
+                (*arguments)[i] =  arg;
+                nargs = i + 1;
+                done = 1;
+            }
+
+        L1:
+            if (!(p->storageClass & STClazy && p->type->ty == Tvoid))
+            {
+                bool isRef = (p->storageClass & (STCref | STCout)) != 0;
+                if (unsigned char wm = arg->type->deduceWild(p->type, isRef))
+                {
+                    if (wildmatch)
+                        wildmatch = MODmerge(wildmatch, wm);
+                    else
+                        wildmatch = wm;
+                    //printf("[%d] p = %s, a = %s, wm = %d, wildmatch = %d\n", i, p->type->toChars(), arg->type->toChars(), wm, wildmatch);
+                }
+            }
+        }
+        if (done)
+            break;
+    }
+    if ((wildmatch == MODmutable || wildmatch == MODimmutable) &&
+        tf->next->hasWild() &&
+        (tf->isref || !tf->next->implicitConvTo(tf->next->immutableOf())))
     {
-        expandTuples(exps);
+        if (fd)
+        {
+            /* If the called function may return the reference to
+             * outer inout data, it should be rejected.
+             *
+             * void foo(ref inout(int) x) {
+             *   ref inout(int) bar(inout(int)) { return x; }
+             *   struct S { ref inout(int) bar() inout { return x; } }
+             *   bar(int.init) = 1;  // bad!
+             *   S().bar() = 1;      // bad!
+             * }
+             */
+            Dsymbol *s = NULL;
+            if (fd->isThis() || fd->isNested())
+                s = fd->toParent2();
+            for (; s; s = s->toParent2())
+            {
+                if (AggregateDeclaration *ad = s->isAggregateDeclaration())
+                {
+                    if (ad->isNested())
+                        continue;
+                    break;
+                }
+                if (FuncDeclaration *ff = s->isFuncDeclaration())
+                {
+                    if (((TypeFunction *)ff->type)->iswild)
+                        goto Linouterr;
 
-        for (size_t i = 0; i < exps->length; i++)
+                    if (ff->isNested() || ff->isThis())
+                        continue;
+                }
+                break;
+            }
+        }
+        else if (tf->isWild())
         {
-            Expression *arg = (*exps)[i];
+        Linouterr:
+            const char *s = wildmatch == MODmutable ? "mutable" : MODtoChars(wildmatch);
+            error(loc, "modify inout to %s is not allowed inside inout function", s);
+            return true;
+        }
+    }
 
-            arg = resolveProperties(sc, arg);
-            if (arg->op == TOKtype)
+    assert(nargs >= nparams);
+    for (size_t i = 0; i < nargs; i++)
+    {
+        Expression *arg = (*arguments)[i];
+        assert(arg);
+        if (i < nparams)
+        {
+            Parameter *p = tf->parameterList[i];
+
+            if (!(p->storageClass & STClazy && p->type->ty == Tvoid))
             {
-                arg->error("cannot pass type %s as a function argument", arg->toChars());
-                arg = new ErrorExp();
+                Type *tprm = p->type;
+                if (p->type->hasWild())
+                    tprm = p->type->substWildTo(wildmatch);
+                if (!tprm->equals(arg->type))
+                {
+                    //printf("arg->type = %s, p->type = %s\n", arg->type->toChars(), p->type->toChars());
+                    arg = arg->implicitCastTo(sc, tprm);
+                    arg = arg->optimize(WANTvalue, (p->storageClass & (STCref | STCout)) != 0);
+                }
+            }
+            if (p->storageClass & STCref)
+            {
+                arg = arg->toLvalue(sc, arg);
+
+                // Look for mutable misaligned pointer, etc., in @safe mode
+                err |= checkUnsafeAccess(sc, arg, false, true);
+            }
+            else if (p->storageClass & STCout)
+            {
+                Type *t = arg->type;
+                if (!t->isMutable() || !t->isAssignable())  // check blit assignable
+                {
+                    arg->error("cannot modify struct %s with immutable members", arg->toChars());
+                    err = true;
+                }
+                else
+                {
+                    // Look for misaligned pointer, etc., in @safe mode
+                    err |= checkUnsafeAccess(sc, arg, false, true);
+                    err |= checkDefCtor(arg->loc, t);   // t must be default constructible
+                }
+                arg = arg->toLvalue(sc, arg);
+            }
+            else if (p->storageClass & STClazy)
+            {
+                // Convert lazy argument to a delegate
+                if (p->type->ty == Tvoid)
+                    arg = toDelegate(arg, p->type, sc);
+                else
+                    arg = toDelegate(arg, arg->type, sc);
+            }
+
+            //printf("arg: %s\n", arg->toChars());
+            //printf("type: %s\n", arg->type->toChars());
+            if (tf->parameterEscapes(p))
+            {
+                /* Argument value can escape from the called function.
+                 * Check arg to see if it matters.
+                 */
+                if (global.params.vsafe)
+                    err |= checkParamArgumentEscape(sc, fd, p->ident, arg, false);
+            }
+            else
+            {
+                /* Argument value cannot escape from the called function.
+                 */
+                Expression *a = arg;
+                if (a->op == TOKcast)
+                    a = ((CastExp *)a)->e1;
+
+                if (a->op == TOKfunction)
+                {
+                    /* Function literals can only appear once, so if this
+                     * appearance was scoped, there cannot be any others.
+                     */
+                    FuncExp *fe = (FuncExp *)a;
+                    fe->fd->tookAddressOf = 0;
+                }
+                else if (a->op == TOKdelegate)
+                {
+                    /* For passing a delegate to a scoped parameter,
+                     * this doesn't count as taking the address of it.
+                     * We only worry about 'escaping' references to the function.
+                     */
+                    DelegateExp *de = (DelegateExp *)a;
+                    if (de->e1->op == TOKvar)
+                    {   VarExp *ve = (VarExp *)de->e1;
+                        FuncDeclaration *f = ve->var->isFuncDeclaration();
+                        if (f)
+                        {   f->tookAddressOf--;
+                            //printf("tookAddressOf = %d\n", f->tookAddressOf);
+                        }
+                    }
+                }
+            }
+            arg = arg->optimize(WANTvalue, (p->storageClass & (STCref | STCout)) != 0);
+        }
+        else
+        {
+            // These will be the trailing ... arguments
+
+            // If not D linkage, do promotions
+            if (tf->linkage != LINKd)
+            {
+                // Promote bytes, words, etc., to ints
+                arg = integralPromotions(arg, sc);
+
+                // Promote floats to doubles
+                switch (arg->type->ty)
+                {
+                    case Tfloat32:
+                        arg = arg->castTo(sc, Type::tfloat64);
+                        break;
+
+                    case Timaginary32:
+                        arg = arg->castTo(sc, Type::timaginary64);
+                        break;
+                }
+
+                if (tf->parameterList.varargs == VARARGvariadic)
+                {
+                    const char *p = tf->linkage == LINKc ? "extern(C)" : "extern(C++)";
+                    if (arg->type->ty == Tarray)
+                    {
+                        arg->error("cannot pass dynamic arrays to %s vararg functions", p);
+                        err = true;
+                    }
+                    if (arg->type->ty == Tsarray)
+                    {
+                        arg->error("cannot pass static arrays to %s vararg functions", p);
+                        err = true;
+                    }
+                }
+            }
+
+            // Do not allow types that need destructors
+            if (arg->type->needsDestruction())
+            {
+                arg->error("cannot pass types that need destruction as variadic arguments");
                 err = true;
             }
-            else if (arg->type->toBasetype()->ty == Tfunction)
+
+            // Convert static arrays to dynamic arrays
+            // BUG: I don't think this is right for D2
+            Type *tb = arg->type->toBasetype();
+            if (tb->ty == Tsarray)
             {
-                arg->error("cannot pass type %s as a function argument", arg->toChars());
-                arg = new ErrorExp();
+                TypeSArray *ts = (TypeSArray *)tb;
+                Type *ta = ts->next->arrayOf();
+                if (ts->size(arg->loc) == 0)
+                    arg = new NullExp(arg->loc, ta);
+                else
+                    arg = arg->castTo(sc, ta);
+            }
+            if (tb->ty == Tstruct)
+            {
+                //arg = callCpCtor(sc, arg);
+            }
+
+            // Give error for overloaded function addresses
+            if (arg->op == TOKsymoff)
+            {   SymOffExp *se = (SymOffExp *)arg;
+                if (se->hasOverloads &&
+                    !se->var->isFuncDeclaration()->isUnique())
+                {   arg->error("function %s is overloaded", arg->toChars());
+                    err = true;
+                }
+            }
+            if (arg->checkValue())
                 err = true;
+            arg = arg->optimize(WANTvalue);
+        }
+        (*arguments)[i] = arg;
+    }
+
+    /* If calling C scanf(), printf(), or any variants, check the format string against the arguments
+     */
+    const bool isVa_list = tf->parameterList.varargs == VARARGnone;
+    if (fd && (fd->flags & FUNCFLAGprintf))
+    {
+        if (StringExp *se = (*arguments)[nparams - 1 - isVa_list]->isStringExp())
+        {
+            Expressions argslice;
+            argslice.reserve(nargs - nparams);
+            for (size_t i = nparams; i < nargs; i++)
+                argslice.push((*arguments)[i]);
+            checkPrintfFormat(se->loc, se->toPtr(), argslice, isVa_list);
+        }
+    }
+    else if (fd && (fd->flags & FUNCFLAGscanf))
+    {
+        if (StringExp *se = (*arguments)[nparams - 1 - isVa_list]->isStringExp())
+        {
+            Expressions argslice;
+            argslice.reserve(nargs - nparams);
+            for (size_t i = nparams; i < nargs; i++)
+                argslice.push((*arguments)[i]);
+            checkPrintfFormat(se->loc, se->toPtr(), argslice, isVa_list);
+        }
+    }
+
+    /* Remaining problems:
+     * 1. order of evaluation - some function push L-to-R, others R-to-L. Until we resolve what array assignment does (which is
+     *    implemented by calling a function) we'll defer this for now.
+     * 2. value structs (or static arrays of them) that need to be copy constructed
+     * 3. value structs (or static arrays of them) that have destructors, and subsequent arguments that may throw before the
+     *    function gets called (functions normally destroy their parameters)
+     * 2 and 3 are handled by doing the argument construction in 'eprefix' so that if a later argument throws, they are cleaned
+     * up properly. Pushing arguments on the stack then cannot fail.
+     */
+    if (1)
+    {
+        /* TODO: tackle problem 1)
+         */
+        const bool leftToRight = true; // TODO: something like !fd.isArrayOp
+        if (!leftToRight)
+            assert(nargs == nparams); // no variadics for RTL order, as they would probably be evaluated LTR and so add complexity
+
+        const ptrdiff_t start = (leftToRight ? 0 : (ptrdiff_t)nargs - 1);
+        const ptrdiff_t end = (leftToRight ? (ptrdiff_t)nargs : -1);
+        const ptrdiff_t step = (leftToRight ? 1 : -1);
+
+        /* Compute indices of last throwing argument and first arg needing destruction.
+         * Used to not set up destructors unless an arg needs destruction on a throw
+         * in a later argument.
+         */
+        ptrdiff_t lastthrow = -1;
+        ptrdiff_t firstdtor = -1;
+        for (ptrdiff_t i = start; i != end; i += step)
+        {
+            Expression *arg = (*arguments)[i];
+            if (canThrow(arg, sc->func, false))
+                lastthrow = i;
+            if (firstdtor == -1 && arg->type->needsDestruction())
+            {
+                Parameter *p = (i >= (ptrdiff_t)nparams ? NULL : tf->parameterList[i]);
+                if (!(p && (p->storageClass & (STClazy | STCref | STCout))))
+                    firstdtor = i;
             }
-            else if (checkNonAssignmentArrayOp(arg))
+        }
+
+        /* Does problem 3) apply to this call?
+         */
+        const bool needsPrefix = (firstdtor >= 0 && lastthrow >= 0
+            && (lastthrow - firstdtor) * step > 0);
+
+        /* If so, initialize 'eprefix' by declaring the gate
+         */
+        VarDeclaration *gate = NULL;
+        if (needsPrefix)
+        {
+            // eprefix => bool __gate [= false]
+            Identifier *idtmp = Identifier::generateId("__gate");
+            gate = new VarDeclaration(loc, Type::tbool, idtmp, NULL);
+            gate->storage_class |= STCtemp | STCctfe | STCvolatile;
+            dsymbolSemantic(gate, sc);
+
+            Expression *ae = new DeclarationExp(loc, gate);
+            eprefix = expressionSemantic(ae, sc);
+        }
+
+        for (ptrdiff_t i = start; i != end; i += step)
+        {
+            Expression *arg = (*arguments)[i];
+
+            Parameter *parameter = (i >= (ptrdiff_t)nparams ? NULL : tf->parameterList[i]);
+            const bool isRef = (parameter && (parameter->storageClass & (STCref | STCout)));
+            const bool isLazy = (parameter && (parameter->storageClass & STClazy));
+
+            /* Skip lazy parameters
+             */
+            if (isLazy)
+                continue;
+
+            /* Do we have a gate? Then we have a prefix and we're not yet past the last throwing arg.
+             * Declare a temporary variable for this arg and append that declaration to 'eprefix',
+             * which will implicitly take care of potential problem 2) for this arg.
+             * 'eprefix' will therefore finally contain all args up to and including the last
+             * potentially throwing arg, excluding all lazy parameters.
+             */
+            if (gate)
             {
-                arg = new ErrorExp();
+                const bool needsDtor = (!isRef && arg->type->needsDestruction() && i != lastthrow);
+
+                /* Declare temporary 'auto __pfx = arg' (needsDtor) or 'auto __pfy = arg' (!needsDtor)
+                 */
+                VarDeclaration *tmp = copyToTemp(0,
+                    needsDtor ? "__pfx" : "__pfy",
+                    !isRef ? arg : arg->addressOf());
+                dsymbolSemantic(tmp, sc);
+
+                /* Modify the destructor so it only runs if gate==false, i.e.,
+                 * only if there was a throw while constructing the args
+                 */
+                if (!needsDtor)
+                {
+                    if (tmp->edtor)
+                    {
+                        assert(i == lastthrow);
+                        tmp->edtor = NULL;
+                    }
+                }
+                else
+                {
+                    // edtor => (__gate || edtor)
+                    assert(tmp->edtor);
+                    Expression *e = tmp->edtor;
+                    e = new LogicalExp(e->loc, TOKoror, new VarExp(e->loc, gate), e);
+                    tmp->edtor = expressionSemantic(e, sc);
+                    //printf("edtor: %s\n", tmp->edtor->toChars());
+                }
+
+                // eprefix => (eprefix, auto __pfx/y = arg)
+                DeclarationExp *ae = new DeclarationExp(loc, tmp);
+                eprefix = Expression::combine(eprefix, expressionSemantic(ae, sc));
+
+                // arg => __pfx/y
+                arg = new VarExp(loc, tmp);
+                arg = expressionSemantic(arg, sc);
+                if (isRef)
+                {
+                    arg = new PtrExp(loc, arg);
+                    arg = expressionSemantic(arg, sc);
+                }
+
+                /* Last throwing arg? Then finalize eprefix => (eprefix, gate = true),
+                 * i.e., disable the dtors right after constructing the last throwing arg.
+                 * From now on, the callee will take care of destructing the args because
+                 * the args are implicitly moved into function parameters.
+                 *
+                 * Set gate to null to let the next iterations know they don't need to
+                 * append to eprefix anymore.
+                 */
+                if (i == lastthrow)
+                {
+                    Expression *e = new AssignExp(gate->loc, new VarExp(gate->loc, gate), new IntegerExp(gate->loc, 1, Type::tbool));
+                    eprefix = Expression::combine(eprefix, expressionSemantic(e, sc));
+                    gate = NULL;
+                }
+            }
+            else
+            {
+                /* No gate, no prefix to append to.
+                 * Handle problem 2) by calling the copy constructor for value structs
+                 * (or static arrays of them) if appropriate.
+                 */
+                Type *tv = arg->type->baseElemOf();
+                if (!isRef && tv->ty == Tstruct)
+                    arg = doCopyOrMove(sc, arg);
+            }
+
+            (*arguments)[i] = arg;
+        }
+    }
+    //if (eprefix) printf("eprefix: %s\n", eprefix->toChars());
+
+    // If D linkage and variadic, add _arguments[] as first argument
+    if (tf->isDstyleVariadic())
+    {
+        assert(arguments->length >= nparams);
+
+        Parameters *args = new Parameters;
+        args->setDim(arguments->length - nparams);
+        for (size_t i = 0; i < arguments->length - nparams; i++)
+        {
+            Parameter *arg = new Parameter(STCin, (*arguments)[nparams + i]->type, NULL, NULL, NULL);
+            (*args)[i] = arg;
+        }
+
+        TypeTuple *tup = new TypeTuple(args);
+        Expression *e = new TypeidExp(loc, tup);
+        e = expressionSemantic(e, sc);
+        arguments->insert(0, e);
+    }
+
+    Type *tret = tf->next;
+    if (isCtorCall)
+    {
+        //printf("[%s] fd = %s %s, %d %d %d\n", loc.toChars(), fd->toChars(), fd->type->toChars(),
+        //    wildmatch, tf->isWild(), fd->isolateReturn());
+        if (!tthis)
+        {
+            assert(sc->intypeof || global.errors);
+            tthis = fd->isThis()->type->addMod(fd->type->mod);
+        }
+        if (tf->isWild() && !fd->isolateReturn())
+        {
+            if (wildmatch)
+                tret = tret->substWildTo(wildmatch);
+            int offset;
+            if (!tret->implicitConvTo(tthis) &&
+                !(MODimplicitConv(tret->mod, tthis->mod) && tret->isBaseOf(tthis, &offset) && offset == 0))
+            {
+                const char* s1 = tret ->isNaked() ? " mutable" : tret ->modToChars();
+                const char* s2 = tthis->isNaked() ? " mutable" : tthis->modToChars();
+                ::error(loc, "inout constructor %s creates%s object, not%s",
+                        fd->toPrettyChars(), s1, s2);
                 err = true;
             }
-            (*exps)[i] = arg;
         }
+        tret = tthis;
     }
-    return err;
+    else if (wildmatch && tret)
+    {
+        /* Adjust function return type based on wildmatch
+         */
+        //printf("wildmatch = x%x, tret = %s\n", wildmatch, tret->toChars());
+        tret = tret->substWildTo(wildmatch);
+    }
+    *prettype = tret;
+    *peprefix = eprefix;
+    return (err || olderrors != global.errors);
 }
 
 /**
@@ -134,6 +2049,8 @@ Package *resolveIsPackage(Dsymbol *sym)
         }
         pkg = imp->pkg;
     }
+    else if (Module *mod = sym->isModule())
+        pkg = mod->isPackageFile ? mod->pkg : sym->isPackage();
     else
         pkg = sym->isPackage();
     if (pkg)
@@ -141,6 +2058,25 @@ Package *resolveIsPackage(Dsymbol *sym)
     return pkg;
 }
 
+static Module *loadStdMath()
+{
+  static Import *impStdMath = NULL;
+  if (!impStdMath)
+    {
+      Identifiers *a = new Identifiers();
+      a->push(Id::std);
+      Import *s = new Import(Loc(), a, Id::math, NULL, false);
+      s->load(NULL);
+      if (s->mod)
+      {
+          s->mod->importAll(NULL);
+          dsymbolSemantic(s->mod, NULL);
+      }
+      impStdMath = s;
+    }
+  return impStdMath->mod;
+}
+
 class ExpressionSemanticVisitor : public Visitor
 {
 public:
@@ -1938,7 +3874,7 @@ public:
 
     void visit(HaltExp *e)
     {
-        e->type = Type::tvoid;
+        e->type = Type::tnoreturn;
         result = e;
     }
 
@@ -1959,7 +3895,9 @@ public:
         Type *tded = NULL;
         if (e->tok2 == TOKpackage || e->tok2 == TOKmodule) // These is() expressions are special because they can work on modules, not just types.
         {
+            const unsigned oldErrors = global.startGagging();
             Dsymbol *sym = e->targ->toDsymbol(sc);
+            global.endGagging(oldErrors);
             if (sym == NULL)
                 goto Lno;
             Package *p = resolveIsPackage(sym);
@@ -2292,7 +4230,7 @@ public:
         if (exp->e1->op == TOKarraylength)
         {
             // arr.length op= e2;
-            e = ArrayLengthExp::rewriteOpAssign(exp);
+            e = rewriteOpAssign(exp);
             e = expressionSemantic(e, sc);
             result = e;
             return;
@@ -2382,27 +4320,39 @@ public:
         result = ((BinExp *)e)->reorderSettingAAElem(sc);
     }
 
-    void visit(CompileExp *exp)
+private:
+    Expression *compileIt(CompileExp *exp)
     {
-        StringExp *se = semanticString(sc, exp->e1, "argument to mixin");
-        if (!se)
-            return setError();
-        se = se->toUTF8(sc);
+        OutBuffer buf;
+        if (expressionsToString(buf, sc, exp->exps))
+            return NULL;
+
         unsigned errors = global.errors;
-        Parser p(exp->loc, sc->_module, (utf8_t *)se->string, se->len, 0);
+        const size_t len = buf.length();
+        const char *str = buf.extractChars();
+        Parser p(exp->loc, sc->_module, (const utf8_t *)str, len, false);
         p.nextToken();
         //printf("p.loc.linnum = %d\n", p.loc.linnum);
+
         Expression *e = p.parseExpression();
-        if (p.errors)
-        {
-            assert(global.errors != errors);        // should have caught all these cases
-            return setError();
-        }
+        if (global.errors != errors)
+            return NULL;
+
         if (p.token.value != TOKeof)
         {
-            exp->error("incomplete mixin expression (%s)", se->toChars());
-            return setError();
+            exp->error("incomplete mixin expression (%s)", str);
+            return NULL;
         }
+        return e;
+    }
+
+public:
+    void visit(CompileExp *exp)
+    {
+        //printf("CompileExp::semantic('%s')\n", exp->toChars());
+        Expression *e = compileIt(exp);
+        if (!e)
+            return setError();
         result = expressionSemantic(e, sc);
     }
 
@@ -2508,6 +4458,8 @@ public:
 
         if (exp->e1->isBool(false))
         {
+            /* This is an `assert(0)` which means halt program execution
+             */
             FuncDeclaration *fd = sc->parent->isFuncDeclaration();
             if (fd)
                 fd->hasReturnExp |= 4;
@@ -2525,8 +4477,10 @@ public:
                 result = e;
                 return;
             }
+            exp->type = Type::tnoreturn;
         }
-        exp->type = Type::tvoid;
+        else
+            exp->type = Type::tvoid;
         result = exp;
     }
 
@@ -3484,7 +5438,8 @@ public:
                 return setError();
             }
 
-            if (!tf->callMatch(NULL, exp->arguments))
+            const char *failMessage = NULL;
+            if (!tf->callMatch(NULL, exp->arguments, 0, &failMessage))
             {
                 OutBuffer buf;
 
@@ -3495,10 +5450,11 @@ public:
                     tthis->modToBuffer(&buf);
 
                 //printf("tf = %s, args = %s\n", tf->deco, (*exp->arguments)[0]->type->deco);
-                ::error(exp->loc, "%s %s %s is not callable using argument types %s",
+                ::error(exp->loc, "%s `%s%s` is not callable using argument types `%s`",
                         p, exp->e1->toChars(), parametersTypeToChars(tf->parameterList),
                         buf.peekChars());
-
+                if (failMessage)
+                    errorSupplemental(exp->loc, failMessage);
                 return setError();
             }
 
@@ -3553,13 +5509,14 @@ public:
             assert(exp->f);
             tiargs = NULL;
 
-            if (ve->hasOverloads)
+            if (exp->f->overnext)
                 exp->f = resolveFuncCall(exp->loc, sc, exp->f, tiargs, NULL, exp->arguments, 2);
             else
             {
                 exp->f = exp->f->toAliasFunc();
                 TypeFunction *tf = (TypeFunction *)exp->f->type;
-                if (!tf->callMatch(NULL, exp->arguments))
+                const char *failMessage = NULL;
+                if (!tf->callMatch(NULL, exp->arguments, 0, &failMessage))
                 {
                     OutBuffer buf;
 
@@ -3568,10 +5525,11 @@ public:
                     buf.writeByte(')');
 
                     //printf("tf = %s, args = %s\n", tf->deco, (*exp->arguments)[0]->type->deco);
-                    ::error(exp->loc, "%s %s is not callable using argument types %s",
-                            exp->e1->toChars(), parametersTypeToChars(tf->parameterList),
+                    ::error(exp->loc, "%s `%s%s` is not callable using argument types `%s`",
+                            exp->f->kind(), exp->e1->toChars(), parametersTypeToChars(tf->parameterList),
                             buf.peekChars());
-
+                    if (failMessage)
+                        errorSupplemental(exp->loc, failMessage);
                     exp->f = NULL;
                 }
             }
@@ -3954,6 +5912,10 @@ public:
                 exp->e1 = exp->e1->castTo(sc, exp->type->pointerTo());
                 break;
 
+            case Tnull:
+                exp->type = Type::tnoreturn;    // typeof(*null) is bottom type
+                break;
+
             default:
                 exp->error("can only * a pointer, not a `%s`", exp->e1->type->toChars());
                 /* fall through */
@@ -7109,25 +9071,6 @@ public:
         result = exp;
     }
 
-    Module *loadStdMath()
-    {
-        static Import *impStdMath = NULL;
-        if (!impStdMath)
-        {
-            Identifiers *a = new Identifiers();
-            a->push(Id::std);
-            Import *s = new Import(Loc(), a, Id::math, NULL, false);
-            s->load(NULL);
-            if (s->mod)
-            {
-                s->mod->importAll(NULL);
-                dsymbolSemantic(s->mod, NULL);
-            }
-            impStdMath = s;
-        }
-        return impStdMath->mod;
-    }
-
     void visit(PowExp *exp)
     {
         if (exp->type)
@@ -7579,7 +9522,7 @@ public:
             exp->error("%s is not an expression", exp->e2->toChars());
             return setError();
         }
-        if (e1x->op == TOKerror)
+        if (e1x->op == TOKerror || e1x->type->ty == Tnoreturn)
         {
             result = e1x;
             return;
@@ -8032,10 +9975,18 @@ public:
 
         Type *t1 = exp->e1->type;
         Type *t2 = exp->e2->type;
+        if (t1->ty == Tnoreturn)
+        {
+            exp->type = t2;
+        }
+        else if (t2->ty == Tnoreturn)
+        {
+            exp->type = t1;
+        }
         // If either operand is void the result is void, we have to cast both
         // the expression to void so that we explicitly discard the expression
         // value if any (bugzilla 16598)
-        if (t1->ty == Tvoid || t2->ty == Tvoid)
+        else if (t1->ty == Tvoid || t2->ty == Tvoid)
         {
             exp->type = Type::tvoid;
             exp->e1 = exp->e1->castTo(sc, exp->type);
diff --git a/gcc/d/dmd/func.c b/gcc/d/dmd/func.c
index 7a216a97941..b8e1e318376 100644
--- a/gcc/d/dmd/func.c
+++ b/gcc/d/dmd/func.c
@@ -1473,7 +1473,8 @@ FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s,
     memset(&m, 0, sizeof(m));
     m.last = MATCHnomatch;
 
-    functionResolve(&m, s, loc, sc, tiargs, tthis, fargs);
+    const char *failMessage = NULL;
+    functionResolve(&m, s, loc, sc, tiargs, tthis, fargs, &failMessage);
 
     if (m.last > MATCHnomatch && m.lastf)
     {
@@ -1555,20 +1556,23 @@ FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s,
                     ::error(loc, "none of the overloads of `%s` are callable using a %sobject, candidates are:",
                         fd->ident->toChars(), thisBuf.peekChars());
                 else
-                    ::error(loc, "%smethod %s is not callable using a %sobject",
+                    ::error(loc, "%smethod `%s` is not callable using a %sobject",
                         funcBuf.peekChars(), fd->toPrettyChars(), thisBuf.peekChars());
             }
             else
             {
                 //printf("tf = %s, args = %s\n", tf->deco, (*fargs)[0]->type->deco);
                 if (hasOverloads)
-                    ::error(loc, "none of the overloads of `%s` are callable using argument types %s, candidates are:",
+                    ::error(loc, "none of the overloads of `%s` are callable using argument types `%s`, candidates are:",
                             fd->ident->toChars(), fargsBuf.peekChars());
                 else
-                    fd->error(loc, "%s%s is not callable using argument types %s",
-                        parametersTypeToChars(tf->parameterList),
-                        tf->modToChars(),
-                        fargsBuf.peekChars());
+                {
+                    fd->error(loc, "%s `%s%s%s` is not callable using argument types `%s`",
+                        fd->kind(), fd->toPrettyChars(), parametersTypeToChars(tf->parameterList),
+                        tf->modToChars(), fargsBuf.peekChars());
+                    if (failMessage)
+                        errorSupplemental(loc, failMessage);
+                }
             }
 
             // Display candidate functions
diff --git a/gcc/d/dmd/hdrgen.c b/gcc/d/dmd/hdrgen.c
index a11c9c353d9..9eba88f1118 100644
--- a/gcc/d/dmd/hdrgen.c
+++ b/gcc/d/dmd/hdrgen.c
@@ -122,7 +122,7 @@ public:
     void visit(CompileStatement *s)
     {
         buf->writestring("mixin(");
-        s->exp->accept(this);
+        argsToBuffer(s->exps);
         buf->writestring(");");
         if (!hgs->forStmtInit)
             buf->writenl();
@@ -1104,6 +1104,18 @@ public:
         buf->writestring("typeof(null)");
     }
 
+    void visit(TypeMixin *t)
+    {
+        buf->writestring("mixin(");
+        argsToBuffer(t->exps);
+        buf->writeByte(')');
+    }
+
+    void visit(TypeNoreturn *)
+    {
+        buf->writestring("noreturn");
+    }
+
     ////////////////////////////////////////////////////////////////////////////
 
     void visit(Dsymbol *s)
@@ -1418,7 +1430,7 @@ public:
     void visit(CompileDeclaration *d)
     {
         buf->writestring("mixin(");
-        d->exp->accept(this);
+        argsToBuffer(d->exps);
         buf->writestring(");");
         buf->writenl();
     }
@@ -2408,8 +2420,15 @@ public:
                     buf->writeByte(')');
                     if (target.ptrsize == 8)
                         goto L4;
-                    else
+                    else if (target.ptrsize == 4 ||
+                             target.ptrsize == 2)
                         goto L3;
+                    else
+                        assert(0);
+
+                case Tvoid:
+                    buf->writestring("cast(void)0");
+                    break;
 
                 default:
                     /* This can happen if errors, such as
@@ -2822,7 +2841,7 @@ public:
     void visit(CompileExp *e)
     {
         buf->writestring("mixin(");
-        expToBuffer(e->e1, PREC_assign);
+        argsToBuffer(e->exps);
         buf->writeByte(')');
     }
 
@@ -3528,6 +3547,13 @@ void arrayObjectsToBuffer(OutBuffer *buf, Objects *objects)
     }
 }
 
+/*************************************************************
+ * Pretty print function parameters.
+ * Params:
+ *  parameters = parameters to print, such as TypeFunction.parameters.
+ *  varargs = kind of varargs, see TypeFunction.varargs.
+ * Returns: Null-terminated string representing parameters.
+ */
 const char *parametersTypeToChars(ParameterList pl)
 {
     OutBuffer buf;
@@ -3536,3 +3562,26 @@ const char *parametersTypeToChars(ParameterList pl)
     v.parametersToBuffer(pl.parameters, pl.varargs);
     return buf.extractChars();
 }
+
+/*************************************************************
+ * Pretty print function parameter.
+ * Params:
+ *  parameter = parameter to print.
+ *  tf = TypeFunction which holds parameter.
+ *  fullQual = whether to fully qualify types.
+ * Returns: Null-terminated string representing parameters.
+ */
+const char *parameterToChars(Parameter *parameter, TypeFunction *tf, bool fullQual)
+{
+    OutBuffer buf;
+    HdrGenState hgs;
+    hgs.fullQual = fullQual;
+    PrettyPrintVisitor v(&buf, &hgs);
+
+    parameter->accept(&v);
+    if (tf->parameterList.varargs == 2 && parameter == tf->parameterList[tf->parameterList.parameters->length - 1])
+    {
+        buf.writestring("...");
+    }
+    return buf.extractChars();
+}
diff --git a/gcc/d/dmd/hdrgen.h b/gcc/d/dmd/hdrgen.h
index d464d4aa618..6822aaf44a9 100644
--- a/gcc/d/dmd/hdrgen.h
+++ b/gcc/d/dmd/hdrgen.h
@@ -47,6 +47,7 @@ void arrayObjectsToBuffer(OutBuffer *buf, Objects *objects);
 void moduleToBuffer(OutBuffer *buf, Module *m);
 
 const char *parametersTypeToChars(ParameterList pl);
+const char *parameterToChars(Parameter *parameter, TypeFunction *tf, bool fullQual);
 
 bool stcToBuffer(OutBuffer *buf, StorageClass stc);
 const char *stcToChars(StorageClass& stc);
diff --git a/gcc/d/dmd/idgen.c b/gcc/d/dmd/idgen.c
index 59faa993b9b..0740653709a 100644
--- a/gcc/d/dmd/idgen.c
+++ b/gcc/d/dmd/idgen.c
@@ -86,10 +86,16 @@ Msgtable msgtable[] =
     { "__c_longlong", NULL },
     { "__c_ulonglong", NULL },
     { "__c_long_double", NULL },
+    { "__c_wchar_t", NULL },
+    { "__c_complex_float", NULL },
+    { "__c_complex_double", NULL },
+    { "__c_complex_real", NULL },
     { "cpp_type_info_ptr", "__cpp_type_info_ptr" },
     { "_assert", "assert" },
     { "_unittest", "unittest" },
     { "_body", "body" },
+    { "printf", NULL },
+    { "scanf", NULL },
 
     { "TypeInfo", NULL },
     { "TypeInfo_Class", NULL },
@@ -395,7 +401,6 @@ Msgtable msgtable[] =
     { "derivedMembers", NULL },
     { "isSame", NULL },
     { "compiles", NULL },
-    { "parameters", NULL },
     { "getAliasThis", NULL },
     { "getAttributes", NULL },
     { "getFunctionAttributes", NULL },
@@ -411,6 +416,7 @@ Msgtable msgtable[] =
     { "getLocation", NULL },
     { "hasPostblit", NULL },
     { "isCopyable", NULL },
+    { "toType", NULL },
 
     // For C++ mangling
     { "allocator", NULL },
diff --git a/gcc/d/dmd/import.h b/gcc/d/dmd/import.h
index e49ad15c2d3..07fb32aa070 100644
--- a/gcc/d/dmd/import.h
+++ b/gcc/d/dmd/import.h
@@ -47,6 +47,7 @@ public:
     Dsymbol *syntaxCopy(Dsymbol *s);    // copy only syntax trees
     void load(Scope *sc);
     void importAll(Scope *sc);
+    void addPackageAccess(ScopeDsymbol *scopesym);
     Dsymbol *toAlias();
     void addMember(Scope *sc, ScopeDsymbol *sds);
     void setScope(Scope* sc);
diff --git a/gcc/d/dmd/module.h b/gcc/d/dmd/module.h
index 03078b5e833..1664492bc2d 100644
--- a/gcc/d/dmd/module.h
+++ b/gcc/d/dmd/module.h
@@ -75,6 +75,7 @@ public:
     unsigned numlines;  // number of lines in source file
     int isDocFile;      // if it is a documentation input file, not D source
     bool isPackageFile; // if it is a package.d
+    Package *pkg;       // if isPackageFile is true, the Package that contains this package.d
     Strings contentImportedFiles;  // array of files whose content was imported
     int needmoduleinfo;
 
diff --git a/gcc/d/dmd/mtype.c b/gcc/d/dmd/mtype.c
index c1071b2f278..6b01999bc7c 100644
--- a/gcc/d/dmd/mtype.c
+++ b/gcc/d/dmd/mtype.c
@@ -39,6 +39,7 @@ Expression *extractSideEffect(Scope *sc, const char *name, Expression **e0, Expr
 Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads);
 Expression *typeToExpression(Type *t);
 Expression *typeToExpressionHelper(TypeQualified *t, Expression *e, size_t i = 0);
+RootObject *compileTypeMixin(TypeMixin *tm, Loc loc, Scope *sc);
 
 /***************************** Type *****************************/
 
@@ -93,6 +94,7 @@ Type *Type::tdchar;
 Type *Type::tshiftcnt;
 Type *Type::terror;
 Type *Type::tnull;
+Type *Type::tnoreturn;
 
 Type *Type::tsize_t;
 Type *Type::tptrdiff_t;
@@ -195,6 +197,8 @@ void Type::_init()
     sizeTy[Tnull] = sizeof(TypeNull);
     sizeTy[Tvector] = sizeof(TypeVector);
     sizeTy[Ttraits] = sizeof(TypeTraits);
+    sizeTy[Tmixin] = sizeof(TypeMixin);
+    sizeTy[Tnoreturn] = sizeof(TypeNoreturn);
 
     initTypeMangle();
 
@@ -216,6 +220,10 @@ void Type::_init()
     }
     basic[Terror] = new TypeError();
 
+    tnoreturn = new TypeNoreturn();
+    tnoreturn->deco = tnoreturn->merge()->deco;
+    basic[Tnoreturn] = tnoreturn;
+
     tvoid = basic[Tvoid];
     tint8 = basic[Tint8];
     tuns8 = basic[Tuns8];
@@ -246,7 +254,7 @@ void Type::_init()
 
     tshiftcnt = tint32;
     terror = basic[Terror];
-    tnull = basic[Tnull];
+    tnoreturn = basic[Tnoreturn];
     tnull = new TypeNull();
     tnull->deco = tnull->merge()->deco;
 
@@ -2079,7 +2087,7 @@ Expression *Type::getProperty(Loc loc, Identifier *ident, int flag)
         if (this != Type::terror)
         {
             if (s)
-                error(loc, "no property `%s` for type `%s`, did you mean `%s`?", ident->toChars(), toChars(), s->toChars());
+                error(loc, "no property `%s` for type `%s`, did you mean `%s`?", ident->toChars(), toChars(), s->toPrettyChars());
             else
                 error(loc, "no property `%s` for type `%s`", ident->toChars(), toChars());
         }
@@ -2413,6 +2421,16 @@ TypeTraits *Type::isTypeTraits()
     return ty == Ttraits ? (TypeTraits *)this : NULL;
 }
 
+TypeMixin *Type::isTypeMixin()
+{
+    return ty == Tmixin ? (TypeMixin *)this : NULL;
+}
+
+TypeNoreturn *Type::isTypeNoreturn()
+{
+    return ty == Tnoreturn ? (TypeNoreturn *)this : NULL;
+}
+
 TypeFunction *Type::toTypeFunction()
 {
     if (ty != Tfunction)
@@ -5175,16 +5193,47 @@ void TypeFunction::purityLevel()
     tf->purity = purity;
 }
 
+// arguments get specially formatted
+static const char *getParamError(TypeFunction *tf, Expression *arg, Parameter *par)
+{
+    if (global.gag && !global.params.showGaggedErrors)
+        return NULL;
+    // show qualification when toChars() is the same but types are different
+    const char *at = arg->type->toChars();
+    bool qual = !arg->type->equals(par->type) && strcmp(at, par->type->toChars()) == 0;
+    if (qual)
+        at = arg->type->toPrettyChars(true);
+    OutBuffer buf;
+    // only mention rvalue if it's relevant
+    const bool rv = !arg->isLvalue() && (par->storageClass & (STCref | STCout)) != 0;
+    buf.printf("cannot pass %sargument `%s` of type `%s` to parameter `%s`",
+        rv ? "rvalue " : "", arg->toChars(), at,
+        parameterToChars(par, tf, qual));
+    return buf.extractChars();
+}
+
+static const char *getMatchError(const char *format, ...)
+{
+    if (global.gag && !global.params.showGaggedErrors)
+        return NULL;
+    OutBuffer buf;
+    va_list ap;
+    va_start(ap, format);
+    buf.vprintf(format, ap);
+    return buf.extractChars();
+}
+
 /********************************
  * 'args' are being matched to function 'this'
  * Determine match level.
  * Input:
  *      flag    1       performing a partial ordering match
+ *      pMessage        address to store error message, or null
  * Returns:
  *      MATCHxxxx
  */
 
-MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag)
+MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag, const char **pMessage)
 {
     //printf("TypeFunction::callMatch() %s\n", toChars());
     MATCH match = MATCHexact;           // assume exact match
@@ -5221,12 +5270,15 @@ MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag)
 
     size_t nparams = parameterList.length();
     size_t nargs = args ? args->length : 0;
-    if (nparams == nargs)
-        ;
-    else if (nargs > nparams)
+    if (nargs > nparams)
     {
         if (parameterList.varargs == VARARGnone)
-            goto Nomatch;               // too many args; no match
+        {
+            // suppress early exit if an error message is wanted,
+            // so we can check any matching args are valid
+            if (!pMessage)
+                goto Nomatch;           // too many args; no match
+        }
         match = MATCHconvert;           // match ... with a "conversion" match level
     }
 
@@ -5309,7 +5361,10 @@ MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag)
                 if (m && !arg->isLvalue())
                 {
                     if (p->storageClass & STCout)
+                    {
+                        if (pMessage) *pMessage = getParamError(this, arg, p);
                         goto Nomatch;
+                    }
 
                     if (arg->op == TOKstring && tp->ty == Tsarray)
                     {
@@ -5331,7 +5386,10 @@ MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag)
                         }
                     }
                     else
+                    {
+                        if (pMessage) *pMessage = getParamError(this, arg, p);
                         goto Nomatch;
+                    }
                 }
 
                 /* Find most derived alias this type being matched.
@@ -5351,7 +5409,10 @@ MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag)
                  *  ref T[dim] <- an lvalue of const(T[dim]) argument
                  */
                 if (!ta->constConv(tp))
+                {
+                    if (pMessage) *pMessage = getParamError(this, arg, p);
                     goto Nomatch;
+                }
             }
         }
 
@@ -5377,7 +5438,11 @@ MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag)
                     tsa = (TypeSArray *)tb;
                     sz = tsa->dim->toInteger();
                     if (sz != nargs - u)
+                    {
+                        if (pMessage)
+                            *pMessage = getMatchError("expected %llu variadic argument(s), not %zu", sz, nargs - u);
                         goto Nomatch;
+                    }
                     /* fall through */
                 case Tarray:
                     {
@@ -5408,7 +5473,10 @@ MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag)
                                 m = arg->implicitConvTo(ta->next);
 
                             if (m == MATCHnomatch)
+                            {
+                                if (pMessage) *pMessage = getParamError(this, arg, p);
                                 goto Nomatch;
+                            }
                             if (m < match)
                                 match = m;
                         }
@@ -5420,9 +5488,14 @@ MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag)
                     goto Ldone;
 
                 default:
-                    goto Nomatch;
+                    break;
                 }
             }
+            if (pMessage && u < nargs)
+                *pMessage = getParamError(this, (*args)[u], p);
+            else if (pMessage)
+                *pMessage = getMatchError("missing argument for parameter #%d: `%s`",
+                    u + 1, parameterToChars(p, this, false));
             goto Nomatch;
         }
         if (m < match)
@@ -5430,6 +5503,12 @@ MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag)
     }
 
 Ldone:
+    if (pMessage && !parameterList.varargs && nargs > nparams)
+    {
+        // all parameters had a match, but there are surplus args
+        *pMessage = getMatchError("expected %d argument(s), not %d", nparams, nargs);
+        goto Nomatch;
+    }
     //printf("match = %d\n", match);
     return match;
 
@@ -5797,6 +5876,20 @@ Type *TypeTraits::syntaxCopy()
     return tt;
 }
 
+Dsymbol *TypeTraits::toDsymbol(Scope *sc)
+{
+    Type *t = NULL;
+    Expression *e = NULL;
+    Dsymbol *s = NULL;
+    resolve(loc, sc, &e, &t, &s);
+    if (t && t->ty != Terror)
+        s = t->toDsymbol(sc);
+    else if (e)
+        s = getDsymbol(e);
+
+    return s;
+}
+
 void TypeTraits::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool)
 {
     *pt = NULL;
@@ -5816,6 +5909,90 @@ d_uns64 TypeTraits::size(Loc)
     return SIZE_INVALID;
 }
 
+/***************************** TypeMixin *****************************/
+
+/******
+ * Implements mixin types.
+ *
+ * Semantic analysis will convert it to a real type.
+ */
+TypeMixin::TypeMixin(const Loc &loc, Expressions *exps)
+    : Type(Tmixin)
+{
+    this->loc = loc;
+    this->exps = exps;
+    this->obj = NULL; // cached result of semantic analysis.
+}
+
+const char *TypeMixin::kind()
+{
+    return "mixin";
+}
+
+Type *TypeMixin::syntaxCopy()
+{
+    return new TypeMixin(loc, Expression::arraySyntaxCopy(exps));
+}
+
+Dsymbol *TypeMixin::toDsymbol(Scope *sc)
+{
+    Type *t = NULL;
+    Expression *e = NULL;
+    Dsymbol *s = NULL;
+    resolve(loc, sc, &e, &t, &s);
+    if (t)
+        s = t->toDsymbol(sc);
+    else if (e)
+        s = getDsymbol(e);
+
+    return s;
+}
+
+void TypeMixin::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid)
+{
+    // if already resolved just set pe/pt/ps and return.
+    if (obj)
+    {
+        *pe = isExpression(obj);
+        *pt = isType(obj);
+        *ps = isDsymbol(obj);
+        return;
+    }
+
+    RootObject *o = compileTypeMixin(this, loc, sc);
+    if (Type *t = isType(o))
+    {
+        t->resolve(loc, sc, pe, pt, ps, intypeid);
+        if (*pt)
+            (*pt) = (*pt)->addMod(mod);
+    }
+    else if (Expression *e = isExpression(o))
+    {
+        e = expressionSemantic(e, sc);
+        if (TypeExp *et = e->isTypeExp())
+        {
+            *pe = NULL;
+            *pt = et->type->addMod(mod);
+            *ps = NULL;
+        }
+        else
+        {
+            *pe = e;
+            *pt = NULL;
+            *ps = NULL;
+        }
+    }
+    else
+    {
+        *pe = NULL;
+        *pt = Type::terror;
+        *ps = NULL;
+    }
+
+    // save the result
+    obj = *pe ? (RootObject *)*pe : (*pt ? (RootObject *)*pt : (RootObject *)*ps);
+}
+
 /***************************** TypeQualified *****************************/
 
 TypeQualified::TypeQualified(TY ty, Loc loc)
@@ -6003,11 +6180,25 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
 
             Type *t = s->getType();     // type symbol, type alias, or type tuple?
             unsigned errorsave = global.errors;
-            Dsymbol *sm = s->searchX(loc, sc, id);
-            if (sm && !(sc->flags & SCOPEignoresymbolvisibility) && !symbolIsVisible(sc, sm))
+            int flags = t == NULL ? SearchLocalsOnly : IgnorePrivateImports;
+            Dsymbol *sm = s->searchX(loc, sc, id, flags);
+            if (sm)
             {
-                ::error(loc, "`%s` is not visible from module `%s`", sm->toPrettyChars(), sc->_module->toChars());
-                sm = NULL;
+                if (!(sc->flags & SCOPEignoresymbolvisibility) && !symbolIsVisible(sc, sm))
+                {
+                    ::error(loc, "`%s` is not visible from module `%s`", sm->toPrettyChars(), sc->_module->toChars());
+                    sm = NULL;
+                }
+                // Same check as in Expression::semanticY(DotIdExp)
+                else if (sm->isPackage() && checkAccess(sc, (Package *)sm))
+                {
+                    // @@@DEPRECATED_2.096@@@
+                    // Should be an error in 2.106. Just remove the deprecation call
+                    // and uncomment the null assignment
+                    ::deprecation(loc, "%s %s is not accessible here, perhaps add 'static import %s;'",
+                         sm->kind(), sm->toPrettyChars(), sm->toPrettyChars());
+                    //sm = null;
+                }
             }
             if (global.errors != errorsave)
             {
@@ -6052,7 +6243,7 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
                     sm = t->toDsymbol(sc);
                     if (sm && id->dyncast() == DYNCAST_IDENTIFIER)
                     {
-                        sm = sm->search(loc, (Identifier *)id);
+                        sm = sm->search(loc, (Identifier *)id, IgnorePrivateImports);
                         if (sm)
                             goto L2;
                     }
@@ -8177,6 +8368,49 @@ Expression *TypeNull::defaultInit(Loc)
     return new NullExp(Loc(), Type::tnull);
 }
 
+/***************************** TypeNoreturn *****************************/
+
+TypeNoreturn::TypeNoreturn()
+    : Type(Tnoreturn)
+{
+    //printf("TypeNoreturn %p\n", this);
+}
+
+const char *TypeNoreturn::kind()
+{
+    return "noreturn";
+}
+
+Type *TypeNoreturn::syntaxCopy()
+{
+    // No semantic analysis done, no need to copy
+    return this;
+}
+
+MATCH TypeNoreturn::implicitConvTo(Type *to)
+{
+    //printf("TypeNoreturn::implicitConvTo(this=%p, to=%p)\n", this, to);
+    //printf("from: %s\n", toChars());
+    //printf("to  : %s\n", to.toChars());
+    MATCH m = Type::implicitConvTo(to);
+    return (m == MATCHexact) ? MATCHexact : MATCHconvert;
+}
+
+bool TypeNoreturn::isBoolean()
+{
+    return true;  // bottom type can be implicitly converted to any other type
+}
+
+d_uns64 TypeNoreturn::size(Loc)
+{
+    return 0;
+}
+
+unsigned TypeNoreturn::alignsize()
+{
+    return 0;
+}
+
 /***********************************************************
  * Encapsulate Parameters* so .length and [i] can be used on it.
  * https://dlang.org/spec/function.html#ParameterList
@@ -8472,3 +8706,25 @@ bool Parameter::isCovariantScope(bool returnByRef, StorageClass from, StorageCla
 
     return covariant[SR::buildSR(returnByRef, from)][SR::buildSR(returnByRef, to)];
 }
+
+/**
+ * For printing two types with qualification when necessary.
+ * Params:
+ *    t1 = The first type to receive the type name for
+ *    t2 = The second type to receive the type name for
+ * Returns:
+ *    The fully-qualified names of both types if the two type names are not the same,
+ *    or the unqualified names of both types if the two type names are the same.
+ */
+void toAutoQualChars(const char **result, Type *t1, Type *t2)
+{
+    const char *s1 = t1->toChars();
+    const char *s2 = t2->toChars();
+    if (strcmp(s1, s2) == 0)
+    {
+        s1 = t1->toPrettyChars(true);
+        s2 = t2->toPrettyChars(true);
+    }
+    result[0] = s1;
+    result[1] = s2;
+}
diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h
index 083d707f8f3..3687053488d 100644
--- a/gcc/d/dmd/mtype.h
+++ b/gcc/d/dmd/mtype.h
@@ -96,6 +96,8 @@ enum ENUMTY
     Tint128,
     Tuns128,
     Ttraits,
+    Tmixin,
+    Tnoreturn,
     TMAX
 };
 typedef unsigned char TY;       // ENUMTY
@@ -201,6 +203,7 @@ public:
     static Type *tdstring;              // immutable(dchar)[]
     static Type *terror;                // for error recovery
     static Type *tnull;                 // for null type
+    static Type *tnoreturn;             // for bottom type typeof(*null)
 
     static Type *tsize_t;               // matches size_t alias
     static Type *tptrdiff_t;            // matches ptrdiff_t alias
@@ -367,7 +370,9 @@ public:
     TypeTuple *isTypeTuple();
     TypeSlice *isTypeSlice();
     TypeNull *isTypeNull();
+    TypeMixin *isTypeMixin();
     TypeTraits *isTypeTraits();
+    TypeNoreturn *isTypeNoreturn();
 
     void accept(Visitor *v) { v->visit(this); }
 };
@@ -686,7 +691,7 @@ public:
     int attributesApply(void *param, int (*fp)(void *, const char *), TRUSTformat trustFormat = TRUSTformatDefault);
 
     Type *substWildTo(unsigned mod);
-    MATCH callMatch(Type *tthis, Expressions *toargs, int flag = 0);
+    MATCH callMatch(Type *tthis, Expressions *toargs, int flag = 0, const char **pMessage = NULL);
     bool checkRetType(Loc loc);
 
     Expression *defaultInit(Loc loc) /*const*/;
@@ -726,11 +731,27 @@ public:
 
     TypeTraits(const Loc &loc, TraitsExp *exp);
     Type *syntaxCopy();
+    Dsymbol *toDsymbol(Scope *sc);
     void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false);
     d_uns64 size(Loc loc);
     void accept(Visitor *v) { v->visit(this); }
 };
 
+class TypeMixin : public Type
+{
+public:
+    Loc loc;
+    Expressions *exps;
+    RootObject *obj;
+
+    TypeMixin(const Loc &loc, Expressions *exps);
+    const char *kind();
+    Type *syntaxCopy();
+    Dsymbol *toDsymbol(Scope *sc);
+    void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false);
+    void accept(Visitor *v) { v->visit(this); }
+};
+
 class TypeQualified : public Type
 {
 public:
@@ -966,6 +987,21 @@ public:
     void accept(Visitor *v) { v->visit(this); }
 };
 
+class TypeNoreturn : public Type
+{
+public:
+    TypeNoreturn();
+    const char *kind();
+
+    Type *syntaxCopy();
+    MATCH implicitConvTo(Type *to);
+    bool isBoolean() /*const*/;
+
+    d_uns64 size(Loc loc) /*const*/;
+    unsigned alignsize();
+    void accept(Visitor *v) { v->visit(this); }
+};
+
 /**************************************************************/
 
 bool arrayTypeCompatible(Loc loc, Type *t1, Type *t2);
diff --git a/gcc/d/dmd/parse.c b/gcc/d/dmd/parse.c
index c050b050404..e1f13214d58 100644
--- a/gcc/d/dmd/parse.c
+++ b/gcc/d/dmd/parse.c
@@ -328,11 +328,9 @@ Dsymbols *Parser::parseDeclDefs(int once, Dsymbol **pLastDecl, PrefixAttributes
                     {
                         // mixin(string)
                         nextToken();
-                        check(TOKlparen, "mixin");
-                        Expression *e = parseAssignExp();
-                        check(TOKrparen);
+                        Expressions *exps = parseArguments();
                         check(TOKsemicolon);
-                        s = new CompileDeclaration(loc, e);
+                        s = new CompileDeclaration(loc, exps);
                         break;
                     }
                     case TOKtemplate:
@@ -1336,7 +1334,7 @@ LINK Parser::parseLinkage(Identifiers **pidents, CPPMANGLE *pcppmangle, bool *pc
                             }
                             else if (!Identifier::isValidIdentifier(name))
                             {
-                                error("expected valid identifer for C++ namespace but got `%s`", name);
+                                error("expected valid identifier for C++ namespace but got `%s`", name);
                                 idents = NULL;
                                 break;
                             }
@@ -2922,6 +2920,18 @@ Objects *Parser::parseTemplateArguments()
     return tiargs;
 }
 
+/***************************************
+ * Parse a Type or an Expression
+ * Returns:
+ *  RootObject representing the AST
+ */
+RootObject *Parser::parseTypeOrAssignExp(TOK endtoken)
+{
+    return isDeclaration(&token, 0, endtoken, NULL)
+        ? (RootObject *)parseType()           // argument is a type
+        : (RootObject *)parseAssignExp();     // argument is an expression
+}
+
 /******************************************
  * Parse template argument list.
  * Input:
@@ -2942,20 +2952,10 @@ Objects *Parser::parseTemplateArgumentList()
     // Get TemplateArgumentList
     while (token.value != endtok)
     {
-            // See if it is an Expression or a Type
-            if (isDeclaration(&token, 0, TOKreserved, NULL))
-            {   // Template argument is a type
-                Type *ta = parseType();
-                tiargs->push(ta);
-            }
-            else
-            {   // Template argument is an expression
-                Expression *ea = parseAssignExp();
-                tiargs->push(ea);
-            }
-            if (token.value != TOKcomma)
-                break;
-            nextToken();
+        tiargs->push(parseTypeOrAssignExp());
+        if (token.value != TOKcomma)
+            break;
+        nextToken();
     }
     check(endtok, "template argument list");
     return tiargs;
@@ -3288,6 +3288,15 @@ Type *Parser::parseBasicType(bool dontLookDotIdents)
             }
             break;
 
+        case TOKmixin:
+            // https://dlang.org/spec/expression.html#mixin_types
+            loc = token.loc;
+            nextToken();
+            if (token.value != TOKlparen)
+                error("found `%s` when expecting `%s` following %s", token.toChars(), Token::toChars(TOKlparen), "`mixin`");
+            t = new TypeMixin(loc, parseArguments());
+            break;
+
         case TOKdot:
             // Leading . as in .foo
             t = parseBasicTypeStartingAt(new TypeIdentifier(token.loc, Id::empty), dontLookDotIdents);
@@ -3602,7 +3611,7 @@ Type *Parser::parseDeclarator(Type *t, int *palt, Identifier **pident,
             if (pident)
                 *pident = token.ident;
             else
-                error("unexpected identifer `%s` in declarator", token.ident->toChars());
+                error("unexpected identifier `%s` in declarator", token.ident->toChars());
             ts = t;
             nextToken();
             break;
@@ -3863,6 +3872,21 @@ void Parser::parseStorageClasses(StorageClass &storage_class, LINK &link,
     }
 }
 
+static void parseAttributes(Parser *p, bool &hasParsedAttributes,
+    StorageClass &storage_class, LINK &link, bool &setAlignment,
+    Expression *&ealign, Expressions *&udas)
+{
+    if (hasParsedAttributes) // only parse once
+        return;
+    hasParsedAttributes = true;
+    udas = NULL;
+    storage_class = STCundefined;
+    link = p->linkage;
+    setAlignment = false;
+    ealign = NULL;
+    p->parseStorageClasses(storage_class, link, setAlignment, ealign, udas);
+}
+
 /**********************************
  * Parse Declarations.
  * These can be:
@@ -3936,26 +3960,48 @@ Dsymbols *Parser::parseDeclarations(bool autodecl, PrefixAttributes *pAttrs, con
                 bool hasParsedAttributes = false;
                 if (token.value == TOKat)
                 {
-                    if (!hasParsedAttributes)
-                    {
-                        hasParsedAttributes = true;
-                        storage_class = STCundefined;
-                        link = linkage;
-                        setAlignment = false;
-                        ealign = NULL;
-                        udas = NULL;
-                        parseStorageClasses(storage_class, link, setAlignment, ealign, udas);
-                    }
+                    parseAttributes(this, hasParsedAttributes,
+                        storage_class, link, setAlignment, ealign, udas);
                 }
 
                 Declaration *v;
-                if (token.value == TOKfunction ||
+                Dsymbol *s;
+
+                // try to parse function type:
+                // TypeCtors? BasicType ( Parameters ) MemberFunctionAttributes
+                bool attributesAppended = false;
+                const StorageClass funcStc = parseTypeCtor();
+                Token *tlu = &token;
+                if (token.value != TOKfunction &&
+                    token.value != TOKdelegate &&
+                    isBasicType(&tlu) && tlu &&
+                    tlu->value == TOKlparen)
+                {
+                    VarArg vargs;
+                    Type *tret = parseBasicType();
+                    Parameters *prms = parseParameters(&vargs);
+                    ParameterList pl = ParameterList(prms, vargs);
+
+                    parseAttributes(this, hasParsedAttributes,
+                        storage_class, link, setAlignment, ealign, udas);
+                    if (udas)
+                        error("user-defined attributes not allowed for `alias` declarations");
+
+                    attributesAppended = true;
+                    storage_class = appendStorageClass(storage_class, funcStc);
+                    Type *tf = new TypeFunction(pl, tret, link, storage_class);
+                    v = new AliasDeclaration(loc, ident, tf);
+                }
+                else if (token.value == TOKfunction ||
                     token.value == TOKdelegate ||
                     (token.value == TOKlparen &&
                      skipAttributes(peekPastParen(&token), &tk) &&
                      (tk->value == TOKgoesto || tk->value == TOKlcurly)) ||
                     token.value == TOKlcurly ||
-                    (token.value == TOKidentifier && peekNext() == TOKgoesto))
+                    (token.value == TOKidentifier && peekNext() == TOKgoesto) ||
+                    (token.value == TOKref && peekNext() == TOKlparen &&
+                     skipAttributes(peekPastParen(peek(&token)), &tk) &&
+                     (tk->value == TOKgoesto || tk->value == TOKlcurly)))
                 {
                     // function (parameters) { statements... }
                     // delegate (parameters) { statements... }
@@ -3963,8 +4009,10 @@ Dsymbols *Parser::parseDeclarations(bool autodecl, PrefixAttributes *pAttrs, con
                     // (parameters) => expression
                     // { statements... }
                     // identifier => expression
+                    // ref (parameters) { statements... }
+                    // ref (parameters) => expression
 
-                    Dsymbol *s = parseFunctionLiteral();
+                    s = parseFunctionLiteral();
 
                     if (udas != NULL)
                     {
@@ -3985,26 +4033,19 @@ Dsymbols *Parser::parseDeclarations(bool autodecl, PrefixAttributes *pAttrs, con
                 else
                 {
                     // StorageClasses type
-                    if (!hasParsedAttributes)
-                    {
-                        hasParsedAttributes = true;
-                        storage_class = STCundefined;
-                        link = linkage;
-                        setAlignment = false;
-                        ealign = NULL;
-                        udas = NULL;
-                        parseStorageClasses(storage_class, link, setAlignment, ealign, udas);
-                    }
-
+                    parseAttributes(this, hasParsedAttributes,
+                        storage_class, link, setAlignment, ealign, udas);
                     if (udas)
                         error("user-defined attributes not allowed for %s declarations", Token::toChars(tok));
 
                     t = parseType();
                     v = new AliasDeclaration(loc, ident, t);
                 }
+                if (!attributesAppended)
+                    storage_class = appendStorageClass(storage_class, funcStc);
                 v->storage_class = storage_class;
 
-                Dsymbol *s = v;
+                s = v;
                 if (tpl)
                 {
                     Dsymbols *a2 = new Dsymbols();
@@ -4358,6 +4399,13 @@ Dsymbol *Parser::parseFunctionLiteral()
         case TOKdelegate:
             save = token.value;
             nextToken();
+            if (token.value == TOKref)
+            {
+                // function ref (parameters) { statements... }
+                // delegate ref (parameters) { statements... }
+                stc = STCref;
+                nextToken();
+            }
             if (token.value != TOKlparen && token.value != TOKlcurly)
             {
                 // function type (parameters) { statements... }
@@ -4377,14 +4425,22 @@ Dsymbol *Parser::parseFunctionLiteral()
                 // delegate { statements... }
                 break;
             }
-            /* fall through */
+            goto LTOKlparen;
+
+        case TOKref:
+            // ref (parameters) => expression
+            // ref (parameters) { statements... }
+            stc = STCref;
+            nextToken();
+            goto LTOKlparen;
 
         case TOKlparen:
+        LTOKlparen:
         {
             // (parameters) => expression
             // (parameters) { statements... }
             parameters = parseParameters(&varargs, &tpl);
-            stc = parsePostfix(STCundefined, NULL);
+            stc = parsePostfix(stc, NULL);
             if (StorageClass modStc = stc & STC_TYPECTOR)
             {
                 if (save == TOKfunction)
@@ -5093,7 +5149,7 @@ Statement *Parser::parseForeach(Loc loc, bool *isRange, bool isDecl)
         check(TOKrparen);
         Loc endloc;
         Statement *body = (!isDecl) ? parseStatement(0, NULL, &endloc) : NULL;
-        if (isRange) 
+        if (isRange)
             *isRange = false;
         return new ForeachStatement(loc, op, parameters, aggr, body, endloc);
     }
@@ -5378,15 +5434,19 @@ Statement *Parser::parseStatement(int flags, const utf8_t** endPtr, Loc *pEndloc
         }
 
         case TOKmixin:
-        {   Token *t = peek(&token);
+        {
+            if (isDeclaration(&token, 3, TOKreserved, NULL))
+                goto Ldeclaration;
+            Token *t = peek(&token);
             if (t->value == TOKlparen)
-            {   // mixin(string)
+            {
+                // mixin(string)
                 Expression *e = parseAssignExp();
                 check(TOKsemicolon);
                 if (e->op == TOKmixin)
                 {
                     CompileExp *cpe = (CompileExp *)e;
-                    s = new CompileStatement(loc, cpe->e1);
+                    s = new CompileStatement(loc, cpe->exps);
                 }
                 else
                 {
@@ -6332,6 +6392,7 @@ bool Parser::isBasicType(Token **pt)
 
         case TOKtypeof:
         case TOKvector:
+        case TOKmixin:
             /* typeof(exp).identifier...
              */
             t = peek(t);
@@ -6592,9 +6653,11 @@ bool Parser::isDeclarator(Token **pt, int *haveId, int *haveTpl, TOK endtok, boo
             case TOKin:
             case TOKout:
             case TOKdo:
+            LTOKdo:
                 // The !parens is to disallow unnecessary parentheses
                 if (!parens && (endtok == TOKreserved || endtok == t->value))
-                {   *pt = t;
+                {
+                    *pt = t;
                     return true;
                 }
                 return false;
@@ -6602,6 +6665,12 @@ bool Parser::isDeclarator(Token **pt, int *haveId, int *haveTpl, TOK endtok, boo
             case TOKif:
                 return haveTpl ? true : false;
 
+            // Used for mixin type parsing
+            case TOKeof:
+                if (endtok == TOKeof)
+                    goto LTOKdo;
+                return false;
+
             default:
             Ldefault:
                 return false;
@@ -7229,15 +7298,7 @@ Expression *Parser::parsePrimaryExp()
         {
             nextToken();
             check(TOKlparen, "typeid");
-            RootObject *o;
-            if (isDeclaration(&token, 0, TOKreserved, NULL))
-            {   // argument is a type
-                o = parseType();
-            }
-            else
-            {   // argument is an expression
-                o = parseAssignExp();
-            }
+            RootObject *o = parseTypeOrAssignExp();
             check(TOKrparen);
             e = new TypeidExp(loc, o);
             break;
@@ -7279,6 +7340,14 @@ Expression *Parser::parsePrimaryExp()
             if (token.value == TOKlparen)
             {
                 nextToken();
+                if (token.value == TOKidentifier && peekNext() == TOKlparen)
+                {
+                    error(loc, "unexpected `(` after `%s`, inside `is` expression. Try enclosing the contents of `is` with a `typeof` expression", token.toChars());
+                    nextToken();
+                    Token *tempTok = peekPastParen(&token);
+                    memcpy(&token, tempTok, sizeof(Token));
+                    goto Lerr;
+                }
                 targ = parseType(&ident);
                 if (token.value == TOKcolon || token.value == TOKequal)
                 {
@@ -7357,11 +7426,11 @@ Expression *Parser::parsePrimaryExp()
 
         case TOKmixin:
         {
+            // https://dlang.org/spec/expression.html#mixin_expressions
             nextToken();
-            check(TOKlparen, "mixin");
-            e = parseAssignExp();
-            check(TOKrparen);
-            e = new CompileExp(loc, e);
+            if (token.value != TOKlparen)
+                error("found `%s` when expecting `%s` following %s", token.toChars(), Token::toChars(TOKlparen), "`mixin`");
+            e = new CompileExp(loc, parseArguments());
             break;
         }
 
@@ -7379,6 +7448,24 @@ Expression *Parser::parsePrimaryExp()
             e = parseNewExp(NULL);
             break;
 
+        case TOKref:
+        {
+            if (peekNext() == TOKlparen)
+            {
+                Token *tk = peekPastParen(peek(&token));
+                if (skipAttributes(tk, &tk) &&
+                    (tk->value == TOKgoesto || tk->value == TOKlcurly))
+                {
+                    // ref (arguments) => expression
+                    // ref (arguments) { statements... }
+                    goto case_delegate;
+                }
+            }
+            nextToken();
+            error("found `%s` when expecting function literal following `ref`", token.toChars());
+            goto Lerr;
+        }
+
         case TOKlparen:
         {
             Token *tk = peekPastParen(&token);
diff --git a/gcc/d/dmd/parse.h b/gcc/d/dmd/parse.h
index 82ce3254607..a2ad47882ef 100644
--- a/gcc/d/dmd/parse.h
+++ b/gcc/d/dmd/parse.h
@@ -83,6 +83,7 @@ public:
     TemplateParameters *parseTemplateParameterList(int flag = 0);
     Dsymbol *parseMixin();
     Objects *parseTemplateArguments();
+    RootObject *parseTypeOrAssignExp(TOK endtoken = TOKreserved);
     Objects *parseTemplateArgumentList();
     Objects *parseTemplateSingleArgument();
     StaticAssert *parseStaticAssert();
diff --git a/gcc/d/dmd/scope.h b/gcc/d/dmd/scope.h
index ea3bf3874e1..ea3061b8fa6 100644
--- a/gcc/d/dmd/scope.h
+++ b/gcc/d/dmd/scope.h
@@ -66,6 +66,10 @@ enum PINLINE;
 #define SCOPEfullinst       0x10000 // fully instantiate templates
 #define SCOPEalias          0x20000 // inside alias declaration
 
+// The following are mutually exclusive
+#define SCOPEprintf         0x40000 // printf-style function
+#define SCOPEscanf          0x80000 // scanf-style function
+
 struct Scope
 {
     Scope *enclosing;           // enclosing Scope
diff --git a/gcc/d/dmd/semantic2.c b/gcc/d/dmd/semantic2.c
index 7bcf6ce4f33..194a3fb9661 100644
--- a/gcc/d/dmd/semantic2.c
+++ b/gcc/d/dmd/semantic2.c
@@ -163,6 +163,15 @@ public:
         if (vd->_init && !vd->toParent()->isFuncDeclaration())
         {
             vd->inuse++;
+
+            /* https://issues.dlang.org/show_bug.cgi?id=20280
+             *
+             * Template instances may import modules that have not
+             * finished semantic1.
+             */
+            if (!vd->type)
+                dsymbolSemantic(vd, sc);
+
             // Bugzilla 14166: Don't run CTFE for the temporary variables inside typeof
             vd->_init = initializerSemantic(vd->_init, sc, vd->type, sc->intypeof == 1 ? INITnointerpret : INITinterpret);
             vd->inuse--;
@@ -265,6 +274,17 @@ public:
     {
         if (fd->semanticRun >= PASSsemantic2done)
             return;
+
+        if (fd->semanticRun < PASSsemanticdone && !fd->errors)
+        {
+            /* https://issues.dlang.org/show_bug.cgi?id=21614
+             *
+             * Template instances may import modules that have not
+             * finished semantic1.
+             */
+            dsymbolSemantic(fd, sc);
+        }
+
         assert(fd->semanticRun <= PASSsemantic2);
         fd->semanticRun = PASSsemantic2;
 
diff --git a/gcc/d/dmd/semantic3.c b/gcc/d/dmd/semantic3.c
index 304eaeeb119..6bd9a6d2e27 100644
--- a/gcc/d/dmd/semantic3.c
+++ b/gcc/d/dmd/semantic3.c
@@ -850,32 +850,18 @@ public:
                     }
                     assert(!funcdecl->returnLabel);
                 }
+                else if (f->next->ty == Tnoreturn)
+                {
+                }
                 else
                 {
                     const bool inlineAsm = (funcdecl->hasReturnExp & 8) != 0;
                     if ((blockexit & BEfallthru) && f->next->ty != Tvoid && !inlineAsm)
                     {
-                        Expression *e;
                         if (!funcdecl->hasReturnExp)
-                            funcdecl->error("has no return statement, but is expected to return a value of type %s", f->next->toChars());
-                        else
-                            funcdecl->error("no return exp; or assert(0); at end of function");
-                        if (global.params.useAssert == CHECKENABLEon &&
-                            !global.params.useInline)
-                        {
-                            /* Add an assert(0, msg); where the missing return
-                             * should be.
-                             */
-                            e = new AssertExp(funcdecl->endloc,
-                                              new IntegerExp(0),
-                                              new StringExp(funcdecl->loc, const_cast<char *>("missing return expression")));
-                        }
+                            funcdecl->error("has no `return` statement, but is expected to return a value of type `%s`", f->next->toChars());
                         else
-                            e = new HaltExp(funcdecl->endloc);
-                        e = new CommaExp(Loc(), e, f->next->defaultInit());
-                        e = expressionSemantic(e, sc2);
-                        Statement *s = new ExpStatement(Loc(), e);
-                        funcdecl->fbody = new CompoundStatement(Loc(), funcdecl->fbody, s);
+                            funcdecl->error("no `return exp;` or `assert(0);` at end of function");
                     }
                 }
 
@@ -1162,15 +1148,7 @@ public:
 
                     if (cd)
                     {
-                        if (!global.params.is64bit &&
-                            global.params.isWindows &&
-                            !funcdecl->isStatic() && !sbody->usesEH() && !global.params.trace)
-                        {
-                            /* The back end uses the "jmonitor" hack for syncing;
-                             * no need to do the sync at this level.
-                             */
-                        }
-                        else
+                        if (target.libraryObjectMonitors(funcdecl, sbody))
                         {
                             Expression *vsync;
                             if (funcdecl->isStatic())
diff --git a/gcc/d/dmd/statement.c b/gcc/d/dmd/statement.c
index 2f7b7e13ffc..1f8e5122b1a 100644
--- a/gcc/d/dmd/statement.c
+++ b/gcc/d/dmd/statement.c
@@ -31,6 +31,7 @@ StorageClass mergeFuncAttrs(StorageClass s1, FuncDeclaration *f);
 bool checkEscapeRef(Scope *sc, Expression *e, bool gag);
 VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e);
 Statement *makeTupleForeachStatic(Scope *sc, ForeachStatement *fs, bool needExpansion);
+bool expressionsToString(OutBuffer &buf, Scope *sc, Expressions *exps);
 
 Identifier *fixupLabelName(Scope *sc, Identifier *ident)
 {
@@ -504,12 +505,19 @@ Statement *DtorExpStatement::syntaxCopy()
 CompileStatement::CompileStatement(Loc loc, Expression *exp)
     : Statement(loc)
 {
-    this->exp = exp;
+    this->exps = new Expressions();
+    this->exps->push(exp);
+}
+
+CompileStatement::CompileStatement(Loc loc, Expressions *exps)
+    : Statement(loc)
+{
+    this->exps = exps;
 }
 
 Statement *CompileStatement::syntaxCopy()
 {
-    return new CompileStatement(loc, exp->syntaxCopy());
+    return new CompileStatement(loc, Expression::arraySyntaxCopy(exps));
 }
 
 static Statements *errorStatements()
@@ -519,32 +527,36 @@ static Statements *errorStatements()
     return a;
 }
 
-Statements *CompileStatement::flatten(Scope *sc)
+static Statements *compileIt(CompileStatement *cs, Scope *sc)
 {
-    //printf("CompileStatement::flatten() %s\n", exp->toChars());
-    StringExp *se = semanticString(sc, exp, "argument to mixin");
-    if (!se)
+    //printf("CompileStatement::compileIt() %s\n", exp->toChars());
+    OutBuffer buf;
+    if (expressionsToString(buf, sc, cs->exps))
         return errorStatements();
-    se = se->toUTF8(sc);
 
     unsigned errors = global.errors;
-    Parser p(loc, sc->_module, (utf8_t *)se->string, se->len, 0);
+    const size_t len = buf.length();
+    const char *str = buf.extractChars();
+    Parser p(cs->loc, sc->_module, (const utf8_t *)str, len, false);
     p.nextToken();
 
     Statements *a = new Statements();
     while (p.token.value != TOKeof)
     {
         Statement *s = p.parseStatement(PSsemi | PScurlyscope);
-        if (!s || p.errors)
-        {
-            assert(!p.errors || global.errors != errors); // make sure we caught all the cases
+        if (!s || global.errors != errors)
             return errorStatements();
-        }
         a->push(s);
     }
     return a;
 }
 
+Statements *CompileStatement::flatten(Scope *sc)
+{
+    //printf("CompileStatement::flatten() %s\n", exp->toChars());
+    return compileIt(this, sc);
+}
+
 /******************************** CompoundStatement ***************************/
 
 CompoundStatement::CompoundStatement(Loc loc, Statements *s)
diff --git a/gcc/d/dmd/statement.h b/gcc/d/dmd/statement.h
index 2d8b46c9487..c64e51a5be7 100644
--- a/gcc/d/dmd/statement.h
+++ b/gcc/d/dmd/statement.h
@@ -173,9 +173,10 @@ public:
 class CompileStatement : public Statement
 {
 public:
-    Expression *exp;
+    Expressions *exps;
 
     CompileStatement(Loc loc, Expression *exp);
+    CompileStatement(Loc loc, Expressions *exps);
     Statement *syntaxCopy();
     Statements *flatten(Scope *sc);
     void accept(Visitor *v) { v->visit(this); }
diff --git a/gcc/d/dmd/statementsem.c b/gcc/d/dmd/statementsem.c
index 5579c1ca893..491d9c9bce9 100644
--- a/gcc/d/dmd/statementsem.c
+++ b/gcc/d/dmd/statementsem.c
@@ -581,7 +581,7 @@ public:
                         {
                             fs->error("constant value %s cannot be ref", ie->toChars());
                         }
-                        else 
+                        else
                         {
                             fs->error("constant value %s cannot be ref", ident->toChars());
                         }
diff --git a/gcc/d/dmd/target.h b/gcc/d/dmd/target.h
index a91880fd0fc..f8f977c9aea 100644
--- a/gcc/d/dmd/target.h
+++ b/gcc/d/dmd/target.h
@@ -21,6 +21,7 @@ class Dsymbol;
 class Expression;
 class FuncDeclaration;
 class Parameter;
+class Statement;
 class Type;
 class TypeFunction;
 class TypeTuple;
@@ -30,6 +31,7 @@ struct TargetC
 {
     unsigned longsize;            // size of a C 'long' or 'unsigned long' type
     unsigned long_doublesize;     // size of a C 'long double'
+    Type *twchar_t;               // C 'wchar_t' type
 };
 
 struct TargetCPP
@@ -44,6 +46,7 @@ struct TargetCPP
     const char *typeMangle(Type *t);
     Type *parameterType(Parameter *p);
     bool fundamentalType(const Type *t, bool& isFundamental);
+    unsigned derivedClassOffset(ClassDeclaration *baseClass);
 };
 
 struct TargetObjC
@@ -108,6 +111,7 @@ public:
     TypeTuple *toArgTypes(Type *t);
     bool isReturnOnStack(TypeFunction *tf, bool needsThis);
     Expression *getTargetInfo(const char* name, const Loc& loc);
+    bool libraryObjectMonitors(FuncDeclaration *fd, Statement *fbody);
 };
 
 extern Target target;
diff --git a/gcc/d/dmd/template.h b/gcc/d/dmd/template.h
index dac1e85b433..fb842ac5b76 100644
--- a/gcc/d/dmd/template.h
+++ b/gcc/d/dmd/template.h
@@ -78,6 +78,7 @@ public:
     bool ismixin;               // template declaration is only to be used as a mixin
     bool isstatic;              // this is static template declaration
     Prot protection;
+    int inuse;                  // for recursive expansion detection
 
     TemplatePrevious *previous;         // threaded list of previous instantiation attempts on stack
 
diff --git a/gcc/d/dmd/templateparamsem.c b/gcc/d/dmd/templateparamsem.c
index 11cd52e351b..d3e9b2390e9 100644
--- a/gcc/d/dmd/templateparamsem.c
+++ b/gcc/d/dmd/templateparamsem.c
@@ -25,7 +25,7 @@ public:
     {
         this->sc = sc;
         this->parameters = parameters;
-	this->result = false;
+        this->result = false;
     }
 
     void visit(TemplateTypeParameter *ttp)
diff --git a/gcc/d/dmd/traits.c b/gcc/d/dmd/traits.c
index b7c612c2af2..99b5457f031 100644
--- a/gcc/d/dmd/traits.c
+++ b/gcc/d/dmd/traits.c
@@ -40,6 +40,8 @@ void freeFieldinit(Scope *sc);
 Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads);
 Package *resolveIsPackage(Dsymbol *sym);
 Expression *typeToExpression(Type *t);
+Type *decoToType(const char *deco);
+bool expressionsToString(OutBuffer &buf, Scope *sc, Expressions *exps);
 
 
 /************************************************
@@ -442,7 +444,6 @@ TraitsInitializer::TraitsInitializer()
         "derivedMembers",
         "isSame",
         "compiles",
-        "parameters",
         "getAliasThis",
         "getAttributes",
         "getFunctionAttributes",
@@ -1032,6 +1033,34 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
         ex = expressionSemantic(ex, sc);
         return ex;
     }
+    else if (e->ident == Id::toType)
+    {
+        if (dim != 1)
+            return dimError(e, 1, dim);
+
+        Expression *ex = isExpression((*e->args)[0]);
+        if (!ex)
+        {
+            e->error("expression expected as second argument of __traits `%s`", e->ident->toChars());
+            return new ErrorExp();
+        }
+        ex = ex->ctfeInterpret();
+
+        StringExp *se = semanticString(sc, ex, "__traits(toType, string)");
+        if (!se)
+        {
+            return new ErrorExp();
+        }
+        Type *t = decoToType(se->toUTF8(sc)->toPtr());
+        if (!t)
+        {
+            e->error("cannot determine `%s`", e->toChars());
+            return new ErrorExp();
+        }
+        ex = new TypeExp(e->loc, t);
+        ex = expressionSemantic(ex, sc);
+        return ex;
+    }
     else if (e->ident == Id::hasMember ||
              e->ident == Id::getMember ||
              e->ident == Id::getOverloads ||
@@ -1674,33 +1703,67 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
 
             RootObject *o = (*e->args)[i];
             Type *t = isType(o);
-            Expression *ex = t ? typeToExpression(t) : isExpression(o);
-            if (!ex && t)
+            while (t)
             {
-                Dsymbol *s;
-                t->resolve(e->loc, sc2, &ex, &t, &s);
-                if (t)
+                if (TypeMixin *tm = t->isTypeMixin())
                 {
-                    typeSemantic(t, e->loc, sc2);
-                    if (t->ty == Terror)
+                    /* The mixin string could be a type or an expression.
+                     * Have to try compiling it to see.
+                     */
+                    OutBuffer buf;
+                    if (expressionsToString(buf, sc, tm->exps))
+                    {
+                        err = true;
+                        break;
+                    }
+                    const size_t len = buf.length();
+                    const char *str = buf.extractChars();
+                    Parser p(e->loc, sc->_module, (const utf8_t *)str, len, false);
+                    p.nextToken();
+                    //printf("p.loc.linnum = %d\n", p.loc.linnum);
+
+                    o = p.parseTypeOrAssignExp(TOKeof);
+                    if (p.errors || p.token.value != TOKeof)
+                    {
                         err = true;
+                        break;
+                    }
+                    t = isType(o);
                 }
-                else if (s && s->errors)
-                    err = true;
+                else
+                    break;
             }
-            if (ex)
+
+            if (!err)
             {
-                ex = expressionSemantic(ex, sc2);
-                ex = resolvePropertiesOnly(sc2, ex);
-                ex = ex->optimize(WANTvalue);
-                if (sc2->func && sc2->func->type->ty == Tfunction)
+                Expression *ex = t ? typeToExpression(t) : isExpression(o);
+                if (!ex && t)
                 {
-                    TypeFunction *tf = (TypeFunction *)sc2->func->type;
-                    canThrow(ex, sc2->func, tf->isnothrow);
+                    Dsymbol *s;
+                    t->resolve(e->loc, sc2, &ex, &t, &s);
+                    if (t)
+                    {
+                        typeSemantic(t, e->loc, sc2);
+                        if (t->ty == Terror)
+                            err = true;
+                    }
+                    else if (s && s->errors)
+                        err = true;
+                }
+                if (ex)
+                {
+                    ex = expressionSemantic(ex, sc2);
+                    ex = resolvePropertiesOnly(sc2, ex);
+                    ex = ex->optimize(WANTvalue);
+                    if (sc2->func && sc2->func->type->ty == Tfunction)
+                    {
+                        TypeFunction *tf = (TypeFunction *)sc2->func->type;
+                        canThrow(ex, sc2->func, tf->isnothrow);
+                    }
+                    ex = checkGC(sc2, ex);
+                    if (ex->op == TOKerror)
+                        err = true;
                 }
-                ex = checkGC(sc2, ex);
-                if (ex->op == TOKerror)
-                    err = true;
             }
 
             // Carefully detach the scope from the parent and throw it away as
diff --git a/gcc/d/dmd/typesem.c b/gcc/d/dmd/typesem.c
index 496cfe3a855..670144d1282 100644
--- a/gcc/d/dmd/typesem.c
+++ b/gcc/d/dmd/typesem.c
@@ -18,6 +18,7 @@
 #include "hdrgen.h"
 #include "id.h"
 #include "init.h"
+#include "parse.h"
 #include "scope.h"
 #include "target.h"
 #include "template.h"
@@ -25,6 +26,7 @@
 
 Expression *typeToExpression(Type *t);
 Expression *typeToExpressionHelper(TypeQualified *t, Expression *e, size_t i = 0);
+bool expressionsToString(OutBuffer &buf, Scope *sc, Expressions *exps);
 char *MODtoChars(MOD mod);
 
 class TypeToExpressionVisitor : public Visitor
@@ -76,6 +78,11 @@ public:
     {
         result = typeToExpressionHelper(t, new ScopeExp(t->loc, t->tempinst));
     }
+
+    void visit(TypeMixin *t)
+    {
+        result = new TypeExp(t->loc, t);
+    }
 };
 
 /* We've mistakenly parsed this as a type.
@@ -84,6 +91,8 @@ public:
  */
 Expression *typeToExpression(Type *t)
 {
+    if (t->mod)
+        return NULL;
     TypeToExpressionVisitor v = TypeToExpressionVisitor(t);
     t->accept(&v);
     return v.result;
@@ -177,6 +186,48 @@ static Expression *semanticLength(Scope *sc, TupleDeclaration *s, Expression *ex
     return exp;
 }
 
+/******************************************
+ * Compile the MixinType, returning the type or expression AST.
+ *
+ * Doesn't run semantic() on the returned object.
+ * Params:
+ *      tm = mixin to compile as a type or expression
+ *      loc = location for error messages
+ *      sc = context
+ * Return:
+ *      null if error, else RootObject AST as parsed
+ */
+RootObject *compileTypeMixin(TypeMixin *tm, Loc loc, Scope *sc)
+{
+    OutBuffer buf;
+    if (expressionsToString(buf, sc, tm->exps))
+        return NULL;
+
+    const unsigned errors = global.errors;
+    const size_t len = buf.length();
+    const char *str = buf.extractChars();
+    Parser p(loc, sc->_module, (const utf8_t *)str, len, false);
+    p.nextToken();
+    //printf("p.loc.linnum = %d\n", p.loc.linnum);
+
+    RootObject *o = p.parseTypeOrAssignExp(TOKeof);
+    if (errors != global.errors)
+    {
+        assert(global.errors != errors); // should have caught all these cases
+        return NULL;
+    }
+    if (p.token.value != TOKeof)
+    {
+        ::error(loc, "incomplete mixin type `%s`", str);
+        return NULL;
+    }
+
+    Type *t = isType(o);
+    Expression *e = t ? typeToExpression(t) : isExpression(o);
+
+    return (!e && t) ? (RootObject *)t : (RootObject *)e;
+}
+
 /******************************************
  * Perform semantic analysis on a type.
  * Params:
@@ -440,7 +491,7 @@ Type *typeSemantic(Type *type, const Loc &loc, Scope *sc)
             // Deal with the case where we thought the index was a type, but
             // in reality it was an expression.
             if (mtype->index->ty == Tident || mtype->index->ty == Tinstance || mtype->index->ty == Tsarray ||
-                mtype->index->ty == Ttypeof || mtype->index->ty == Treturn)
+                mtype->index->ty == Ttypeof || mtype->index->ty == Treturn || mtype->index->ty == Tmixin)
             {
                 Expression *e;
                 Type *t;
@@ -1072,6 +1123,7 @@ Type *typeSemantic(Type *type, const Loc &loc, Scope *sc)
                 mtype->exp->ident != Id::getMember &&
                 mtype->exp->ident != Id::parent &&
                 mtype->exp->ident != Id::child &&
+                mtype->exp->ident != Id::toType &&
                 mtype->exp->ident != Id::getOverloads &&
                 mtype->exp->ident != Id::getVirtualFunctions &&
                 mtype->exp->ident != Id::getVirtualMethods &&
@@ -1275,7 +1327,7 @@ Type *typeSemantic(Type *type, const Loc &loc, Scope *sc)
 
         void visit(TypeStruct *mtype)
         {
-            //printf("TypeStruct::semantic('%s')\n", mtype->sym->toChars());
+            //printf("TypeStruct::semantic('%s')\n", mtype->toChars());
             if (mtype->deco)
             {
                 if (sc && sc->cppmangle != CPPMANGLEdefault)
@@ -1304,7 +1356,7 @@ Type *typeSemantic(Type *type, const Loc &loc, Scope *sc)
 
         void visit(TypeClass *mtype)
         {
-            //printf("TypeClass::semantic(%s)\n", mtype->sym->toChars());
+            //printf("TypeClass::semantic(%s)\n", mtype->toChars());
             if (mtype->deco)
             {
                 if (sc && sc->cppmangle != CPPMANGLEdefault)
@@ -1386,6 +1438,25 @@ Type *typeSemantic(Type *type, const Loc &loc, Scope *sc)
             Type *t = new TypeTuple(args);
             result = typeSemantic(t, loc, sc);
         }
+
+        void visit(TypeMixin *mtype)
+        {
+            //printf("TypeMixin::semantic() %s\n", mtype->toChars());
+
+            Expression *e = NULL;
+            Type *t = NULL;
+            Dsymbol *s = NULL;
+            mtype->resolve(loc, sc, &e, &t, &s);
+
+            if (t && t->ty != Terror)
+            {
+                result = t;
+                return;
+            }
+
+            ::error(mtype->loc, "`mixin(%s)` does not give a valid type", mtype->obj->toChars());
+            return error();
+        }
     };
     TypeSemanticVisitor v(loc, sc);
     type->accept(&v);
diff --git a/gcc/d/dmd/visitor.h b/gcc/d/dmd/visitor.h
index a274e6f083e..09ba2024e30 100644
--- a/gcc/d/dmd/visitor.h
+++ b/gcc/d/dmd/visitor.h
@@ -81,7 +81,9 @@ class TypeClass;
 class TypeTuple;
 class TypeSlice;
 class TypeNull;
+class TypeNoreturn;
 class TypeTraits;
+class TypeMixin;
 
 class Dsymbol;
 
@@ -374,7 +376,9 @@ public:
     virtual void visit(TypeTuple *t) { visit((Type *)t); }
     virtual void visit(TypeSlice *t) { visit((TypeNext *)t); }
     virtual void visit(TypeNull *t) { visit((Type *)t); }
+    virtual void visit(TypeNoreturn *t) { visit((Type *)t); }
     virtual void visit(TypeTraits *t) { visit((Type *)t); }
+    virtual void visit(TypeMixin *t) { visit((Type *)t); }
 
     virtual void visit(Dsymbol *) { assert(0); }
 
diff --git a/gcc/d/toir.cc b/gcc/d/toir.cc
index ee3e3d5bdd5..41d07a7b70e 100644
--- a/gcc/d/toir.cc
+++ b/gcc/d/toir.cc
@@ -1068,6 +1068,13 @@ public:
 
 	add_stmt (return_expr (decl));
       }
+    else if (tf->next->ty == Tnoreturn)
+      {
+	/* Returning an expression that has no value, but has a side effect
+	   that should never return.  */
+	add_stmt (build_expr_dtor (s->exp));
+	add_stmt (return_expr (NULL_TREE));
+      }
     else
       {
 	/* Convert for initializing the DECL_RESULT.  */
diff --git a/gcc/d/types.cc b/gcc/d/types.cc
index 3cddfc5dd46..924d8298211 100644
--- a/gcc/d/types.cc
+++ b/gcc/d/types.cc
@@ -603,6 +603,12 @@ public:
     t->ctype = ptr_type_node;
   }
 
+  /* Bottom type used for functions that never return.  */
+
+  void visit (TypeNoreturn *t)
+  {
+    t->ctype = void_type_node;
+  }
 
   /* Basic Data Types.  */
 
@@ -852,7 +858,46 @@ public:
     tree basetype = (t->sym->memtype)
       ? build_ctype (t->sym->memtype) : void_type_node;
 
-    if (!INTEGRAL_TYPE_P (basetype) || TREE_CODE (basetype) == BOOLEAN_TYPE)
+    if (t->sym->isSpecial ())
+      {
+	/* Special enums are opaque types that bind to C types.  */
+	const char *ident = t->toChars ();
+	Type *underlying = NULL;
+
+	/* Skip over the prefixing `__c_'.  */
+	gcc_assert (strncmp (ident, "__c_", strlen ("__c_")) == 0);
+	ident = ident + strlen ("__c_");
+
+	/* To keep things compatible within the code generation we stick to
+	   mapping to equivalent D types.  However it should be OK to use the
+	   GCC provided C types here as the front-end enforces that everything
+	   must be explicitly cast from a D type to any of the opaque types.  */
+	if (strcmp (ident, "long") == 0)
+	  underlying = build_frontend_type (long_integer_type_node);
+	else if (strcmp (ident, "ulong") == 0)
+	  underlying = build_frontend_type (long_unsigned_type_node);
+	else if (strcmp (ident, "wchar_t") == 0)
+	  underlying = target.c.twchar_t;
+	else if (strcmp (ident, "longlong") == 0)
+	  underlying = build_frontend_type (long_long_integer_type_node);
+	else if (strcmp (ident, "ulonglong") == 0)
+	  underlying = build_frontend_type (long_long_unsigned_type_node);
+	else if (strcmp (ident, "long_double") == 0)
+	  underlying = build_frontend_type (long_double_type_node);
+	else if (strcmp (ident, "complex_real") == 0)
+	  underlying = build_frontend_type (complex_long_double_type_node);
+	else if (strcmp (ident, "complex_float") == 0)
+	  underlying = build_frontend_type (complex_float_type_node);
+	else if (strcmp (ident, "complex_double") == 0)
+	  underlying = build_frontend_type (complex_double_type_node);
+
+	/* Conversion failed or there's an unhandled special type.  */
+	gcc_assert (underlying != NULL);
+
+	t->ctype = build_variant_type_copy (build_ctype (underlying));
+	build_type_decl (t->ctype, t->sym);
+      }
+    else if (!INTEGRAL_TYPE_P (basetype) || TREE_CODE (basetype) == BOOLEAN_TYPE)
       {
 	/* Enums in D2 can have a base type that is not necessarily integral.
 	   For these, we simplify this a little by using the base type directly
diff --git a/gcc/testsuite/gdc.test/compilable/bug20796.d b/gcc/testsuite/gdc.test/compilable/bug20796.d
new file mode 100644
index 00000000000..00d00c840c4
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/bug20796.d
@@ -0,0 +1,2 @@
+// EXTRA_SOURCES: protection/issue20796/package.d
+// https://issues.dlang.org/show_bug.cgi?id=20796
diff --git a/gcc/testsuite/gdc.test/compilable/cppmangle.d b/gcc/testsuite/gdc.test/compilable/cppmangle.d
index 7fcd41ab214..954a9bee72e 100644
--- a/gcc/testsuite/gdc.test/compilable/cppmangle.d
+++ b/gcc/testsuite/gdc.test/compilable/cppmangle.d
@@ -372,3 +372,21 @@ version (Posix)
     static assert(T.boo.mangleof == "_ZN1T3booE");
 }
 
+/*****************************************/
+
+alias noreturn = typeof(*null);
+
+extern (C++)
+{
+    alias fpcpp = noreturn function();
+    int funccpp(fpcpp);
+
+    version (Posix)
+        static assert(funccpp.mangleof == "_Z7funccppPFvvE");
+
+    version (Win32)
+        static assert(funccpp.mangleof == "?funccpp@@YAHP6AXXZ@Z");
+
+    version (Win64)
+        static assert(funccpp.mangleof == "?funccpp@@YAHP6AXXZ@Z");
+}
diff --git a/gcc/testsuite/gdc.test/compilable/ddocunittest.d b/gcc/testsuite/gdc.test/compilable/ddocunittest.d
index 940ef1caf34..8c691b6ffd9 100644
--- a/gcc/testsuite/gdc.test/compilable/ddocunittest.d
+++ b/gcc/testsuite/gdc.test/compilable/ddocunittest.d
@@ -357,6 +357,7 @@ auto redBlackTree(bool allowDuplicates, E)(E[] elems...)
 }
 /// ditto
 auto redBlackTree(alias less, E)(E[] elems...)
+if (__traits(compiles, (E a, E b) => mixin(less)))
 {
     return 3;
 }
diff --git a/gcc/testsuite/gdc.test/compilable/extra-files/serenity7190/core/Controller.d b/gcc/testsuite/gdc.test/compilable/extra-files/serenity7190/core/Controller.d
index 9ade3170ee2..62de518aa99 100644
--- a/gcc/testsuite/gdc.test/compilable/extra-files/serenity7190/core/Controller.d
+++ b/gcc/testsuite/gdc.test/compilable/extra-files/serenity7190/core/Controller.d
@@ -3,6 +3,12 @@ class Controller {
         enum _s_pkg = __traits(parent, __traits(parent, __traits(parent, T))).stringof["package ".length .. $];
 
         enum _s_model = T.stringof[0 .. $-`Controller`.length] ~ `Model`;
+
+        import serenity7190.core.Model;
+        // expands to "import example7190.models.HomeModel;"
+        mixin(q{import } ~ _s_pkg ~ q{.models.} ~ _s_model ~ q{;});
+
+        // "enum _ = is(example7190.models.HomeModel.HomeModel : serenity7190.core.Model.Model);"
         mixin(q{enum _ = is(} ~ _s_pkg ~ q{.models.} ~ _s_model ~ q{.} ~ _s_model ~ q{ : serenity7190.core.Model.Model);});
     }
-}
\ No newline at end of file
+}
diff --git a/gcc/testsuite/gdc.test/compilable/extra-files/test20280a.d b/gcc/testsuite/gdc.test/compilable/extra-files/test20280a.d
new file mode 100644
index 00000000000..edb409540c7
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/extra-files/test20280a.d
@@ -0,0 +1,12 @@
+module test20280a;
+
+struct Alpha(uint _)
+{
+    import test20280a;
+}
+
+struct Foxtrot(uint _)
+{
+    alias Attributes = Alpha!10;
+    enum A = 10;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/fix21585.d b/gcc/testsuite/gdc.test/compilable/fix21585.d
new file mode 100644
index 00000000000..a83fb899708
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/fix21585.d
@@ -0,0 +1,24 @@
+/* TEST_OUTPUT:
+---
+i int
+d double
+Pi int*
+---
+*/
+
+pragma(msg, 1.mangleof, " ", __traits(toType, 1.mangleof));
+pragma(msg, (1.0).mangleof, " ", __traits(toType, (1.0).mangleof));
+pragma(msg, (int*).mangleof, " ", __traits(toType, (int*).mangleof));
+
+template Type(T) { alias Type = T; }
+
+Type!(__traits(toType, 1.mangleof)) j = 3;
+
+alias T = Type!(__traits(toType, 1.mangleof));
+static assert(is(T == int));
+
+__traits(toType, "i") x = 7;
+
+static assert(is(Type!(__traits(toType, 1.mangleof)) == int));
+static assert(is(Type!(__traits(toType, (1.0).mangleof)) == double));
+static assert(is(Type!(__traits(toType, (int*).mangleof)) == int*));
diff --git a/gcc/testsuite/gdc.test/compilable/fix21647.d b/gcc/testsuite/gdc.test/compilable/fix21647.d
new file mode 100644
index 00000000000..c129fa013a1
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/fix21647.d
@@ -0,0 +1,30 @@
+/*
+REQUIRED_ARGS:
+TEST_OUTPUT:
+---
+cast(void)0
+cast(void)0
+void
+cast(void)0
+cast(void)0
+cast(void)0
+void
+---
+*/
+
+
+// https://issues.dlang.org/show_bug.cgi?id=21647
+
+void foo() { return cast(void)1; }
+
+void main(){}
+
+alias V = void;
+
+void test1() { pragma(msg, foo()); }
+void test2() { pragma(msg, main()); }
+void test3() { pragma(msg, V); }
+
+pragma(msg, foo());
+pragma(msg, main());
+pragma(msg, V);
diff --git a/gcc/testsuite/gdc.test/compilable/ice10598.d b/gcc/testsuite/gdc.test/compilable/ice10598.d
deleted file mode 100644
index 58a7c3be5f5..00000000000
--- a/gcc/testsuite/gdc.test/compilable/ice10598.d
+++ /dev/null
@@ -1,3 +0,0 @@
-// EXTRA_SOURCES: imports/ice10598a.d imports/ice10598b.d
-
-void main() {}
diff --git a/gcc/testsuite/gdc.test/compilable/imports/issue21614a.d b/gcc/testsuite/gdc.test/compilable/imports/issue21614a.d
new file mode 100644
index 00000000000..ee3c9eb2965
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/issue21614a.d
@@ -0,0 +1,22 @@
+module imports.issue21614a;
+
+struct FormatSpec(Char)
+{
+    import imports.issue21614a;
+}
+
+template Tuple(Specs...)
+{
+    struct Tuple
+    {
+        alias spec = FormatSpec!char();
+        this(Specs)
+        {
+        }
+    }
+}
+
+auto findRoot(T)(T)
+{
+    return Tuple!(T)();
+}
diff --git a/gcc/testsuite/gdc.test/compilable/imports/pkg20537/package.d b/gcc/testsuite/gdc.test/compilable/imports/pkg20537/package.d
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test17991a/a.d b/gcc/testsuite/gdc.test/compilable/imports/test17991a/a.d
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test17991a/package.d b/gcc/testsuite/gdc.test/compilable/imports/test17991a/package.d
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test20151a/b/c/c.d b/gcc/testsuite/gdc.test/compilable/imports/test20151a/b/c/c.d
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test20530a.d b/gcc/testsuite/gdc.test/compilable/imports/test20530a.d
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test21501b.d b/gcc/testsuite/gdc.test/compilable/imports/test21501b.d
new file mode 100644
index 00000000000..c1f8fab982f
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/test21501b.d
@@ -0,0 +1,7 @@
+module imports.test21501b;
+import test21501a;
+
+struct B
+{
+    A data;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test21501c.d b/gcc/testsuite/gdc.test/compilable/imports/test21501c.d
new file mode 100644
index 00000000000..cc1f95f3fc9
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/test21501c.d
@@ -0,0 +1,4 @@
+module imports.test21501c;
+
+alias C = int;
+const D = 1;
diff --git a/gcc/testsuite/gdc.test/compilable/issue16020.d b/gcc/testsuite/gdc.test/compilable/issue16020.d
new file mode 100644
index 00000000000..cfd078cdcd1
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/issue16020.d
@@ -0,0 +1,39 @@
+module issue16020;
+
+alias F1 = const(int)(); const(int) f1(){return 42;}
+static assert (is(F1 == typeof(f1)));
+
+alias F2 = float(float); float f2(float p){return p;}
+static assert (is(F2 == typeof(f2)));
+
+alias F3 = void(); void f3(){}
+static assert (is(F3 == typeof(f3)));
+
+alias void F41() @safe;
+alias F42 = void() @safe;
+alias F43 = @safe void();
+static assert (is(F41 == F42));
+static assert (is(F43 == F42));
+
+alias void F51() @system;
+alias F52 = void() @safe;
+static assert (!is(F51 == F52));
+
+alias F61 = int() const shared;
+alias int F62() const shared ;
+alias F63 = const shared int();
+static assert (is(F61 == F62));
+static assert (is(F63 == F62));
+
+alias F71 = int() immutable inout;
+alias int F72() immutable inout;
+alias F73 = immutable inout int();
+static assert (is(F71 == F72));
+static assert (is(F73 == F72));
+
+alias FunTemplate(T) = void(T t);
+alias Specialized = FunTemplate!int;
+alias Compared = void(int);
+static assert(is(Specialized == Compared));
+
+void main() {}
diff --git a/gcc/testsuite/gdc.test/compilable/issue21614.d b/gcc/testsuite/gdc.test/compilable/issue21614.d
new file mode 100644
index 00000000000..1843fe6ec36
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/issue21614.d
@@ -0,0 +1,10 @@
+// EXTRA_FILES: imports/issue21614a.d
+// REQUIRED_ARGS: -i
+
+// https://issues.dlang.org/show_bug.cgi?id=21614
+
+void logmdigammaInverse(real y)
+{
+    import imports.issue21614a;
+    findRoot(y);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/issue21726.d b/gcc/testsuite/gdc.test/compilable/issue21726.d
new file mode 100644
index 00000000000..c8a86752a56
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/issue21726.d
@@ -0,0 +1,2 @@
+// EXTRA_SOURCES: protection/issue21726/typecons.d
+// https://issues.dlang.org/show_bug.cgi?id=21726
diff --git a/gcc/testsuite/gdc.test/compilable/mixintype.d b/gcc/testsuite/gdc.test/compilable/mixintype.d
new file mode 100644
index 00000000000..abbf85a9528
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/mixintype.d
@@ -0,0 +1,55 @@
+
+alias Int = mixin("int");
+alias Lint = mixin("Int");
+
+int test1(mixin("int")* p)
+{
+    mixin("int")[] a;
+    mixin("int[]") b;
+    mixin("int[] c;");
+    mixin("*p = c[0];");
+    *p = mixin("c[0]");
+    return *p + a[0] + b[0] + c[0];
+}
+
+/******************************************/
+
+void test2()
+{
+    auto a = __traits(allMembers, mixin(__MODULE__));
+}
+
+/*****************************************/
+
+void test3()
+{
+    char val;
+    int mod;
+    enum b = __traits(compiles, mixin("*cast(int*)&val + mod"));
+    static assert(b == true);
+}
+
+/********************************************/
+
+
+struct S
+{
+    int fielda;
+    int fieldb;
+}
+
+template Foo4(alias T)
+{
+    enum Foo4 = true;
+}
+
+void test4()
+{
+    S sa;
+    auto a = Foo4!( __traits(getMember,sa,"fielda") );
+
+    S sb;
+    enum getStuff = q{ __traits(getMember,sb,"fieldb") };
+    auto b = Foo4!(mixin(getStuff));
+}
+
diff --git a/gcc/testsuite/gdc.test/compilable/mixintype2.d b/gcc/testsuite/gdc.test/compilable/mixintype2.d
new file mode 100644
index 00000000000..43803df12cf
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/mixintype2.d
@@ -0,0 +1,68 @@
+
+alias fun = mixin("(){}");
+
+void test1()
+{
+    int x = 1;
+    static immutable c = 2;
+
+    fun();
+    foo!(mixin("int"))();
+    foo!(mixin("long*"))();
+    foo!(mixin("ST!(int, S.T)"))();
+    foo!(mixin(ST!(int, S.T)))();
+
+    int[mixin("string")] a1;
+    int[mixin("5")] a2;
+    int[mixin("c")] a3;
+    int[] v1 = new int[mixin("3")];
+    auto v2 = new int[mixin("x")];
+
+    mixin(q{__traits(getMember, S, "T")}) ftv;
+
+    alias T = int*;
+    static assert(__traits(compiles, mixin("int")));
+    static assert(__traits(compiles, mixin(q{int[mixin("string")]})));
+    static assert(__traits(compiles, mixin(q{int[mixin("2")]})));
+    static assert(__traits(compiles, mixin(T)));
+    static assert(__traits(compiles, mixin("int*")));
+    static assert(__traits(compiles, mixin(typeof(0))));
+}
+
+struct S { alias T = float*; }
+
+struct ST(X,Y) {}
+
+void foo(alias t)() {}
+
+/**************************************************/
+// https://issues.dlang.org/show_bug.cgi?id=21074
+
+alias Byte = ubyte;
+alias Byte2(A) = ubyte;
+alias T0 = mixin(q{const(Byte)})*;
+alias T1 = mixin(q{const(Byte[1])})*;
+alias T2 = mixin(q{const(Byte2!int)})*;
+alias T3 = mixin(q{const(mixin(Byte2!int))})*;
+alias T4 = mixin(q{const(mixin("__traits(getMember, S, \"T\")"))})*;
+alias T5 = const(mixin(q{Byte}))*;
+alias T6 = const(mixin(q{immutable(Byte)}))*;
+alias T7 = const(mixin(q{shared(Byte)}))*;
+alias T8 = const(mixin(q{Byte*}));
+
+// the following tests now work
+static assert(is(T0 == const(ubyte)*));
+static assert(is(T1 == const(ubyte[1])*));
+static assert(is(T2 == const(ubyte)*));
+static assert(is(T3 == const(ubyte)*));
+static assert(is(T4 == const(float*)*));
+static assert(is(T5 == const(ubyte)*));
+static assert(is(T6 == immutable(ubyte)*));
+static assert(is(T7 == const(shared(ubyte))*));
+static assert(is(T8 == const(ubyte*)));
+
+// this doesn't work but I'll file a new issue
+/*
+alias T8 = mixin(q{immutable(__traits(getMember, S, "T"))})*;
+static assert(is(T8 == immutable(float*)*));
+*/
diff --git a/gcc/testsuite/gdc.test/compilable/noreturn1.d b/gcc/testsuite/gdc.test/compilable/noreturn1.d
new file mode 100644
index 00000000000..e21adc476c9
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/noreturn1.d
@@ -0,0 +1,21 @@
+/*
+TEST_OUTPUT:
+---
+noreturn
+---
+*/
+
+alias noreturn = typeof(*null);
+pragma(msg, noreturn);
+
+noreturn exits(int* p) { *p = 3; }
+
+noreturn exit();
+
+int test1(int i)
+{
+    if (exit())
+        return i + 1;
+    return i - 1;
+}
+
diff --git a/gcc/testsuite/gdc.test/compilable/protection/issue20796/package.d b/gcc/testsuite/gdc.test/compilable/protection/issue20796/package.d
new file mode 100644
index 00000000000..d0b5f5a7860
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/protection/issue20796/package.d
@@ -0,0 +1,5 @@
+module issue20796;
+
+package(issue20796) void foo()
+{
+}
diff --git a/gcc/testsuite/gdc.test/compilable/protection/issue21726/format/package.d b/gcc/testsuite/gdc.test/compilable/protection/issue21726/format/package.d
new file mode 100644
index 00000000000..e0f6ba7d263
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/protection/issue21726/format/package.d
@@ -0,0 +1,7 @@
+module protection.issue21726.format;
+
+package(protection.issue21726.format):
+
+package(protection.issue21726) int issuePkgSym;
+package(protection) int protectionPkgSym();
+int formatPkgSym;
diff --git a/gcc/testsuite/gdc.test/compilable/protection/issue21726/package.d b/gcc/testsuite/gdc.test/compilable/protection/issue21726/package.d
new file mode 100644
index 00000000000..f8986c949bd
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/protection/issue21726/package.d
@@ -0,0 +1 @@
+module protection.issue21726;
diff --git a/gcc/testsuite/gdc.test/compilable/protection/issue21726/typecons.d b/gcc/testsuite/gdc.test/compilable/protection/issue21726/typecons.d
new file mode 100644
index 00000000000..faed95e5f5e
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/protection/issue21726/typecons.d
@@ -0,0 +1,6 @@
+module protection.issue21726.typecons;
+
+import protection.issue21726.format : issuePkgSym;
+import protection.issue21726.format : protectionPkgSym;
+static assert(!__traits(compiles,
+                        { import protection.issue21726.format : formatPkgSym; }));
diff --git a/gcc/testsuite/gdc.test/compilable/test16002.d b/gcc/testsuite/gdc.test/compilable/test16002.d
index f3303c0e310..f7b4c2e96a8 100644
--- a/gcc/testsuite/gdc.test/compilable/test16002.d
+++ b/gcc/testsuite/gdc.test/compilable/test16002.d
@@ -22,3 +22,6 @@ static assert(is(b == module));
 // This is supposed to work even though we haven't directly imported imports.pkgmodule.
 static assert(is(imports.pkgmodule == module));
 static assert(!is(MyStruct == module));
+
+static assert(!is(imports.nonexistent == package));
+static assert(!is(imports.nonexistent == module));
diff --git a/gcc/testsuite/gdc.test/compilable/test17991.d b/gcc/testsuite/gdc.test/compilable/test17991.d
new file mode 100644
index 00000000000..8bc9fa94f5f
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test17991.d
@@ -0,0 +1,3 @@
+// https://issues.dlang.org/show_bug.cgi?id=17991
+// EXTRA_FILES: imports/test17991a/package.d imports/test17991a/a.d
+import imports.test17991a, imports.test17991a.a;
diff --git a/gcc/testsuite/gdc.test/compilable/test19292.d b/gcc/testsuite/gdc.test/compilable/test19292.d
new file mode 100644
index 00000000000..8122851c6ca
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test19292.d
@@ -0,0 +1,15 @@
+// https://issues.dlang.org/show_bug.cgi?id=19292
+
+mixin("enum a = ", 87, ";");
+static assert(a == 87);
+
+int test()
+{
+    mixin("enum x = ", 7, ";");
+    return mixin("1", x, 2U);
+}
+
+void testit()
+{
+    static assert(test() == 172);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test20151a.d b/gcc/testsuite/gdc.test/compilable/test20151a.d
new file mode 100644
index 00000000000..d9ae28fabe1
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test20151a.d
@@ -0,0 +1,3 @@
+// EXTRA_FILES: imports/test20151a/b/c/c.d
+module imports.test20151a;
+import imports.test20151a.b.c.c;
diff --git a/gcc/testsuite/gdc.test/compilable/test20280.d b/gcc/testsuite/gdc.test/compilable/test20280.d
new file mode 100644
index 00000000000..76a10823e49
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test20280.d
@@ -0,0 +1,8 @@
+// PERMUTE_ARGS:
+// REQUIRED_ARGS: -Icompilable/extra-files
+// EXTRA_FILES: extra-files/test20280a.d
+module test20280;
+
+import test20280a;
+
+alias Charlie = Foxtrot!(0);
diff --git a/gcc/testsuite/gdc.test/compilable/test20530.d b/gcc/testsuite/gdc.test/compilable/test20530.d
new file mode 100644
index 00000000000..be80dbb34d1
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test20530.d
@@ -0,0 +1,46 @@
+// EXTRA_FILES: imports/test20530a.d imports/plainpackage/plainmodule.d imports/pkgmodule/package.d imports/pkgmodule/plainmodule.d
+module mod;
+static assert(is(mod == module));
+static assert(is(mixin("mod") == module));
+static assert(!is(mod == package));
+static assert(!is(mixin("mod") == package));
+
+import imports.test20530a;
+static assert(is(imports == package));
+static assert(is(mixin("imports") == package));
+static assert(!is(imports == module));
+static assert(!is(mixin("imports") == module));
+
+import imports.plainpackage.plainmodule;
+import imports.pkgmodule.plainmodule;
+
+struct MyStruct;
+
+alias a = mixin("imports.plainpackage");
+alias b = mixin("imports.pkgmodule.plainmodule");
+
+static assert(is(mixin("imports.plainpackage") == package));
+static assert(is(mixin("a") == package));
+static assert(!is(mixin("imports.plainpackage.plainmodule") == package));
+static assert(!is(mixin("b") == package));
+static assert(is(mixin("imports.pkgmodule") == package));
+mixin("static assert(is(imports.pkgmodule == package));");
+
+static assert(!is(mixin("MyStruct") == package));
+
+static assert(!is(mixin("imports.plainpackage") == module));
+static assert(!is(mixin("a") == module));
+static assert(is(mixin("imports.plainpackage.plainmodule") == module));
+static assert(is(mixin("b") == module));
+static assert(is(mixin("imports.pkgmodule") == module));
+mixin("static assert(is(imports.pkgmodule == module));");
+
+static assert(!is(mixin("MyStruct") == module));
+
+static assert(!is(mixin("imports.nonexistent") == package));
+static assert(!is(mixin("imports.nonexistent") == module));
+
+// this won't work due to mixin argument .stringof expansion,
+// it will expand to mixin(package imports.pkgmodule). Issue 20519.
+//static assert(is(mixin(imports.pkgmodule) == package));
+//static assert(is(mixin(imports.pkgmodule) == module));
diff --git a/gcc/testsuite/gdc.test/compilable/test20537.d b/gcc/testsuite/gdc.test/compilable/test20537.d
new file mode 100644
index 00000000000..f2d05d26fee
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test20537.d
@@ -0,0 +1,10 @@
+// REQUIRED_ARGS: -Icompilable/imports
+// EXTRA_FILES: imports/pkg20537/package.d
+import pkg20537;
+
+static assert(is(pkg20537 == module));
+static assert(__traits(isModule, pkg20537));
+static assert(is(mixin("pkg20537") == module));
+static assert(is(pkg20537 == package));
+static assert(__traits(isPackage, pkg20537));
+static assert(is(mixin("pkg20537") == package));
diff --git a/gcc/testsuite/gdc.test/compilable/test20692.d b/gcc/testsuite/gdc.test/compilable/test20692.d
new file mode 100644
index 00000000000..2d67211c74d
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test20692.d
@@ -0,0 +1,18 @@
+// https://issues.dlang.org/show_bug.cgi?id=20692
+
+struct S() {
+    void fun() {
+        gun("");
+    }
+    void gun(T)(T) {
+        alias buggy = bug;
+    }
+}
+
+alias X = S!();
+
+void main() {
+    X().gun(0);
+}
+
+alias bug =  __traits(getMember, X, "fun");
diff --git a/gcc/testsuite/gdc.test/compilable/test21501a.d b/gcc/testsuite/gdc.test/compilable/test21501a.d
new file mode 100644
index 00000000000..096fd51b653
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test21501a.d
@@ -0,0 +1,19 @@
+// EXTRA_SOURCES: imports/test21501b.d imports/test21501c.d
+// https://issues.dlang.org/show_bug.cgi?id=21501
+
+module test21501a;
+import imports.test21501b;
+import imports.test21501c;
+
+alias Identity(alias T) = T;
+
+struct A
+{
+    alias     a = imports.test21501c.C;
+    const int b = imports.test21501c.D; // fixed
+    alias     c = Identity!(mixin(q{imports.test21501c.C})); // fixed
+    const int d = Identity!(mixin(q{imports.test21501c.D})); // fixed
+
+    static assert(is(a == c) && is(a == int));
+    static assert(b == d && b == 1);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test9029.d b/gcc/testsuite/gdc.test/compilable/test9029.d
new file mode 100644
index 00000000000..bbbd98a729c
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test9029.d
@@ -0,0 +1,39 @@
+// https://issues.dlang.org/show_bug.cgi?id=9029
+enum NameOf(alias S) = S.stringof;
+
+static assert(NameOf!int == "int");
+
+enum BothMatch(alias S) = "alias";
+enum BothMatch(T) = "type";
+
+void foo9029() { }
+
+struct Struct { }
+
+static assert(BothMatch!int == "type");
+static assert(BothMatch!(void function()) == "type");
+static assert(BothMatch!BothMatch == "alias");
+static assert(BothMatch!Struct == "type");
+static assert(BothMatch!foo9029 == "alias");
+static assert(BothMatch!5 == "alias");
+
+// https://issues.dlang.org/show_bug.cgi?id=19884
+mixin template genCtEvaluate()
+{
+    void evaluate(alias op)() { }
+}
+struct S
+{
+    mixin genCtEvaluate!() mixinEval;
+    alias evaluate = mixinEval.evaluate;
+    void evaluate() { }
+}
+alias List(Ops...) = Ops;
+void main()
+{
+    S g;
+    foreach (op; List!(0))
+    {
+        g.evaluate!op();
+    }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/bug15613.d b/gcc/testsuite/gdc.test/fail_compilation/bug15613.d
new file mode 100644
index 00000000000..e8072fdbaf8
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/bug15613.d
@@ -0,0 +1,18 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/bug15613.d(16): Error: function `bug15613.f(int...)` is not callable using argument types `(typeof(null))`
+fail_compilation/bug15613.d(16):        cannot pass argument `null` of type `typeof(null)` to parameter `int...`
+fail_compilation/bug15613.d(17): Error: function `bug15613.g(Object, ...)` is not callable using argument types `(int)`
+fail_compilation/bug15613.d(17):        cannot pass argument `8` of type `int` to parameter `Object`
+---
+*/
+
+void f(int...);
+void g(Object, ...);
+
+void main()
+{
+    f(null);
+    g(8);
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/bug16165.d b/gcc/testsuite/gdc.test/fail_compilation/bug16165.d
new file mode 100644
index 00000000000..fdfbf73f415
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/bug16165.d
@@ -0,0 +1,18 @@
+void f(int x, Object y);
+
+void g()
+{
+       Object o;
+       f(o, o, 404);
+       f(5, 6, 404);
+}
+
+/* 
+TEST_OUTPUT:
+---
+fail_compilation/bug16165.d(6): Error: function `bug16165.f(int x, Object y)` is not callable using argument types `(Object, Object, int)`
+fail_compilation/bug16165.d(6):        cannot pass argument `o` of type `object.Object` to parameter `int x`
+fail_compilation/bug16165.d(7): Error: function `bug16165.f(int x, Object y)` is not callable using argument types `(int, int, int)`
+fail_compilation/bug16165.d(7):        cannot pass argument `6` of type `int` to parameter `Object y`
+---
+ */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/bug9631.d b/gcc/testsuite/gdc.test/fail_compilation/bug9631.d
new file mode 100644
index 00000000000..852eaae7479
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/bug9631.d
@@ -0,0 +1,100 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/bug9631.d(20): Error: cannot implicitly convert expression `F()` of type `bug9631.T1!().F` to `bug9631.T2!().F`
+---
+*/
+
+template T1()
+{
+    struct F { }
+}
+
+template T2()
+{
+    struct F { }
+}
+
+void main()
+{
+    T2!().F x = T1!().F();
+}
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/bug9631.d(41): Error: incompatible types for ((x) == (y)): 'bug9631.S' and 'bug9631.tem!
+).S'
+---
+*/
+
+struct S { char c; }
+
+template tem()
+{
+    struct S { int i; }
+}
+
+void equal()
+{
+    S x;
+    auto y = tem!().S();
+    bool b = x == y;
+}
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/bug9631.d(79): Error: function `bug9631.arg.f(int i, S s)` is not callable using argumen
+ types `(int, S)`
+fail_compilation/bug9631.d(79):        cannot pass argument `y` of type `bug9631.tem!().S` to parameter `
+ug9631.S s`
+fail_compilation/bug9631.d(80): Error: function literal `__lambda2(S s)` is not callable using argument t
+pes `(S)`
+fail_compilation/bug9631.d(80):        cannot pass argument `x` of type `bug9631.S` to parameter `bug9631
+tem!().S s`
+fail_compilation/bug9631.d(86): Error: constructor `bug9631.arg.A.this(S _param_0)` is not callable using
+argument types `(S)`
+fail_compilation/bug9631.d(86):        cannot pass argument `S(0)` of type `bug9631.tem!().S` to paramete
+ `bug9631.S _param_0`
+---
+*/
+void arg()
+{
+    S x;
+    tem!().S y;
+
+    void f(int i, S s);
+    f(4, y);
+    (tem!().S s){}(x);
+
+    struct A
+    {
+        this(S){}
+    }
+    A(tem!().S());
+}
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/bug9631.d(106): Error: function `bug9631.targ.ft!().ft(S _param_0)` is not callable using argument types `(S)`
+fail_compilation/bug9631.d(106):        cannot pass argument `x` of type `bug9631.S` to parameter `bug9631.tem!().S _param_0`
+fail_compilation/bug9631.d(107): Error: template `bug9631.targ.ft` cannot deduce function from argument types `!()(S)`, candidates are:
+fail_compilation/bug9631.d(105):        `bug9631.targ.ft()(tem!().S)`
+fail_compilation/bug9631.d(109): Error: template `bug9631.targ.ft2` cannot deduce function from argument types `!()(S, int)`, candidates are:
+fail_compilation/bug9631.d(108):        `bug9631.targ.ft2(T)(S, T)`
+---
+*/
+void targ()
+{
+    S x;
+    tem!().S y;
+
+    void ft()(tem!().S){}
+    ft!()(x);
+    ft(x);
+    void ft2(T)(S, T){}
+    ft2(y, 1);
+}
+
diff --git a/gcc/testsuite/gdc.test/fail_compilation/chkformat.d b/gcc/testsuite/gdc.test/fail_compilation/chkformat.d
new file mode 100644
index 00000000000..7451b3f506b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/chkformat.d
@@ -0,0 +1,139 @@
+/*
+REQUIRED_ARGS: -de
+TEST_OUTPUT:
+---
+fail_compilation/chkformat.d(101): Deprecation: width argument `0L` for format specification `"%*.*d"` must be `int`, not `long`
+fail_compilation/chkformat.d(101): Deprecation: precision argument `1L` for format specification `"%*.*d"` must be `int`, not `long`
+fail_compilation/chkformat.d(101): Deprecation: argument `2L` for format specification `"%*.*d"` must be `int`, not `long`
+fail_compilation/chkformat.d(104): Deprecation: argument `4` for format specification `"%lld"` must be `long`, not `int`
+fail_compilation/chkformat.d(105): Deprecation: argument `5` for format specification `"%jd"` must be `core.stdc.stdint.intmax_t`, not `int`
+fail_compilation/chkformat.d(106): Deprecation: argument `6.0` for format specification `"%zd"` must be `size_t`, not `double`
+fail_compilation/chkformat.d(107): Deprecation: argument `7.0` for format specification `"%td"` must be `ptrdiff_t`, not `double`
+fail_compilation/chkformat.d(108): Deprecation: argument `8.0L` for format specification `"%g"` must be `double`, not `real`
+fail_compilation/chkformat.d(109): Deprecation: argument `9.0` for format specification `"%Lg"` must be `real`, not `double`
+fail_compilation/chkformat.d(110): Deprecation: argument `10` for format specification `"%p"` must be `void*`, not `int`
+fail_compilation/chkformat.d(111): Deprecation: argument `& u` for format specification `"%n"` must be `int*`, not `uint*`
+fail_compilation/chkformat.d(113): Deprecation: argument `& u` for format specification `"%lln"` must be `long*`, not `int*`
+fail_compilation/chkformat.d(114): Deprecation: argument `& u` for format specification `"%hn"` must be `short*`, not `int*`
+fail_compilation/chkformat.d(115): Deprecation: argument `& u` for format specification `"%hhn"` must be `byte*`, not `int*`
+fail_compilation/chkformat.d(116): Deprecation: argument `16L` for format specification `"%c"` must be `char`, not `long`
+fail_compilation/chkformat.d(117): Deprecation: argument `17L` for format specification `"%c"` must be `char`, not `long`
+fail_compilation/chkformat.d(118): Deprecation: argument `& u` for format specification `"%s"` must be `char*`, not `int*`
+fail_compilation/chkformat.d(119): Deprecation: argument `& u` for format specification `"%ls"` must be `wchar_t*`, not `int*`
+fail_compilation/chkformat.d(201): Deprecation: argument `0L` for format specification `"%d"` must be `int*`, not `long`
+fail_compilation/chkformat.d(202): Deprecation: more format specifiers than 1 arguments
+fail_compilation/chkformat.d(203): Deprecation: argument `0L` for format specification `"%d"` must be `int*`, not `long`
+fail_compilation/chkformat.d(204): Deprecation: argument `0L` for format specification `"%3u"` must be `uint*`, not `long`
+fail_compilation/chkformat.d(205): Deprecation: argument `u` for format specification `"%200u"` must be `uint*`, not `uint`
+fail_compilation/chkformat.d(206): Deprecation: argument `3.0` for format specification `"%hhd"` must be `byte*`, not `double`
+fail_compilation/chkformat.d(207): Deprecation: argument `4` for format specification `"%hd"` must be `short*`, not `int`
+fail_compilation/chkformat.d(209): Deprecation: argument `4` for format specification `"%lld"` must be `long*`, not `int`
+fail_compilation/chkformat.d(210): Deprecation: argument `5` for format specification `"%jd"` must be `core.stdc.stdint.intmax_t*`, not `int`
+fail_compilation/chkformat.d(211): Deprecation: argument `6.0` for format specification `"%zd"` must be `size_t*`, not `double`
+fail_compilation/chkformat.d(212): Deprecation: argument `7.0` for format specification `"%td"` must be `ptrdiff_t*`, not `double`
+fail_compilation/chkformat.d(213): Deprecation: format specifier `"%Ld"` is invalid
+fail_compilation/chkformat.d(214): Deprecation: argument `0` for format specification `"%u"` must be `uint*`, not `int`
+fail_compilation/chkformat.d(215): Deprecation: argument `0` for format specification `"%hhu"` must be `ubyte*`, not `int`
+fail_compilation/chkformat.d(216): Deprecation: argument `0` for format specification `"%hu"` must be `ushort*`, not `int`
+fail_compilation/chkformat.d(218): Deprecation: argument `0` for format specification `"%llu"` must be `ulong*`, not `int`
+fail_compilation/chkformat.d(219): Deprecation: argument `0` for format specification `"%ju"` must be `ulong*`, not `int`
+fail_compilation/chkformat.d(220): Deprecation: argument `0` for format specification `"%zu"` must be `size_t*`, not `int`
+fail_compilation/chkformat.d(221): Deprecation: argument `0` for format specification `"%tu"` must be `ptrdiff_t*`, not `int`
+fail_compilation/chkformat.d(222): Deprecation: argument `8.0L` for format specification `"%g"` must be `float*`, not `real`
+fail_compilation/chkformat.d(223): Deprecation: argument `8.0L` for format specification `"%lg"` must be `double*`, not `real`
+fail_compilation/chkformat.d(224): Deprecation: argument `9.0` for format specification `"%Lg"` must be `real*`, not `double`
+fail_compilation/chkformat.d(225): Deprecation: argument `& u` for format specification `"%s"` must be `char*`, not `int*`
+fail_compilation/chkformat.d(226): Deprecation: argument `& u` for format specification `"%ls"` must be `wchar_t*`, not `int*`
+fail_compilation/chkformat.d(227): Deprecation: argument `v` for format specification `"%p"` must be `void**`, not `void*`
+fail_compilation/chkformat.d(228): Deprecation: argument `& u` for format specification `"%n"` must be `int*`, not `ushort*`
+fail_compilation/chkformat.d(229): Deprecation: argument `& u` for format specification `"%hhn"` must be `byte*`, not `int*`
+fail_compilation/chkformat.d(230): Deprecation: format specifier `"%[n"` is invalid
+fail_compilation/chkformat.d(231): Deprecation: format specifier `"%]"` is invalid
+fail_compilation/chkformat.d(232): Deprecation: argument `& u` for format specification `"%90s"` must be `char*`, not `int*`
+fail_compilation/chkformat.d(233): Deprecation: argument `0L` for format specification `"%d"` must be `int*`, not `long`
+fail_compilation/chkformat.d(234): Deprecation: argument `0L` for format specification `"%d"` must be `int*`, not `long`
+---
+*/
+
+
+import core.stdc.stdio;
+
+#line 100
+
+void test1() {  printf("%*.*d\n", 0L, 1L, 2L); }
+//void test2() { }
+//void test3() {  printf("%ld\n", 3.0); }
+void test4() {  printf("%lld\n", 4); }
+void test5() {  printf("%jd\n", 5); }
+void test6() {  printf("%zd\n", 6.0); }
+void test7() {  printf("%td\n", 7.0); }
+void test8() {  printf("%g\n", 8.0L); }
+void test9() {  printf("%Lg\n", 9.0); }
+void test10() {  printf("%p\n", 10); }
+void test11() { uint u; printf("%n\n", &u); }
+//void test12() { ushort u; printf("%ln\n", &u); }
+void test13() { int u; printf("%lln\n", &u); }
+void test14() { int u; printf("%hn\n", &u); }
+void test15() { int u; printf("%hhn\n", &u); }
+void test16() { printf("%c\n", 16L); }
+void test17() { printf("%c\n", 17L); }
+void test18() { int u; printf("%s\n", &u); }
+void test19() { int u; printf("%ls\n", &u); }
+//void test20() { int u; char[] s; sprintf(&s[0], "%d\n", &u); }
+//void test21() { int u; fprintf(null, "%d\n", &u); }
+
+#line 200
+
+void test31() {  scanf("%d\n", 0L); }
+void test32() {  int i; scanf("%d %d\n", &i); }
+void test33() {  scanf("%d%*c\n", 0L); }
+void test34() {  scanf("%3u\n", 0L); }
+void test35() {  uint u; scanf("%200u%*s\n", u); }
+void test36() {  scanf("%hhd\n", 3.0); }
+void test37() {  scanf("%hd\n", 4); }
+//void test38() {  scanf("%ld\n", 3.0); }
+void test39() {  scanf("%lld\n", 4); }
+void test40() { scanf("%jd\n", 5); }
+void test41() { scanf("%zd\n", 6.0); }
+void test42() { scanf("%td\n", 7.0); }
+void test43() { scanf("%Ld\n", 0); }
+void test44() { scanf("%u\n", 0); }
+void test45() { scanf("%hhu\n", 0); }
+void test46() { scanf("%hu\n", 0); }
+//void test47() { scanf("%lu\n", 0); }
+void test48() { scanf("%llu\n", 0); }
+void test49() { scanf("%ju\n", 0); }
+void test50() { scanf("%zu\n", 0); }
+void test51() { scanf("%tu\n", 0); }
+void test52() { scanf("%g\n", 8.0L); }
+void test53() { scanf("%lg\n", 8.0L); }
+void test54() { scanf("%Lg\n", 9.0); }
+void test55() { int u; scanf("%s\n", &u); }
+void test56() { int u; scanf("%ls\n", &u); }
+void test57() { void* v; scanf("%p\n", v); }
+void test58() { ushort u; scanf("%n\n", &u); }
+void test59() { int u; scanf("%hhn\n", &u); }
+void test60() { int u; scanf("%[n", &u); }
+void test61() { int u; scanf("%]\n", &u); }
+void test62() { int u; scanf("%90s\n", &u); }
+void test63() { sscanf("1234", "%d\n", 0L); }
+void test64() { fscanf(null, "%d\n", 0L); }
+
+/* TEST_OUTPUT:
+---
+fail_compilation/chkformat.d(301): Deprecation: format specifier `"%K"` is invalid
+fail_compilation/chkformat.d(302): Deprecation: format specifier `"%Q"` is invalid
+---
+*/
+
+import core.stdc.stdarg;
+
+#line 300
+
+void test301() { va_list vargs; vprintf("%K", vargs); }
+void test302() { va_list vargs; vscanf("%Q", vargs); }
+
+// TODO - C++ 11 only:
+//void test() { vscanf(); }
+//void test() { vfscanf(); }
+//void test() { vsscanf(); }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/cppmangle.d b/gcc/testsuite/gdc.test/fail_compilation/cppmangle.d
index b8b2f03f019..ca9ed9a71a7 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/cppmangle.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/cppmangle.d
@@ -2,7 +2,7 @@
 TEST_OUTPUT:
 ---
 fail_compilation/cppmangle.d(10): Error: invalid zero length C++ namespace
-fail_compilation/cppmangle.d(14): Error: expected valid identifer for C++ namespace but got `0num`
+fail_compilation/cppmangle.d(14): Error: expected valid identifier for C++ namespace but got `0num`
 fail_compilation/cppmangle.d(18): Error: string expected following `,` for C++ namespace, not `)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag11819b.d b/gcc/testsuite/gdc.test/fail_compilation/diag11819b.d
index 2280691abf6..a5d6a14212e 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag11819b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag11819b.d
@@ -14,7 +14,7 @@ fail_compilation/diag11819b.d(37): Error: unrecognized trait `AllMembers`, did y
 fail_compilation/diag11819b.d(38): Error: unrecognized trait `DerivedMembers`, did you mean `derivedMembers`?
 fail_compilation/diag11819b.d(39): Error: unrecognized trait `IsSame`, did you mean `isSame`?
 fail_compilation/diag11819b.d(40): Error: unrecognized trait `Compiles`, did you mean `compiles`?
-fail_compilation/diag11819b.d(41): Error: unrecognized trait `Parameters`, did you mean `parameters`?
+fail_compilation/diag11819b.d(41): Error: unrecognized trait `Parameters`
 fail_compilation/diag11819b.d(42): Error: unrecognized trait `GetAliasThis`, did you mean `getAliasThis`?
 fail_compilation/diag11819b.d(43): Error: unrecognized trait `GetAttributes`, did you mean `getAttributes`?
 fail_compilation/diag11819b.d(44): Error: unrecognized trait `GetFunctionAttributes`, did you mean `getFunctionAttributes`?
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag13082.d b/gcc/testsuite/gdc.test/fail_compilation/diag13082.d
index 13259cef004..7360a3df62f 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag13082.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag13082.d
@@ -1,8 +1,10 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag13082.d(22): Error: constructor diag13082.C.this (int a) is not callable using argument types (string)
-fail_compilation/diag13082.d(23): Error: constructor diag13082.S.this (int a) is not callable using argument types (string)
+fail_compilation/diag13082.d(24): Error: constructor `diag13082.C.this(int a)` is not callable using argument types `(string)`
+fail_compilation/diag13082.d(24):        cannot pass argument `b` of type `string` to parameter `int a`
+fail_compilation/diag13082.d(25): Error: constructor `diag13082.S.this(int a)` is not callable using argument types `(string)`
+fail_compilation/diag13082.d(25):        cannot pass argument `b` of type `string` to parameter `int a`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag16271.d b/gcc/testsuite/gdc.test/fail_compilation/diag16271.d
new file mode 100644
index 00000000000..b85dc8d21bb
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag16271.d
@@ -0,0 +1,12 @@
+/*
+TEST_OUTPUT
+---
+fail_compilation/diag16271.d(10): Error: found `x` when expecting function literal following `ref`
+---
+*/
+
+void main()
+{
+    auto fun = ref x;
+}
+
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag8101.d b/gcc/testsuite/gdc.test/fail_compilation/diag8101.d
index 6fc38099048..3b2401ad8cf 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag8101.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag8101.d
@@ -1,29 +1,30 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag8101.d(56): Error: function diag8101.f_0 (int) is not callable using argument types ()
-fail_compilation/diag8101.d(57): Error: none of the overloads of 'f_1' are callable using argument types (), candidates are:
-fail_compilation/diag8101.d(32):        diag8101.f_1(int)
-fail_compilation/diag8101.d(33):        diag8101.f_1(int, int)
-fail_compilation/diag8101.d(58): Error: none of the overloads of 'f_2' are callable using argument types (), candidates are:
-fail_compilation/diag8101.d(35):        diag8101.f_2(int)
-fail_compilation/diag8101.d(36):        diag8101.f_2(int, int)
-fail_compilation/diag8101.d(37):        diag8101.f_2(int, int, int)
-fail_compilation/diag8101.d(38):        diag8101.f_2(int, int, int, int)
-fail_compilation/diag8101.d(39):        diag8101.f_2(int, int, int, int, int)
-fail_compilation/diag8101.d(58):        ... (1 more, -v to show) ...
-fail_compilation/diag8101.d(60): Error: template diag8101.t_0 cannot deduce function from argument types !()(), candidates are:
-fail_compilation/diag8101.d(42):        diag8101.t_0(T1)()
-fail_compilation/diag8101.d(61): Error: template diag8101.t_1 cannot deduce function from argument types !()(), candidates are:
-fail_compilation/diag8101.d(44):        diag8101.t_1(T1)()
-fail_compilation/diag8101.d(45):        diag8101.t_1(T1, T2)()
-fail_compilation/diag8101.d(62): Error: template diag8101.t_2 cannot deduce function from argument types !()(), candidates are:
-fail_compilation/diag8101.d(47):        diag8101.t_2(T1)()
-fail_compilation/diag8101.d(48):        diag8101.t_2(T1, T2)()
-fail_compilation/diag8101.d(49):        diag8101.t_2(T1, T2, T3)()
-fail_compilation/diag8101.d(50):        diag8101.t_2(T1, T2, T3, T4)()
-fail_compilation/diag8101.d(51):        diag8101.t_2(T1, T2, T3, T4, T5)()
-fail_compilation/diag8101.d(62):        ... (1 more, -v to show) ...
+fail_compilation/diag8101.d(57): Error: function `diag8101.f_0(int)` is not callable using argument types `()`
+fail_compilation/diag8101.d(57):        missing argument for parameter #1: `int`
+fail_compilation/diag8101.d(58): Error: none of the overloads of `f_1` are callable using argument types `()`, candidates are:
+fail_compilation/diag8101.d(33):        `diag8101.f_1(int)`
+fail_compilation/diag8101.d(34):        `diag8101.f_1(int, int)`
+fail_compilation/diag8101.d(59): Error: none of the overloads of `f_2` are callable using argument types `()`, candidates are:
+fail_compilation/diag8101.d(36):        `diag8101.f_2(int)`
+fail_compilation/diag8101.d(37):        `diag8101.f_2(int, int)`
+fail_compilation/diag8101.d(38):        `diag8101.f_2(int, int, int)`
+fail_compilation/diag8101.d(39):        `diag8101.f_2(int, int, int, int)`
+fail_compilation/diag8101.d(40):        `diag8101.f_2(int, int, int, int, int)`
+fail_compilation/diag8101.d(59):        ... (1 more, -v to show) ...
+fail_compilation/diag8101.d(61): Error: template `diag8101.t_0` cannot deduce function from argument types `!()()`, candidates are:
+fail_compilation/diag8101.d(43):        `diag8101.t_0(T1)()`
+fail_compilation/diag8101.d(62): Error: template `diag8101.t_1` cannot deduce function from argument types `!()()`, candidates are:
+fail_compilation/diag8101.d(45):        `diag8101.t_1(T1)()`
+fail_compilation/diag8101.d(46):        `diag8101.t_1(T1, T2)()`
+fail_compilation/diag8101.d(63): Error: template `diag8101.t_2` cannot deduce function from argument types `!()()`, candidates are:
+fail_compilation/diag8101.d(48):        `diag8101.t_2(T1)()`
+fail_compilation/diag8101.d(49):        `diag8101.t_2(T1, T2)()`
+fail_compilation/diag8101.d(50):        `diag8101.t_2(T1, T2, T3)()`
+fail_compilation/diag8101.d(51):        `diag8101.t_2(T1, T2, T3, T4)()`
+fail_compilation/diag8101.d(52):        `diag8101.t_2(T1, T2, T3, T4, T5)()`
+fail_compilation/diag8101.d(63):        ... (1 more, -v to show) ...
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag8101b.d b/gcc/testsuite/gdc.test/fail_compilation/diag8101b.d
index a3baa272fae..228ba169e8e 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag8101b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag8101b.d
@@ -1,14 +1,15 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag8101b.d(26): Error: none of the overloads of 'foo' are callable using argument types (double), candidates are:
-fail_compilation/diag8101b.d(17):        diag8101b.S.foo(int _param_0)
-fail_compilation/diag8101b.d(18):        diag8101b.S.foo(int _param_0, int _param_1)
-fail_compilation/diag8101b.d(28): Error: function diag8101b.S.bar (int _param_0) is not callable using argument types (double)
-fail_compilation/diag8101b.d(31): Error: none of the overloads of 'foo' are callable using a const object, candidates are:
-fail_compilation/diag8101b.d(17):        diag8101b.S.foo(int _param_0)
-fail_compilation/diag8101b.d(18):        diag8101b.S.foo(int _param_0, int _param_1)
-fail_compilation/diag8101b.d(33): Error: mutable method diag8101b.S.bar is not callable using a const object
+fail_compilation/diag8101b.d(27): Error: none of the overloads of `foo` are callable using argument types `(double)`, candidates are:
+fail_compilation/diag8101b.d(18):        `diag8101b.S.foo(int _param_0)`
+fail_compilation/diag8101b.d(19):        `diag8101b.S.foo(int _param_0, int _param_1)`
+fail_compilation/diag8101b.d(29): Error: function `diag8101b.S.bar(int _param_0)` is not callable using argument types `(double)`
+fail_compilation/diag8101b.d(29):        cannot pass argument `1.00000` of type `double` to parameter `int _param_0`
+fail_compilation/diag8101b.d(32): Error: none of the overloads of `foo` are callable using a `const` object, candidates are:
+fail_compilation/diag8101b.d(18):        `diag8101b.S.foo(int _param_0)`
+fail_compilation/diag8101b.d(19):        `diag8101b.S.foo(int _param_0, int _param_1)`
+fail_compilation/diag8101b.d(34): Error: mutable method `diag8101b.S.bar` is not callable using a `const` object
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag9420.d b/gcc/testsuite/gdc.test/fail_compilation/diag9420.d
index dfaf7c84a09..6b2577d910e 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag9420.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag9420.d
@@ -1,7 +1,8 @@
 /*
 TEST_OUTPUT
 ---
-fail_compilation/diag9420.d(20): Error: function diag9420.S.t3!().tx () is not callable using argument types (int)
+fail_compilation/diag9420.d(21): Error: function `diag9420.S.t3!().tx()` is not callable using argument types `(int)`
+fail_compilation/diag9420.d(21):        expected 0 argument(s), not 1
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail11038.d b/gcc/testsuite/gdc.test/fail_compilation/fail11038.d
new file mode 100644
index 00000000000..8f39ccc51eb
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail11038.d
@@ -0,0 +1,17 @@
+// https://issues.dlang.org/show_bug.cgi?id=11038
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail11038.d(16): Error: `writeln` is not defined, perhaps `import std.stdio;` is needed?
+---
+*/
+
+static
+{
+    import std.stdio;
+}
+
+void main()
+{
+    writeln("foo");  // compiles
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail11445.d b/gcc/testsuite/gdc.test/fail_compilation/fail11445.d
index a3cfc11ed19..ed3f226e4f2 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail11445.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail11445.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail11445.d(11): Error: incompatible types for ((a) + (b)): 'double[string]' and 'double[string]'
+fail_compilation/fail11445.d(11): Error: incompatible types for ((a) + (b)): both operands are of type 'double[string]'
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail15361.d b/gcc/testsuite/gdc.test/fail_compilation/fail15361.d
new file mode 100644
index 00000000000..8e5f9800a81
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail15361.d
@@ -0,0 +1,8 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail15361.d(8): Error: unexpected `(` after `errorize`, inside `is` expression. Try enclosing the contents of `is` with a `typeof` expression
+---
+*/
+
+enum isErrorizable(T) = is(errorize(T.init));
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail15896.d b/gcc/testsuite/gdc.test/fail_compilation/fail15896.d
new file mode 100644
index 00000000000..e52503d0975
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail15896.d
@@ -0,0 +1,18 @@
+// REQUIRED_ARGS: -de
+// EXTRA_FILES: imports/imp15896.d
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail15896.d(11): Error: module `imports.imp15896` member `thebar` is not visible from module `fail15896`
+fail_compilation/fail15896.d(11): Error: module `imports.imp15896` member `packagebar` is not visible from module `fail15896`
+---
+*/
+
+import imports.imp15896 : thebar, packagebar;
+
+int func()
+{
+    thebar +=1;
+    packagebar += 1;
+    return 0;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail17630.d b/gcc/testsuite/gdc.test/fail_compilation/fail17630.d
new file mode 100644
index 00000000000..9b6ed82d4b3
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail17630.d
@@ -0,0 +1,15 @@
+// REQUIRED_ARGS: -de
+// EXTRA_FILES: imports/a17630.d
+// EXTRA_SOURCES: imports/b17630.d
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail17630.d(13): Error: module `a17630` import `Erase` not found, did you mean variable `b17630.Erase`?
+---
+*/
+
+void main()
+{
+    import imports.a17630 : Erase;
+    assert(Erase == 2);
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail18219.d b/gcc/testsuite/gdc.test/fail_compilation/fail18219.d
new file mode 100644
index 00000000000..f3ec6806f6b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail18219.d
@@ -0,0 +1,20 @@
+// EXTRA_SOURCES: imports/b18219.d
+// EXTRA_FILES: imports/a18219.d
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail18219.d(16): Error: no property `Foobar` for type `AST`, did you mean `b18219.Foobar`?
+fail_compilation/fail18219.d(17): Error: no property `Bar` for type `a18219.AST`
+fail_compilation/fail18219.d(18): Error: no property `fun` for type `AST`, did you mean `b18219.fun`?
+fail_compilation/fail18219.d(19): Error: no property `Foobar` for type `AST`, did you mean `b18219.Foobar`?
+---
+*/
+import imports.a18219;
+
+void main()
+{
+    AST.Foobar t;
+    AST.Bar l;
+    AST.fun();
+    AST.Foobar.smeth();
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19107.d b/gcc/testsuite/gdc.test/fail_compilation/fail19107.d
new file mode 100644
index 00000000000..c748650b2e4
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19107.d
@@ -0,0 +1,21 @@
+// REQUIRED_ARGS:
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test19107.d(20): Error: template `test19107.all` cannot deduce function from argument types `!((c) => c)(string[])`, candidates are:
+fail_compilation/test19107.d(14):        `test19107.all(alias pred, T)(T t) if (is(typeof(I!pred(t))))`
+---
+*/
+
+// https://issues.dlang.org/show_bug.cgi?id=19107
+
+import imports.test19107b;
+
+void all(alias pred, T)(T t)
+    if (is(typeof(I!pred(t))))
+{ }
+
+void main(string[] args)
+{
+    args.all!(c => c);
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail263.d b/gcc/testsuite/gdc.test/fail_compilation/fail263.d
index f7dfe21e336..8cf9b20ac2b 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail263.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail263.d
@@ -1,7 +1,8 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail263.d(18): Error: function fail263.f (byte* p) is not callable using argument types (const(byte)*)
+fail_compilation/fail263.d(19): Error: function `fail263.f(byte* p)` is not callable using argument types `(const(byte)*)`
+fail_compilation/fail263.d(19):        cannot pass argument `cast(const(byte)*)A` of type `const(byte)*` to parameter `byte* p`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail3.d b/gcc/testsuite/gdc.test/fail_compilation/fail3.d
index 332e561cd0c..0b7516cbc06 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail3.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail3.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail3.d(40): Error: incompatible types for ((a) + (b)): 'vec2' and 'vec2'
+fail_compilation/fail3.d(41): Error: incompatible types for ((a) + (b)): both operands are of type 'vec2'
 ---
 */
 
@@ -14,6 +14,7 @@ template vector(T)
         T x, y;
     }
 
+    // not struct member
     vec2 opAdd(vec2 a, vec2 b)
     {
         vec2 r;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail322.d b/gcc/testsuite/gdc.test/fail_compilation/fail322.d
index 0ffa15a4875..491111fe610 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail322.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail322.d
@@ -1,13 +1,18 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail322.d(10): Error: function fail322.digestToString2 (ref char[16] digest) is not callable using argument types (string)
+fail_compilation/fail322.d(13): Error: function `fail322.digestToString2(ref char[16] digest)` is not callable using argument types `(string)`
+fail_compilation/fail322.d(13):        cannot pass rvalue argument `"1234567890123456"` of type `string` to parameter `ref char[16] digest`
+fail_compilation/fail322.d(15): Error: function `fail322.digestToString2(ref char[16] digest)` is not callable using argument types `(const(char[16]))`
+fail_compilation/fail322.d(15):        cannot pass argument `s` of type `const(char[16])` to parameter `ref char[16] digest`
 ---
 */
 
 void main()
 {
     digestToString2("1234567890123456");
+    const char[16] s;
+    digestToString2(s);
 }
 
 void digestToString2(ref char[16] digest)
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail332.d b/gcc/testsuite/gdc.test/fail_compilation/fail332.d
index 03f3706d696..91f80464705 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail332.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail332.d
@@ -1,15 +1,56 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail332.d(14): Error: function fail332.foo (int _param_0, ...) is not callable using argument types ()
+fail_compilation/fail332.d(22): Error: function `fail332.foo(int _param_0, ...)` is not callable using argument types `()`
+fail_compilation/fail332.d(22):        missing argument for parameter #1: `int _param_0`
+fail_compilation/fail332.d(23): Error: function `fail332.foo(int _param_0, ...)` is not callable using argument types `(typeof(null))`
+fail_compilation/fail332.d(23):        cannot pass argument `null` of type `typeof(null)` to parameter `int _param_0`
+fail_compilation/fail332.d(25): Error: function `fail332.baz(int[] _param_0...)` is not callable using argument types `(string)`
+fail_compilation/fail332.d(25):        cannot pass argument `""` of type `string` to parameter `int[] _param_0...`
+fail_compilation/fail332.d(26): Error: function `fail332.baz(int[] _param_0...)` is not callable using argument types `(int, typeof(null))`
+fail_compilation/fail332.d(26):        cannot pass argument `null` of type `typeof(null)` to parameter `int[] _param_0...`
 ---
 */
 
 import core.vararg;
 
 void foo(int, ...) {}
+void baz(int[]...) {}
 
-void bar()
+void test()
 {
     foo();
+    foo(null);
+
+    baz("");
+    baz(3, null);
+}
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail332.d(50): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `()`
+fail_compilation/fail332.d(50):        missing argument for parameter #1: `Object`
+fail_compilation/fail332.d(51): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `(int)`
+fail_compilation/fail332.d(51):        cannot pass argument `4` of type `int` to parameter `Object`
+fail_compilation/fail332.d(52): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `(typeof(null))`
+fail_compilation/fail332.d(52):        expected 2 variadic argument(s), not 0
+fail_compilation/fail332.d(53): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `(typeof(null), int)`
+fail_compilation/fail332.d(53):        expected 2 variadic argument(s), not 1
+fail_compilation/fail332.d(54): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `(typeof(null), int, string)`
+fail_compilation/fail332.d(54):        cannot pass argument `""` of type `string` to parameter `int[2]...`
+fail_compilation/fail332.d(55): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `(typeof(null), int, int, int)`
+fail_compilation/fail332.d(55):        expected 2 variadic argument(s), not 3
+---
+*/
+void bar(Object, int[2]...);
+
+void test2()
+{
+    bar();
+    bar(4);
+    bar(null);
+    bar(null, 2);
+    bar(null, 2, "");
+    bar(null, 2,3,4);
 }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail347.d b/gcc/testsuite/gdc.test/fail_compilation/fail347.d
index 03ae7036d81..61718df59e2 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail347.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail347.d
@@ -2,7 +2,7 @@
 TEST_OUTPUT:
 ---
 fail_compilation/fail347.d(21): Error: undefined identifier `bbr`, did you mean variable `bar`?
-fail_compilation/fail347.d(22): Error: no property 'ofo' for type 'S', did you mean 'foo'?
+fail_compilation/fail347.d(22): Error: no property 'ofo' for type 'S', did you mean 'fail347.S.foo'?
 fail_compilation/fail347.d(23): Error: undefined identifier `strlenx`, did you mean function `strlen`?
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail53.d b/gcc/testsuite/gdc.test/fail_compilation/fail53.d
index 2570dd8939c..556896c76c3 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail53.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail53.d
@@ -1,7 +1,8 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail53.d(25): Error: function object.Object.opEquals (Object o) is not callable using argument types (int)
+fail_compilation/fail53.d(26): Error: function `object.Object.opEquals(Object o)` is not callable using argument types `(int)`
+fail_compilation/fail53.d(26):        cannot pass argument `i` of type `int` to parameter `Object o`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail55.d b/gcc/testsuite/gdc.test/fail_compilation/fail55.d
index 57117d86ee4..290c2b6695f 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail55.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail55.d
@@ -1,7 +1,8 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail55.d(22): Error: function object.Object.opCmp (Object o) is not callable using argument types (int)
+fail_compilation/fail55.d(23): Error: function `object.Object.opCmp(Object o)` is not callable using argument types `(int)`
+fail_compilation/fail55.d(23):        cannot pass argument `0` of type `int` to parameter `Object o`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail79.d b/gcc/testsuite/gdc.test/fail_compilation/fail79.d
index 46581d9d43c..da06984e9ef 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail79.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail79.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail79.d(13): Error: incompatible types for ((& a) + (& b)): 'int*' and 'int*'
+fail_compilation/fail79.d(13): Error: incompatible types for ((& a) + (& b)): both operands are of type 'int*'
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail99.d b/gcc/testsuite/gdc.test/fail_compilation/fail99.d
index da87ed66acb..c147b810ee6 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail99.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail99.d
@@ -1,7 +1,8 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail99.d(12): Error: delegate dg (int) is not callable using argument types ()
+fail_compilation/fail99.d(13): Error: delegate `dg(int)` is not callable using argument types `()`
+fail_compilation/fail99.d(13):        missing argument for parameter #1: `int`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fix21585.d b/gcc/testsuite/gdc.test/fail_compilation/fix21585.d
new file mode 100644
index 00000000000..48c74cb3698
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fix21585.d
@@ -0,0 +1,19 @@
+/* https://issues.dlang.org/show_bug.cgi?id=21585
+TEST_OUTPUT:
+---
+fail_compilation/fix21585.d(103): Error: expected 1 arguments for `toType` but had 0
+fail_compilation/fix21585.d(104): Error: expression expected as second argument of __traits `toType`
+fail_compilation/fix21585.d(105): Error: `string` expected for __traits(toType, string), not `(1)` of type `int`
+fail_compilation/fix21585.d(106): Error: cannot determine `__traits(toType, "hello betty")`
+---
+*/
+
+#line 100
+
+template Type(T) { alias Type = T; }
+
+alias T1 = Type!(__traits(toType));
+alias T2 = Type!(__traits(toType, int));
+alias T3 = Type!(__traits(toType, 1));
+alias T4 = Type!(__traits(toType, "hello betty"));
+
diff --git a/gcc/testsuite/gdc.test/fail_compilation/format.d b/gcc/testsuite/gdc.test/fail_compilation/format.d
new file mode 100644
index 00000000000..3a2422791f7
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/format.d
@@ -0,0 +1,44 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/format.d(101): Error: function `format.printf1` `pragma(printf)` functions must be `extern(C) void printf1([parameters...], const(char)*, ...)` not `void(const(char)*, ...)`
+fail_compilation/format.d(102): Error: function `format.printf2` `pragma(printf)` functions must be `extern(C) int printf2([parameters...], const(char)*, ...)` not `extern (C) int(const(int)*, ...)`
+fail_compilation/format.d(103): Error: function `format.printf3` `pragma(printf)` functions must be `extern(C) int printf3([parameters...], const(char)*, va_list)`
+fail_compilation/format.d(104): Error: function `format.printf4` `pragma(printf)` functions must be `extern(C) int printf4([parameters...], const(char)*, ...)` not `extern (C) int(const(char)*, int, ...)`
+---
+ */
+
+#line 100
+
+pragma(printf)           void printf1(const(char)*, ...);
+pragma(printf) extern (C) int printf2(const(int )*, ...);
+pragma(printf) extern (C) int printf3(const(char)*);
+pragma(printf) extern (C) int printf4(const(char)*, int, ...);
+
+pragma(printf) extern (C) int printf5(const(char)*, ...);
+pragma(printf) extern (C) int printf6(immutable(char)*, ...);
+pragma(printf) extern (C) int printf7(char*, ...);
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/format.d(203): Error: function `format.vprintf1` `pragma(printf)` functions must be `extern(C) void vprintf1([parameters...], const(char)*, va_list)`
+fail_compilation/format.d(204): Error: function `format.vprintf2` `pragma(printf)` functions must be `extern(C) int vprintf2([parameters...], const(char)*, va_list)`
+fail_compilation/format.d(205): Error: function `format.vprintf3` `pragma(printf)` functions must be `extern(C) int vprintf3([parameters...], const(char)*, va_list)`
+fail_compilation/format.d(206): Error: function `format.vprintf4` `pragma(printf)` functions must be `extern(C) int vprintf4([parameters...], const(char)*, va_list)`
+---
+ */
+
+#line 200
+
+import core.stdc.stdarg;
+
+pragma(printf)           void vprintf1(const(char)*, va_list);
+pragma(printf) extern (C) int vprintf2(const(int )*, va_list);
+pragma(printf) extern (C) int vprintf3(const(char)*);
+pragma(printf) extern (C) int vprintf4(const(char)*, int, va_list);
+
+pragma(printf) extern (C) int vprintf5(const(char)*, va_list);
+pragma(printf) extern (C) int vprintf6(immutable(char)*, va_list);
+pragma(printf) extern (C) int vprintf7(char*, va_list);
+
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice10598.d b/gcc/testsuite/gdc.test/fail_compilation/ice10598.d
new file mode 100644
index 00000000000..ba6cdf73211
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice10598.d
@@ -0,0 +1,10 @@
+// REQUIRED_ARGS: -de
+// EXTRA_SOURCES: imports/ice10598a.d imports/ice10598b.d
+/* TEST_OUTPUT:
+---
+fail_compilation/imports/ice10598a.d(5): Deprecation: module imports.ice10598b is not accessible here, perhaps add 'static import imports.ice10598b;'
+fail_compilation/imports/ice10598a.d(5): Deprecation: module imports.ice10598b is not accessible here, perhaps add 'static import imports.ice10598b;'
+---
+*/
+
+void main() {}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice10922.d b/gcc/testsuite/gdc.test/fail_compilation/ice10922.d
index 1ddad18eba5..9eeb622300a 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice10922.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice10922.d
@@ -1,7 +1,8 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice10922.d(9): Error: function ice10922.__lambda4 (const(uint) n) is not callable using argument types ()
+fail_compilation/ice10922.d(10): Error: function `ice10922.__lambda4(const(uint) n)` is not callable using argument types `()`
+fail_compilation/ice10922.d(10):        missing argument for parameter #1: `const(uint) n`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice12497.d b/gcc/testsuite/gdc.test/fail_compilation/ice12497.d
deleted file mode 100644
index ab95e81d5b7..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/ice12497.d
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
-TEST_OUTPUT:
----
-fail_compilation/ice12497.d(15): Error: string expected for argument to mixin, not (foo()) of type void
-fail_compilation/ice12497.d(17): Error: string expected for argument to mixin, not (foo()) of type void
----
-*/
-
-void foo() {}
-
-void main()
-{
-    struct S
-    {
-        mixin(foo());   // MixinDeclaration
-    }
-    mixin(foo());       // MixinStatement
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice12501.d b/gcc/testsuite/gdc.test/fail_compilation/ice12501.d
index f57980d7bc3..2c45c8a359d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice12501.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice12501.d
@@ -1,9 +1,11 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice12501.d(29): Error: function ice12501.foo (int value) is not callable using argument types (int, int)
-fail_compilation/ice12501.d(29): Error: function ice12501.foo (int value) is not callable using argument types (int, int)
-fail_compilation/ice12501.d(43): Error: template instance ice12501.reduce!(foo, foo).reduce!(Tuple!(int, int), int[]) error instantiating
+fail_compilation/ice12501.d(31): Error: function `ice12501.foo(int value)` is not callable using argument types `(int, int)`
+fail_compilation/ice12501.d(31):        expected 1 argument(s), not 2
+fail_compilation/ice12501.d(31): Error: function `ice12501.foo(int value)` is not callable using argument types `(int, int)`
+fail_compilation/ice12501.d(31):        expected 1 argument(s), not 2
+fail_compilation/ice12501.d(45): Error: template instance `ice12501.reduce!(foo, foo).reduce!(Tuple!(int, int), int[])` error instantiating
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice14907.d b/gcc/testsuite/gdc.test/fail_compilation/ice14907.d
new file mode 100644
index 00000000000..6d9edf0c903
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice14907.d
@@ -0,0 +1,22 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/ice14907.d(14): Error: struct ice14907.S(int v = S) recursive template expansion
+fail_compilation/ice14907.d(19):        while looking for match for `S!()`
+fail_compilation/ice14907.d(15): Error: template ice14907.f(int v = f)() recursive template expansion
+fail_compilation/ice14907.d(20):        while looking for match for `f!()`
+fail_compilation/ice14907.d(15): Error: template ice14907.f(int v = f)() recursive template expansion
+fail_compilation/ice14907.d(21): Error: template `ice14907.f` cannot deduce function from argument types `!()()`, candidates are:
+fail_compilation/ice14907.d(15):        `ice14907.f(int v = f)()`
+---
+*/
+
+struct S(int v = S) {}
+void f(int v = f)() {}
+
+void main()
+{
+    S!() s;     // OK <- ICE
+    f!()();     // OK <- ICE
+    f();        // OK <- ICE
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice14923.d b/gcc/testsuite/gdc.test/fail_compilation/ice14923.d
index 86e3b2a2071..e3b677e2cdb 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice14923.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice14923.d
@@ -1,8 +1,9 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice14923.d(21): Error: function ice14923.parse (C a) is not callable using argument types (A)
-fail_compilation/ice14923.d(21):        instantiated from here: bar!((b) => parse(b))
+fail_compilation/ice14923.d(22): Error: function `ice14923.parse(C a)` is not callable using argument types `(A)`
+fail_compilation/ice14923.d(22):        cannot pass argument `b` of type `ice14923.A` to parameter `C a`
+fail_compilation/ice14923.d(22):        instantiated from here: `bar!((b) => parse(b))`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice8255.d b/gcc/testsuite/gdc.test/fail_compilation/ice8255.d
index d98e38ad9a4..0db3abc395f 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice8255.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice8255.d
@@ -1,8 +1,9 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice8255.d(10): Error: function ice8255.F!(G).F.f (ref G _param_0) is not callable using argument types (G)
-fail_compilation/ice8255.d(10):        while evaluating pragma(msg, F().f(G()))
+fail_compilation/ice8255.d(11): Error: function `ice8255.F!(G).F.f(ref G _param_0)` is not callable using argument types `(G)`
+fail_compilation/ice8255.d(11):        cannot pass rvalue argument `G()` of type `G` to parameter `ref G _param_0`
+fail_compilation/ice8255.d(11):        while evaluating `pragma(msg, F().f(G()))`
 ---
 */
 struct G {}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice9540.d b/gcc/testsuite/gdc.test/fail_compilation/ice9540.d
index d6c9cdae0f3..f95cb974c79 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice9540.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice9540.d
@@ -1,8 +1,9 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice9540.d(34): Error: function ice9540.A.test.AddFront!(this, f).AddFront.dg (int _param_0) is not callable using argument types ()
-fail_compilation/ice9540.d(25): Error: template instance ice9540.A.test.AddFront!(this, f) error instantiating
+fail_compilation/ice9540.d(35): Error: function `ice9540.A.test.AddFront!(this, f).AddFront.dg(int _param_0)` is not callable using argument types `()`
+fail_compilation/ice9540.d(35):        missing argument for parameter #1: `int _param_0`
+fail_compilation/ice9540.d(26): Error: template instance `ice9540.A.test.AddFront!(this, f)` error instantiating
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/a17630.d b/gcc/testsuite/gdc.test/fail_compilation/imports/a17630.d
new file mode 100644
index 00000000000..c10484175d4
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/a17630.d
@@ -0,0 +1,3 @@
+module a17630;
+
+import b17630;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/a18219.d b/gcc/testsuite/gdc.test/fail_compilation/imports/a18219.d
new file mode 100644
index 00000000000..1a88493ef15
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/a18219.d
@@ -0,0 +1,6 @@
+module a18219;
+
+struct AST
+{
+    import b18219;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/b17630.d b/gcc/testsuite/gdc.test/fail_compilation/imports/b17630.d
new file mode 100644
index 00000000000..5ad5f9917f7
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/b17630.d
@@ -0,0 +1,3 @@
+module b17630;
+
+int Erase;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/b18219.d b/gcc/testsuite/gdc.test/fail_compilation/imports/b18219.d
new file mode 100644
index 00000000000..6008c8a1e21
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/b18219.d
@@ -0,0 +1,15 @@
+module b18219;
+
+class Foobar
+{
+    int a;
+    this(int a)
+    {
+        this.a = a;
+    }
+    static int smeth()
+    {
+        return 1;
+    }
+}
+void fun() {}
diff --git a/gcc/testsuite/gdc.test/compilable/imports/ice10598a.d b/gcc/testsuite/gdc.test/fail_compilation/imports/ice10598a.d
similarity index 100%
rename from gcc/testsuite/gdc.test/compilable/imports/ice10598a.d
rename to gcc/testsuite/gdc.test/fail_compilation/imports/ice10598a.d
diff --git a/gcc/testsuite/gdc.test/compilable/imports/ice10598b.d b/gcc/testsuite/gdc.test/fail_compilation/imports/ice10598b.d
similarity index 100%
rename from gcc/testsuite/gdc.test/compilable/imports/ice10598b.d
rename to gcc/testsuite/gdc.test/fail_compilation/imports/ice10598b.d
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/imp15896.d b/gcc/testsuite/gdc.test/fail_compilation/imports/imp15896.d
new file mode 100644
index 00000000000..d7edcc1bcc1
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/imp15896.d
@@ -0,0 +1,4 @@
+module imports.imp15896;
+
+private int thebar=4;
+package int packagebar=3;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/test21651b.d b/gcc/testsuite/gdc.test/fail_compilation/imports/test21651b.d
new file mode 100644
index 00000000000..4c85aade3bc
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/test21651b.d
@@ -0,0 +1,3 @@
+module imports.test21651b;
+
+alias T = int;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/issue16020.d b/gcc/testsuite/gdc.test/fail_compilation/issue16020.d
new file mode 100644
index 00000000000..75e3b9f0b81
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/issue16020.d
@@ -0,0 +1,13 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/issue16020.d(12): Error: user-defined attributes not allowed for `alias` declarations
+fail_compilation/issue16020.d(13): Error: semicolon expected to close `alias` declaration
+fail_compilation/issue16020.d(13): Error: declaration expected, not `(`
+---
+*/
+module issue16020;
+
+struct UDA{}
+alias Fun = @UDA void();
+alias FunTemplate = void(T)(T t);
diff --git a/gcc/testsuite/gdc.test/fail_compilation/mixintype2.d b/gcc/testsuite/gdc.test/fail_compilation/mixintype2.d
new file mode 100644
index 00000000000..b18627dd879
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/mixintype2.d
@@ -0,0 +1,16 @@
+
+/* TEST_OUTPUT:
+---
+fail_compilation/mixintype2.d(10): Error: alias `mixintype2.Foo.T` recursive alias declaration
+fail_compilation/mixintype2.d(16): Error: `mixin(0)` does not give a valid type
+---
+*/
+
+struct Foo {
+    alias T = mixin("T2");
+}
+alias T1 = mixin("Foo.T");
+alias T2 = mixin("T1");
+void func (T2 p) {}
+
+enum mixin(0) a = 0;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test16002.d b/gcc/testsuite/gdc.test/fail_compilation/test16002.d
deleted file mode 100644
index 80ae40b6b88..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/test16002.d
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
-REQUIRED_ARGS:
-PERMUTE_ARGS:
-TEST_OUTPUT:
----
-fail_compilation/test16002.d(100): Error: undefined identifier `imports.nonexistent`
-fail_compilation/test16002.d(101): Error: undefined identifier `imports.nonexistent`
----
-*/
-
-module test.fail_compilation.test16002;
-
-#line 100
-enum A = is(imports.nonexistent == package);
-enum B = is(imports.nonexistent == module);
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21651.d b/gcc/testsuite/gdc.test/fail_compilation/test21651.d
new file mode 100644
index 00000000000..a4d959f4626
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21651.d
@@ -0,0 +1,11 @@
+// REQUIRED_ARGS: -de
+// EXTRA_SOURCES: imports/test21651b.d
+/* TEST_OUTPUT:
+---
+fail_compilation/test21651.d(11): Deprecation: module imports.test21651b is not accessible here, perhaps add 'static import imports.test21651b;'
+---
+*/
+
+module imports.test21651;
+
+imports.test21651b.T a;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/warn12809.d b/gcc/testsuite/gdc.test/fail_compilation/warn12809.d
index 100f0fb9f33..06c998d6005 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/warn12809.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/warn12809.d
@@ -32,3 +32,44 @@ void test_unrachable3()
 
     int x = 1;      // unreachable
 }
+
+/********************************************/
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/warn12809.d(108): Warning: statement is not reachable
+fail_compilation/warn12809.d(115): Warning: statement is not reachable
+fail_compilation/warn12809.d(122): Warning: statement is not reachable
+Error: warnings are treated as errors
+       Use -wi if you wish to treat warnings only as informational.
+---
+*/
+
+#line 100
+
+alias noreturn = typeof(*null);
+
+noreturn foo();
+
+void test1(ref int i)
+{
+    foo();
+    i = 3;
+}
+
+void test2()
+{
+    try foo();
+    finally { }
+    int x = 1;
+}
+
+void test3()
+{
+    try { }
+    finally foo();
+    int x = 1;
+}
+
+
diff --git a/gcc/testsuite/gdc.test/runnable/funclit.d b/gcc/testsuite/gdc.test/runnable/funclit.d
index d45e3e6ddfd..c299badec15 100644
--- a/gcc/testsuite/gdc.test/runnable/funclit.d
+++ b/gcc/testsuite/gdc.test/runnable/funclit.d
@@ -1241,6 +1241,66 @@ void test15794()
     gun15794!(() => 0)(); // Line 26
 }
 
+/***************************************************/
+// https://issues.dlang.org/show_bug.cgi?id=16271
+
+ref auto funa16271(alias dg, T)(ref T a)
+{
+    return dg(a);
+}
+
+ref auto func16271(alias dg)()
+{
+    return dg();
+}
+
+void assign16271(T)(ref T a, T b)
+{
+    alias fun = ref (ref a) => a;
+    fun(a) = b;
+}
+
+void test16271()
+{
+    int x;
+    (ref () => x )() = 1;           assert(x == 1);
+    func16271!(ref () => x) = 2;    assert(x == 2);
+    assign16271(x, 3);              assert(x == 3);
+
+    alias alx = func16271!(ref () => x);
+    alx = 4;    assert(x == 4);
+
+    alias alf = ref (ref a) => a;
+    auto  auf = ref (ref int a) => a;
+    alf(x) = 5;    assert(x == 5);
+    auf(x) = 6;    assert(x == 6);
+
+    assert((funa16271!(         ref    (ref a) => a)(x) += 1) == 7 );
+    assert((funa16271!(function ref    (ref a) => a)(x) += 1) == 8 );
+    assert((funa16271!(function ref int(ref a) => a)(x) += 1) == 9 );
+    assert((funa16271!(delegate ref    (ref a) => a)(x) += 1) == 10);
+    assert((funa16271!(delegate ref int(ref a) => a)(x) += 1) == 11);
+    assert(x == 11);
+
+    alias aldc  = ref () @trusted @nogc { return x; };
+    auto  audc  = ref () @safe nothrow  { return x; };
+    alias alfuc = function ref (ref x) @trusted { return x; };
+    alias aldec = delegate ref () @trusted { return x; };
+    aldc()   = 12;    assert(x == 12);
+    audc()   = 13;    assert(x == 13);
+    alfuc(x) = 14;    assert(x == 14);
+    aldec()  = 15;    assert(x == 15);
+
+    template T()
+    {
+        int x;
+        alias alf = ref () => x;
+        auto auf = ref () => x;
+    }
+    T!().alf() = 1;  assert(T!().x == 1);
+    T!().auf() = 2;  assert(T!().x == 2);
+}
+
 /***************************************************/
 
 int main()
@@ -1299,6 +1359,7 @@ int main()
     test13879();
     test14745();
     test15794();
+    test16271();
 
     printf("Success\n");
     return 0;
diff --git a/gcc/testsuite/gdc.test/runnable/mangle.d b/gcc/testsuite/gdc.test/runnable/mangle.d
index e6d36453d88..9a8420aa20b 100644
--- a/gcc/testsuite/gdc.test/runnable/mangle.d
+++ b/gcc/testsuite/gdc.test/runnable/mangle.d
@@ -599,6 +599,12 @@ void fooB(void delegate (void delegate()) scope dg)
 //pragma(msg, fooB.mangleof);
 static assert(typeof(fooA).mangleof != typeof(fooB).mangleof);
 
+/***************************************************/
+
+alias noreturn = typeof(*null);
+alias fpd = noreturn function();
+int funcd(fpd);
+static assert(funcd.mangleof == "_D6mangle5funcdFPFZNnZi");
 
 /***************************************************/
 
diff --git a/gcc/testsuite/gdc.test/runnable/noreturn1.d b/gcc/testsuite/gdc.test/runnable/noreturn1.d
new file mode 100644
index 00000000000..447ea28294c
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/noreturn1.d
@@ -0,0 +1,74 @@
+alias noreturn = typeof(*null);
+
+extern (C) noreturn exit();
+
+/*****************************************/
+
+bool testf(int i)
+{
+    return i && assert(0);
+}
+
+bool testt(int i)
+{
+    return i || assert(0);
+}
+
+int testa(int i)
+{
+    if (i && exit())
+        return i + 1;
+    return i - 1;
+}
+
+int testb(int i)
+{
+    if (i || exit())
+        return i + 1;
+    return i - 1;
+}
+
+void test1()
+{
+    assert(testf(0) == false);
+    assert(testt(1) == true);
+
+    assert(testa(0) == -1);
+    assert(testb(3) == 4);
+}
+
+/*****************************************/
+
+noreturn exit1() { assert(0); }
+noreturn exit2() { assert(0); }
+
+
+int heli1(int i)
+{
+    return i ? exit1() : i - 1;
+}
+
+int heli2(int i)
+{
+    return i ? i - 1 : exit1();
+}
+
+noreturn heli3(int i)
+{
+    return i ? exit1() : exit2();
+}
+
+void test2()
+{
+    assert(heli1(0) == -1);
+    assert(heli2(1) == 0);
+}
+
+/*****************************************/
+
+int main()
+{
+    test1();
+    test2();
+    return 0;
+}
diff --git a/gcc/testsuite/gdc.test/runnable_cxx/cppa.d b/gcc/testsuite/gdc.test/runnable_cxx/cppa.d
index b9b4832991e..cb576ba59a8 100644
--- a/gcc/testsuite/gdc.test/runnable_cxx/cppa.d
+++ b/gcc/testsuite/gdc.test/runnable_cxx/cppa.d
@@ -571,18 +571,20 @@ void test13289()
     assert(f13289_cpp_test());
 }
 
+version(Posix)
+{
+    enum __c_wchar_t : dchar;
+}
+else version(Windows)
+{
+    enum __c_wchar_t : wchar;
+}
+alias wchar_t = __c_wchar_t;
 extern(C++)
 {
     bool f13289_cpp_test();
 
-    version(Posix)
-    {
-        dchar f13289_cpp_wchar_t(dchar);
-    }
-    else version(Windows)
-    {
-        wchar f13289_cpp_wchar_t(wchar);
-    }
+    wchar_t f13289_cpp_wchar_t(wchar_t);
 
     wchar f13289_d_wchar(wchar ch)
     {
@@ -606,6 +608,17 @@ extern(C++)
             return ch;
         }
     }
+    wchar_t f13289_d_wchar_t(wchar_t ch)
+    {
+        if (ch <= 'z' && ch >= 'a')
+        {
+            return cast(wchar_t)(ch - ('a' - 'A'));
+        }
+        else
+        {
+            return ch;
+        }
+    }
 }
 
 /****************************************/
diff --git a/gcc/testsuite/gdc.test/runnable_cxx/extra-files/cppb.cpp b/gcc/testsuite/gdc.test/runnable_cxx/extra-files/cppb.cpp
index 587145c61c3..823c6603878 100644
--- a/gcc/testsuite/gdc.test/runnable_cxx/extra-files/cppb.cpp
+++ b/gcc/testsuite/gdc.test/runnable_cxx/extra-files/cppb.cpp
@@ -412,8 +412,12 @@ wchar_t f13289_d_wchar(wchar_t ch);
 unsigned int f13289_d_dchar(unsigned int ch);
 #endif
 
+wchar_t f13289_d_wchar_t(wchar_t ch);
+
 bool f13289_cpp_test()
 {
+    if (!(f13289_d_wchar_t(L'e') == L'E')) return false;
+    if (!(f13289_d_wchar_t(L'F') == L'F')) return false;
 #if __linux__ || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun || __NetBSD__
     if (!(f13289_d_wchar((unsigned short)'c') == (unsigned short)'C')) return false;
     if (!(f13289_d_wchar((unsigned short)'D') == (unsigned short)'D')) return false;
diff --git a/gcc/testsuite/gdc.test/runnable_cxx/extra-files/test21515.cpp b/gcc/testsuite/gdc.test/runnable_cxx/extra-files/test21515.cpp
new file mode 100644
index 00000000000..076777a268b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable_cxx/extra-files/test21515.cpp
@@ -0,0 +1,82 @@
+#include <assert.h>
+#include <complex.h>
+
+// Use custom types for inspecting parts instead of including tgmath.h
+union cfloat_t { _Complex float z; struct { float re; float im; }; };
+union cdouble_t { _Complex double z; struct { double re; double im; }; };
+union creal_t { _Complex long double z; struct { long double re; long double im; }; };
+
+// extern(C) tests
+extern "C" _Complex float ccomplexf() { return 2.0f+I; }
+extern "C" _Complex double ccomplex() { return 2.0+I; }
+extern "C" _Complex long double ccomplexl() { return 2.0L+I; }
+extern "C" void ccomplexf2(_Complex float c) { cfloat_t z = {c}; assert(z.re == 2 && z.im == 1); }
+extern "C" void ccomplex2(_Complex double c) { cdouble_t z = {c}; assert(z.re == 2 && z.im == 1); }
+extern "C" void ccomplexl2(_Complex long double c) { creal_t z = {c}; assert(z.re == 2 && z.im == 1); }
+
+// extern(C++) tests
+_Complex float cpcomplexf() { return 2.0f+I; }
+_Complex double cpcomplex() { return 2.0+I; }
+_Complex long double cpcomplexl() { return 2.0L+I; }
+void cpcomplexf(_Complex float c) { cfloat_t z = {c}; assert(z.re == 2 && z.im == 1); }
+void cpcomplex(_Complex double c) { cdouble_t z = {c}; assert(z.re == 2 && z.im == 1); }
+void cpcomplexl(_Complex long double c) { creal_t z = {c}; assert(z.re == 2 && z.im == 1); }
+
+// Struct tests
+struct wrap_complexf { _Complex float c; };
+struct wrap_complex { _Complex double c; };
+struct wrap_complexl { _Complex long double c; };
+
+wrap_complexf wcomplexf()
+{
+    wrap_complexf s;
+    s.c = 2.0f+I;
+    return s;
+}
+
+wrap_complex wcomplex()
+{
+    wrap_complex s;
+    s.c = 2.0+I;
+    return s;
+}
+
+wrap_complexl wcomplexl()
+{
+    wrap_complexl s;
+    s.c = 2.0L+I;
+    return s;
+}
+
+void wcomplexf(wrap_complexf s) { cfloat_t z = {s.c}; assert(z.re == 2 && z.im == 1); }
+void wcomplex(wrap_complex s)   { cdouble_t z = {s.c}; assert(z.re == 2 && z.im == 1); }
+void wcomplexl(wrap_complexl s) { creal_t z = {s.c}; assert(z.re == 2 && z.im == 1); }
+
+struct soft_complexf { float re; float im; };
+struct soft_complex { double re; double im; };
+struct soft_complexl { long double re; long double im; };
+
+soft_complexf scomplexf()
+{
+    soft_complexf s;
+    s.re = 2.0f; s.im = 1.0f;
+    return s;
+}
+
+soft_complex scomplex()
+{
+    soft_complex s;
+    s.re = 2.0; s.im = 1.0;
+    return s;
+}
+
+soft_complexl scomplexl()
+{
+    soft_complexl s;
+    s.re = 2.0L; s.im = 1.0L;
+    return s;
+}
+
+void scomplexf(soft_complexf s) { assert(s.re == 2 && s.im == 1); }
+void scomplex(soft_complex s)   { assert(s.re == 2 && s.im == 1); }
+void scomplexl(soft_complexl s) { assert(s.re == 2 && s.im == 1); }
diff --git a/gcc/testsuite/gdc.test/runnable_cxx/test21515.d b/gcc/testsuite/gdc.test/runnable_cxx/test21515.d
new file mode 100644
index 00000000000..cc4420734a6
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable_cxx/test21515.d
@@ -0,0 +1,104 @@
+// https://issues.dlang.org/show_bug.cgi?id=21515
+// EXTRA_CPP_SOURCES: test21515.cpp
+// DISABLED: win32 win64
+
+// ABI layout of native complex
+struct _Complex(T) { T re; T im; }
+
+// Special enum definitions.
+version (Posix)
+{
+    align(float.alignof)  enum __c_complex_float : _Complex!float;
+    align(double.alignof) enum __c_complex_double : _Complex!double;
+    align(real.alignof)   enum __c_complex_real : _Complex!real;
+}
+else
+{
+    align(float.sizeof * 2)  enum __c_complex_float : _Complex!float;
+    align(double.sizeof * 2) enum __c_complex_double : _Complex!double;
+    align(real.alignof)      enum __c_complex_real : _Complex!real;
+}
+alias complex_float = __c_complex_float;
+alias complex_double = __c_complex_double;
+alias complex_real = __c_complex_real;
+
+extern(C) complex_float  ccomplexf();
+extern(C) complex_double ccomplex();
+extern(C) complex_real   ccomplexl();
+extern(C) void           ccomplexf2(complex_float c);
+extern(C) void           ccomplex2(complex_double c);
+extern(C) void           ccomplexl2(complex_real c);
+
+extern(C++) complex_float  cpcomplexf();
+extern(C++) complex_double cpcomplex();
+extern(C++) complex_real   cpcomplexl();
+extern(C++) void           cpcomplexf(complex_float c);
+extern(C++) void           cpcomplex(complex_double c);
+extern(C++) void           cpcomplexl(complex_real c);
+
+struct wrap_complexf { complex_float c; alias c this; };
+struct wrap_complex  { complex_double c; alias c this; };
+struct wrap_complexl { complex_real c; alias c this; };
+
+extern(C++) wrap_complexf wcomplexf();
+extern(C++) wrap_complex  wcomplex();
+extern(C++) wrap_complexl wcomplexl();
+extern(C++) void          wcomplexf(wrap_complexf c);
+extern(C++) void          wcomplex(wrap_complex c);
+extern(C++) void          wcomplexl(wrap_complexl c);
+
+struct soft_complexf { float re; float im; };
+struct soft_complex  { double re; double im; };
+struct soft_complexl { real re; real im; };
+
+extern(C++) soft_complexf scomplexf();
+extern(C++) soft_complex  scomplex();
+extern(C++) soft_complexl scomplexl();
+extern(C++) void          scomplexf(soft_complexf c);
+extern(C++) void          scomplex(soft_complex c);
+extern(C++) void          scomplexl(soft_complexl c);
+
+int main()
+{
+    auto a1 = ccomplexf();
+    auto b1 = ccomplex();
+    auto c1 = ccomplexl();
+    assert(a1.re == 2 && a1.im == 1);
+    assert(b1.re == 2 && b1.im == 1);
+    assert(c1.re == 2 && c1.im == 1);
+    ccomplexf2(a1);
+    ccomplex2(b1);
+    ccomplexl2(c1);
+
+    auto a2 = cpcomplexf();
+    auto b2 = cpcomplex();
+    auto c2 = cpcomplexl();
+    assert(a2.re == 2 && a2.im == 1);
+    assert(b2.re == 2 && b2.im == 1);
+    assert(c2.re == 2 && c2.im == 1);
+    cpcomplexf(a2);
+    cpcomplex(b2);
+    cpcomplexl(c2);
+
+    auto a3 = wcomplexf();
+    auto b3 = wcomplex();
+    auto c3 = wcomplexl();
+    assert(a3.re == 2 && a3.im == 1);
+    assert(b3.re == 2 && b3.im == 1);
+    assert(c3.re == 2 && c3.im == 1);
+    wcomplexf(a3);
+    wcomplex(b3);
+    wcomplexl(c3);
+
+    auto a4 = scomplexf();
+    auto b4 = scomplex();
+    auto c4 = scomplexl();
+    assert(a4.re == 2 && a4.im == 1);
+    assert(b4.re == 2 && b4.im == 1);
+    assert(c4.re == 2 && c4.im == 1);
+    scomplexf(a4);
+    scomplex(b4);
+    scomplexl(c4);
+
+    return 0;
+}
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index a4a9a940baf..b797682a4d9 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@
-0fd4364c4a4eb2ce0ebb8f613092c5bed7a63bf9
+483bc12977af3c1288fd52e7b4fa14b716896c5a
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/druntime repository.
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 535ca26e860..2a5c793d7c1 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -208,16 +208,17 @@ DRUNTIME_DSOURCES_BIONIC = core/sys/bionic/err.d \
 
 DRUNTIME_DSOURCES_DARWIN = core/sys/darwin/crt_externs.d \
 	core/sys/darwin/dlfcn.d core/sys/darwin/err.d \
-	core/sys/darwin/execinfo.d core/sys/darwin/ifaddrs.d \
-	core/sys/darwin/mach/dyld.d core/sys/darwin/mach/getsect.d \
-	core/sys/darwin/mach/kern_return.d core/sys/darwin/mach/loader.d \
-	core/sys/darwin/mach/nlist.d core/sys/darwin/mach/port.d \
-	core/sys/darwin/mach/semaphore.d core/sys/darwin/mach/stab.d \
-	core/sys/darwin/mach/thread_act.d core/sys/darwin/netinet/in_.d \
-	core/sys/darwin/pthread.d core/sys/darwin/stdlib.d \
-	core/sys/darwin/string.d core/sys/darwin/sys/attr.d \
-	core/sys/darwin/sys/cdefs.d core/sys/darwin/sys/event.d \
-	core/sys/darwin/sys/mman.d core/sys/darwin/sys/sysctl.d
+	core/sys/darwin/execinfo.d core/sys/darwin/fcntl.d \
+	core/sys/darwin/ifaddrs.d core/sys/darwin/mach/dyld.d \
+	core/sys/darwin/mach/getsect.d core/sys/darwin/mach/kern_return.d \
+	core/sys/darwin/mach/loader.d core/sys/darwin/mach/nlist.d \
+	core/sys/darwin/mach/port.d core/sys/darwin/mach/semaphore.d \
+	core/sys/darwin/mach/stab.d core/sys/darwin/mach/thread_act.d \
+	core/sys/darwin/netinet/in_.d core/sys/darwin/pthread.d \
+	core/sys/darwin/stdlib.d core/sys/darwin/string.d \
+	core/sys/darwin/sys/attr.d core/sys/darwin/sys/cdefs.d \
+	core/sys/darwin/sys/event.d core/sys/darwin/sys/mman.d \
+	core/sys/darwin/sys/sysctl.d
 
 DRUNTIME_DSOURCES_DRAGONFLYBSD = core/sys/dragonflybsd/dlfcn.d \
 	core/sys/dragonflybsd/err.d core/sys/dragonflybsd/execinfo.d \
@@ -275,7 +276,8 @@ DRUNTIME_DSOURCES_OPENBSD = core/sys/openbsd/dlfcn.d \
 	core/sys/openbsd/sys/elf.d core/sys/openbsd/sys/elf32.d \
 	core/sys/openbsd/sys/elf64.d core/sys/openbsd/sys/elf_common.d \
 	core/sys/openbsd/sys/link_elf.d core/sys/openbsd/sys/mman.d \
-	core/sys/openbsd/sys/sysctl.d core/sys/openbsd/time.d
+	core/sys/openbsd/sys/sysctl.d core/sys/openbsd/time.d \
+	core/sys/openbsd/unistd.d
 
 DRUNTIME_DSOURCES_POSIX = core/sys/posix/aio.d \
 	core/sys/posix/arpa/inet.d core/sys/posix/config.d \
@@ -382,22 +384,22 @@ DRUNTIME_DSOURCES_WINDOWS = core/sys/windows/accctrl.d \
 	core/sys/windows/sqlext.d core/sys/windows/sqltypes.d \
 	core/sys/windows/sqlucode.d core/sys/windows/sspi.d \
 	core/sys/windows/stacktrace.d core/sys/windows/stat.d \
-	core/sys/windows/stdc/time.d core/sys/windows/subauth.d \
-	core/sys/windows/threadaux.d core/sys/windows/tlhelp32.d \
-	core/sys/windows/tmschema.d core/sys/windows/unknwn.d \
-	core/sys/windows/uuid.d core/sys/windows/vfw.d \
-	core/sys/windows/w32api.d core/sys/windows/winbase.d \
-	core/sys/windows/winber.d core/sys/windows/wincon.d \
-	core/sys/windows/wincrypt.d core/sys/windows/windef.d \
-	core/sys/windows/windows.d core/sys/windows/winerror.d \
-	core/sys/windows/wingdi.d core/sys/windows/winhttp.d \
-	core/sys/windows/wininet.d core/sys/windows/winioctl.d \
-	core/sys/windows/winldap.d core/sys/windows/winnetwk.d \
-	core/sys/windows/winnls.d core/sys/windows/winnt.d \
-	core/sys/windows/winperf.d core/sys/windows/winreg.d \
-	core/sys/windows/winsock2.d core/sys/windows/winspool.d \
-	core/sys/windows/winsvc.d core/sys/windows/winuser.d \
-	core/sys/windows/winver.d core/sys/windows/wtsapi32.d \
-	core/sys/windows/wtypes.d
+	core/sys/windows/stdc/malloc.d core/sys/windows/stdc/time.d \
+	core/sys/windows/subauth.d core/sys/windows/threadaux.d \
+	core/sys/windows/tlhelp32.d core/sys/windows/tmschema.d \
+	core/sys/windows/unknwn.d core/sys/windows/uuid.d \
+	core/sys/windows/vfw.d core/sys/windows/w32api.d \
+	core/sys/windows/winbase.d core/sys/windows/winber.d \
+	core/sys/windows/wincon.d core/sys/windows/wincrypt.d \
+	core/sys/windows/windef.d core/sys/windows/windows.d \
+	core/sys/windows/winerror.d core/sys/windows/wingdi.d \
+	core/sys/windows/winhttp.d core/sys/windows/wininet.d \
+	core/sys/windows/winioctl.d core/sys/windows/winldap.d \
+	core/sys/windows/winnetwk.d core/sys/windows/winnls.d \
+	core/sys/windows/winnt.d core/sys/windows/winperf.d \
+	core/sys/windows/winreg.d core/sys/windows/winsock2.d \
+	core/sys/windows/winspool.d core/sys/windows/winsvc.d \
+	core/sys/windows/winuser.d core/sys/windows/winver.d \
+	core/sys/windows/wtsapi32.d core/sys/windows/wtypes.d
 
 DRUNTIME_DISOURCES = __entrypoint.di __main.di
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 7960add41d8..b00fe022cfa 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -256,8 +256,9 @@ am__objects_3 = core/sys/posix/aio.lo core/sys/posix/arpa/inet.lo \
 @DRUNTIME_OS_POSIX_TRUE@am__objects_4 = $(am__objects_3)
 am__objects_5 = core/sys/darwin/crt_externs.lo \
 	core/sys/darwin/dlfcn.lo core/sys/darwin/err.lo \
-	core/sys/darwin/execinfo.lo core/sys/darwin/ifaddrs.lo \
-	core/sys/darwin/mach/dyld.lo core/sys/darwin/mach/getsect.lo \
+	core/sys/darwin/execinfo.lo core/sys/darwin/fcntl.lo \
+	core/sys/darwin/ifaddrs.lo core/sys/darwin/mach/dyld.lo \
+	core/sys/darwin/mach/getsect.lo \
 	core/sys/darwin/mach/kern_return.lo \
 	core/sys/darwin/mach/loader.lo core/sys/darwin/mach/nlist.lo \
 	core/sys/darwin/mach/port.lo core/sys/darwin/mach/semaphore.lo \
@@ -322,7 +323,8 @@ am__objects_15 = core/sys/openbsd/dlfcn.lo core/sys/openbsd/err.lo \
 	core/sys/openbsd/sys/elf32.lo core/sys/openbsd/sys/elf64.lo \
 	core/sys/openbsd/sys/elf_common.lo \
 	core/sys/openbsd/sys/link_elf.lo core/sys/openbsd/sys/mman.lo \
-	core/sys/openbsd/sys/sysctl.lo core/sys/openbsd/time.lo
+	core/sys/openbsd/sys/sysctl.lo core/sys/openbsd/time.lo \
+	core/sys/openbsd/unistd.lo
 @DRUNTIME_OS_OPENBSD_TRUE@am__objects_16 = $(am__objects_15)
 am__objects_17 = core/sys/linux/config.lo core/sys/linux/dlfcn.lo \
 	core/sys/linux/elf.lo core/sys/linux/epoll.lo \
@@ -408,23 +410,24 @@ am__objects_19 = core/sys/windows/accctrl.lo \
 	core/sys/windows/sql.lo core/sys/windows/sqlext.lo \
 	core/sys/windows/sqltypes.lo core/sys/windows/sqlucode.lo \
 	core/sys/windows/sspi.lo core/sys/windows/stacktrace.lo \
-	core/sys/windows/stat.lo core/sys/windows/stdc/time.lo \
-	core/sys/windows/subauth.lo core/sys/windows/threadaux.lo \
-	core/sys/windows/tlhelp32.lo core/sys/windows/tmschema.lo \
-	core/sys/windows/unknwn.lo core/sys/windows/uuid.lo \
-	core/sys/windows/vfw.lo core/sys/windows/w32api.lo \
-	core/sys/windows/winbase.lo core/sys/windows/winber.lo \
-	core/sys/windows/wincon.lo core/sys/windows/wincrypt.lo \
-	core/sys/windows/windef.lo core/sys/windows/windows.lo \
-	core/sys/windows/winerror.lo core/sys/windows/wingdi.lo \
-	core/sys/windows/winhttp.lo core/sys/windows/wininet.lo \
-	core/sys/windows/winioctl.lo core/sys/windows/winldap.lo \
-	core/sys/windows/winnetwk.lo core/sys/windows/winnls.lo \
-	core/sys/windows/winnt.lo core/sys/windows/winperf.lo \
-	core/sys/windows/winreg.lo core/sys/windows/winsock2.lo \
-	core/sys/windows/winspool.lo core/sys/windows/winsvc.lo \
-	core/sys/windows/winuser.lo core/sys/windows/winver.lo \
-	core/sys/windows/wtsapi32.lo core/sys/windows/wtypes.lo
+	core/sys/windows/stat.lo core/sys/windows/stdc/malloc.lo \
+	core/sys/windows/stdc/time.lo core/sys/windows/subauth.lo \
+	core/sys/windows/threadaux.lo core/sys/windows/tlhelp32.lo \
+	core/sys/windows/tmschema.lo core/sys/windows/unknwn.lo \
+	core/sys/windows/uuid.lo core/sys/windows/vfw.lo \
+	core/sys/windows/w32api.lo core/sys/windows/winbase.lo \
+	core/sys/windows/winber.lo core/sys/windows/wincon.lo \
+	core/sys/windows/wincrypt.lo core/sys/windows/windef.lo \
+	core/sys/windows/windows.lo core/sys/windows/winerror.lo \
+	core/sys/windows/wingdi.lo core/sys/windows/winhttp.lo \
+	core/sys/windows/wininet.lo core/sys/windows/winioctl.lo \
+	core/sys/windows/winldap.lo core/sys/windows/winnetwk.lo \
+	core/sys/windows/winnls.lo core/sys/windows/winnt.lo \
+	core/sys/windows/winperf.lo core/sys/windows/winreg.lo \
+	core/sys/windows/winsock2.lo core/sys/windows/winspool.lo \
+	core/sys/windows/winsvc.lo core/sys/windows/winuser.lo \
+	core/sys/windows/winver.lo core/sys/windows/wtsapi32.lo \
+	core/sys/windows/wtypes.lo
 @DRUNTIME_OS_MINGW_TRUE@am__objects_20 = $(am__objects_19)
 am__objects_21 = core/sys/solaris/dlfcn.lo core/sys/solaris/elf.lo \
 	core/sys/solaris/err.lo core/sys/solaris/execinfo.lo \
@@ -837,16 +840,17 @@ DRUNTIME_DSOURCES_BIONIC = core/sys/bionic/err.d \
 
 DRUNTIME_DSOURCES_DARWIN = core/sys/darwin/crt_externs.d \
 	core/sys/darwin/dlfcn.d core/sys/darwin/err.d \
-	core/sys/darwin/execinfo.d core/sys/darwin/ifaddrs.d \
-	core/sys/darwin/mach/dyld.d core/sys/darwin/mach/getsect.d \
-	core/sys/darwin/mach/kern_return.d core/sys/darwin/mach/loader.d \
-	core/sys/darwin/mach/nlist.d core/sys/darwin/mach/port.d \
-	core/sys/darwin/mach/semaphore.d core/sys/darwin/mach/stab.d \
-	core/sys/darwin/mach/thread_act.d core/sys/darwin/netinet/in_.d \
-	core/sys/darwin/pthread.d core/sys/darwin/stdlib.d \
-	core/sys/darwin/string.d core/sys/darwin/sys/attr.d \
-	core/sys/darwin/sys/cdefs.d core/sys/darwin/sys/event.d \
-	core/sys/darwin/sys/mman.d core/sys/darwin/sys/sysctl.d
+	core/sys/darwin/execinfo.d core/sys/darwin/fcntl.d \
+	core/sys/darwin/ifaddrs.d core/sys/darwin/mach/dyld.d \
+	core/sys/darwin/mach/getsect.d core/sys/darwin/mach/kern_return.d \
+	core/sys/darwin/mach/loader.d core/sys/darwin/mach/nlist.d \
+	core/sys/darwin/mach/port.d core/sys/darwin/mach/semaphore.d \
+	core/sys/darwin/mach/stab.d core/sys/darwin/mach/thread_act.d \
+	core/sys/darwin/netinet/in_.d core/sys/darwin/pthread.d \
+	core/sys/darwin/stdlib.d core/sys/darwin/string.d \
+	core/sys/darwin/sys/attr.d core/sys/darwin/sys/cdefs.d \
+	core/sys/darwin/sys/event.d core/sys/darwin/sys/mman.d \
+	core/sys/darwin/sys/sysctl.d
 
 DRUNTIME_DSOURCES_DRAGONFLYBSD = core/sys/dragonflybsd/dlfcn.d \
 	core/sys/dragonflybsd/err.d core/sys/dragonflybsd/execinfo.d \
@@ -904,7 +908,8 @@ DRUNTIME_DSOURCES_OPENBSD = core/sys/openbsd/dlfcn.d \
 	core/sys/openbsd/sys/elf.d core/sys/openbsd/sys/elf32.d \
 	core/sys/openbsd/sys/elf64.d core/sys/openbsd/sys/elf_common.d \
 	core/sys/openbsd/sys/link_elf.d core/sys/openbsd/sys/mman.d \
-	core/sys/openbsd/sys/sysctl.d core/sys/openbsd/time.d
+	core/sys/openbsd/sys/sysctl.d core/sys/openbsd/time.d \
+	core/sys/openbsd/unistd.d
 
 DRUNTIME_DSOURCES_POSIX = core/sys/posix/aio.d \
 	core/sys/posix/arpa/inet.d core/sys/posix/config.d \
@@ -1011,23 +1016,23 @@ DRUNTIME_DSOURCES_WINDOWS = core/sys/windows/accctrl.d \
 	core/sys/windows/sqlext.d core/sys/windows/sqltypes.d \
 	core/sys/windows/sqlucode.d core/sys/windows/sspi.d \
 	core/sys/windows/stacktrace.d core/sys/windows/stat.d \
-	core/sys/windows/stdc/time.d core/sys/windows/subauth.d \
-	core/sys/windows/threadaux.d core/sys/windows/tlhelp32.d \
-	core/sys/windows/tmschema.d core/sys/windows/unknwn.d \
-	core/sys/windows/uuid.d core/sys/windows/vfw.d \
-	core/sys/windows/w32api.d core/sys/windows/winbase.d \
-	core/sys/windows/winber.d core/sys/windows/wincon.d \
-	core/sys/windows/wincrypt.d core/sys/windows/windef.d \
-	core/sys/windows/windows.d core/sys/windows/winerror.d \
-	core/sys/windows/wingdi.d core/sys/windows/winhttp.d \
-	core/sys/windows/wininet.d core/sys/windows/winioctl.d \
-	core/sys/windows/winldap.d core/sys/windows/winnetwk.d \
-	core/sys/windows/winnls.d core/sys/windows/winnt.d \
-	core/sys/windows/winperf.d core/sys/windows/winreg.d \
-	core/sys/windows/winsock2.d core/sys/windows/winspool.d \
-	core/sys/windows/winsvc.d core/sys/windows/winuser.d \
-	core/sys/windows/winver.d core/sys/windows/wtsapi32.d \
-	core/sys/windows/wtypes.d
+	core/sys/windows/stdc/malloc.d core/sys/windows/stdc/time.d \
+	core/sys/windows/subauth.d core/sys/windows/threadaux.d \
+	core/sys/windows/tlhelp32.d core/sys/windows/tmschema.d \
+	core/sys/windows/unknwn.d core/sys/windows/uuid.d \
+	core/sys/windows/vfw.d core/sys/windows/w32api.d \
+	core/sys/windows/winbase.d core/sys/windows/winber.d \
+	core/sys/windows/wincon.d core/sys/windows/wincrypt.d \
+	core/sys/windows/windef.d core/sys/windows/windows.d \
+	core/sys/windows/winerror.d core/sys/windows/wingdi.d \
+	core/sys/windows/winhttp.d core/sys/windows/wininet.d \
+	core/sys/windows/winioctl.d core/sys/windows/winldap.d \
+	core/sys/windows/winnetwk.d core/sys/windows/winnls.d \
+	core/sys/windows/winnt.d core/sys/windows/winperf.d \
+	core/sys/windows/winreg.d core/sys/windows/winsock2.d \
+	core/sys/windows/winspool.d core/sys/windows/winsvc.d \
+	core/sys/windows/winuser.d core/sys/windows/winver.d \
+	core/sys/windows/wtsapi32.d core/sys/windows/wtypes.d
 
 DRUNTIME_DISOURCES = __entrypoint.di __main.di
 all: all-am
@@ -1346,6 +1351,7 @@ core/sys/darwin/crt_externs.lo: core/sys/darwin/$(am__dirstamp)
 core/sys/darwin/dlfcn.lo: core/sys/darwin/$(am__dirstamp)
 core/sys/darwin/err.lo: core/sys/darwin/$(am__dirstamp)
 core/sys/darwin/execinfo.lo: core/sys/darwin/$(am__dirstamp)
+core/sys/darwin/fcntl.lo: core/sys/darwin/$(am__dirstamp)
 core/sys/darwin/ifaddrs.lo: core/sys/darwin/$(am__dirstamp)
 core/sys/darwin/mach/$(am__dirstamp):
 	@$(MKDIR_P) core/sys/darwin/mach
@@ -1510,6 +1516,7 @@ core/sys/openbsd/sys/link_elf.lo:  \
 core/sys/openbsd/sys/mman.lo: core/sys/openbsd/sys/$(am__dirstamp)
 core/sys/openbsd/sys/sysctl.lo: core/sys/openbsd/sys/$(am__dirstamp)
 core/sys/openbsd/time.lo: core/sys/openbsd/$(am__dirstamp)
+core/sys/openbsd/unistd.lo: core/sys/openbsd/$(am__dirstamp)
 core/sys/linux/$(am__dirstamp):
 	@$(MKDIR_P) core/sys/linux
 	@: > core/sys/linux/$(am__dirstamp)
@@ -1690,6 +1697,8 @@ core/sys/windows/stat.lo: core/sys/windows/$(am__dirstamp)
 core/sys/windows/stdc/$(am__dirstamp):
 	@$(MKDIR_P) core/sys/windows/stdc
 	@: > core/sys/windows/stdc/$(am__dirstamp)
+core/sys/windows/stdc/malloc.lo:  \
+	core/sys/windows/stdc/$(am__dirstamp)
 core/sys/windows/stdc/time.lo: core/sys/windows/stdc/$(am__dirstamp)
 core/sys/windows/subauth.lo: core/sys/windows/$(am__dirstamp)
 core/sys/windows/threadaux.lo: core/sys/windows/$(am__dirstamp)
diff --git a/libphobos/libdruntime/core/stdc/complex.d b/libphobos/libdruntime/core/stdc/complex.d
index d878366b3bd..b84651f3f15 100644
--- a/libphobos/libdruntime/core/stdc/complex.d
+++ b/libphobos/libdruntime/core/stdc/complex.d
@@ -19,163 +19,97 @@ extern (C):
 nothrow:
 @nogc:
 
-///
+// @@@DEPRECATED_2.105@@@
+deprecated:
 alias creal complex;
-///
 alias ireal imaginary;
-///
 cdouble cacos(cdouble z);
-///
 cfloat  cacosf(cfloat z);
-///
 creal   cacosl(creal z);
 
-///
 cdouble casin(cdouble z);
-///
 cfloat  casinf(cfloat z);
-///
 creal   casinl(creal z);
 
-///
 cdouble catan(cdouble z);
-///
 cfloat  catanf(cfloat z);
-///
 creal   catanl(creal z);
 
-///
 cdouble ccos(cdouble z);
-///
 cfloat  ccosf(cfloat z);
-///
 creal   ccosl(creal z);
 
-///
 cdouble csin(cdouble z);
-///
 cfloat  csinf(cfloat z);
-///
 creal   csinl(creal z);
 
-///
 cdouble ctan(cdouble z);
-///
 cfloat  ctanf(cfloat z);
-///
 creal   ctanl(creal z);
 
-///
 cdouble cacosh(cdouble z);
-///
 cfloat  cacoshf(cfloat z);
-///
 creal   cacoshl(creal z);
 
-///
 cdouble casinh(cdouble z);
-///
 cfloat  casinhf(cfloat z);
-///
 creal   casinhl(creal z);
 
-///
 cdouble catanh(cdouble z);
-///
 cfloat  catanhf(cfloat z);
-///
 creal   catanhl(creal z);
 
-///
 cdouble ccosh(cdouble z);
-///
 cfloat  ccoshf(cfloat z);
-///
 creal   ccoshl(creal z);
 
-///
 cdouble csinh(cdouble z);
-///
 cfloat  csinhf(cfloat z);
-///
 creal   csinhl(creal z);
 
-///
 cdouble ctanh(cdouble z);
-///
 cfloat  ctanhf(cfloat z);
-///
 creal   ctanhl(creal z);
 
-///
 cdouble cexp(cdouble z);
-///
 cfloat  cexpf(cfloat z);
-///
 creal   cexpl(creal z);
 
-///
 cdouble clog(cdouble z);
-///
 cfloat  clogf(cfloat z);
-///
 creal   clogl(creal z);
 
-///
  double cabs(cdouble z);
- ///
  float  cabsf(cfloat z);
- ///
  real   cabsl(creal z);
 
- ///
 cdouble cpow(cdouble x, cdouble y);
-///
 cfloat  cpowf(cfloat x, cfloat y);
-///
 creal   cpowl(creal x, creal y);
 
-///
 cdouble csqrt(cdouble z);
-///
 cfloat  csqrtf(cfloat z);
-///
 creal   csqrtl(creal z);
 
-///
  double carg(cdouble z);
- ///
  float  cargf(cfloat z);
- ///
  real   cargl(creal z);
 
-///
 pragma(inline, true) double cimag(cdouble z) { return z.im; }
-///
 pragma(inline, true) float  cimagf(cfloat z) { return z.im; }
-///
 pragma(inline, true) real   cimagl(creal z)  { return z.im; }
 
-///
 cdouble conj(cdouble z);
-///
 cfloat  conjf(cfloat z);
-///
 creal   conjl(creal z);
 
-///
 cdouble cproj(cdouble z);
-///
 cfloat  cprojf(cfloat z);
-///
 creal   cprojl(creal z);
 
 // Note: `creal` is a keyword in D and so this function is inaccessible, use `creald` instead
 //pragma(inline, true) double creal(cdouble z) { return z.re; }
 
-///
 pragma(inline, true) double creald(cdouble z) { return z.re; }
-///
 pragma(inline, true) float  crealf(cfloat z) { return z.re; }
-///
 pragma(inline, true) real   creall(creal z)  { return z.re; }
diff --git a/libphobos/libdruntime/core/stdc/config.d b/libphobos/libdruntime/core/stdc/config.d
index cdb987f1415..802f5b6fb21 100644
--- a/libphobos/libdruntime/core/stdc/config.d
+++ b/libphobos/libdruntime/core/stdc/config.d
@@ -34,6 +34,7 @@ version (StdDdoc)
             alias ddoc_long = int;
             alias ddoc_ulong = uint;
         }
+        struct ddoc_complex(T) { T re; T im; };
     }
 
     /***
@@ -89,6 +90,24 @@ version (StdDdoc)
      * C++ compiler's `ptrdiff_t` type.
      */
     alias cpp_ptrdiff_t = ptrdiff_t;
+
+    /***
+     * Used for a complex floating point type that corresponds in size and ABI to the associated
+     * C compiler's `_Complex float` type.
+     */
+    alias c_complex_float = ddoc_complex!float;
+
+    /***
+     * Used for a complex floating point type that corresponds in size and ABI to the associated
+     * C compiler's `_Complex double` type.
+     */
+    alias c_complex_double = ddoc_complex!double;
+
+    /***
+     * Used for a complex floating point type that corresponds in size and ABI to the associated
+     * C compiler's `_Complex long double` type.
+     */
+    alias c_complex_real = ddoc_complex!real;
 }
 else
 {
@@ -230,4 +249,28 @@ else
     alias cpp_size_t = size_t;
     alias cpp_ptrdiff_t = ptrdiff_t;
 }
+
+// ABI layout of native complex types.
+private struct _Complex(T)
+{
+    T re;
+    T im;
+}
+
+version (Posix)
+{
+    align(float.alignof)  enum __c_complex_float : _Complex!float;
+    align(double.alignof) enum __c_complex_double : _Complex!double;
+    align(real.alignof)   enum __c_complex_real : _Complex!real;
+}
+else
+{
+    align(float.sizeof * 2)  enum __c_complex_float : _Complex!float;
+    align(double.sizeof * 2) enum __c_complex_double : _Complex!double;
+    align(real.alignof)      enum __c_complex_real : _Complex!real;
+}
+
+alias c_complex_float = __c_complex_float;
+alias c_complex_double = __c_complex_double;
+alias c_complex_real = __c_complex_real;
 }
diff --git a/libphobos/libdruntime/core/stdc/errno.d b/libphobos/libdruntime/core/stdc/errno.d
index 31f7d11c762..57bc15da6eb 100644
--- a/libphobos/libdruntime/core/stdc/errno.d
+++ b/libphobos/libdruntime/core/stdc/errno.d
@@ -156,15 +156,9 @@ else version (Haiku)
 else
 {
     ///
-    @property int errno() { return getErrno(); }
+    extern(C) pragma(mangle, "getErrno") @property int errno();
     ///
-    @property int errno(int n) { return setErrno(n); }
-
-    extern (C)
-    {
-        private int getErrno();      // for internal use
-        private int setErrno(int);   // for internal use
-    }
+    extern(C) pragma(mangle, "setErrno") @property int errno(int n);
 }
 
 extern (C):
@@ -1532,7 +1526,11 @@ else version (OpenBSD)
     enum EIDRM              = 89;       /// Identifier removed
     enum ENOMSG             = 90;       /// No message of desired type
     enum ENOTSUP            = 91;       /// Not supported
-    enum ELAST              = 91;       /// Must be equal largest errno
+    enum EBADMSG            = 92;       /// Bad message
+    enum ENOTRECOVERABLE    = 93;       /// State not recoverable
+    enum EOWNERDEAD         = 94;       /// Previous owner died
+    enum EPROTO             = 95;       /// Protocol error
+    enum ELAST              = 95;       /// Must be equal largest errno
 }
 else version (DragonFlyBSD)
 {
diff --git a/libphobos/libdruntime/core/stdc/math.d b/libphobos/libdruntime/core/stdc/math.d
index e8d1fa8e7b5..fba78ee233a 100644
--- a/libphobos/libdruntime/core/stdc/math.d
+++ b/libphobos/libdruntime/core/stdc/math.d
@@ -319,16 +319,12 @@ version (CRuntime_DigitalMars)
   {
     //int fpclassify(real-floating x);
     ///
-    pure int fpclassify(float x)     { return __fpclassify_f(x); }
+    extern(C) pragma(mangle, "__fpclassify_f") pure int fpclassify(float x);
     ///
-    pure int fpclassify(double x)    { return __fpclassify_d(x); }
+    extern(C) pragma(mangle, "__fpclassify_d") pure int fpclassify(double x);
     ///
-    pure int fpclassify(real x)
-    {
-        return (real.sizeof == double.sizeof)
-            ? __fpclassify_d(x)
-            : __fpclassify_ld(x);
-    }
+    extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__fpclassify_d" : "__fpclassify_ld")
+    pure int fpclassify(real x);
 
     //int isfinite(real-floating x);
     ///
@@ -442,24 +438,18 @@ else version (CRuntime_Microsoft) // fully supported since MSVCRT 12 (VS 2013) o
         FP_NAN       =  2,
     }
 
-    pure private short _fdclass(float x);
-    pure private short _dclass(double x);
-
-    pure private int _fdsign(float x);
-    pure private int _dsign(double x);
-
   extern(D)
   {
     //int fpclassify(real-floating x);
     ///
-    pure int fpclassify()(float x)   { return _fdclass(x); }
+    extern(C) pragma(mangle, "_fdclass") pure int fpclassify(float x);
     ///
-    pure int fpclassify()(double x)  { return _dclass(x);  }
+    extern(C) pragma(mangle, "_dclass")  pure int fpclassify(double x);
     ///
     pure int fpclassify()(real x)
     {
         static if (real.sizeof == double.sizeof)
-            return _dclass(cast(double) x);
+            return fpclassify(cast(double) x);
         else
             static assert(false, "fpclassify(real) not supported by MS C runtime");
     }
@@ -495,7 +485,7 @@ else version (CRuntime_Microsoft) // fully supported since MSVCRT 12 (VS 2013) o
         ///
         pure int isnan(float x)      { version (Win64) return _isnanf(x); else return _isnan(cast(double) x); }
         ///
-        pure int isnan(double x)     { return _isnan(x); }
+        extern(C) pragma(mangle, "_isnan") pure int isnan(double x);
         ///
         pure int isnan(real x)       { return _isnan(cast(double) x); }
     }
@@ -510,14 +500,14 @@ else version (CRuntime_Microsoft) // fully supported since MSVCRT 12 (VS 2013) o
 
     //int signbit(real-floating x);
     ///
-    pure int signbit()(float x)   { return _fdsign(x); }
+    extern(C) pragma(mangle, "_fdsign") pure int signbit(float x);
     ///
-    pure int signbit()(double x)  { return _dsign(x);  }
+    extern(C) pragma(mangle, "_dsign")  pure int signbit(double x);
     ///
     pure int signbit()(real x)
     {
         static if (real.sizeof == double.sizeof)
-            return _dsign(cast(double) x);
+            return signbit(cast(double) x);
         else
             return (cast(short*)&(x))[4] & 0x8000;
     }
@@ -573,55 +563,39 @@ else version (CRuntime_Glibc)
   {
     //int fpclassify(real-floating x);
       ///
-    pure int fpclassify(float x)     { return __fpclassifyf(x); }
+    extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x);
     ///
-    pure int fpclassify(double x)    { return __fpclassify(x);  }
+    extern(C) pragma(mangle, "__fpclassify")  pure int fpclassify(double x);
     ///
-    pure int fpclassify(real x)
-    {
-        return (real.sizeof == double.sizeof)
-            ? __fpclassify(x)
-            : __fpclassifyl(x);
-    }
+    extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__fpclassify" : "__fpclassifyl")
+    pure int fpclassify(real x);
 
     //int isfinite(real-floating x);
     ///
-    pure int isfinite(float x)       { return __finitef(x); }
+    extern(C) pragma(mangle, "__finitef") pure int isfinite(float x);
     ///
-    pure int isfinite(double x)      { return __finite(x);  }
+    extern(C) pragma(mangle, "__finite")  pure int isfinite(double x);
     ///
-    pure int isfinite(real x)
-    {
-        return (real.sizeof == double.sizeof)
-            ? __finite(x)
-            : __finitel(x);
-    }
+    extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__finite" : "__finitel")
+    pure int isfinite(real x);
 
     //int isinf(real-floating x);
     ///
-    pure int isinf(float x)          { return __isinff(x);  }
+    extern(C) pragma(mangle, "__isinff") pure int isinf(float x);
     ///
-    pure int isinf(double x)         { return __isinf(x);   }
+    extern(C) pragma(mangle, "__isinf")  pure int isinf(double x);
     ///
-    pure int isinf(real x)
-    {
-        return (real.sizeof == double.sizeof)
-            ? __isinf(x)
-            : __isinfl(x);
-    }
+    extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__isinf" : "__isinfl")
+    pure int isinf(real x);
 
     //int isnan(real-floating x);
     ///
-    pure int isnan(float x)          { return __isnanf(x);  }
+    extern(C) pragma(mangle, "__isnanf") pure int isnan(float x);
     ///
-    pure int isnan(double x)         { return __isnan(x);   }
+    extern(C) pragma(mangle, "__isnan")  pure int isnan(double x);
     ///
-    pure int isnan(real x)
-    {
-        return (real.sizeof == double.sizeof)
-            ? __isnan(x)
-            : __isnanl(x);
-    }
+    extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__isnan" : "__isnanl")
+    pure int isnan(real x);
 
     //int isnormal(real-floating x);
     ///
@@ -633,16 +607,12 @@ else version (CRuntime_Glibc)
 
     //int signbit(real-floating x);
     ///
-    pure int signbit(float x)     { return __signbitf(x); }
+    extern(C) pragma(mangle, "__signbitf") pure int signbit(float x);
     ///
-    pure int signbit(double x)    { return __signbit(x);  }
+    extern(C) pragma(mangle, "__signbit")  pure int signbit(double x);
     ///
-    pure int signbit(real x)
-    {
-        return (real.sizeof == double.sizeof)
-            ? __signbit(x)
-            : __signbitl(x);
-    }
+    extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__signbit" : "__signbitl")
+    pure int signbit(real x);
   }
 }
 else version (CRuntime_Musl)
@@ -685,16 +655,12 @@ else version (CRuntime_Musl)
   {
     //int fpclassify(real-floating x);
       ///
-    int fpclassify(float x)     { return __fpclassifyf(x); }
+    extern(C) pragma(mangle, "__fpclassifyf") int fpclassify(float x);
     ///
-    int fpclassify(double x)    { return __fpclassify(x);  }
+    extern(C) pragma(mangle, "__fpclassify")  int fpclassify(double x);
     ///
-    int fpclassify(real x)
-    {
-        return (real.sizeof == double.sizeof)
-            ? __fpclassify(x)
-            : __fpclassifyl(x);
-    }
+    extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__fpclassify" : "__fpclassifyl")
+    int fpclassify(real x);
     private uint __FLOAT_BITS(float __f)
     {
         union __u_t {
@@ -765,16 +731,12 @@ else version (CRuntime_Musl)
 
     //int signbit(real-floating x);
     ///
-    int signbit(float x)     { return __signbitf(x); }
+    extern(C) pragma(mangle, "__signbitf") int signbit(float x);
     ///
-    int signbit(double x)    { return __signbit(x);  }
+    extern(C) pragma(mangle, "__signbit")  int signbit(double x);
     ///
-    int signbit(real x)
-    {
-        return (real.sizeof == double.sizeof)
-            ? __signbit(x)
-            : __signbitl(x);
-    }
+    extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__signbit" : "__signbitl")
+    int signbit(real x);
   }
 }
 else version (CRuntime_UClibc)
@@ -826,52 +788,36 @@ else version (CRuntime_UClibc)
   extern (D)
   {
     ///
-    int fpclassify(float x)     { return __fpclassifyf(x); }
+    extern(C) pragma(mangle, "__fpclassifyf") int fpclassify(float x);
     ///
-    int fpclassify(double x)    { return __fpclassify(x);  }
+    extern(C) pragma(mangle, "__fpclassify")  int fpclassify(double x);
     ///
-    int fpclassify(real x)
-    {
-        return (real.sizeof == double.sizeof)
-            ? __fpclassify(x)
-            : __fpclassifyl(x);
-    }
+    extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__fpclassify" : "__fpclassifyl")
+    int fpclassify(real x);
 
     ///
-    int isfinite(float x)       { return __finitef(x); }
+    extern(C) pragma(mangle, "__finitef") int isfinite(float x);
     ///
-    int isfinite(double x)      { return __finite(x);  }
+    extern(C) pragma(mangle, "__finite")  int isfinite(double x);
     ///
-    int isfinite(real x)
-    {
-        return (real.sizeof == double.sizeof)
-            ? __finite(x)
-            : __finitel(x);
-    }
+    extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__finite" : "__finitel")
+    int isfinite(real x);
 
     ///
-    int isinf(float x)          { return __isinff(x);  }
+    extern(C) pragma(mangle, "__isinff") int isinf(float x);
     ///
-    int isinf(double x)         { return __isinf(x);   }
+    extern(C) pragma(mangle, "__isinf")  int isinf(double x);
     ///
-    int isinf(real x)
-    {
-        return (real.sizeof == double.sizeof)
-            ? __isinf(x)
-            : __isinfl(x);
-    }
+    extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__isinf" : "__isinfl")
+    int isinf(real x);
 
     ///
-    int isnan(float x)          { return __isnanf(x);  }
+    extern(C) pragma(mangle, "__isnanf") int isnan(float x);
     ///
-    int isnan(double x)         { return __isnan(x);   }
+    extern(C) pragma(mangle, "__isnan")  int isnan(double x);
     ///
-    int isnan(real x)
-    {
-        return (real.sizeof == double.sizeof)
-            ? __isnan(x)
-            : __isnanl(x);
-    }
+    extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__isnan" : "__isnanl")
+    int isnan(real x);
 
     ///
     int isnormal(float x)       { return fpclassify(x) == FP_NORMAL; }
@@ -881,16 +827,12 @@ else version (CRuntime_UClibc)
     int isnormal(real x)        { return fpclassify(x) == FP_NORMAL; }
 
     ///
-    int signbit(float x)     { return __signbitf(x); }
+    extern(C) pragma(mangle, "__signbitf") int signbit(float x);
     ///
-    int signbit(double x)    { return __signbit(x);  }
+    extern(C) pragma(mangle, "__signbit")  int signbit(double x);
     ///
-    int signbit(real x)
-    {
-        return (real.sizeof == double.sizeof)
-            ? __signbit(x)
-            : __signbitl(x);
-    }
+    extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__signbit" : "__signbitl")
+    int signbit(real x);
   }
 }
 else version (MinGW)
@@ -925,16 +867,12 @@ else version (MinGW)
   {
     //int fpclassify(real-floating x);
       ///
-    pure int fpclassify(float x)     { return __fpclassifyf(x); }
+    extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x);
     ///
-    pure int fpclassify(double x)    { return __fpclassify(x);  }
+    extern(C) pragma(mangle, "__fpclassify")  pure int fpclassify(double x);
     ///
-    pure int fpclassify(real x)
-    {
-        return (real.sizeof == double.sizeof)
-            ? __fpclassify(x)
-            : __fpclassifyl(x);
-    }
+    extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__fpclassify" : "__fpclassifyl")
+    pure int fpclassify(real x);
 
     //int isfinite(real-floating x);
     ///
@@ -954,16 +892,12 @@ else version (MinGW)
 
     //int isnan(real-floating x);
     ///
-    pure int isnan(float x)          { return __isnanf(x);  }
+    extern(C) pragma(mangle, "__isnanf") pure int isnan(float x);
     ///
-    pure int isnan(double x)         { return __isnan(x);   }
+    extern(C) pragma(mangle, "__isnan")  pure int isnan(double x);
     ///
-    pure int isnan(real x)
-    {
-        return (real.sizeof == double.sizeof)
-            ? __isnan(x)
-            : __isnanl(x);
-    }
+    extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__isnan" : "__isnanl")
+    pure int isnan(real x);
 
     //int isnormal(real-floating x);
     ///
@@ -975,16 +909,12 @@ else version (MinGW)
 
     //int signbit(real-floating x);
     ///
-    int signbit(float x)     { return __signbitf(x); }
+    extern(C) pragma(mangle, "__signbitf") pure int signbit(float x);
     ///
-    int signbit(double x)    { return __signbit(x);  }
+    extern(C) pragma(mangle, "__signbit")  pure int signbit(double x);
     ///
-    int signbit(real x)
-    {
-        return (real.sizeof == double.sizeof)
-            ? __signbit(x)
-            : __signbitl(x);
-    }
+    extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__signbit" : "__signbitl")
+    int signbit(real x);
   }
 }
 else version (Darwin)
@@ -1070,35 +1000,35 @@ else version (Darwin)
   {
     //int fpclassify(real-floating x);
     ///
-    pure int fpclassify(float x)     { return __fpclassifyf(x); }
+    extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x);
     ///
-    pure int fpclassify(double x)    { return __fpclassifyd(x); }
+    extern(C) pragma(mangle, "__fpclassifyd") pure int fpclassify(double x);
     ///
-    pure int fpclassify(real x)      { return __fpclassifyl(x); }
+    extern(C) pragma(mangle, __fpclassifyl.mangleof) pure int fpclassify(real x);
 
     //int isfinite(real-floating x);
     ///
-    pure int isfinite(float x)       { return __isfinitef(x); }
+    extern(C) pragma(mangle, "__isfinitef") pure int isfinite(float x);
     ///
-    pure int isfinite(double x)      { return __isfinited(x); }
+    extern(C) pragma(mangle, "__isfinited") pure int isfinite(double x);
     ///
-    pure int isfinite(real x)        { return __isfinitel(x); }
+    extern(C) pragma(mangle, __isfinitel.mangleof) pure int isfinite(real x);
 
     //int isinf(real-floating x);
     ///
-    pure int isinf(float x)          { return __isinff(x); }
+    extern(C) pragma(mangle, "__isinff") pure int isinf(float x);
     ///
-    pure int isinf(double x)         { return __isinfd(x); }
+    extern(C) pragma(mangle, "__isinfd") pure int isinf(double x);
     ///
-    pure int isinf(real x)           { return __isinfl(x); }
+    extern(C) pragma(mangle, __isinfl.mangleof) pure int isinf(real x);
 
     //int isnan(real-floating x);
     ///
-    pure int isnan(float x)          { return __isnanf(x); }
+    extern(C) pragma(mangle, "__isnanf") pure int isnan(float x);
     ///
-    pure int isnan(double x)         { return __isnand(x); }
+    extern(C) pragma(mangle, "__isnand") pure int isnan(double x);
     ///
-    pure int isnan(real x)           { return __isnanl(x); }
+    extern(C) pragma(mangle, __isnanl.mangleof) pure int isnan(real x);
 
     //int isnormal(real-floating x);
     ///
@@ -1110,11 +1040,11 @@ else version (Darwin)
 
     //int signbit(real-floating x);
     ///
-    pure int signbit(float x)     { return __signbitf(x); }
+    extern(C) pragma(mangle, "__signbitf") pure int signbit(float x);
     ///
-    pure int signbit(double x)    { return __signbitd(x); }
+    extern(C) pragma(mangle, "__signbitd") pure int signbit(double x);
     ///
-    pure int signbit(real x)      { return __signbitl(x); }
+    extern(C) pragma(mangle, "__signbitl") pure int signbit(real x);
   }
 }
 else version (FreeBSD)
@@ -1163,27 +1093,27 @@ else version (FreeBSD)
   {
     //int fpclassify(real-floating x);
       ///
-    pure int fpclassify(float x)     { return __fpclassifyf(x); }
+    extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x);
     ///
-    pure int fpclassify(double x)    { return __fpclassifyd(x); }
+    extern(C) pragma(mangle, "__fpclassifyd") pure int fpclassify(double x);
     ///
-    pure int fpclassify(real x)      { return __fpclassifyl(x); }
+    extern(C) pragma(mangle, "__fpclassifyl") pure int fpclassify(real x);
 
     //int isfinite(real-floating x);
     ///
-    pure int isfinite(float x)       { return __isfinitef(x); }
+    extern(C) pragma(mangle, "__isfinitef") pure int isfinite(float x);
     ///
-    pure int isfinite(double x)      { return __isfinite(x); }
+    extern(C) pragma(mangle, "__isfinite")  pure int isfinite(double x);
     ///
-    pure int isfinite(real x)        { return __isfinitel(x); }
+    extern(C) pragma(mangle, "__isfinitel") pure int isfinite(real x);
 
     //int isinf(real-floating x);
     ///
-    pure int isinf(float x)          { return __isinff(x); }
+    extern(C) pragma(mangle, "__isinff") pure int isinf(float x);
     ///
     pure int isinf(double x)         { return __isinfl(x); }
     ///
-    pure int isinf(real x)           { return __isinfl(x); }
+    extern(C) pragma(mangle, "__isinfl") pure int isinf(real x);
 
     //int isnan(real-floating x);
     ///
@@ -1191,21 +1121,21 @@ else version (FreeBSD)
     ///
     pure int isnan(double x)         { return __isnanl(x); }
     ///
-    pure int isnan(real x)           { return __isnanl(x); }
+    extern(C) pragma(mangle, "__isnanl") pure int isnan(real x);
 
     //int isnormal(real-floating x);
     ///
-    pure int isnormal(float x)       { return __isnormalf(x); }
+    extern(C) pragma(mangle, "__isnormalf") pure int isnormal(float x);
     ///
-    pure int isnormal(double x)      { return __isnormal(x); }
+    extern(C) pragma(mangle, "__isnormal")  pure int isnormal(double x);
     ///
-    pure int isnormal(real x)        { return __isnormall(x); }
+    extern(C) pragma(mangle, "__isnormall") pure int isnormal(real x);
 
     //int signbit(real-floating x);
     ///
-    pure int signbit(float x)        { return __signbitf(x); }
+    extern(C) pragma(mangle, "__signbitf") pure int signbit(float x);
     ///
-    pure int signbit(double x)       { return __signbit(x); }
+    extern(C) pragma(mangle, "__signbit")  pure int signbit(double x);
     ///
     pure int signbit(real x)         { return __signbit(x); }
   }
@@ -1256,27 +1186,27 @@ else version (OpenBSD)
   {
     //int fpclassify(real-floating x);
       ///
-    pure int fpclassify(float x)     { return __fpclassifyf(x); }
+    extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x);
     ///
-    pure int fpclassify(double x)    { return __fpclassifyd(x); }
+    extern(C) pragma(mangle, "__fpclassifyd") pure int fpclassify(double x);
     ///
-    pure int fpclassify(real x)      { return __fpclassifyl(x); }
+    extern(C) pragma(mangle, "__fpclassifyl") pure int fpclassify(real x);
 
     //int isfinite(real-floating x);
     ///
-    pure int isfinite(float x)       { return __isfinitef(x); }
+    extern(C) pragma(mangle, "__isfinitef") pure int isfinite(float x);
     ///
-    pure int isfinite(double x)      { return __isfinite(x); }
+    extern(C) pragma(mangle, "__isfinite")  pure int isfinite(double x);
     ///
-    pure int isfinite(real x)        { return __isfinitel(x); }
+    extern(C) pragma(mangle, "__isfinitel") pure int isfinite(real x);
 
     //int isinf(real-floating x);
     ///
-    pure int isinf(float x)          { return __isinff(x); }
+    extern(C) pragma(mangle, "__isinff") pure int isinf(float x);
     ///
     pure int isinf(double x)         { return __isinfl(x); }
     ///
-    pure int isinf(real x)           { return __isinfl(x); }
+    extern(C) pragma(mangle, "__isinfl") pure int isinf(real x);
 
     //int isnan(real-floating x);
     ///
@@ -1284,21 +1214,21 @@ else version (OpenBSD)
     ///
     pure int isnan(double x)         { return __isnanl(x); }
     ///
-    pure int isnan(real x)           { return __isnanl(x); }
+    extern(C) pragma(mangle, "__isnanl") pure int isnan(real x);
 
     //int isnormal(real-floating x);
     ///
-    pure int isnormal(float x)       { return __isnormalf(x); }
+    extern(C) pragma(mangle, "__isnormalf") pure int isnormal(float x);
     ///
-    pure int isnormal(double x)      { return __isnormal(x); }
+    extern(C) pragma(mangle, "__isnormal")  pure int isnormal(double x);
     ///
-    pure int isnormal(real x)        { return __isnormall(x); }
+    extern(C) pragma(mangle, "__isnormall") pure int isnormal(real x);
 
     //int signbit(real-floating x);
     ///
-    pure int signbit(float x)        { return __signbitf(x); }
+    extern(C) pragma(mangle, "__signbitf") pure int signbit(float x);
     ///
-    pure int signbit(double x)       { return __signbit(x); }
+    extern(C) pragma(mangle, "__signbit")  pure int signbit(double x);
     ///
     pure int signbit(real x)         { return __signbit(x); }
   }
@@ -1337,16 +1267,12 @@ else version (NetBSD)
   {
     //int fpclassify(real-floating x);
     ///
-    pure int fpclassify(float x)     { return __fpclassifyf(x); }
+    extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x);
     ///
-    pure int fpclassify(double x)    { return __fpclassifyd(x); }
+    extern(C) pragma(mangle, "__fpclassifyd") pure int fpclassify(double x);
     ///
-    pure int fpclassify(real x)
-    {
-        return (real.sizeof == double.sizeof)
-            ? __fpclassifyd(x)
-            : __fpclassifyl(x);
-    }
+    extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__fpclassifyd" : "__fpclassifyl")
+    pure int fpclassify(real x);
 
     //int isfinite(real-floating x);
     ///
@@ -1433,29 +1359,29 @@ else version (DragonFlyBSD)
 
   extern (D)
   {
-    pure int fpclassify(float x)     { return __fpclassifyf(x); }
-    pure int fpclassify(double x)    { return __fpclassifyd(x); }
-    pure int fpclassify(real x)      { return __fpclassifyl(x); }
+    extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x);
+    extern(C) pragma(mangle, "__fpclassifyd") pure int fpclassify(double x);
+    extern(C) pragma(mangle, "__fpclassifyl") pure int fpclassify(real x);
 
-    pure int isfinite(float x)       { return __isfinitef(x); }
-    pure int isfinite(double x)      { return __isfinite(x); }
-    pure int isfinite(real x)        { return __isfinitel(x); }
+    extern(C) pragma(mangle, "__isfinitef") pure int isfinite(float x);
+    extern(C) pragma(mangle, "__isfinite")  pure int isfinite(double x);
+    extern(C) pragma(mangle, "__isfinitel") pure int isfinite(real x);
 
-    pure int isinf(float x)          { return __isinff(x); }
-    pure int isinf(double x)         { return __isinf(x); }
-    pure int isinf(real x)           { return __isinfl(x); }
+    extern(C) pragma(mangle, "__isinff") pure int isinf(float x);
+    extern(C) pragma(mangle, "__isinf")  pure int isinf(double x);
+    extern(C) pragma(mangle, "__isinfl") pure int isinf(real x);
 
-    pure int isnan(float x)          { return __isnanf(x); }
-    pure int isnan(double x)         { return __isnan(x); }
-    pure int isnan(real x)           { return __isnanl(x); }
+    extern(C) pragma(mangle, "__isnanf") pure int isnan(float x);
+    extern(C) pragma(mangle, "__isnan")  pure int isnan(double x);
+    extern(C) pragma(mangle, "__isnanl") pure int isnan(real x);
 
-    pure int isnormal(float x)       { return __isnormalf(x); }
-    pure int isnormal(double x)      { return __isnormal(x); }
-    pure int isnormal(real x)        { return __isnormall(x); }
+    extern(C) pragma(mangle, "__isnormalf") pure int isnormal(float x);
+    extern(C) pragma(mangle, "__isnormal")  pure int isnormal(double x);
+    extern(C) pragma(mangle, "__isnormall") pure int isnormal(real x);
 
-    pure int signbit(float x)        { return __signbitf(x); }
-    pure int signbit(double x)       { return __signbit(x); }
-    pure int signbit(real x)         { return __signbitl(x); }
+    extern(C) pragma(mangle, "__signbitf") pure int signbit(float x);
+    extern(C) pragma(mangle, "__signbit")  pure int signbit(double x);
+    extern(C) pragma(mangle, "__signbitl") pure int signbit(real x);
   }
 }
 else version (Solaris)
@@ -1468,16 +1394,12 @@ else version (Solaris)
   {
     //int isnan(real-floating x);
       ///
-    pure int isnan(float x)          { return __isnanf(x);  }
+    extern(C) pragma(mangle, "__isnanf") pure int isnan(float x);
     ///
-    pure int isnan(double x)         { return __isnan(x);   }
+    extern(C) pragma(mangle, "__isnan")  pure int isnan(double x);
     ///
-    pure int isnan(real x)
-    {
-        return (real.sizeof == double.sizeof)
-            ? __isnan(x)
-            : __isnanl(x);
-    }
+    extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__isnan" : "__isnanl")
+    pure int isnan(real x);
   }
 }
 else version (CRuntime_Bionic)
@@ -1527,49 +1449,49 @@ else version (CRuntime_Bionic)
   {
     //int fpclassify(real-floating x);
       ///
-    pure int fpclassify(float x)     { return __fpclassifyf(x); }
+    extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x);
     ///
-    pure int fpclassify(double x)    { return __fpclassifyd(x); }
+    extern(C) pragma(mangle, "__fpclassifyd") pure int fpclassify(double x);
     ///
-    pure int fpclassify(real x)      { return __fpclassifyl(x); }
+    extern(C) pragma(mangle, "__fpclassifyl") pure int fpclassify(real x);
 
     //int isfinite(real-floating x);
     ///
-    pure int isfinite(float x)       { return __isfinitef(x); }
+    extern(C) pragma(mangle, "__isfinitef") pure int isfinite(float x);
     ///
-    pure int isfinite(double x)      { return __isfinite(x); }
+    extern(C) pragma(mangle, "__isfinite")  pure int isfinite(double x);
     ///
-    pure int isfinite(real x)        { return __isfinitel(x); }
+    extern(C) pragma(mangle, "__isfinitel") pure int isfinite(real x);
 
     //int isinf(real-floating x);
     ///
-    pure int isinf(float x)          { return __isinff(x); }
+    extern(C) pragma(mangle, "__isinff") pure int isinf(float x);
     ///
-    pure int isinf(double x)         { return __isinf(x); }
+    extern(C) pragma(mangle, "__isinf")  pure int isinf(double x);
     ///
-    pure int isinf(real x)           { return __isinfl(x); }
+    extern(C) pragma(mangle, "__isinfl") pure int isinf(real x);
 
     //int isnan(real-floating x);
     ///
-    pure int isnan(float x)          { return isnanf(x); }
+    extern(C) pragma(mangle, "isnanf")   pure int isnan(float x);
     ///
-    pure int isnan(real x)           { return __isnanl(x); }
+    extern(C) pragma(mangle, "__isnanl") pure int isnan(real x);
 
     //int isnormal(real-floating x);
     ///
-    pure int isnormal(float x)       { return __isnormalf(x); }
+    extern(C) pragma(mangle, "__isnormalf") pure int isnormal(float x);
     ///
-    pure int isnormal(double x)      { return __isnormal(x); }
+    extern(C) pragma(mangle, "__isnormal")  pure int isnormal(double x);
     ///
-    pure int isnormal(real x)        { return __isnormall(x); }
+    extern(C) pragma(mangle, "__isnormall") pure int isnormal(real x);
 
     //int signbit(real-floating x);
     ///
-    pure int signbit(float x)        { return __signbitf(x); }
+    extern(C) pragma(mangle, "__signbitf") pure int signbit(float x);
     ///
-    pure int signbit(double x)       { return __signbit(x); }
+    extern(C) pragma(mangle, "__signbit")  pure int signbit(double x);
     ///
-    pure int signbit(real x)         { return __signbitl(x); }
+    extern(C) pragma(mangle, "__signbitl") pure int signbit(real x);
   }
 }
 
@@ -1841,14 +1763,12 @@ version (CRuntime_Microsoft) // fully supported since MSVCRT 12 (VS 2013) only
     ///
     extern(D) pure real  fabsl()(real x)  { return fabs(cast(double) x); }
 
-    private double _hypot(double x, double y);
-    private float  _hypotf(float x, float y);
     ///
-    extern(D) double hypot(double x, double y) { return _hypot(x, y); }
+    extern(C) pragma(mangle, "_hypot")  double hypot(double x, double y);
     ///
-    extern(D) float  hypotf(float x, float y)  { return _hypotf(x, y); }
+    extern(C) pragma(mangle, "_hypotf") float  hypotf(float x, float y);
     ///
-    extern(D) real   hypotl(real x, real y)    { return _hypot(cast(double) x, cast(double) y); }
+    extern(D) real   hypotl(real x, real y)    { return hypot(cast(double) x, cast(double) y); }
 
     ///
     double  pow(double x, double y);
diff --git a/libphobos/libdruntime/core/stdc/stdio.d b/libphobos/libdruntime/core/stdc/stdio.d
index 67011596b1c..532a0803f55 100644
--- a/libphobos/libdruntime/core/stdc/stdio.d
+++ b/libphobos/libdruntime/core/stdc/stdio.d
@@ -1166,61 +1166,73 @@ version (MinGW)
     // Prefer the MinGW versions over the MSVC ones, as the latter don't handle
     // reals at all.
     ///
+    pragma(printf)
     int __mingw_fprintf(FILE* stream, scope const char* format, scope const ...);
     ///
     alias __mingw_fprintf fprintf;
 
     ///
+    pragma(scanf)
     int __mingw_fscanf(FILE* stream, scope const char* format, scope ...);
     ///
     alias __mingw_fscanf fscanf;
 
     ///
+    pragma(printf)
     int __mingw_sprintf(scope char* s, scope const char* format, scope const ...);
     ///
     alias __mingw_sprintf sprintf;
 
     ///
+    pragma(scanf)
     int __mingw_sscanf(scope const char* s, scope const char* format, scope ...);
     ///
     alias __mingw_sscanf sscanf;
 
     ///
+    pragma(printf)
     int __mingw_vfprintf(FILE* stream, scope const char* format, va_list arg);
     ///
     alias __mingw_vfprintf vfprintf;
 
     ///
+    pragma(scanf)
     int __mingw_vfscanf(FILE* stream, scope const char* format, va_list arg);
     ///
     alias __mingw_vfscanf vfscanf;
 
     ///
+    pragma(printf)
     int __mingw_vsprintf(scope char* s, scope const char* format, va_list arg);
     ///
     alias __mingw_vsprintf vsprintf;
 
     ///
+    pragma(scanf)
     int __mingw_vsscanf(scope const char* s, scope const char* format, va_list arg);
     ///
     alias __mingw_vsscanf vsscanf;
 
     ///
+    pragma(printf)
     int __mingw_vprintf(scope const char* format, va_list arg);
     ///
     alias __mingw_vprintf vprintf;
 
     ///
+    pragma(scanf)
     int __mingw_vscanf(scope const char* format, va_list arg);
     ///
     alias __mingw_vscanf vscanf;
 
     ///
+    pragma(printf)
     int __mingw_printf(scope const char* format, scope const ...);
     ///
     alias __mingw_printf printf;
 
     ///
+    pragma(scanf)
     int __mingw_scanf(scope const char* format, scope ...);
     ///
     alias __mingw_scanf scanf;
@@ -1228,28 +1240,40 @@ version (MinGW)
 else
 {
     ///
+    pragma(printf)
     int fprintf(FILE* stream, scope const char* format, scope const ...);
     ///
+    pragma(scanf)
     int fscanf(FILE* stream, scope const char* format, scope ...);
     ///
+    pragma(printf)
     int sprintf(scope char* s, scope const char* format, scope const ...);
     ///
+    pragma(scanf)
     int sscanf(scope const char* s, scope const char* format, scope ...);
     ///
+    pragma(printf)
     int vfprintf(FILE* stream, scope const char* format, va_list arg);
     ///
+    pragma(scanf)
     int vfscanf(FILE* stream, scope const char* format, va_list arg);
     ///
+    pragma(printf)
     int vsprintf(scope char* s, scope const char* format, va_list arg);
     ///
+    pragma(scanf)
     int vsscanf(scope const char* s, scope const char* format, va_list arg);
     ///
+    pragma(printf)
     int vprintf(scope const char* format, va_list arg);
     ///
+    pragma(scanf)
     int vscanf(scope const char* format, va_list arg);
     ///
+    pragma(printf)
     int printf(scope const char* format, scope const ...);
     ///
+    pragma(scanf)
     int scanf(scope const char* format, scope ...);
 }
 
@@ -1278,12 +1302,13 @@ extern (D) @trusted
     int getchar()()                 { return getc(stdin);     }
     ///
     int putchar()(int c)            { return putc(c,stdout);  }
-    ///
-    int getc()(FILE* stream)        { return fgetc(stream);   }
-    ///
-    int putc()(int c, FILE* stream) { return fputc(c,stream); }
 }
 
+///
+alias getc = fgetc;
+///
+alias putc = fputc;
+
 ///
 @trusted int ungetc(int c, FILE* stream); // No unsafe pointer manipulation.
 
@@ -1323,11 +1348,13 @@ version (CRuntime_DigitalMars)
     pure int  fileno()(FILE* stream)   { return stream._file; }
   }
   ///
+    pragma(printf)
     int   _snprintf(scope char* s, size_t n, scope const char* fmt, scope const ...);
     ///
     alias _snprintf snprintf;
 
     ///
+    pragma(printf)
     int   _vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
     ///
     alias _vsnprintf vsnprintf;
@@ -1351,6 +1378,7 @@ else version (CRuntime_Microsoft)
 
   version (MinGW)
   {
+    pragma(printf)
     int   __mingw_snprintf(scope char* s, size_t n, scope const char* fmt, scope const ...);
     ///
     alias __mingw_snprintf _snprintf;
@@ -1358,6 +1386,7 @@ else version (CRuntime_Microsoft)
     alias __mingw_snprintf snprintf;
 
     ///
+    pragma(printf)
     int   __mingw_vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
     ///
     alias __mingw_vsnprintf _vsnprintf;
@@ -1367,13 +1396,17 @@ else version (CRuntime_Microsoft)
   else
   {
     ///
+    pragma(printf)
     int _snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
     ///
+    pragma(printf)
     int  snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
 
     ///
+    pragma(printf)
     int _vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
     ///
+    pragma(printf)
     int  vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
   }
 
@@ -1410,8 +1443,10 @@ else version (CRuntime_Glibc)
   }
 
     ///
+    pragma(printf)
     int  snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
     ///
+    pragma(printf)
     int  vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
 }
 else version (Darwin)
@@ -1432,8 +1467,10 @@ else version (Darwin)
   }
 
     ///
+    pragma(printf)
     int  snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
     ///
+    pragma(printf)
     int  vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
 }
 else version (FreeBSD)
@@ -1454,8 +1491,10 @@ else version (FreeBSD)
   }
 
     ///
+    pragma(printf)
     int  snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
     ///
+    pragma(printf)
     int  vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
 }
 else version (NetBSD)
@@ -1476,8 +1515,10 @@ else version (NetBSD)
   }
 
     ///
+    pragma(printf)
     int  snprintf(char* s, size_t n, const scope char* format, scope const ...);
     ///
+    pragma(printf)
     int  vsnprintf(char* s, size_t n, const scope char* format, va_list arg);
 }
 else version (OpenBSD)
@@ -1567,8 +1608,10 @@ else version (OpenBSD)
     }
 
     ///
+    pragma(printf)
     int  snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
     ///
+    pragma(printf)
     int  vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
 }
 else version (DragonFlyBSD)
@@ -1599,7 +1642,9 @@ else version (DragonFlyBSD)
   enum __SALC = 0x4000;
   enum __SIGN = 0x8000;
 
+    pragma(printf)
     int  snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
+    pragma(printf)
     int  vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
 }
 else version (Solaris)
@@ -1620,8 +1665,10 @@ else version (Solaris)
   }
 
     ///
+    pragma(printf)
     int  snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
     ///
+    pragma(printf)
     int  vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
 }
 else version (CRuntime_Bionic)
@@ -1642,8 +1689,10 @@ else version (CRuntime_Bionic)
   }
 
     ///
+    pragma(printf)
     int  snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
     ///
+    pragma(printf)
     int  vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
 }
 else version (CRuntime_Musl)
@@ -1663,8 +1712,10 @@ else version (CRuntime_Musl)
     }
 
     ///
+    pragma(printf)
     int snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
     ///
+    pragma(printf)
     int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
 }
 else version (CRuntime_UClibc)
@@ -1685,8 +1736,10 @@ else version (CRuntime_UClibc)
   }
 
     ///
+    pragma(printf)
     int  snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
     ///
+    pragma(printf)
     int  vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
 }
 else
diff --git a/libphobos/libdruntime/core/stdc/stdlib.d b/libphobos/libdruntime/core/stdc/stdlib.d
index 7caef4c1339..5d69b880bc8 100644
--- a/libphobos/libdruntime/core/stdc/stdlib.d
+++ b/libphobos/libdruntime/core/stdc/stdlib.d
@@ -164,13 +164,13 @@ void*   realloc(void* ptr, size_t size);
 void    free(void* ptr);
 
 ///
-void    abort() @safe;
+noreturn abort() @safe;
 ///
-void    exit(int status);
+noreturn exit(int status);
 ///
 int     atexit(void function() func);
 ///
-void    _Exit(int status);
+noreturn _Exit(int status);
 
 ///
 char*   getenv(scope const char* name);
diff --git a/libphobos/libdruntime/core/stdc/tgmath.d b/libphobos/libdruntime/core/stdc/tgmath.d
index 4dd1b3ccc66..2ff1522fd81 100644
--- a/libphobos/libdruntime/core/stdc/tgmath.d
+++ b/libphobos/libdruntime/core/stdc/tgmath.d
@@ -32,12 +32,10 @@ version (NetBSD)
     ///
     alias core.stdc.math.acosl         acos;
 
-    ///
-    alias core.stdc.complex.cacos      acos;
-    ///
-    alias core.stdc.complex.cacosf     acos;
-    ///
-    alias core.stdc.complex.cacosl     acos;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.cacos      acos;
+    deprecated alias core.stdc.complex.cacosf     acos;
+    deprecated alias core.stdc.complex.cacosl     acos;
 
     ///
     alias core.stdc.math.asin          asin;
@@ -46,12 +44,10 @@ version (NetBSD)
     ///
     alias core.stdc.math.asinl         asin;
 
-    ///
-    alias core.stdc.complex.casin      asin;
-    ///
-    alias core.stdc.complex.casinf     asin;
-    ///
-    alias core.stdc.complex.casinl     asin;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.casin      asin;
+    deprecated alias core.stdc.complex.casinf     asin;
+    deprecated alias core.stdc.complex.casinl     asin;
 
     ///
     alias core.stdc.math.atan          atan;
@@ -60,12 +56,10 @@ version (NetBSD)
     ///
     alias core.stdc.math.atanl         atan;
 
-    ///
-    alias core.stdc.complex.catan      atan;
-    ///
-    alias core.stdc.complex.catanf     atan;
-    ///
-    alias core.stdc.complex.catanl     atan;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.catan      atan;
+    deprecated alias core.stdc.complex.catanf     atan;
+    deprecated alias core.stdc.complex.catanl     atan;
 
     ///
     alias core.stdc.math.atan2         atan2;
@@ -81,12 +75,10 @@ version (NetBSD)
     ///
     alias core.stdc.math.cosl          cos;
 
-    ///
-    alias core.stdc.complex.ccos       cos;
-    ///
-    alias core.stdc.complex.ccosf      cos;
-    ///
-    alias core.stdc.complex.ccosl      cos;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.ccos       cos;
+    deprecated alias core.stdc.complex.ccosf      cos;
+    deprecated alias core.stdc.complex.ccosl      cos;
 
     ///
     alias core.stdc.math.sin           sin;
@@ -95,12 +87,10 @@ version (NetBSD)
     ///
     alias core.stdc.math.sinl          sin;
 
-    ///
-    alias core.stdc.complex.csin       csin;
-    ///
-    alias core.stdc.complex.csinf      csin;
-    ///
-    alias core.stdc.complex.csinl      csin;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.csin       csin;
+    deprecated alias core.stdc.complex.csinf      csin;
+    deprecated alias core.stdc.complex.csinl      csin;
 
     ///
     alias core.stdc.math.tan           tan;
@@ -109,12 +99,10 @@ version (NetBSD)
     ///
     alias core.stdc.math.tanl          tan;
 
-    ///
-    alias core.stdc.complex.ctan       tan;
-    ///
-    alias core.stdc.complex.ctanf      tan;
-    ///
-    alias core.stdc.complex.ctanl      tan;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.ctan       tan;
+    deprecated alias core.stdc.complex.ctanf      tan;
+    deprecated alias core.stdc.complex.ctanl      tan;
 
     ///
     alias core.stdc.math.acosh         acosh;
@@ -123,12 +111,10 @@ version (NetBSD)
     ///
     alias core.stdc.math.acoshl        acosh;
 
-    ///
-    alias core.stdc.complex.cacosh     acosh;
-    ///
-    alias core.stdc.complex.cacoshf    acosh;
-    ///
-    alias core.stdc.complex.cacoshl    acosh;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.cacosh     acosh;
+    deprecated alias core.stdc.complex.cacoshf    acosh;
+    deprecated alias core.stdc.complex.cacoshl    acosh;
 
     ///
     alias core.stdc.math.asinh         asinh;
@@ -137,12 +123,10 @@ version (NetBSD)
     ///
     alias core.stdc.math.asinhl        asinh;
 
-    ///
-    alias core.stdc.complex.casinh     asinh;
-    ///
-    alias core.stdc.complex.casinhf    asinh;
-    ///
-    alias core.stdc.complex.casinhl    asinh;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.casinh     asinh;
+    deprecated alias core.stdc.complex.casinhf    asinh;
+    deprecated alias core.stdc.complex.casinhl    asinh;
 
     ///
     alias core.stdc.math.atanh         atanh;
@@ -151,12 +135,10 @@ version (NetBSD)
     ///
     alias core.stdc.math.atanhl        atanh;
 
-    ///
-    alias core.stdc.complex.catanh     atanh;
-    ///
-    alias core.stdc.complex.catanhf    atanh;
-    ///
-    alias core.stdc.complex.catanhl    atanh;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.catanh     atanh;
+    deprecated alias core.stdc.complex.catanhf    atanh;
+    deprecated alias core.stdc.complex.catanhl    atanh;
 
     ///
     alias core.stdc.math.cosh          cosh;
@@ -165,12 +147,10 @@ version (NetBSD)
     ///
     alias core.stdc.math.coshl         cosh;
 
-    ///
-    alias core.stdc.complex.ccosh      cosh;
-    ///
-    alias core.stdc.complex.ccoshf     cosh;
-    ///
-    alias core.stdc.complex.ccoshl     cosh;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.ccosh      cosh;
+    deprecated alias core.stdc.complex.ccoshf     cosh;
+    deprecated alias core.stdc.complex.ccoshl     cosh;
 
     ///
     alias core.stdc.math.sinh          sinh;
@@ -179,12 +159,10 @@ version (NetBSD)
     ///
     alias core.stdc.math.sinhl         sinh;
 
-    ///
-    alias core.stdc.complex.csinh      sinh;
-    ///
-    alias core.stdc.complex.csinhf     sinh;
-    ///
-    alias core.stdc.complex.csinhl     sinh;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.csinh      sinh;
+    deprecated alias core.stdc.complex.csinhf     sinh;
+    deprecated alias core.stdc.complex.csinhl     sinh;
 
     ///
     alias core.stdc.math.tanh          tanh;
@@ -193,12 +171,10 @@ version (NetBSD)
     ///
     alias core.stdc.math.tanhl         tanh;
 
-    ///
-    alias core.stdc.complex.ctanh      tanh;
-    ///
-    alias core.stdc.complex.ctanhf     tanh;
-    ///
-    alias core.stdc.complex.ctanhl     tanh;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.ctanh      tanh;
+    deprecated alias core.stdc.complex.ctanhf     tanh;
+    deprecated alias core.stdc.complex.ctanhl     tanh;
 
     ///
     alias core.stdc.math.exp           exp;
@@ -207,12 +183,10 @@ version (NetBSD)
     ///
     alias core.stdc.math.expl          exp;
 
-    ///
-    alias core.stdc.complex.cexp       exp;
-    ///
-    alias core.stdc.complex.cexpf      exp;
-    ///
-    alias core.stdc.complex.cexpl      exp;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.cexp       exp;
+    deprecated alias core.stdc.complex.cexpf      exp;
+    deprecated alias core.stdc.complex.cexpl      exp;
 
     ///
     alias core.stdc.math.exp2          exp2;
@@ -256,12 +230,10 @@ version (NetBSD)
     ///
     alias core.stdc.math.logl          log;
 
-    ///
-    alias core.stdc.complex.clog       log;
-    ///
-    alias core.stdc.complex.clogf      log;
-    ///
-    alias core.stdc.complex.clogl      log;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.clog       log;
+    deprecated alias core.stdc.complex.clogf      log;
+    deprecated alias core.stdc.complex.clogl      log;
 
     ///
     alias core.stdc.math.log10         log10;
@@ -325,12 +297,10 @@ version (NetBSD)
     ///
     alias core.stdc.math.fabsl         fabs;
 
-    ///
-    alias core.stdc.complex.cabs       fabs;
-    ///
-    alias core.stdc.complex.cabsf      fabs;
-    ///
-    alias core.stdc.complex.cabsl      fabs;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.cabs       fabs;
+    deprecated alias core.stdc.complex.cabsf      fabs;
+    deprecated alias core.stdc.complex.cabsl      fabs;
 
     ///
     alias core.stdc.math.hypot         hypot;
@@ -346,12 +316,10 @@ version (NetBSD)
     ///
     alias core.stdc.math.powl          pow;
 
-    ///
-    alias core.stdc.complex.cpow       pow;
-    ///
-    alias core.stdc.complex.cpowf      pow;
-    ///
-    alias core.stdc.complex.cpowl      pow;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.cpow       pow;
+    deprecated alias core.stdc.complex.cpowf      pow;
+    deprecated alias core.stdc.complex.cpowl      pow;
 
     ///
     alias core.stdc.math.sqrt          sqrt;
@@ -360,12 +328,10 @@ version (NetBSD)
     ///
     alias core.stdc.math.sqrtl         sqrt;
 
-    ///
-    alias core.stdc.complex.csqrt      sqrt;
-    ///
-    alias core.stdc.complex.csqrtf     sqrt;
-    ///
-    alias core.stdc.complex.csqrtl     sqrt;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.csqrt      sqrt;
+    deprecated alias core.stdc.complex.csqrtf     sqrt;
+    deprecated alias core.stdc.complex.csqrtl     sqrt;
 
     ///
     alias core.stdc.math.erf           erf;
@@ -539,37 +505,23 @@ version (NetBSD)
     ///
     alias core.stdc.math.fmal          fma;
 
-    ///
-    alias core.stdc.complex.carg       carg;
-    ///
-    alias core.stdc.complex.cargf      carg;
-    ///
-    alias core.stdc.complex.cargl      carg;
-
-    ///
-    alias core.stdc.complex.cimag      cimag;
-    ///
-    alias core.stdc.complex.cimagf     cimag;
-    ///
-    alias core.stdc.complex.cimagl     cimag;
-
-    ///
-    alias core.stdc.complex.conj       conj;
-    ///
-    alias core.stdc.complex.conjf      conj;
-    ///
-    alias core.stdc.complex.conjl      conj;
-
-    ///
-    alias core.stdc.complex.cproj      cproj;
-    ///
-    alias core.stdc.complex.cprojf     cproj;
-    ///
-    alias core.stdc.complex.cprojl     cproj;
-
-//  alias core.stdc.complex.creal      creal;
-//  alias core.stdc.complex.crealf     creal;
-//  alias core.stdc.complex.creall     creal;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.carg       carg;
+    deprecated alias core.stdc.complex.cargf      carg;
+    deprecated alias core.stdc.complex.cargl      carg;
+    deprecated alias core.stdc.complex.cimag      cimag;
+    deprecated alias core.stdc.complex.cimagf     cimag;
+    deprecated alias core.stdc.complex.cimagl     cimag;
+    deprecated alias core.stdc.complex.conj       conj;
+    deprecated alias core.stdc.complex.conjf      conj;
+    deprecated alias core.stdc.complex.conjl      conj;
+    deprecated alias core.stdc.complex.cproj      cproj;
+    deprecated alias core.stdc.complex.cprojf     cproj;
+    deprecated alias core.stdc.complex.cprojl     cproj;
+
+//  deprecated alias core.stdc.complex.creal      creal;
+//  deprecated alias core.stdc.complex.crealf     creal;
+//  deprecated alias core.stdc.complex.creall     creal;
 }
 else version (OpenBSD)
 {
@@ -580,12 +532,10 @@ else version (OpenBSD)
     ///
     alias core.stdc.math.acosl         acos;
 
-    ///
-    alias core.stdc.complex.cacos      acos;
-    ///
-    alias core.stdc.complex.cacosf     acos;
-    ///
-    alias core.stdc.complex.cacosl     acos;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.cacos      acos;
+    deprecated alias core.stdc.complex.cacosf     acos;
+    deprecated alias core.stdc.complex.cacosl     acos;
 
     ///
     alias core.stdc.math.asin          asin;
@@ -594,12 +544,10 @@ else version (OpenBSD)
     ///
     alias core.stdc.math.asinl         asin;
 
-    ///
-    alias core.stdc.complex.casin      asin;
-    ///
-    alias core.stdc.complex.casinf     asin;
-    ///
-    alias core.stdc.complex.casinl     asin;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.casin      asin;
+    deprecated alias core.stdc.complex.casinf     asin;
+    deprecated alias core.stdc.complex.casinl     asin;
 
     ///
     alias core.stdc.math.atan          atan;
@@ -608,12 +556,10 @@ else version (OpenBSD)
     ///
     alias core.stdc.math.atanl         atan;
 
-    ///
-    alias core.stdc.complex.catan      atan;
-    ///
-    alias core.stdc.complex.catanf     atan;
-    ///
-    alias core.stdc.complex.catanl     atan;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.catan      atan;
+    deprecated alias core.stdc.complex.catanf     atan;
+    deprecated alias core.stdc.complex.catanl     atan;
 
     ///
     alias core.stdc.math.atan2         atan2;
@@ -629,12 +575,10 @@ else version (OpenBSD)
     ///
     alias core.stdc.math.cosl          cos;
 
-    ///
-    alias core.stdc.complex.ccos       cos;
-    ///
-    alias core.stdc.complex.ccosf      cos;
-    ///
-    alias core.stdc.complex.ccosl      cos;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.ccos       cos;
+    deprecated alias core.stdc.complex.ccosf      cos;
+    deprecated alias core.stdc.complex.ccosl      cos;
 
     ///
     alias core.stdc.math.sin           sin;
@@ -643,12 +587,10 @@ else version (OpenBSD)
     ///
     alias core.stdc.math.sinl          sin;
 
-    ///
-    alias core.stdc.complex.csin       csin;
-    ///
-    alias core.stdc.complex.csinf      csin;
-    ///
-    alias core.stdc.complex.csinl      csin;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.csin       csin;
+    deprecated alias core.stdc.complex.csinf      csin;
+    deprecated alias core.stdc.complex.csinl      csin;
 
     ///
     alias core.stdc.math.tan           tan;
@@ -657,12 +599,10 @@ else version (OpenBSD)
     ///
     alias core.stdc.math.tanl          tan;
 
-    ///
-    alias core.stdc.complex.ctan       tan;
-    ///
-    alias core.stdc.complex.ctanf      tan;
-    ///
-    alias core.stdc.complex.ctanl      tan;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.ctan       tan;
+    deprecated alias core.stdc.complex.ctanf      tan;
+    deprecated alias core.stdc.complex.ctanl      tan;
 
     ///
     alias core.stdc.math.acosh         acosh;
@@ -671,12 +611,10 @@ else version (OpenBSD)
     ///
     alias core.stdc.math.acoshl        acosh;
 
-    ///
-    alias core.stdc.complex.cacosh     acosh;
-    ///
-    alias core.stdc.complex.cacoshf    acosh;
-    ///
-    alias core.stdc.complex.cacoshl    acosh;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.cacosh     acosh;
+    deprecated alias core.stdc.complex.cacoshf    acosh;
+    deprecated alias core.stdc.complex.cacoshl    acosh;
 
     ///
     alias core.stdc.math.asinh         asinh;
@@ -685,12 +623,10 @@ else version (OpenBSD)
     ///
     alias core.stdc.math.asinhl        asinh;
 
-    ///
-    alias core.stdc.complex.casinh     asinh;
-    ///
-    alias core.stdc.complex.casinhf    asinh;
-    ///
-    alias core.stdc.complex.casinhl    asinh;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.casinh     asinh;
+    deprecated alias core.stdc.complex.casinhf    asinh;
+    deprecated alias core.stdc.complex.casinhl    asinh;
 
     ///
     alias core.stdc.math.atanh         atanh;
@@ -699,12 +635,10 @@ else version (OpenBSD)
     ///
     alias core.stdc.math.atanhl        atanh;
 
-    ///
-    alias core.stdc.complex.catanh     atanh;
-    ///
-    alias core.stdc.complex.catanhf    atanh;
-    ///
-    alias core.stdc.complex.catanhl    atanh;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.catanh     atanh;
+    deprecated alias core.stdc.complex.catanhf    atanh;
+    deprecated alias core.stdc.complex.catanhl    atanh;
 
     ///
     alias core.stdc.math.cosh          cosh;
@@ -713,12 +647,10 @@ else version (OpenBSD)
     ///
     alias core.stdc.math.coshl         cosh;
 
-    ///
-    alias core.stdc.complex.ccosh      cosh;
-    ///
-    alias core.stdc.complex.ccoshf     cosh;
-    ///
-    alias core.stdc.complex.ccoshl     cosh;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.ccosh      cosh;
+    deprecated alias core.stdc.complex.ccoshf     cosh;
+    deprecated alias core.stdc.complex.ccoshl     cosh;
 
     ///
     alias core.stdc.math.sinh          sinh;
@@ -727,12 +659,10 @@ else version (OpenBSD)
     ///
     alias core.stdc.math.sinhl         sinh;
 
-    ///
-    alias core.stdc.complex.csinh      sinh;
-    ///
-    alias core.stdc.complex.csinhf     sinh;
-    ///
-    alias core.stdc.complex.csinhl     sinh;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.csinh      sinh;
+    deprecated alias core.stdc.complex.csinhf     sinh;
+    deprecated alias core.stdc.complex.csinhl     sinh;
 
     ///
     alias core.stdc.math.tanh          tanh;
@@ -741,12 +671,10 @@ else version (OpenBSD)
     ///
     alias core.stdc.math.tanhl         tanh;
 
-    ///
-    alias core.stdc.complex.ctanh      tanh;
-    ///
-    alias core.stdc.complex.ctanhf     tanh;
-    ///
-    alias core.stdc.complex.ctanhl     tanh;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.ctanh      tanh;
+    deprecated alias core.stdc.complex.ctanhf     tanh;
+    deprecated alias core.stdc.complex.ctanhl     tanh;
 
     ///
     alias core.stdc.math.exp           exp;
@@ -755,12 +683,10 @@ else version (OpenBSD)
     ///
     alias core.stdc.math.expl          exp;
 
-    ///
-    alias core.stdc.complex.cexp       exp;
-    ///
-    alias core.stdc.complex.cexpf      exp;
-    ///
-    alias core.stdc.complex.cexpl      exp;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.cexp       exp;
+    deprecated alias core.stdc.complex.cexpf      exp;
+    deprecated alias core.stdc.complex.cexpl      exp;
 
     ///
     alias core.stdc.math.exp2          exp2;
@@ -804,12 +730,10 @@ else version (OpenBSD)
     ///
     alias core.stdc.math.logl          log;
 
-    ///
-    alias core.stdc.complex.clog       log;
-    ///
-    alias core.stdc.complex.clogf      log;
-    ///
-    alias core.stdc.complex.clogl      log;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.clog       log;
+    deprecated alias core.stdc.complex.clogf      log;
+    deprecated alias core.stdc.complex.clogl      log;
 
     ///
     alias core.stdc.math.log10         log10;
@@ -874,12 +798,10 @@ else version (OpenBSD)
     ///
     alias core.stdc.math.fabsl         fabs;
 
-    ///
-    alias core.stdc.complex.cabs       fabs;
-    ///
-    alias core.stdc.complex.cabsf      fabs;
-    ///
-    alias core.stdc.complex.cabsl      fabs;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.cabs       fabs;
+    deprecated alias core.stdc.complex.cabsf      fabs;
+    deprecated alias core.stdc.complex.cabsl      fabs;
 
     ///
     alias core.stdc.math.hypot         hypot;
@@ -895,12 +817,10 @@ else version (OpenBSD)
     ///
     alias core.stdc.math.powl          pow;
 
-    ///
-    alias core.stdc.complex.cpow       pow;
-    ///
-    alias core.stdc.complex.cpowf      pow;
-    ///
-    alias core.stdc.complex.cpowl      pow;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.cpow       pow;
+    deprecated alias core.stdc.complex.cpowf      pow;
+    deprecated alias core.stdc.complex.cpowl      pow;
 
     ///
     alias core.stdc.math.sqrt          sqrt;
@@ -909,12 +829,10 @@ else version (OpenBSD)
     ///
     alias core.stdc.math.sqrtl         sqrt;
 
-    ///
-    alias core.stdc.complex.csqrt      sqrt;
-    ///
-    alias core.stdc.complex.csqrtf     sqrt;
-    ///
-    alias core.stdc.complex.csqrtl     sqrt;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.csqrt      sqrt;
+    deprecated alias core.stdc.complex.csqrtf     sqrt;
+    deprecated alias core.stdc.complex.csqrtl     sqrt;
 
     ///
     alias core.stdc.math.erf           erf;
@@ -1077,37 +995,23 @@ else version (OpenBSD)
     ///
     alias core.stdc.math.fmal          fma;
 
-    ///
-    alias core.stdc.complex.carg       carg;
-    ///
-    alias core.stdc.complex.cargf      carg;
-    ///
-    alias core.stdc.complex.cargl      carg;
-
-    ///
-    alias core.stdc.complex.cimag      cimag;
-    ///
-    alias core.stdc.complex.cimagf     cimag;
-    ///
-    alias core.stdc.complex.cimagl     cimag;
-
-    ///
-    alias core.stdc.complex.conj       conj;
-    ///
-    alias core.stdc.complex.conjf      conj;
-    ///
-    alias core.stdc.complex.conjl      conj;
-
-    ///
-    alias core.stdc.complex.cproj      cproj;
-    ///
-    alias core.stdc.complex.cprojf     cproj;
-    ///
-    alias core.stdc.complex.cprojl     cproj;
-
-//  alias core.stdc.complex.creal      creal;
-//  alias core.stdc.complex.crealf     creal;
-//  alias core.stdc.complex.creall     creal;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.carg       carg;
+    deprecated alias core.stdc.complex.cargf      carg;
+    deprecated alias core.stdc.complex.cargl      carg;
+    deprecated alias core.stdc.complex.cimag      cimag;
+    deprecated alias core.stdc.complex.cimagf     cimag;
+    deprecated alias core.stdc.complex.cimagl     cimag;
+    deprecated alias core.stdc.complex.conj       conj;
+    deprecated alias core.stdc.complex.conjf      conj;
+    deprecated alias core.stdc.complex.conjl      conj;
+    deprecated alias core.stdc.complex.cproj      cproj;
+    deprecated alias core.stdc.complex.cprojf     cproj;
+    deprecated alias core.stdc.complex.cprojl     cproj;
+
+//  deprecated alias core.stdc.complex.creal      creal;
+//  deprecated alias core.stdc.complex.crealf     creal;
+//  deprecated alias core.stdc.complex.creall     creal;
 }
 else
 {
@@ -1118,12 +1022,10 @@ else
     ///
     alias core.stdc.math.acosl         acos;
 
-    ///
-    alias core.stdc.complex.cacos      acos;
-    ///
-    alias core.stdc.complex.cacosf     acos;
-    ///
-    alias core.stdc.complex.cacosl     acos;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.cacos      acos;
+    deprecated alias core.stdc.complex.cacosf     acos;
+    deprecated alias core.stdc.complex.cacosl     acos;
 
     ///
     alias core.stdc.math.asin          asin;
@@ -1132,12 +1034,10 @@ else
     ///
     alias core.stdc.math.asinl         asin;
 
-    ///
-    alias core.stdc.complex.casin      asin;
-    ///
-    alias core.stdc.complex.casinf     asin;
-    ///
-    alias core.stdc.complex.casinl     asin;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.casin      asin;
+    deprecated alias core.stdc.complex.casinf     asin;
+    deprecated alias core.stdc.complex.casinl     asin;
 
     ///
     alias core.stdc.math.atan          atan;
@@ -1146,12 +1046,10 @@ else
     ///
     alias core.stdc.math.atanl         atan;
 
-    ///
-    alias core.stdc.complex.catan      atan;
-    ///
-    alias core.stdc.complex.catanf     atan;
-    ///
-    alias core.stdc.complex.catanl     atan;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.catan      atan;
+    deprecated alias core.stdc.complex.catanf     atan;
+    deprecated alias core.stdc.complex.catanl     atan;
 
     ///
     alias core.stdc.math.atan2         atan2;
@@ -1167,12 +1065,10 @@ else
     ///
     alias core.stdc.math.cosl          cos;
 
-    ///
-    alias core.stdc.complex.ccos       cos;
-    ///
-    alias core.stdc.complex.ccosf      cos;
-    ///
-    alias core.stdc.complex.ccosl      cos;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.ccos       cos;
+    deprecated alias core.stdc.complex.ccosf      cos;
+    deprecated alias core.stdc.complex.ccosl      cos;
 
     ///
     alias core.stdc.math.sin           sin;
@@ -1181,12 +1077,10 @@ else
     ///
     alias core.stdc.math.sinl          sin;
 
-    ///
-    alias core.stdc.complex.csin       csin;
-    ///
-    alias core.stdc.complex.csinf      csin;
-    ///
-    alias core.stdc.complex.csinl      csin;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.csin       csin;
+    deprecated alias core.stdc.complex.csinf      csin;
+    deprecated alias core.stdc.complex.csinl      csin;
 
     ///
     alias core.stdc.math.tan           tan;
@@ -1195,12 +1089,10 @@ else
     ///
     alias core.stdc.math.tanl          tan;
 
-    ///
-    alias core.stdc.complex.ctan       tan;
-    ///
-    alias core.stdc.complex.ctanf      tan;
-    ///
-    alias core.stdc.complex.ctanl      tan;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.ctan       tan;
+    deprecated alias core.stdc.complex.ctanf      tan;
+    deprecated alias core.stdc.complex.ctanl      tan;
 
     ///
     alias core.stdc.math.acosh         acosh;
@@ -1209,12 +1101,10 @@ else
     ///
     alias core.stdc.math.acoshl        acosh;
 
-    ///
-    alias core.stdc.complex.cacosh     acosh;
-    ///
-    alias core.stdc.complex.cacoshf    acosh;
-    ///
-    alias core.stdc.complex.cacoshl    acosh;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.cacosh     acosh;
+    deprecated alias core.stdc.complex.cacoshf    acosh;
+    deprecated alias core.stdc.complex.cacoshl    acosh;
 
     ///
     alias core.stdc.math.asinh         asinh;
@@ -1223,12 +1113,10 @@ else
     ///
     alias core.stdc.math.asinhl        asinh;
 
-    ///
-    alias core.stdc.complex.casinh     asinh;
-    ///
-    alias core.stdc.complex.casinhf    asinh;
-    ///
-    alias core.stdc.complex.casinhl    asinh;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.casinh     asinh;
+    deprecated alias core.stdc.complex.casinhf    asinh;
+    deprecated alias core.stdc.complex.casinhl    asinh;
 
     ///
     alias core.stdc.math.atanh         atanh;
@@ -1237,12 +1125,10 @@ else
     ///
     alias core.stdc.math.atanhl        atanh;
 
-    ///
-    alias core.stdc.complex.catanh     atanh;
-    ///
-    alias core.stdc.complex.catanhf    atanh;
-    ///
-    alias core.stdc.complex.catanhl    atanh;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.catanh     atanh;
+    deprecated alias core.stdc.complex.catanhf    atanh;
+    deprecated alias core.stdc.complex.catanhl    atanh;
 
     ///
     alias core.stdc.math.cosh          cosh;
@@ -1251,12 +1137,10 @@ else
     ///
     alias core.stdc.math.coshl         cosh;
 
-    ///
-    alias core.stdc.complex.ccosh      cosh;
-    ///
-    alias core.stdc.complex.ccoshf     cosh;
-    ///
-    alias core.stdc.complex.ccoshl     cosh;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.ccosh      cosh;
+    deprecated alias core.stdc.complex.ccoshf     cosh;
+    deprecated alias core.stdc.complex.ccoshl     cosh;
 
     ///
     alias core.stdc.math.sinh          sinh;
@@ -1265,12 +1149,10 @@ else
     ///
     alias core.stdc.math.sinhl         sinh;
 
-    ///
-    alias core.stdc.complex.csinh      sinh;
-    ///
-    alias core.stdc.complex.csinhf     sinh;
-    ///
-    alias core.stdc.complex.csinhl     sinh;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.csinh      sinh;
+    deprecated alias core.stdc.complex.csinhf     sinh;
+    deprecated alias core.stdc.complex.csinhl     sinh;
 
     ///
     alias core.stdc.math.tanh          tanh;
@@ -1279,12 +1161,10 @@ else
     ///
     alias core.stdc.math.tanhl         tanh;
 
-    ///
-    alias core.stdc.complex.ctanh      tanh;
-    ///
-    alias core.stdc.complex.ctanhf     tanh;
-    ///
-    alias core.stdc.complex.ctanhl     tanh;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.ctanh      tanh;
+    deprecated alias core.stdc.complex.ctanhf     tanh;
+    deprecated alias core.stdc.complex.ctanhl     tanh;
 
     ///
     alias core.stdc.math.exp           exp;
@@ -1293,12 +1173,10 @@ else
     ///
     alias core.stdc.math.expl          exp;
 
-    ///
-    alias core.stdc.complex.cexp       exp;
-    ///
-    alias core.stdc.complex.cexpf      exp;
-    ///
-    alias core.stdc.complex.cexpl      exp;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.cexp       exp;
+    deprecated alias core.stdc.complex.cexpf      exp;
+    deprecated alias core.stdc.complex.cexpl      exp;
 
     ///
     alias core.stdc.math.exp2          exp2;
@@ -1342,12 +1220,10 @@ else
     ///
     alias core.stdc.math.logl          log;
 
-    ///
-    alias core.stdc.complex.clog       log;
-    ///
-    alias core.stdc.complex.clogf      log;
-    ///
-    alias core.stdc.complex.clogl      log;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.clog       log;
+    deprecated alias core.stdc.complex.clogf      log;
+    deprecated alias core.stdc.complex.clogl      log;
 
     ///
     alias core.stdc.math.log10         log10;
@@ -1418,12 +1294,10 @@ else
         alias core.stdc.math.fabsl         fabs;
     }
 
-    ///
-    alias core.stdc.complex.cabs       fabs;
-    ///
-    alias core.stdc.complex.cabsf      fabs;
-    ///
-    alias core.stdc.complex.cabsl      fabs;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.cabs       fabs;
+    deprecated alias core.stdc.complex.cabsf      fabs;
+    deprecated alias core.stdc.complex.cabsl      fabs;
 
     ///
     alias core.stdc.math.hypot         hypot;
@@ -1439,12 +1313,10 @@ else
     ///
     alias core.stdc.math.powl          pow;
 
-    ///
-    alias core.stdc.complex.cpow       pow;
-    ///
-    alias core.stdc.complex.cpowf      pow;
-    ///
-    alias core.stdc.complex.cpowl      pow;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.cpow       pow;
+    deprecated alias core.stdc.complex.cpowf      pow;
+    deprecated alias core.stdc.complex.cpowl      pow;
 
     ///
     alias core.stdc.math.sqrt          sqrt;
@@ -1453,12 +1325,10 @@ else
     ///
     alias core.stdc.math.sqrtl         sqrt;
 
-    ///
-    alias core.stdc.complex.csqrt      sqrt;
-    ///
-    alias core.stdc.complex.csqrtf     sqrt;
-    ///
-    alias core.stdc.complex.csqrtl     sqrt;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.csqrt      sqrt;
+    deprecated alias core.stdc.complex.csqrtf     sqrt;
+    deprecated alias core.stdc.complex.csqrtl     sqrt;
 
     ///
     alias core.stdc.math.erf           erf;
@@ -1635,35 +1505,20 @@ else
     ///
     alias core.stdc.math.fmal          fma;
 
-    ///
-    alias core.stdc.complex.carg       carg;
-    ///
-    alias core.stdc.complex.cargf      carg;
-    ///
-    alias core.stdc.complex.cargl      carg;
-
-    ///
-    alias core.stdc.complex.cimag      cimag;
-    ///
-    alias core.stdc.complex.cimagf     cimag;
-    ///
-    alias core.stdc.complex.cimagl     cimag;
-
-    ///
-    alias core.stdc.complex.conj       conj;
-    ///
-    alias core.stdc.complex.conjf      conj;
-    ///
-    alias core.stdc.complex.conjl      conj;
-
-    ///
-    alias core.stdc.complex.cproj      cproj;
-    ///
-    alias core.stdc.complex.cprojf     cproj;
-    ///
-    alias core.stdc.complex.cprojl     cproj;
-
-//  alias core.stdc.complex.creal      creal;
-//  alias core.stdc.complex.crealf     creal;
-//  alias core.stdc.complex.creall     creal;
+    // @@@DEPRECATED_2.105@@@
+    deprecated alias core.stdc.complex.carg       carg;
+    deprecated alias core.stdc.complex.cargf      carg;
+    deprecated alias core.stdc.complex.cargl      carg;
+    deprecated alias core.stdc.complex.cimag      cimag;
+    deprecated alias core.stdc.complex.cimagf     cimag;
+    deprecated alias core.stdc.complex.cimagl     cimag;
+    deprecated alias core.stdc.complex.conj       conj;
+    deprecated alias core.stdc.complex.conjf      conj;
+    deprecated alias core.stdc.complex.conjl      conj;
+    deprecated alias core.stdc.complex.cproj      cproj;
+    deprecated alias core.stdc.complex.cprojf     cproj;
+    deprecated alias core.stdc.complex.cprojl     cproj;
+//  deprecated alias core.stdc.complex.creal      creal;
+//  deprecated alias core.stdc.complex.crealf     creal;
+//  deprecated alias core.stdc.complex.creall     creal;
 }
diff --git a/libphobos/libdruntime/core/stdc/wchar_.d b/libphobos/libdruntime/core/stdc/wchar_.d
index eecc8ef918e..6da5618ada6 100644
--- a/libphobos/libdruntime/core/stdc/wchar_.d
+++ b/libphobos/libdruntime/core/stdc/wchar_.d
@@ -173,12 +173,13 @@ extern (D) @trusted
     wint_t getwchar()                     { return fgetwc(stdin);     }
     ///
     wint_t putwchar(wchar_t c)            { return fputwc(c,stdout);  }
-    ///
-    wint_t getwc(FILE* stream)            { return fgetwc(stream);    }
-    ///
-    wint_t putwc(wchar_t c, FILE* stream) { return fputwc(c, stream); }
 }
 
+///
+alias getwc = fgetwc;
+///
+alias putwc = fputwc;
+
 // No unsafe pointer manipulation.
 @trusted
 {
diff --git a/libphobos/libdruntime/core/sys/darwin/fcntl.d b/libphobos/libdruntime/core/sys/darwin/fcntl.d
new file mode 100644
index 00000000000..47d895ad6cb
--- /dev/null
+++ b/libphobos/libdruntime/core/sys/darwin/fcntl.d
@@ -0,0 +1,20 @@
+module core.sys.darwin.fcntl;
+
+public import core.sys.posix.fcntl;
+
+version (OSX)
+    version = Darwin;
+else version (iOS)
+    version = Darwin;
+else version (TVOS)
+    version = Darwin;
+else version (WatchOS)
+    version = Darwin;
+
+version (Darwin):
+extern (C):
+nothrow:
+@nogc:
+@system:
+
+enum F_FULLFSYNC = 51;
diff --git a/libphobos/libdruntime/core/sys/linux/epoll.d b/libphobos/libdruntime/core/sys/linux/epoll.d
index 0c3aed98853..f5ff7dba0f8 100644
--- a/libphobos/libdruntime/core/sys/linux/epoll.d
+++ b/libphobos/libdruntime/core/sys/linux/epoll.d
@@ -10,6 +10,8 @@ module core.sys.linux.epoll;
 
 version (linux):
 
+import core.sys.posix.signal : sigset_t;
+
 extern (C):
 @system:
 @nogc:
@@ -52,16 +54,19 @@ enum
     EPOLLHUP    = 0x010,
     EPOLLRDHUP  = 0x2000, // since Linux 2.6.17
     EPOLLEXCLUSIVE = 1u << 28, // since Linux 4.5
+    EPOLLWAKEUP = 1u << 29,
     EPOLLONESHOT = 1u << 30,
     EPOLLET     = 1u << 31
 }
 
-/* Valid opcodes ( "op" parameter ) to issue to epoll_ctl().  */
+/**
+ * Valid opcodes ( "op" parameter ) to issue to epoll_ctl().
+ */
 enum
 {
-    EPOLL_CTL_ADD = 1, // Add a file descriptor to the interface.
-    EPOLL_CTL_DEL = 2, // Remove a file descriptor from the interface.
-    EPOLL_CTL_MOD = 3, // Change file descriptor epoll_event structure.
+    EPOLL_CTL_ADD = 1, /// Add a file descriptor to the interface.
+    EPOLL_CTL_DEL = 2, /// Remove a file descriptor from the interface.
+    EPOLL_CTL_MOD = 3, /// Change file descriptor epoll_event structure.
 }
 
 version (X86_Any)
@@ -142,7 +147,82 @@ union epoll_data_t
     ulong u64;
 }
 
+/**
+ * Creates an epoll instance.
+ *
+ * Params:
+ *   size = a hint specifying the number of file descriptors to be associated
+ *          with the new instance.  T
+ * Returns: an fd for the new instance. The fd returned by epoll_create() should
+ *          be closed with close().
+ * See_also: epoll_create1 (int flags)
+ */
 int epoll_create (int size);
+
+/* Same as epoll_create but with an FLAGS parameter.  The unused SIZE
+   parameter has been dropped.  */
+
+/**
+ * Creates an epoll instance.
+ *
+ * Params:
+ *   flags = a specified flag. If flags is 0, then, other than the fact that the
+ *           obsolete size argument is dropped, epoll_create1() is the same as
+ *           epoll_create().
+ * Returns: an fd for the new instance. The fd returned by epoll_create() should
+ *          be closed with close().
+ * See_also: epoll_create (int size)
+ */
 int epoll_create1 (int flags);
+
+/**
+ * Manipulate an epoll instance
+ *
+ * Params:
+ *   epfd = an epoll file descriptor instance
+ *   op = one of the EPOLL_CTL_* constants
+ *   fd = target file descriptor of the operation
+ *   event = describes which events the caller is interested in and any
+ *           associated user dat
+ * Returns: 0 in case of success, -1 in case of error ( the "errno" variable
+ *          will contain the specific error code )
+ */
 int epoll_ctl (int epfd, int op, int fd, epoll_event *event);
+
+
+/**
+ * Wait for events on an epoll instance.
+ *
+ *
+ * Params:
+ *   epfd = an epoll file descriptor instance
+ *   events = a buffer that will contain triggered events
+ *   maxevents = the maximum number of events to be returned ( usually size of
+ *               "events" )
+ *   timeout = specifies the maximum wait time in milliseconds (-1 == infinite)
+ *
+ * Returns: the number of triggered events returned in "events" buffer. Or -1 in
+ *          case of error with the "errno" variable set to the specific error
+ *          code.
+ */
 int epoll_wait (int epfd, epoll_event *events, int maxevents, int timeout);
+
+/**
+ * Wait for events on an epoll instance
+ *
+ *
+ * Params:
+ *   epfd = an epoll file descriptor instance
+ *   events = a buffer that will contain triggered events
+ *   maxevents = the maximum number of events to be returned ( usually size of
+ *               "events" )
+ *   timeout = specifies the maximum wait time in milliseconds (-1 == infinite)
+ *   ss = a signal set. May be specified as `null`, in which case epoll_pwait() is
+ *        equivalent to epoll_wait().
+ *
+ * Returns: the number of triggered events returned in "events" buffer. Or -1 in
+ *          case of error with the "errno" variable set to the specific error
+ *          code.
+ */
+int epoll_pwait (int epfd, epoll_event *events, int maxevents, int timeout,
+    const sigset_t *ss);
diff --git a/libphobos/libdruntime/core/sys/openbsd/string.d b/libphobos/libdruntime/core/sys/openbsd/string.d
index 8d35b9c9c12..cb978c8249b 100644
--- a/libphobos/libdruntime/core/sys/openbsd/string.d
+++ b/libphobos/libdruntime/core/sys/openbsd/string.d
@@ -18,4 +18,6 @@ nothrow:
 static if (__BSD_VISIBLE)
 {
     pure void* memmem(return const void* haystack, size_t haystacklen, scope const void* needle, size_t needlelen);
+    pure int timingsafe_bcmp(scope const void*, scope const void*, size_t);
+    pure int timingsafe_memcmp(scope const void*, scope const void*, size_t);
 }
diff --git a/libphobos/libdruntime/core/sys/openbsd/unistd.d b/libphobos/libdruntime/core/sys/openbsd/unistd.d
new file mode 100644
index 00000000000..ddd102cdeae
--- /dev/null
+++ b/libphobos/libdruntime/core/sys/openbsd/unistd.d
@@ -0,0 +1,17 @@
+/**
+  * D header file for OpenBSD unistd.h.
+  *
+  * Copyright: Copyright © 2021, The D Language Foundation
+  * License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
+  * Authors: Brian Callahan
+  */
+module core.sys.openbsd.unistd;
+public import core.sys.posix.unistd;
+
+version (OpenBSD):
+extern (C):
+nothrow:
+@nogc:
+
+int pledge(const scope char*, const scope char*);
+int unveil(const scope char*, const scope char*);
diff --git a/libphobos/libdruntime/core/sys/posix/config.d b/libphobos/libdruntime/core/sys/posix/config.d
index c02debffadd..3b575fa5b48 100644
--- a/libphobos/libdruntime/core/sys/posix/config.d
+++ b/libphobos/libdruntime/core/sys/posix/config.d
@@ -117,6 +117,7 @@ else version (CRuntime_UClibc)
 else version (CRuntime_Bionic)
 {
     enum _GNU_SOURCE         = false;
+    enum __USE_FILE_OFFSET64 = false; // see https://android.googlesource.com/platform/bionic/+/master/docs/32-bit-abi.md
     enum __USE_GNU           = _GNU_SOURCE;
 
     version (D_LP64)
diff --git a/libphobos/libdruntime/core/sys/posix/dlfcn.d b/libphobos/libdruntime/core/sys/posix/dlfcn.d
index e97c7ea3960..2477e26dc53 100644
--- a/libphobos/libdruntime/core/sys/posix/dlfcn.d
+++ b/libphobos/libdruntime/core/sys/posix/dlfcn.d
@@ -139,7 +139,7 @@ else version (Darwin)
     char* dlerror();
     void* dlopen(const scope char*, int);
     void* dlsym(void*, const scope char*);
-    int   dladdr(void* addr, Dl_info* info);
+    int   dladdr(scope const void* addr, Dl_info* info);
 
     struct Dl_info
     {
@@ -294,6 +294,15 @@ else version (CRuntime_Musl)
     const(char)* dlerror();
     void*        dlopen(const scope char*, int);
     void*        dlsym(void*, const scope char*);
+
+    int dladdr(scope const void *addr, Dl_info *info);
+    struct Dl_info
+    {
+        const(char)* dli_fname;
+        void*        dli_fbase;
+        const(char)* dli_sname;
+        void*        dli_saddr;
+    }
 }
 else version (CRuntime_UClibc)
 {
diff --git a/libphobos/libdruntime/core/sys/posix/signal.d b/libphobos/libdruntime/core/sys/posix/signal.d
index 44f45f2e0c3..0dce8c53f31 100644
--- a/libphobos/libdruntime/core/sys/posix/signal.d
+++ b/libphobos/libdruntime/core/sys/posix/signal.d
@@ -3503,7 +3503,7 @@ struct sigevent
     pthread_attr_t* sigev_notify_attributes;
 }
 
-int sigqueue(pid_t, int, in sigval);
+int sigqueue(pid_t, int, const sigval);
 int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
 int sigwaitinfo(const scope sigset_t*, siginfo_t*);
 */
@@ -3543,7 +3543,7 @@ version (CRuntime_Glibc)
         } _sigev_un_t _sigev_un;
     }
 
-    int sigqueue(pid_t, int, in sigval);
+    int sigqueue(pid_t, int, const sigval);
     int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
     int sigwaitinfo(const scope sigset_t*, siginfo_t*);
 }
@@ -3566,7 +3566,7 @@ else version (FreeBSD)
         }
     }
 
-    int sigqueue(pid_t, int, in sigval);
+    int sigqueue(pid_t, int, const sigval);
     int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
     int sigwaitinfo(const scope sigset_t*, siginfo_t*);
 }
@@ -3581,7 +3581,7 @@ else version (NetBSD)
         void /* pthread_attr_t */*sigev_notify_attributes;
     }
 
-    int sigqueue(pid_t, int, in sigval);
+    int sigqueue(pid_t, int, const sigval);
     int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
     int sigwaitinfo(const scope sigset_t*, siginfo_t*);
 }
@@ -3613,7 +3613,7 @@ else version (DragonFlyBSD)
         void function(_sigval_t)  sigev_notify_function;
     }
 
-    int sigqueue(pid_t, int, in sigval);
+    int sigqueue(pid_t, int, const sigval);
     int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
     int sigwaitinfo(const scope sigset_t*, siginfo_t*);
 }
@@ -3640,7 +3640,7 @@ else version (Solaris)
         int __sigev_pad2;
     }
 
-    int sigqueue(pid_t, int, in sigval);
+    int sigqueue(pid_t, int, const sigval);
     int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
     int sigwaitinfo(const scope sigset_t*, siginfo_t*);
 }
@@ -3717,7 +3717,7 @@ else version (CRuntime_UClibc)
     @property void function(sigval) sigev_notify_function(ref sigevent _sigevent) { return _sigevent._sigev_un._sigev_thread._function; }
     @property void* sigev_notify_attributes(ref sigevent _sigevent) { return  _sigevent._sigev_un._sigev_thread._attribute; }
 
-    int sigqueue(pid_t, int, in sigval);
+    int sigqueue(pid_t, int, const sigval);
     int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
     int sigwaitinfo(const scope sigset_t*, siginfo_t*);
 }
diff --git a/libphobos/libdruntime/core/sys/posix/unistd.d b/libphobos/libdruntime/core/sys/posix/unistd.d
index a691884cb2e..d996556fca0 100644
--- a/libphobos/libdruntime/core/sys/posix/unistd.d
+++ b/libphobos/libdruntime/core/sys/posix/unistd.d
@@ -2722,3 +2722,51 @@ else version (CRuntime_UClibc)
     int        truncate(const scope char*, off_t);
   }
 }
+
+// Non-standard definition to access user process environment
+version (CRuntime_Glibc)
+{
+    extern __gshared const char** environ;
+}
+else version (Darwin)
+{
+    extern (D) @property const(char**) environ()()
+    {
+        pragma (inline, true);
+        import core.sys.darwin.crt_externs : _NSGetEnviron;
+        return *_NSGetEnviron();
+    }
+}
+else version (FreeBSD)
+{
+    extern __gshared const char** environ;
+}
+else version (NetBSD)
+{
+    extern __gshared const char** environ;
+}
+else version (OpenBSD)
+{
+    extern __gshared const char** environ;
+}
+else version (DragonFlyBSD)
+{
+    extern __gshared const char** environ;
+}
+else version (CRuntime_Bionic)
+{
+    extern __gshared const char** environ;
+}
+else version (CRuntime_Musl)
+{
+    extern __gshared const char** environ;
+}
+else version (Solaris)
+{
+    extern __gshared const char** environ;
+}
+else version (CRuntime_UClibc)
+{
+    extern __gshared const char** __environ;
+    alias environ = __environ;
+}
diff --git a/libphobos/libdruntime/core/sys/windows/com.d b/libphobos/libdruntime/core/sys/windows/com.d
index 90a294343fc..88007adb141 100644
--- a/libphobos/libdruntime/core/sys/windows/com.d
+++ b/libphobos/libdruntime/core/sys/windows/com.d
@@ -39,16 +39,16 @@ public import core.sys.windows.winerror :
     RPC_E_CHANGED_MODE;
 
 public import core.sys.windows.wtypes :
-    OLECHAR, LPOLESTR, LPCOLESTR;
-
-alias CLSCTX_INPROC_SERVER     = core.sys.windows.wtypes.CLSCTX.CLSCTX_INPROC_SERVER    ;
-alias CLSCTX_INPROC_HANDLER    = core.sys.windows.wtypes.CLSCTX.CLSCTX_INPROC_HANDLER   ;
-alias CLSCTX_LOCAL_SERVER      = core.sys.windows.wtypes.CLSCTX.CLSCTX_LOCAL_SERVER     ;
-alias CLSCTX_INPROC_SERVER16   = core.sys.windows.wtypes.CLSCTX.CLSCTX_INPROC_SERVER16  ;
-alias CLSCTX_REMOTE_SERVER     = core.sys.windows.wtypes.CLSCTX.CLSCTX_REMOTE_SERVER    ;
-alias CLSCTX_INPROC_HANDLER16  = core.sys.windows.wtypes.CLSCTX.CLSCTX_INPROC_HANDLER16 ;
-alias CLSCTX_INPROC_SERVERX86  = core.sys.windows.wtypes.CLSCTX.CLSCTX_INPROC_SERVERX86 ;
-alias CLSCTX_INPROC_HANDLERX86 = core.sys.windows.wtypes.CLSCTX.CLSCTX_INPROC_HANDLERX86;
+    CLSCTX, OLECHAR, LPOLESTR, LPCOLESTR;
+
+alias CLSCTX_INPROC_SERVER     = CLSCTX.CLSCTX_INPROC_SERVER    ;
+alias CLSCTX_INPROC_HANDLER    = CLSCTX.CLSCTX_INPROC_HANDLER   ;
+alias CLSCTX_LOCAL_SERVER      = CLSCTX.CLSCTX_LOCAL_SERVER     ;
+alias CLSCTX_INPROC_SERVER16   = CLSCTX.CLSCTX_INPROC_SERVER16  ;
+alias CLSCTX_REMOTE_SERVER     = CLSCTX.CLSCTX_REMOTE_SERVER    ;
+alias CLSCTX_INPROC_HANDLER16  = CLSCTX.CLSCTX_INPROC_HANDLER16 ;
+alias CLSCTX_INPROC_SERVERX86  = CLSCTX.CLSCTX_INPROC_SERVERX86 ;
+alias CLSCTX_INPROC_HANDLERX86 = CLSCTX.CLSCTX_INPROC_HANDLERX86;
 
 alias COINIT_APARTMENTTHREADED   = COINIT.COINIT_APARTMENTTHREADED;
 alias COINIT_MULTITHREADED       = COINIT.COINIT_MULTITHREADED    ;
diff --git a/libphobos/libdruntime/core/sys/windows/dll.d b/libphobos/libdruntime/core/sys/windows/dll.d
index 9f36ac389a6..3df0d7fd41b 100644
--- a/libphobos/libdruntime/core/sys/windows/dll.d
+++ b/libphobos/libdruntime/core/sys/windows/dll.d
@@ -31,17 +31,7 @@ public import core.sys.windows.threadaux;
 //  not access tls_array[tls_index] as needed for thread local _tlsstart and _tlsend
 extern (C)
 {
-        version (MinGW)
-        {
-            extern __gshared void* _tls_start;
-            extern __gshared void* _tls_end;
-            extern __gshared void* __xl_a;
-
-            alias _tls_start _tlsstart;
-            alias _tls_end   _tlsend;
-            alias __xl_a     _tls_callbacks_a;
-        }
-        else version (Win32)
+    version (Win32)
     {
         version (CRuntime_DigitalMars)
         {
diff --git a/libphobos/libdruntime/core/sys/windows/stdc/malloc.d b/libphobos/libdruntime/core/sys/windows/stdc/malloc.d
new file mode 100644
index 00000000000..f52ba37f27e
--- /dev/null
+++ b/libphobos/libdruntime/core/sys/windows/stdc/malloc.d
@@ -0,0 +1,26 @@
+/**
+  * D header file for Windows malloc.h.
+ *
+ * Translated from MinGW Windows headers
+ *
+ * Authors: Iain Buclaw
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Source: $(DRUNTIMESRC src/core/sys/windows/stdc/_malloc.d)
+ */
+module core.sys.windows.stdc.malloc;
+version (CRuntime_Microsoft):
+extern (C):
+@system:
+nothrow:
+@nogc:
+
+export void* _recalloc(void*, size_t, size_t);
+
+export void _aligned_free(void*);
+export void* _aligned_malloc(size_t, size_t);
+
+export void* _aligned_offset_malloc(size_t, size_t, size_t);
+export void* _aligned_realloc(void*, size_t, size_t);
+export void* _aligned_recalloc(void*, size_t, size_t, size_t);
+export void* _aligned_offset_realloc(void*, size_t, size_t, size_t);
+export void* _aligned_offset_recalloc(void*, size_t, size_t, size_t, size_t);
diff --git a/libphobos/libdruntime/gc/impl/conservative/gc.d b/libphobos/libdruntime/gc/impl/conservative/gc.d
index b7bb9b0c36f..300a32ad2b0 100644
--- a/libphobos/libdruntime/gc/impl/conservative/gc.d
+++ b/libphobos/libdruntime/gc/impl/conservative/gc.d
@@ -76,7 +76,7 @@ debug(PRINTF_TO_FILE)
                 gcStartTick = MonoTime.currTime;
             immutable timeElapsed = MonoTime.currTime - gcStartTick;
             immutable secondsAsDouble = timeElapsed.total!"hnsecs" / cast(double)convert!("seconds", "hnsecs")(1);
-            len = fprintf(gcx_fh, "%10.6lf: ", secondsAsDouble);
+            len = fprintf(gcx_fh, "%10.6f: ", secondsAsDouble);
         }
         len += fprintf(gcx_fh, fmt, args);
         fflush(gcx_fh);
@@ -159,7 +159,7 @@ debug (LOGGING)
             printf("    p = %p, size = %zd, parent = %p ", p, size, parent);
             if (file)
             {
-                printf("%s(%u)", file, line);
+                printf("%s(%u)", file, cast(uint)line);
             }
             printf("\n");
         }
diff --git a/libphobos/libdruntime/object.d b/libphob[...]

[diff truncated at 524288 bytes]


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

only message in thread, other threads:[~2021-04-03 23:27 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-03 23:27 [gcc r11-7978] d: Merge upstream dmd 3b808e838, druntime 483bc129, phobos f89dc217a Iain Buclaw

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).