diff mbox series

[committed,02/19] d: Update D front-end to build with latest version

Message ID 20211130141754.576528-1-ibuclaw@gdcproject.org
State Committed
Headers show
Series [committed,01/19] configure, d: Add support for bootstrapping the D front-end | expand

Commit Message

Iain Buclaw Nov. 30, 2021, 2:17 p.m. UTC
This patch updates the code generator to work with the new front-end interface.

Bootstrapped, regression tested, and committed to mainline.

Regards,
Iain.

---
gcc/d/ChangeLog:

	* Make-lang.in (d-warn): Use strict warnings.
	(DMD_WARN_CXXFLAGS): Remove.
	(DMD_COMPILE): Remove.
	(CHECKING_DFLAGS): Define.
	(WARN_DFLAGS): Define.
	(ALL_DFLAGS): Define.
	(DCOMPILE.base): Define.
	(DCOMPILE): Define.
	(DPOSTCOMPILE): Define.
	(DLINKER): Define.
	(DLLINKER): Define.
	(D_FRONTEND_OBJS): Add new dmd front-end objects.
	(D_GENERATED_SRCS): Remove.
	(D_GENERATED_OBJS): Remove.
	(D_ALL_OBJS): Remove D_GENERATED_OBJS.
	(d21$(exeext)): Build using DLLINKER and -static-libphobos.
	(d.tags): Remove dmd/*.c and dmd/root/*.c.
	(d.mostlyclean): Remove D_GENERATED_SRCS, d/idgen$(build_exeext),
	d/impcnvgen$(build_exeext).
	(D_INCLUDES): Include $(srcdir)/d/dmd/res.
	(CFLAGS-d/id.o): Remove.
	(CFLAGS-d/impcnvtab.o): Remove.
	(d/%.o): Build using DCOMPILE and DPOSTCOMPILE.  Update dependencies
	from d/dmd/%.c to d/dmd/%.d.
	(d/idgen$(build_exeext)): Remove.
	(d/impcnvgen$(build_exeext)): Remove.
	(d/id.c): Remove.
	(d/id.h): Remove.
	(d/impcnvtab.c): Remove.
	(d/%.dmdgen.o): Remove.
	(D_SYSTEM_H): Remove.
	(d/idgen.dmdgen.o): Remove.
	(d/impcnvgen.dmdgen.o): Remove.
	* config-lang.in (boot_language): New variable.
	* d-attribs.cc: Include dmd/expression.h.
	* d-builtins.cc: Include d-frontend.h.
	(build_frontend_type): Update for new front-end interface.
	(d_eval_constant_expression): Likewise.
	(d_build_builtins_module): Likewise.
	(maybe_set_builtin_1): Likewise.
	(d_build_d_type_nodes): Likewise.
	* d-codegen.cc (d_decl_context): Likewise.
	(declaration_reference_p): Likewise.
	(declaration_type): Likewise.
	(parameter_reference_p): Likewise.
	(parameter_type): Likewise.
	(get_array_length): Likewise.
	(build_delegate_cst): Likewise.
	(build_typeof_null_value): Likewise.
	(identity_compare_p): Likewise.
	(lower_struct_comparison): Likewise.
	(build_filename_from_loc): Likewise.
	(build_assert_call): Remove LIBCALL_SWITCH_ERROR.
	(build_bounds_index_condition): Call LIBCALL_ARRAYBOUNDS_INDEXP on
	bounds error.
	(build_bounds_slice_condition): Call LIBCALL_ARRAYBOUNDS_SLICEP on
	bounds error.
	(array_bounds_check): Update for new front-end interface.
	(checkaction_trap_p): Handle CHECKACTION_context.
	(get_function_type): Update for new front-end interface.
	(d_build_call): Likewise.
	* d-compiler.cc: Remove include of dmd/scope.h.
	(Compiler::genCmain): Remove.
	(Compiler::paintAsType): Update for new front-end interface.
	(Compiler::onParseModule): Likewise.
	* d-convert.cc (convert_expr): Remove call to LIBCALL_ARRAYCAST.
	(convert_for_rvalue): Update for new front-end interface.
	(convert_for_assignment): Likewise.
	(convert_for_condition): Likewise.
	(d_array_convert): Likewise.
	* d-diagnostic.cc (error): Remove.
	(errorSupplemental): Remove.
	(warning): Remove.
	(warningSupplemental): Remove.
	(deprecation): Remove.
	(deprecationSupplemental): Remove.
	(message): Remove.
	(vtip): New.
	* d-frontend.cc (global): Remove.
	(Global::_init): Remove.
	(Global::startGagging): Remove.
	(Global::endGagging): Remove.
	(Global::increaseErrorCount): Remove.
	(Loc::Loc): Remove.
	(Loc::toChars): Remove.
	(Loc::equals): Remove.
	(isBuiltin): Update for new front-end interface.
	(eval_builtin): Likewise.
	(getTypeInfoType): Likewise.
	(inlineCopy): Remove.
	* d-incpath.cc: Include d-frontend.h.
	(add_globalpaths): Call d_gc_malloc to allocate Strings.
	(add_filepaths): Likewise.
	* d-lang.cc: Include dmd/id.h, dmd/root/file.h, d-frontend.h.  Remove
	include of dmd/mars.h, id.h.
	(entrypoint_module): Remove.
	(entrypoint_root_module): Remove.
	(deps_write_string): Update for new front-end interface.
	(deps_write): Likewise.
	(d_init_options): Call rt_init.  Remove setting global params that are
	default initialized by the front-end.
	(d_handle_option): Handle OPT_fcheckaction_, OPT_fdump_c___spec_,
	OPT_fdump_c___spec_verbose, OPT_fextern_std_, OPT_fpreview,
	OPT_revert, OPT_fsave_mixins_, and OPT_ftransition.
	(d_post_options): Propagate dip1021 and dip1000 preview flags to
	dip25, and flag_diagnostics_show_caret to printErrorContext.
	(d_add_entrypoint_module): Remove.
	(d_parse_file): Update for new front-end interface.
	(d_type_promotes_to): Likewise.
	(d_types_compatible_p): Likewise.
	* d-longdouble.cc (CTFloat::zero): Remove.
	(CTFloat::one): Remove.
	(CTFloat::minusone): Remove.
	(CTFloat::half): Remove.
	* d-system.h (POSIX): Remove.
	(realpath): Remove.
	(isalpha): Remove.
	(isalnum): Remove.
	(isdigit): Remove.
	(islower): Remove.
	(isprint): Remove.
	(isspace): Remove.
	(isupper): Remove.
	(isxdigit): Remove.
	(tolower): Remove.
	(_mkdir): Remove.
	(INT32_MAX): Remove.
	(INT32_MIN): Remove.
	(INT64_MIN): Remove.
	(UINT32_MAX): Remove.
	(UINT64_MAX): Remove.
	* d-target.cc: Include calls.h.
	(target): Remove.
	(define_float_constants): Remove initialization of snan.
	(Target::_init): Update for new front-end interface.
	(Target::isVectorTypeSupported): Likewise.
	(Target::isVectorOpSupported): Remove cases for unordered operators.
	(TargetCPP::typeMangle): Update for new front-end interface.
	(TargetCPP::parameterType): Likewise.
	(Target::systemLinkage): Likewise.
	(Target::isReturnOnStack): Likewise.
	(Target::isCalleeDestroyingArgs): Define.
	(Target::preferPassByRef): Define.
	* d-tree.h (d_add_entrypoint_module): Remove.
	* decl.cc (gcc_attribute_p): Update for new front-end interface.
	(apply_pragma_crt): Define.
	(DeclVisitor::visit(PragmaDeclaration *)): Handle pragmas
	crt_constructor and crt_destructor.
	(DeclVisitor::visit(TemplateDeclaration *)): Update for new front-end
	interface.
	(DeclVisitor::visit): Likewise.
	(DeclVisitor::finish_vtable): Likewise.
	(get_symbol_decl): Error if template has more than one nesting
	context.  Update for new front-end interface.
	(make_thunk): Update for new front-end interface.
	(get_vtable_decl): Likewise.
	* expr.cc (ExprVisitor::visit): Likewise.
	(build_return_dtor): Likewise.
	* imports.cc (ImportVisitor::visit): Likewise.
	* intrinsics.cc: Include dmd/expression.h.  Remove include of
	dmd/mangle.h.
	(maybe_set_intrinsic): Update for new front-end interface.
	* intrinsics.def (INTRINSIC_ROL): Update intrinsic signature.
	(INTRINSIC_ROR): Likewise.
	(INTRINSIC_ROR_TIARG): Likewise.
	(INTRINSIC_TOPREC): Likewise.
	(INTRINSIC_TOPRECL): Likewise.
	(INTRINSIC_TAN): Update intrinsic module and signature.
	(INTRINSIC_ISNAN): Likewise.
	(INTRINSIC_ISFINITE): Likewise.
	(INTRINSIC_COPYSIGN): Define intrinsic.
	(INTRINSIC_COPYSIGNI): Define intrinsic.
	(INTRINSIC_EXP): Update intrinsic module.
	(INTRINSIC_EXPM1): Likewise.
	(INTRINSIC_EXP2): Likewise.
	(INTRINSIC_LOG): Likewise.
	(INTRINSIC_LOG2): Likewise.
	(INTRINSIC_LOG10): Likewise.
	(INTRINSIC_POW): Likewise.
	(INTRINSIC_ROUND): Likewise.
	(INTRINSIC_FLOORF): Likewise.
	(INTRINSIC_FLOOR): Likewise.
	(INTRINSIC_FLOORL): Likewise.
	(INTRINSIC_CEILF): Likewise.
	(INTRINSIC_CEIL): Likewise.
	(INTRINSIC_CEILL): Likewise.
	(INTRINSIC_TRUNC): Likewise.
	(INTRINSIC_FMIN): Likewise.
	(INTRINSIC_FMAX): Likewise.
	(INTRINSIC_FMA): Likewise.
	(INTRINSIC_VA_ARG): Update intrinsic signature.
	(INTRINSIC_VASTART): Likewise.
	* lang.opt (fcheck=): Add alternate aliases for contract switches.
	(fcheckaction=): New option.
	(check_action): New Enum and EnumValue entries.
	(fdump-c++-spec-verbose): New option.
	(fdump-c++-spec=): New option.
	(fextern-std=): New option.
	(extern_stdcpp): New Enum and EnumValue entries
	(fpreview=): New options.
	(frevert=): New options.
	(fsave-mixins): New option.
	(ftransition=): Update options.
	* modules.cc (get_internal_fn): Replace Prot with Visibility.
	(build_internal_fn): Likewise.
	(build_dso_cdtor_fn): Likewise.
	(build_module_tree): Remove check for __entrypoint module.
	* runtime.def (P5): Define.
	(ARRAYBOUNDS_SLICEP): Define.
	(ARRAYBOUNDS_INDEXP): Define.
	(NEWTHROW): Define.
	(ADCMP2): Remove.
	(ARRAYCAST): Remove.
	(SWITCH_STRING): Remove.
	(SWITCH_USTRING): Remove.
	(SWITCH_DSTRING): Remove.
	(SWITCH_ERROR): Remove.
	* toir.cc (IRVisitor::visit): Update for new front-end interface.
	(IRVisitor::check_previous_goto): Remove checks for case and default
	statements.
	(IRVisitor::visit(SwitchStatement *)): Remove handling of string
	switch conditions.
	* typeinfo.cc: Include d-frontend.h.
	(get_typeinfo_kind): Update for new front-end interface.
	(make_frontend_typeinfo): Likewise.
	(TypeInfoVisitor::visit): Likewise.
	(builtin_typeinfo_p): Likewise.
	(get_typeinfo_decl): Likewise.
	(build_typeinfo): Likewise.
	* types.cc (valist_array_p): Likewise.
	(make_array_type): Likewise.
	(merge_aggregate_types): Likewise.
	(TypeVisitor::visit(TypeBasic *)): Likewise.
	(TypeVisitor::visit(TypeFunction *)): Likewise.
	(TypeVisitor::visit(TypeStruct *)): Update comment.
	* verstr.h: Removed.
	* ChangeLog.d: New file.
	* d-frontend.h: New file.
---
 gcc/d/Make-lang.in    | 132 ++++++++++---------
 gcc/d/config-lang.in  |   2 +
 gcc/d/d-attribs.cc    |   1 +
 gcc/d/d-builtins.cc   |  52 ++++----
 gcc/d/d-codegen.cc    |  78 ++++++++----
 gcc/d/d-compiler.cc   |  49 ++------
 gcc/d/d-convert.cc    |  86 +++++++------
 gcc/d/d-diagnostic.cc |  75 +----------
 gcc/d/d-frontend.cc   | 119 +-----------------
 gcc/d/d-frontend.h    |  37 ++++++
 gcc/d/d-incpath.cc    |   5 +-
 gcc/d/d-lang.cc       | 287 ++++++++++++++++++++++++++++++------------
 gcc/d/d-longdouble.cc |   6 -
 gcc/d/d-system.h      |  52 --------
 gcc/d/d-target.cc     | 112 ++++++++++-------
 gcc/d/d-tree.h        |   1 -
 gcc/d/decl.cc         | 166 +++++++++++++++++-------
 gcc/d/expr.cc         | 267 +++++++++++++++++----------------------
 gcc/d/imports.cc      |   8 +-
 gcc/d/intrinsics.cc   |  10 +-
 gcc/d/intrinsics.def  |  97 +++++++-------
 gcc/d/lang.opt        | 165 ++++++++++++++++++++++--
 gcc/d/modules.cc      |  22 ++--
 gcc/d/runtime.def     |  30 ++---
 gcc/d/toir.cc         | 101 +++------------
 gcc/d/typeinfo.cc     |  60 +++++----
 gcc/d/types.cc        |  74 +++++------
 gcc/d/verstr.h        |   1 -
 28 files changed, 1082 insertions(+), 1013 deletions(-)
 create mode 100644 gcc/d/d-frontend.h
 delete mode 100644 gcc/d/verstr.h
diff mbox series

Patch

diff --git a/gcc/d/Make-lang.in b/gcc/d/Make-lang.in
index 1ed813443b3..4c0a0321eba 100644
--- a/gcc/d/Make-lang.in
+++ b/gcc/d/Make-lang.in
@@ -46,30 +46,61 @@  gdc-cross$(exeext): gdc$(exeext)
 	-rm -f gdc-cross$(exeext)
 	cp gdc$(exeext) gdc-cross$(exeext)
 
-# Filter out pedantic and virtual overload warnings.
-d-warn = $(filter-out -pedantic -Woverloaded-virtual, $(STRICT_WARN))
-
-# Also filter out warnings for missing format attributes in the D Frontend.
-DMD_WARN_CXXFLAGS = $(filter-out -Wmissing-format-attribute, $(WARN_CXXFLAGS))
-DMD_COMPILE = $(subst $(WARN_CXXFLAGS), $(DMD_WARN_CXXFLAGS), $(COMPILE))
+# Use strict warnings.
+d-warn = $(STRICT_WARN)
+
+# D compiler and flags for building the front-end.
+ifeq ($(TREECHECKING),)
+CHECKING_DFLAGS = -frelease
+else
+CHECKING_DFLAGS =
+endif
+WARN_DFLAGS = -Wall -Wdeprecated $(NOCOMMON_FLAG)
+
+ALL_DFLAGS = $(DFLAGS-$@) $(GDCFLAGS) -fversion=IN_GCC $(CHECKING_DFLAGS) \
+	$(PICFLAG) $(ALIASING_FLAGS) $(COVERAGE_FLAGS) $(WARN_DFLAGS)
+
+DCOMPILE.base = $(GDC) $(NO_PIE_CFLAGS) -c $(ALL_DFLAGS) -o $@
+DCOMPILE = $(DCOMPILE.base) -MT $@ -MMD -MP -MF $(@D)/$(DEPDIR)/$(*F).TPo
+DPOSTCOMPILE = @mv $(@D)/$(DEPDIR)/$(*F).TPo $(@D)/$(DEPDIR)/$(*F).Po
+DLINKER = $(GDC) $(NO_PIE_FLAG) -lstdc++
+
+# Like LINKER, but use a mutex for serializing front end links.
+ifeq (@DO_LINK_MUTEX@,true)
+DLLINKER = $(SHELL) $(srcdir)/lock-and-run.sh linkfe.lck $(DLINKER)
+else
+DLLINKER = $(DLINKER)
+endif
 
 # D Frontend object files.
 D_FRONTEND_OBJS = \
 	d/aav.o \
 	d/access.o \
+	d/aggregate.o \
 	d/aliasthis.o \
 	d/apply.o \
+	d/array.o \
 	d/arrayop.o \
+	d/arraytypes.o \
 	d/attrib.o \
+	d/ast_node.o \
+	d/astcodegen.o \
+	d/astenums.o \
+	d/bitarray.o \
 	d/blockexit.o \
+	d/builtin.o \
 	d/canthrow.o \
-	d/checkedint.o \
 	d/chkformat.o \
 	d/clone.o \
+	d/compiler.o \
+	d/complex.o \
 	d/cond.o \
 	d/constfold.o \
+	d/cparse.o \
 	d/cppmangle.o \
 	d/ctfeexpr.o \
+	d/ctfloat.o \
+	d/ctorflow.o \
 	d/dcast.o \
 	d/dclass.o \
 	d/declaration.o \
@@ -86,32 +117,49 @@  D_FRONTEND_OBJS = \
 	d/dsymbol.o \
 	d/dsymbolsem.o \
 	d/dtemplate.o \
+	d/dtoh.o \
 	d/dversion.o \
 	d/entity.o \
+	d/errors.o \
 	d/escape.o \
 	d/expression.o \
 	d/expressionsem.o \
 	d/file.o \
 	d/filename.o \
+	d/foreachvar.o \
 	d/func.o \
+	d/globals.o \
+	d/gluelayer.o \
+	d/hash.o \
 	d/hdrgen.o \
 	d/iasm.o \
 	d/iasmgcc.o \
+	d/id.o \
 	d/identifier.o \
+	d/impcnvtab.o \
 	d/imphint.o \
 	d/init.o \
 	d/initsem.o \
+	d/inline.o \
 	d/intrange.o \
 	d/json.o \
+	d/lambdacomp.o \
 	d/lexer.o \
+	d/longdouble.o \
 	d/mtype.o \
 	d/nogc.o \
 	d/nspace.o \
+	d/ob.o \
 	d/objc.o \
 	d/opover.o \
 	d/optimize.o \
 	d/outbuffer.o \
 	d/parse.o \
+	d/parsetimevisitor.o \
+	d/permissivevisitor.o \
+	d/port.o \
+	d/printast.o \
+	d/region.o \
 	d/rmem.o \
 	d/rootobject.o \
 	d/safe.o \
@@ -121,20 +169,23 @@  D_FRONTEND_OBJS = \
 	d/sideeffect.o \
 	d/speller.o \
 	d/statement.o \
+	d/statement_rewrite_walker.o \
 	d/statementsem.o \
 	d/staticassert.o \
 	d/staticcond.o \
+	d/stmtstate.o \
+	d/string.o \
 	d/stringtable.o \
+	d/target.o \
 	d/templateparamsem.o \
 	d/tokens.o \
 	d/traits.o \
+	d/transitivevisitor.o \
 	d/typesem.o \
+	d/typinf.o \
 	d/utf.o \
-	d/utils.o
-
-# D Frontend generated files.
-D_GENERATED_SRCS = d/id.c d/id.h d/impcnvtab.c
-D_GENERATED_OBJS = d/id.o d/impcnvtab.o
+	d/utils.o \
+	d/visitor.o
 
 # Language-specific object files for D.
 D_OBJS = \
@@ -163,13 +214,13 @@  D_OBJS = \
 	d/types.o
 
 # All language-specific object files for D.
-D_ALL_OBJS = $(D_FRONTEND_OBJS) $(D_GENERATED_OBJS) $(D_OBJS) $(D_TARGET_OBJS)
+D_ALL_OBJS = $(D_FRONTEND_OBJS) $(D_OBJS) $(D_TARGET_OBJS)
 
 d_OBJS = $(D_ALL_OBJS) d/d-spec.o
 
 d21$(exeext): $(D_ALL_OBJS) attribs.o $(BACKEND) $(LIBDEPS) $(d.prev)
 	@$(call LINK_PROGRESS,$(INDEX.d),start)
-	+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
+	+$(DLLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -static-libphobos -o $@ \
 		$(D_ALL_OBJS) attribs.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
 	@$(call LINK_PROGRESS,$(INDEX.d),end)
 
@@ -221,7 +272,7 @@  d.srcextra:
 
 d.tags: force
 	cd $(srcdir)/d; \
-	$(ETAGS) -o TAGS.sub *.c *.cc *.h dmd/*.c dmd/*.h dmd/root/*.h dmd/root/*.c; \
+	$(ETAGS) -o TAGS.sub *.c *.cc *.h dmd/*.h dmd/root/*.h; \
 	$(ETAGS) --include TAGS.sub --include ../TAGS.sub
 
 d.man: doc/gdc.1
@@ -313,8 +364,6 @@  d.uninstall:
 d.mostlyclean:
 	-rm -f d/*$(objext)
 	-rm -f d/*$(coverageexts)
-	-rm -f $(D_GENERATED_SRCS)
-	-rm -f d/idgen$(build_exeext) d/impcnvgen$(build_exeext)
 	-rm -f gdc$(exeext) gdc-cross$(exeext) d21$(exeext)
 d.clean:
 d.distclean:
@@ -337,48 +386,13 @@  d.stagefeedback: stagefeedback-start
 	-mv d/*$(objext) stagefeedback/d
 
 # Include the dfrontend and build directories for headers.
-D_INCLUDES = -I$(srcdir)/d -I$(srcdir)/d/dmd -Id
-
-CFLAGS-d/id.o += $(D_INCLUDES)
-CFLAGS-d/impcnvtab.o += $(D_INCLUDES)
+D_INCLUDES = -I$(srcdir)/d -J$(srcdir)/d/dmd -J$(srcdir)/d/dmd/res
 
 # Override build rules for D frontend.
-d/%.o: d/dmd/%.c $(D_GENERATED_SRCS)
-	$(DMD_COMPILE) $(D_INCLUDES) $<
-	$(POSTCOMPILE)
-
-d/%.o: d/dmd/root/%.c $(D_GENERATED_SRCS)
-	$(DMD_COMPILE) $(D_INCLUDES) $<
-	$(POSTCOMPILE)
-
-# Generated programs.
-d/idgen$(build_exeext): d/idgen.dmdgen.o $(BUILD_LIBDEPS)
-	+$(LINKER_FOR_BUILD) $(BUILD_LINKERFLAGS) $(BUILD_LDFLAGS) -o $@ \
-	    $(filter-out $(BUILD_LIBDEPS), $^) $(BUILD_LIBS)
-
-d/impcnvgen$(build_exeext): d/impcnvgen.dmdgen.o $(BUILD_LIBDEPS)
-	+$(LINKER_FOR_BUILD) $(BUILD_LINKERFLAGS) $(BUILD_LDFLAGS) -o $@ \
-	    $(filter-out $(BUILD_LIBDEPS), $^) $(BUILD_LIBS)
-
-# Generated sources.
-d/id.c: d/idgen$(build_exeext)
-	cd d && ./idgen$(build_exeext)
-
-# idgen also generates id.h; just verify it exists.
-d/id.h: d/id.c
-
-d/impcnvtab.c: d/impcnvgen$(build_exeext)
-	cd d && ./impcnvgen$(build_exeext)
-
-# Compile the generator programs.
-d/%.dmdgen.o: $(srcdir)/d/dmd/%.c
-	$(COMPILER_FOR_BUILD) -c $(BUILD_COMPILERFLAGS) $(D_INCLUDES) \
-		$(BUILD_CPPFLAGS) -o $@ $<
-
-# Header dependencies for the generator programs.
-D_SYSTEM_H = d/dmd/root/dsystem.h d/d-system.h
-
-d/idgen.dmdgen.o: d/dmd/idgen.c $(D_SYSTEM_H) $(BCONFIG_H) $(SYSTEM_H)
+d/%.o: d/dmd/%.d
+	$(DCOMPILE) $(D_INCLUDES) $<
+	$(DPOSTCOMPILE)
 
-d/impcnvgen.dmdgen.o: d/dmd/impcnvgen.c d/dmd/mtype.h $(D_SYSTEM_H) \
-	$(BCONFIG_H) $(SYSTEM_H)
+d/%.o: d/dmd/root/%.d
+	$(DCOMPILE) $(D_INCLUDES) $<
+	$(DPOSTCOMPILE)
diff --git a/gcc/d/config-lang.in b/gcc/d/config-lang.in
index 0568b8da1de..00a71d6b8b5 100644
--- a/gcc/d/config-lang.in
+++ b/gcc/d/config-lang.in
@@ -19,10 +19,12 @@ 
 # We define several parameters used by configure:
 #
 # language	- name of language as it would appear in $(LANGUAGES)
+# boot_language	- "yes" if we need to build this language in stage1
 # compilers	- value to add to $(COMPILERS)
 
 language="d"
 
+boot_language=yes
 compilers="d21\$(exeext)"
 
 phobos_target_deps="target-zlib target-libbacktrace"
diff --git a/gcc/d/d-attribs.cc b/gcc/d/d-attribs.cc
index b79cf96f55c..04b9791ab1b 100644
--- a/gcc/d/d-attribs.cc
+++ b/gcc/d/d-attribs.cc
@@ -24,6 +24,7 @@  along with GCC; see the file COPYING3.  If not see
 
 #include "dmd/attrib.h"
 #include "dmd/declaration.h"
+#include "dmd/expression.h"
 #include "dmd/module.h"
 #include "dmd/mtype.h"
 #include "dmd/template.h"
diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc
index 33347a14c67..ab3a950689f 100644
--- a/gcc/d/d-builtins.cc
+++ b/gcc/d/d-builtins.cc
@@ -39,6 +39,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "stor-layout.h"
 
 #include "d-tree.h"
+#include "d-frontend.h"
 #include "d-target.h"
 
 
@@ -98,7 +99,7 @@  build_frontend_type (tree type)
 	  if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == char_type_node)
 	    return Type::tchar->addMod (dtype->mod)->pointerTo ()->addMod (mod);
 
-	  if (dtype->ty == Tfunction)
+	  if (dtype->ty == TY::Tfunction)
 	    return (TypePointer::create (dtype))->addMod (mod);
 
 	  return dtype->pointerTo ()->addMod (mod);
@@ -130,7 +131,7 @@  build_frontend_type (tree type)
 
       /* For now, skip support for cent/ucent until the frontend
 	 has better support for handling it.  */
-      for (size_t i = Tint8; i <= Tuns64; i++)
+      for (size_t i = (size_t) TY::Tint8; i <= (size_t) TY::Tuns64; i++)
 	{
 	  dtype = Type::basic[i];
 
@@ -148,7 +149,7 @@  build_frontend_type (tree type)
     {
       unsigned size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
 
-      for (size_t i = Tfloat32; i <= Tfloat80; i++)
+      for (size_t i = (size_t) TY::Tfloat32; i <= (size_t) TY::Tfloat80; i++)
 	{
 	  dtype = Type::basic[i];
 
@@ -164,7 +165,8 @@  build_frontend_type (tree type)
     case COMPLEX_TYPE:
     {
       unsigned size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
-      for (size_t i = Tcomplex32; i <= Tcomplex80; i++)
+      for (size_t i = (size_t) TY::Tcomplex32; i <= (size_t) TY::Tcomplex80;
+	   i++)
 	{
 	  dtype = Type::basic[i];
 
@@ -235,7 +237,7 @@  build_frontend_type (tree type)
       sdecl->structsize = int_size_in_bytes (type);
       sdecl->alignsize = TYPE_ALIGN_UNIT (type);
       sdecl->alignment = STRUCTALIGN_DEFAULT;
-      sdecl->sizeok = SIZEOKdone;
+      sdecl->sizeok = Sizeok::done;
       sdecl->type = (TypeStruct::create (sdecl))->addMod (mod);
       sdecl->type->ctype = type;
       sdecl->type->merge2 ();
@@ -243,7 +245,7 @@  build_frontend_type (tree type)
       /* Add both named and anonymous fields as members of the struct.
 	 Anonymous fields still need a name in D, so call them "__pad%u".  */
       unsigned anonfield_id = 0;
-      sdecl->members = new Dsymbols;
+      sdecl->members = d_gc_malloc<Dsymbols> ();
 
       for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
 	{
@@ -253,7 +255,6 @@  build_frontend_type (tree type)
 	      /* Drop any field types that got cached before the conversion
 		 of this record type failed.  */
 	      builtin_converted_decls.truncate (saved_builtin_decls_length);
-	      delete sdecl->members;
 	      return NULL;
 	    }
 
@@ -292,7 +293,7 @@  build_frontend_type (tree type)
 	  tree parms = TYPE_ARG_TYPES (type);
 	  VarArg varargs_p = VARARGvariadic;
 
-	  Parameters *args = new Parameters;
+	  Parameters *args = d_gc_malloc<Parameters> ();
 	  args->reserve (list_length (parms));
 
 	  /* Attempt to convert all parameter types.  */
@@ -318,7 +319,6 @@  build_frontend_type (tree type)
 		  /* Drop any parameter types that got cached before the
 		     conversion of this function type failed.  */
 		  builtin_converted_decls.truncate (saved_builtin_decls_length);
-		  delete args;
 		  return NULL;
 		}
 
@@ -329,7 +329,7 @@  build_frontend_type (tree type)
 	     have no named parameters, and so can't be represented in D.  */
 	  if (args->length != 0 || varargs_p == VARARGnone)
 	    {
-	      dtype = TypeFunction::create (args, dtype, varargs_p, LINKc);
+	      dtype = TypeFunction::create (args, dtype, varargs_p, LINK::c);
 	      return dtype->addMod (mod);
 	    }
 	}
@@ -386,7 +386,7 @@  d_eval_constant_expression (const Loc &loc, tree cst)
       else if (code == VECTOR_CST)
 	{
 	  dinteger_t nunits = VECTOR_CST_NELTS (cst).to_constant ();
-	  Expressions *elements = new Expressions;
+	  Expressions *elements = d_gc_malloc<Expressions> ();
 	  elements->setDim (nunits);
 
 	  for (size_t i = 0; i < nunits; i++)
@@ -520,7 +520,7 @@  build_alias_declaration (const char *alias, Type *type)
 void
 d_build_builtins_module (Module *m)
 {
-  Dsymbols *members = new Dsymbols;
+  Dsymbols *members = d_gc_malloc<Dsymbols> ();
   tree decl;
 
   for (size_t i = 0; vec_safe_iterate (gcc_builtins_functions, i, &decl); ++i)
@@ -543,16 +543,16 @@  d_build_builtins_module (Module *m)
 	   flag_unsafe_math_optimizations.
 	 - Built-ins never use the GC or raise a D exception, and so are always
 	   marked as `nothrow' and `@nogc'.  */
-      tf->purity = DECL_PURE_P (decl) ? PUREstrong
-	: TREE_READONLY (decl) ? PUREconst
-	: DECL_IS_NOVOPS (decl) ? PUREweak
-	: !DECL_ASSEMBLER_NAME_SET_P (decl) ? PUREweak
-	: PUREimpure;
-      tf->trust = !DECL_ASSEMBLER_NAME_SET_P (decl) ? TRUSTsafe
-	: TREE_NOTHROW (decl) ? TRUSTtrusted
-	: TRUSTsystem;
-      tf->isnothrow = true;
-      tf->isnogc = true;
+      tf->purity = DECL_PURE_P (decl) ? PURE::strong
+	: TREE_READONLY (decl) ? PURE::const_
+	: DECL_IS_NOVOPS (decl) ? PURE::weak
+	: !DECL_ASSEMBLER_NAME_SET_P (decl) ? PURE::weak
+	: PURE::impure;
+      tf->trust = !DECL_ASSEMBLER_NAME_SET_P (decl) ? TRUST::safe
+	: TREE_NOTHROW (decl) ? TRUST::trusted
+	: TRUST::system;
+      tf->isnothrow (true);
+      tf->isnogc (true);
 
       FuncDeclaration *func
 	= FuncDeclaration::create (Loc (), Loc (),
@@ -560,7 +560,7 @@  d_build_builtins_module (Module *m)
 				   STCextern, tf);
       DECL_LANG_SPECIFIC (decl) = build_lang_decl (func);
       func->csym = decl;
-      func->builtin = BUILTINgcc;
+      func->builtin = BUILTIN::gcc;
 
       members->push (func);
     }
@@ -660,7 +660,7 @@  d_build_builtins_module (Module *m)
     members->push (build_alias_declaration ("__builtin_unwind_uint", t));
   }
 
-  m->members->push (LinkDeclaration::create (LINKc, members));
+  m->members->push (LinkDeclaration::create (Loc (), LINK::c, members));
 }
 
 /* Search for any `extern(C)' functions that match any known GCC library builtin
@@ -700,7 +700,7 @@  maybe_set_builtin_1 (Dsymbol *d)
 	  /* Found a match, tell the frontend this is a builtin.  */
 	  DECL_LANG_SPECIFIC (t) = build_lang_decl (fd);
 	  fd->csym = t;
-	  fd->builtin = BUILTINgcc;
+	  fd->builtin = BUILTIN::gcc;
 	  return;
 	}
     }
@@ -858,7 +858,7 @@  d_build_d_type_nodes (void)
 
   /* Calling build_ctype() links the front-end Type to the GCC node,
      and sets the TYPE_NAME to the D language type.  */
-  for (unsigned ty = 0; ty < TMAX; ty++)
+  for (unsigned ty = 0; ty < (unsigned) TY::TMAX; ty++)
     {
       if (Type::basic[ty] != NULL)
 	build_ctype (Type::basic[ty]);
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index e63365055d3..403e3c74377 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -76,7 +76,7 @@  d_decl_context (Dsymbol *dsym)
 	 but only for extern(D) symbols.  */
       if (parent->isModule ())
 	{
-	  if ((decl != NULL && decl->linkage != LINKd)
+	  if ((decl != NULL && decl->linkage != LINK::d)
 	      || (ad != NULL && ad->classKind != ClassKind::d))
 	    return NULL_TREE;
 
@@ -131,7 +131,7 @@  declaration_reference_p (Declaration *decl)
   Type *tb = decl->type->toBasetype ();
 
   /* Declaration is a reference type.  */
-  if (tb->ty == Treference || decl->storage_class & (STCout | STCref))
+  if (tb->ty == TY::Treference || decl->storage_class & (STCout | STCref))
     return true;
 
   return false;
@@ -146,7 +146,7 @@  declaration_type (Declaration *decl)
   if (decl->storage_class & STClazy)
     {
       TypeFunction *tf = TypeFunction::create (NULL, decl->type,
-					       VARARGnone, LINKd);
+					       VARARGnone, LINK::d);
       TypeDelegate *t = TypeDelegate::create (tf);
       return build_ctype (t->merge2 ());
     }
@@ -181,7 +181,7 @@  parameter_reference_p (Parameter *arg)
   Type *tb = arg->type->toBasetype ();
 
   /* Parameter is a reference type.  */
-  if (tb->ty == Treference || arg->storageClass & (STCout | STCref))
+  if (tb->ty == TY::Treference || arg->storageClass & (STCout | STCref))
     return true;
 
   return false;
@@ -196,7 +196,7 @@  parameter_type (Parameter *arg)
   if (arg->storageClass & STClazy)
     {
       TypeFunction *tf = TypeFunction::create (NULL, arg->type,
-					       VARARGnone, LINKd);
+					       VARARGnone, LINK::d);
       TypeDelegate *t = TypeDelegate::create (tf);
       return build_ctype (t->merge2 ());
     }
@@ -319,10 +319,10 @@  get_array_length (tree exp, Type *type)
 
   switch (tb->ty)
     {
-    case Tsarray:
+    case TY::Tsarray:
       return size_int (tb->isTypeSArray ()->dim->toUInteger ());
 
-    case Tarray:
+    case TY::Tarray:
       return d_array_length (exp);
 
     default:
@@ -411,7 +411,7 @@  build_delegate_cst (tree method, tree object, Type *type)
   tree ctype;
 
   Type *tb = type->toBasetype ();
-  if (tb->ty == Tdelegate)
+  if (tb->ty == TY::Tdelegate)
     ctype = build_ctype (type);
   else
     {
@@ -464,11 +464,11 @@  build_typeof_null_value (Type *type)
   tree value;
 
   /* For dynamic arrays, set length and pointer fields to zero.  */
-  if (tb->ty == Tarray)
+  if (tb->ty == TY::Tarray)
     value = d_array_value (build_ctype (type), size_int (0), null_pointer_node);
 
   /* For associative arrays, set the pointer field to null.  */
-  else if (tb->ty == Taarray)
+  else if (tb->ty == TY::Taarray)
     {
       tree ctype = build_ctype (type);
       gcc_assert (TYPE_ASSOCIATIVE_ARRAY (ctype));
@@ -478,7 +478,7 @@  build_typeof_null_value (Type *type)
     }
 
   /* For delegates, set the frame and function pointer fields to null.  */
-  else if (tb->ty == Tdelegate)
+  else if (tb->ty == TY::Tdelegate)
     value = build_delegate_cst (null_pointer_node, null_pointer_node, type);
 
   /* Simple zero constant for all other types.  */
@@ -882,7 +882,9 @@  identity_compare_p (StructDeclaration *sd)
 	}
 
       /* Check for types that may have padding.  */
-      if ((tb->ty == Tcomplex80 || tb->ty == Tfloat80 || tb->ty == Timaginary80)
+      if ((tb->ty == TY::Tcomplex80
+	   || tb->ty == TY::Tfloat80
+	   || tb->ty == TY::Timaginary80)
 	  && target.realpad != 0)
 	return false;
 
@@ -960,12 +962,12 @@  lower_struct_comparison (tree_code code, StructDeclaration *sd,
 	  /* Compare inner data structures.  */
 	  tcmp = lower_struct_comparison (code, ts->sym, t1ref, t2ref);
 	}
-      else if (type->ty != Tvector && type->isintegral ())
+      else if (type->ty != TY::Tvector && type->isintegral ())
 	{
 	  /* Integer comparison, no special handling required.  */
 	  tcmp = build_boolop (code, t1ref, t2ref);
 	}
-      else if (type->ty != Tvector && type->isfloating ())
+      else if (type->ty != TY::Tvector && type->isfloating ())
 	{
 	  /* Floating-point comparison, don't compare padding in type.  */
 	  if (!type->iscomplex ())
@@ -1839,7 +1841,7 @@  static tree
 build_filename_from_loc (const Loc &loc)
 {
   const char *filename = loc.filename
-    ? loc.filename : d_function_chain->module->srcfile->toChars ();
+    ? loc.filename : d_function_chain->module->srcfile.toChars ();
 
   unsigned length = strlen (filename);
   tree str = build_string (length, filename);
@@ -1862,7 +1864,6 @@  build_assert_call (const Loc &loc, libcall_fn libcall, tree msg)
     {
     case LIBCALL_ASSERT_MSG:
     case LIBCALL_UNITTEST_MSG:
-    case LIBCALL_SWITCH_ERROR:
       /* File location is passed as a D string.  */
       if (loc.filename)
 	{
@@ -1912,7 +1913,7 @@  build_array_bounds_call (const Loc &loc)
 
 /* Builds a bounds condition checking that INDEX is between 0 and LENGTH
    in the index expression IE.  The condition returns the INDEX if true, or
-   throws a `RangeError`.  */
+   throws a `ArrayIndexError`.  */
 
 tree
 build_bounds_index_condition (IndexExp *ie, tree index, tree length)
@@ -1927,7 +1928,16 @@  build_bounds_index_condition (IndexExp *ie, tree index, tree length)
      No need to check whether INDEX >= 0 as the front-end should
      have already taken care of implicit casts to unsigned.  */
   tree condition = fold_build2 (GE_EXPR, d_bool_type, index, length);
-  tree boundserr = build_array_bounds_call (ie->e2->loc);
+  tree boundserr;
+
+  if (checkaction_trap_p ())
+    boundserr = build_call_expr (builtin_decl_explicit (BUILT_IN_TRAP), 0);
+  else
+    {
+      boundserr = build_libcall (LIBCALL_ARRAYBOUNDS_INDEXP, Type::tvoid, 4,
+				 build_filename_from_loc (ie->e2->loc),
+				 size_int (ie->e2->loc.linnum), index, length);
+    }
 
   return build_condition (TREE_TYPE (index), condition, boundserr, index);
 }
@@ -1963,7 +1973,22 @@  build_bounds_slice_condition (SliceExp *se, tree lower, tree upper, tree length)
 
       if (condition != NULL_TREE)
 	{
-	  tree boundserr = build_array_bounds_call (se->loc);
+	  tree boundserr;
+
+	  if (checkaction_trap_p ())
+	    {
+	      boundserr =
+		build_call_expr (builtin_decl_explicit (BUILT_IN_TRAP), 0);
+	    }
+	  else
+	    {
+	      boundserr = build_libcall (LIBCALL_ARRAYBOUNDS_SLICEP,
+					 Type::tvoid, 5,
+					 build_filename_from_loc (se->loc),
+					 size_int (se->loc.linnum),
+					 lower, upper, length);
+	    }
+
 	  upper = build_condition (TREE_TYPE (upper), condition,
 				   boundserr, upper);
 	}
@@ -1993,9 +2018,9 @@  array_bounds_check (void)
     case CHECKENABLEsafeonly:
       /* For D2 safe functions only.  */
       fd = d_function_chain->function;
-      if (fd && fd->type->ty == Tfunction)
+      if (fd && fd->type->ty == TY::Tfunction)
 	{
-	  if (fd->type->isTypeFunction ()->trust == TRUSTsafe)
+	  if (fd->type->isTypeFunction ()->trust == TRUST::safe)
 	    return true;
 	}
       return false;
@@ -2014,6 +2039,7 @@  checkaction_trap_p (void)
   switch (global.params.checkAction)
     {
     case CHECKACTION_D:
+    case CHECKACTION_context:
       return false;
 
     case CHECKACTION_C:
@@ -2032,11 +2058,11 @@  TypeFunction *
 get_function_type (Type *t)
 {
   TypeFunction *tf = NULL;
-  if (t->ty == Tpointer)
+  if (t->ty == TY::Tpointer)
     t = t->nextOf ()->toBasetype ();
-  if (t->ty == Tfunction)
+  if (t->ty == TY::Tfunction)
     tf = t->isTypeFunction ();
-  else if (t->ty == Tdelegate)
+  else if (t->ty == TY::Tdelegate)
     tf = t->isTypeDelegate ()->next->isTypeFunction ();
   return tf;
 }
@@ -2096,7 +2122,7 @@  d_build_call (TypeFunction *tf, tree callable, tree object,
 
   gcc_assert (FUNC_OR_METHOD_TYPE_P (ctype));
   gcc_assert (tf != NULL);
-  gcc_assert (tf->ty == Tfunction);
+  gcc_assert (tf->ty == TY::Tfunction);
 
   if (TREE_CODE (ctype) != FUNCTION_TYPE && object == NULL_TREE)
     {
@@ -2195,7 +2221,7 @@  d_build_call (TypeFunction *tf, tree callable, tree object,
   SET_EXPR_LOCATION (result, input_location);
 
   /* Enforce left to right evaluation.  */
-  if (tf->linkage == LINKd)
+  if (tf->linkage == LINK::d)
     CALL_EXPR_ARGS_ORDERED (result) = 1;
 
   result = maybe_expand_intrinsic (result);
diff --git a/gcc/d/d-compiler.cc b/gcc/d/d-compiler.cc
index 512ef4bab3e..3df40073ac5 100644
--- a/gcc/d/d-compiler.cc
+++ b/gcc/d/d-compiler.cc
@@ -20,7 +20,6 @@  along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 
 #include "dmd/compiler.h"
-#include "dmd/scope.h"
 #include "dmd/expression.h"
 #include "dmd/identifier.h"
 #include "dmd/module.h"
@@ -34,40 +33,6 @@  along with GCC; see the file COPYING3.  If not see
 
 /* Implements the Compiler interface used by the frontend.  */
 
-/* Generate C main() in response to seeing D main().  This used to be in
-   libdruntime, but contained a reference to _Dmain which didn't work when
-   druntime was made into a shared library and was linked to a program, such
-   as a C++ program, that didn't have a _Dmain.  */
-
-void
-Compiler::genCmain (Scope *sc)
-{
-  static bool initialized = false;
-
-  if (initialized)
-    return;
-
-  /* The D code to be generated is provided by __entrypoint.di, try to load it,
-     but don't fail if unfound.  */
-  unsigned errors = global.startGagging ();
-  Module *m = Module::load (Loc (), NULL, Identifier::idPool ("__entrypoint"));
-
-  if (global.endGagging (errors))
-    m = NULL;
-
-  if (m != NULL)
-    {
-      m->importedFrom = m;
-      m->importAll (NULL);
-      dsymbolSemantic (m, NULL);
-      semantic2 (m, NULL);
-      semantic3 (m, NULL);
-      d_add_entrypoint_module (m, sc->_module);
-    }
-
-  initialized = true;
-}
-
 /* Perform a reinterpret cast of EXPR to type TYPE for use in CTFE.
    The front end should have already ensured that EXPR is a constant,
    so we just lower the value to GCC and return the converted CST.  */
@@ -123,7 +88,7 @@  Compiler::paintAsType (UnionExp *, Expression *expr, Type *type)
   /* Encode CST to buffer.  */
   int len = native_encode_expr (cst, buffer, sizeof (buffer));
 
-  if (tb->ty == Tsarray)
+  if (tb->ty == TY::Tsarray)
     {
       /* Interpret value as a vector of the same size,
 	 then return the array literal.  */
@@ -161,22 +126,22 @@  Compiler::onParseModule (Module *m)
 {
   ModuleDeclaration *md = m->md;
 
-  if (!md || !md->id || !md->packages)
+  if (!md || !md->id|| md->packages.length == 0)
     {
       Identifier *id = (md && md->id) ? md->id : m->ident;
       if (!strcmp (id->toChars (), "object"))
 	create_tinfo_types (m);
     }
-  else if (md->packages->length == 1)
+  else if (md->packages.length == 1)
     {
-      if (!strcmp ((*md->packages)[0]->toChars (), "gcc")
+      if (!strcmp (md->packages.ptr[0]->toChars (), "gcc")
 	  && !strcmp (md->id->toChars (), "builtins"))
 	d_build_builtins_module (m);
     }
-  else if (md->packages->length == 2)
+  else if (md->packages.length == 2)
     {
-      if (!strcmp ((*md->packages)[0]->toChars (), "core")
-	  && !strcmp ((*md->packages)[1]->toChars (), "stdc"))
+      if (!strcmp (md->packages.ptr[0]->toChars (), "core")
+	  && !strcmp (md->packages.ptr[1]->toChars (), "stdc"))
 	d_add_builtin_module (m);
     }
 }
diff --git a/gcc/d/d-convert.cc b/gcc/d/d-convert.cc
index 3b4790298a5..25fd603edfa 100644
--- a/gcc/d/d-convert.cc
+++ b/gcc/d/d-convert.cc
@@ -361,14 +361,14 @@  convert_expr (tree exp, Type *etype, Type *totype)
 
   switch (ebtype->ty)
     {
-    case Tdelegate:
-      if (tbtype->ty == Tdelegate)
+    case TY::Tdelegate:
+      if (tbtype->ty == TY::Tdelegate)
 	{
 	  exp = d_save_expr (exp);
 	  return build_delegate_cst (delegate_method (exp),
 				     delegate_object (exp), totype);
 	}
-      else if (tbtype->ty == Tpointer)
+      else if (tbtype->ty == TY::Tpointer)
 	{
 	  /* The front-end converts <delegate>.ptr to cast (void *)<delegate>.
 	     Maybe should only allow void* ?  */
@@ -382,8 +382,8 @@  convert_expr (tree exp, Type *etype, Type *totype)
 	}
       break;
 
-    case Tstruct:
-      if (tbtype->ty == Tstruct)
+    case TY::Tstruct:
+      if (tbtype->ty == TY::Tstruct)
 	{
 	  if (totype->size () == etype->size ())
 	    {
@@ -400,8 +400,8 @@  convert_expr (tree exp, Type *etype, Type *totype)
       /* else, default conversion, which should produce an error.  */
       break;
 
-    case Tclass:
-      if (tbtype->ty == Tclass)
+    case TY::Tclass:
+      if (tbtype->ty == TY::Tclass)
 	{
 	  ClassDeclaration *cdfrom = ebtype->isClassHandle ();
 	  ClassDeclaration *cdto = tbtype->isClassHandle ();
@@ -460,12 +460,12 @@  convert_expr (tree exp, Type *etype, Type *totype)
       /* else default conversion.  */
       break;
 
-    case Tsarray:
-      if (tbtype->ty == Tpointer)
+    case TY::Tsarray:
+      if (tbtype->ty == TY::Tpointer)
 	{
 	  result = build_nop (build_ctype (totype), build_address (exp));
 	}
-      else if (tbtype->ty == Tarray)
+      else if (tbtype->ty == TY::Tarray)
 	{
 	  dinteger_t dim = ebtype->isTypeSArray ()->dim->toInteger ();
 	  dinteger_t esize = ebtype->nextOf ()->size ();
@@ -490,12 +490,12 @@  convert_expr (tree exp, Type *etype, Type *totype)
 	  return d_array_value (build_ctype (totype), size_int (dim),
 				build_nop (ptrtype, build_address (exp)));
 	}
-      else if (tbtype->ty == Tsarray)
+      else if (tbtype->ty == TY::Tsarray)
 	{
 	  /* D allows casting a static array to any static array type.  */
 	  return build_nop (build_ctype (totype), exp);
 	}
-      else if (tbtype->ty == Tstruct)
+      else if (tbtype->ty == TY::Tstruct)
 	{
 	  /* And allows casting a static array to any struct type too.
 	     Type sizes should have already been checked by the frontend.  */
@@ -510,12 +510,12 @@  convert_expr (tree exp, Type *etype, Type *totype)
 	}
       break;
 
-    case Tarray:
-      if (tbtype->ty == Tpointer)
+    case TY::Tarray:
+      if (tbtype->ty == TY::Tpointer)
 	{
 	  return d_convert (build_ctype (totype), d_array_ptr (exp));
 	}
-      else if (tbtype->ty == Tarray)
+      else if (tbtype->ty == TY::Tarray)
 	{
 	  /* Assume tvoid->size() == 1.  */
 	  d_uns64 fsize = ebtype->nextOf ()->toBasetype ()->size ();
@@ -523,9 +523,18 @@  convert_expr (tree exp, Type *etype, Type *totype)
 
 	  if (fsize != tsize)
 	    {
-	      /* Conversion requires a reinterpret cast of array.  */
-	      return build_libcall (LIBCALL_ARRAYCAST, totype, 3,
-				    size_int (tsize), size_int (fsize), exp);
+	      /* Conversion requires a reinterpret cast of array.
+		 This case should have been lowered in the semantic pass.  */
+	      if (tsize != 0 && fsize % tsize == 0)
+		{
+		  /* Set array dimension to (length * (fsize / tsize)).  */
+		  tree newlength = size_mult_expr (d_array_length (exp),
+						   size_int (fsize / tsize));
+		  return d_array_value (build_ctype (totype), newlength,
+					d_array_ptr (exp));
+		}
+	      else
+		gcc_unreachable ();
 	    }
 	  else
 	    {
@@ -534,7 +543,7 @@  convert_expr (tree exp, Type *etype, Type *totype)
 	      return build_vconvert (build_ctype (totype), exp);
 	    }
 	}
-      else if (tbtype->ty == Tsarray)
+      else if (tbtype->ty == TY::Tsarray)
 	{
 	  /* Strings are treated as dynamic arrays in D2.  */
 	  if (ebtype->isString () && tbtype->isString ())
@@ -548,23 +557,23 @@  convert_expr (tree exp, Type *etype, Type *totype)
 	}
       break;
 
-    case Taarray:
-      if (tbtype->ty == Taarray)
+    case TY::Taarray:
+      if (tbtype->ty == TY::Taarray)
 	return build_vconvert (build_ctype (totype), exp);
       /* Can convert associative arrays to void pointers.  */
-      else if (tbtype->ty == Tpointer && tbtype->nextOf ()->ty == Tvoid)
+      else if (tbtype->ty == TY::Tpointer && tbtype->nextOf ()->ty == TY::Tvoid)
 	return build_vconvert (build_ctype (totype), exp);
       /* Else, default conversion, which should product an error.  */
       break;
 
-    case Tpointer:
+    case TY::Tpointer:
       /* Can convert void pointers to associative arrays too.  */
-      if (tbtype->ty == Taarray && ebtype->nextOf ()->ty == Tvoid)
+      if (tbtype->ty == TY::Taarray && ebtype->nextOf ()->ty == TY::Tvoid)
 	return build_vconvert (build_ctype (totype), exp);
       break;
 
-    case Tnull:
-    case Tnoreturn:
+    case TY::Tnull:
+    case TY::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);
@@ -574,8 +583,8 @@  convert_expr (tree exp, Type *etype, Type *totype)
 	result = compound_expr (exp, result);
       break;
 
-    case Tvector:
-      if (tbtype->ty == Tsarray)
+    case TY::Tvector:
+      if (tbtype->ty == TY::Tsarray)
 	{
 	  if (tbtype->size () == ebtype->size ())
 	    return build_vconvert (build_ctype (totype), exp);
@@ -613,7 +622,7 @@  convert_for_rvalue (tree expr, Type *etype, Type *totype)
   Type *ebtype = etype->toBasetype ();
   Type *tbtype = totype->toBasetype ();
 
-  if (ebtype->ty == Tbool)
+  if (ebtype->ty == TY::Tbool)
     {
       /* If casting from bool, the result is either 0 or 1, any other value
 	 violates @safe code, so enforce that it is never invalid.  */
@@ -651,7 +660,7 @@  convert_for_assignment (tree expr, Type *etype, Type *totype)
 
   /* Assuming this only has to handle converting a non Tsarray type to
      arbitrarily dimensioned Tsarrays.  */
-  if (tbtype->ty == Tsarray)
+  if (tbtype->ty == TY::Tsarray)
     {
       Type *telem = tbtype->nextOf ()->baseElemOf ();
 
@@ -685,7 +694,7 @@  convert_for_assignment (tree expr, Type *etype, Type *totype)
     }
 
   /* D Front end uses IntegerExp(0) to mean zero-init an array or structure.  */
-  if ((tbtype->ty == Tsarray || tbtype->ty == Tstruct)
+  if ((tbtype->ty == TY::Tsarray || tbtype->ty == TY::Tstruct)
       && ebtype->isintegral ())
     {
       if (!integer_zerop (expr))
@@ -736,12 +745,12 @@  convert_for_condition (tree expr, Type *type)
 
   switch (type->toBasetype ()->ty)
     {
-    case Taarray:
+    case TY::Taarray:
       /* Checks that aa.ptr !is null.  */
       result = component_ref (expr, TYPE_FIELDS (TREE_TYPE (expr)));
       break;
 
-    case Tarray:
+    case TY::Tarray:
       {
 	/* Checks (arr.length || arr.ptr) (i.e arr !is null).  */
 	expr = d_save_expr (expr);
@@ -762,7 +771,7 @@  convert_for_condition (tree expr, Type *type)
 	break;
       }
 
-    case Tdelegate:
+    case TY::Tdelegate:
       {
 	/* Checks (function || object), but what good is it if there is
 	   a null function pointer?  */
@@ -783,7 +792,7 @@  convert_for_condition (tree expr, Type *type)
 	break;
       }
 
-    case Tnoreturn:
+    case TY::Tnoreturn:
       /* Front-end allows conditionals that never return, represent the
 	 conditional result value as all zeros.  */
       result = build_zero_cst (d_bool_type);
@@ -810,10 +819,10 @@  d_array_convert (Expression *exp)
 {
   Type *tb = exp->type->toBasetype ();
 
-  if (tb->ty == Tarray)
+  if (tb->ty == TY::Tarray)
     return build_expr (exp);
 
-  if (tb->ty == Tsarray)
+  if (tb->ty == TY::Tsarray)
     {
       Type *totype = tb->nextOf ()->arrayOf ();
       return convert_expr (build_expr (exp), exp->type, totype);
@@ -832,7 +841,8 @@  d_array_convert (Type *etype, Expression *exp)
 {
   Type *tb = exp->type->toBasetype ();
 
-  if ((tb->ty != Tarray && tb->ty != Tsarray) || same_type_p (tb, etype))
+  if ((tb->ty != TY::Tarray && tb->ty != TY::Tsarray)
+      || same_type_p (tb, etype))
     {
       /* Convert single element to an array.  */
       tree expr = build_expr (exp);
diff --git a/gcc/d/d-diagnostic.cc b/gcc/d/d-diagnostic.cc
index 1982bd954a8..947b6e21d60 100644
--- a/gcc/d/d-diagnostic.cc
+++ b/gcc/d/d-diagnostic.cc
@@ -222,15 +222,6 @@  d_diagnostic_report_diagnostic (const Loc &loc, int opt, const char *format,
    message prefix PREFIX1 and PREFIX2, increasing the global or gagged
    error count.  */
 
-void ATTRIBUTE_GCC_DIAG(2,3)
-error (const Loc &loc, const char *format, ...)
-{
-  va_list ap;
-  va_start (ap, format);
-  verror (loc, format, ap);
-  va_end (ap);
-}
-
 void ATTRIBUTE_GCC_DIAG(2,0)
 verror (const Loc &loc, const char *format, va_list ap,
 	const char *prefix1, const char *prefix2, const char *)
@@ -263,15 +254,6 @@  verror (const Loc &loc, const char *format, va_list ap,
 /* Print supplementary message about the last error with explicit location LOC.
    This doesn't increase the global error count.  */
 
-void ATTRIBUTE_GCC_DIAG(2,3)
-errorSupplemental (const Loc &loc, const char *format, ...)
-{
-  va_list ap;
-  va_start (ap, format);
-  verrorSupplemental (loc, format, ap);
-  va_end (ap);
-}
-
 void ATTRIBUTE_GCC_DIAG(2,0)
 verrorSupplemental (const Loc &loc, const char *format, va_list ap)
 {
@@ -284,15 +266,6 @@  verrorSupplemental (const Loc &loc, const char *format, va_list ap)
 /* Print a warning message with explicit location LOC, increasing the
    global warning count.  */
 
-void ATTRIBUTE_GCC_DIAG(2,3)
-warning (const Loc &loc, const char *format, ...)
-{
-  va_list ap;
-  va_start (ap, format);
-  vwarning (loc, format, ap);
-  va_end (ap);
-}
-
 void ATTRIBUTE_GCC_DIAG(2,0)
 vwarning (const Loc &loc, const char *format, va_list ap)
 {
@@ -311,15 +284,6 @@  vwarning (const Loc &loc, const char *format, va_list ap)
 /* Print supplementary message about the last warning with explicit location
    LOC.  This doesn't increase the global warning count.  */
 
-void ATTRIBUTE_GCC_DIAG(2,3)
-warningSupplemental (const Loc &loc, const char *format, ...)
-{
-  va_list ap;
-  va_start (ap, format);
-  vwarningSupplemental (loc, format, ap);
-  va_end (ap);
-}
-
 void ATTRIBUTE_GCC_DIAG(2,0)
 vwarningSupplemental (const Loc &loc, const char *format, va_list ap)
 {
@@ -333,15 +297,6 @@  vwarningSupplemental (const Loc &loc, const char *format, va_list ap)
    message prefix PREFIX1 and PREFIX2, increasing the global warning or
    error count depending on how deprecations are treated.  */
 
-void ATTRIBUTE_GCC_DIAG(2,3)
-deprecation (const Loc &loc, const char *format, ...)
-{
-  va_list ap;
-  va_start (ap, format);
-  vdeprecation (loc, format, ap);
-  va_end (ap);
-}
-
 void ATTRIBUTE_GCC_DIAG(2,0)
 vdeprecation (const Loc &loc, const char *format, va_list ap,
 	      const char *prefix1, const char *prefix2)
@@ -372,15 +327,6 @@  vdeprecation (const Loc &loc, const char *format, va_list ap,
 /* Print supplementary message about the last deprecation with explicit
    location LOC.  This does not increase the global error count.  */
 
-void ATTRIBUTE_GCC_DIAG(2,3)
-deprecationSupplemental (const Loc &loc, const char *format, ...)
-{
-  va_list ap;
-  va_start (ap, format);
-  vdeprecationSupplemental (loc, format, ap);
-  va_end (ap);
-}
-
 void ATTRIBUTE_GCC_DIAG(2,0)
 vdeprecationSupplemental (const Loc &loc, const char *format, va_list ap)
 {
@@ -392,30 +338,19 @@  vdeprecationSupplemental (const Loc &loc, const char *format, va_list ap)
 
 /* Print a verbose message with explicit location LOC.  */
 
-void ATTRIBUTE_GCC_DIAG(2, 3)
-message (const Loc &loc, const char *format, ...)
-{
-  va_list ap;
-  va_start (ap, format);
-  vmessage (loc, format, ap);
-  va_end (ap);
-}
-
 void ATTRIBUTE_GCC_DIAG(2,0)
 vmessage (const Loc &loc, const char *format, va_list ap)
 {
   d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_NOTE, true);
 }
 
-/* Same as above, but doesn't take a location argument.  */
+/* Print a tip message with prefix and highlighing.  */
 
-void ATTRIBUTE_GCC_DIAG(1, 2)
-message (const char *format, ...)
+void ATTRIBUTE_GCC_DIAG(1,0)
+vtip (const char *format, va_list ap)
 {
-  va_list ap;
-  va_start (ap, format);
-  vmessage (Loc (), format, ap);
-  va_end (ap);
+  if (!global.gag)
+    d_diagnostic_report_diagnostic (Loc (), 0, format, ap, DK_DEBUG, true);
 }
 
 /* Call this after printing out fatal error messages to clean up and
diff --git a/gcc/d/d-frontend.cc b/gcc/d/d-frontend.cc
index 30fc6d435d0..522095f12c5 100644
--- a/gcc/d/d-frontend.cc
+++ b/gcc/d/d-frontend.cc
@@ -27,116 +27,11 @@  along with GCC; see the file COPYING3.  If not see
 #include "dmd/scope.h"
 
 #include "tree.h"
-#include "options.h"
 #include "fold-const.h"
 #include "diagnostic.h"
 
 #include "d-tree.h"
 
-
-/* Implements the Global interface defined by the frontend.
-   Used for managing the state of the current compilation.  */
-
-Global global;
-
-void
-Global::_init (void)
-{
-  this->mars_ext = "d";
-  this->hdr_ext  = "di";
-  this->doc_ext  = "html";
-  this->ddoc_ext = "ddoc";
-  this->json_ext = "json";
-  this->obj_ext = "o";
-
-  this->run_noext = true;
-  this->version = "v"
-#include "verstr.h"
-    ;
-
-  this->stdmsg = stderr;
-}
-
-/* Start gagging. Return the current number of gagged errors.  */
-
-unsigned
-Global::startGagging (void)
-{
-  this->gag++;
-  return this->gaggedErrors;
-}
-
-/* End gagging, restoring the old gagged state.  Return true if errors
-   occured while gagged.  */
-
-bool
-Global::endGagging (unsigned oldGagged)
-{
-  bool anyErrs = (this->gaggedErrors != oldGagged);
-  this->gag--;
-
-  /* Restore the original state of gagged errors; set total errors
-     to be original errors + new ungagged errors.  */
-  this->errors -= (this->gaggedErrors - oldGagged);
-  this->gaggedErrors = oldGagged;
-
-  return anyErrs;
-}
-
-/* Increment the error count to record that an error has occured in the
-   current context.  An error message may or may not have been printed.  */
-
-void
-Global::increaseErrorCount (void)
-{
-  if (gag)
-    this->gaggedErrors++;
-
-  this->errors++;
-}
-
-
-/* Implements the Loc interface defined by the frontend.
-   Used for keeping track of current file/line position in code.  */
-
-Loc::Loc (const char *filename, unsigned linnum, unsigned charnum)
-{
-  this->linnum = linnum;
-  this->charnum = charnum;
-  this->filename = filename;
-}
-
-const char *
-Loc::toChars (void) const
-{
-  OutBuffer buf;
-
-  if (this->filename)
-    buf.printf ("%s", this->filename);
-
-  if (this->linnum)
-    {
-      buf.printf (":%u", this->linnum);
-      if (this->charnum)
-	buf.printf (":%u", this->charnum);
-    }
-
-  return buf.extractChars ();
-}
-
-bool
-Loc::equals (const Loc &loc)
-{
-  if (this->linnum != loc.linnum || this->charnum != loc.charnum)
-    return false;
-
-  if (!FileName::equals (this->filename, loc.filename))
-    return false;
-
-  return true;
-}
-
-
 /* Implements back-end specific interfaces used by the frontend.  */
 
 /* Determine if function FD is a builtin one that we can evaluate in CTFE.  */
@@ -144,7 +39,7 @@  Loc::equals (const Loc &loc)
 BUILTIN
 isBuiltin (FuncDeclaration *fd)
 {
-  if (fd->builtin != BUILTINunknown)
+  if (fd->builtin != BUILTIN::unknown)
     return fd->builtin;
 
   maybe_set_intrinsic (fd);
@@ -158,7 +53,7 @@  isBuiltin (FuncDeclaration *fd)
 Expression *
 eval_builtin (Loc loc, FuncDeclaration *fd, Expressions *arguments)
 {
-  if (fd->builtin == BUILTINunimp)
+  if (fd->builtin == BUILTIN::unimp)
     return NULL;
 
   tree decl = get_symbol_decl (fd);
@@ -185,16 +80,8 @@  eval_builtin (Loc loc, FuncDeclaration *fd, Expressions *arguments)
 Type *
 getTypeInfoType (Loc loc, Type *type, Scope *sc)
 {
-  gcc_assert (type->ty != Terror);
+  gcc_assert (type->ty != TY::Terror);
   check_typeinfo_type (loc, sc);
   create_typeinfo (type, sc ? sc->_module->importedFrom : NULL);
   return type->vtinfo->type;
 }
-
-/* Return an inlined copy of a default argument for a function parameter.  */
-
-Expression *
-inlineCopy (Expression *e, Scope *)
-{
-  return e->copy ();
-}
diff --git a/gcc/d/d-frontend.h b/gcc/d/d-frontend.h
new file mode 100644
index 00000000000..3edf812212a
--- /dev/null
+++ b/gcc/d/d-frontend.h
@@ -0,0 +1,37 @@ 
+/* d-frontend.h -- D frontend interface to the gcc back-end.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_D_FRONTEND_H
+#define GCC_D_FRONTEND_H
+
+/* These functions are defined in D runtime.  */
+extern "C" int rt_init (void);
+extern "C" int rt_term (void);
+//extern "C" void gc_disable (void);
+extern "C" void *gc_malloc (size_t sz, unsigned ba = 0, const void *ti = NULL);
+extern "C" void gc_free (void *);
+extern "C" void gc_collect (void);
+
+template<typename T>
+inline T *
+d_gc_malloc (void)
+{
+  void *ptr = gc_malloc (sizeof (T));
+  return new(ptr) T ();
+}
+
+#endif
diff --git a/gcc/d/d-incpath.cc b/gcc/d/d-incpath.cc
index d86392903e3..9a65622229b 100644
--- a/gcc/d/d-incpath.cc
+++ b/gcc/d/d-incpath.cc
@@ -20,6 +20,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 
 #include "dmd/globals.h"
+#include "d-frontend.h"
 
 #include "cppdefault.h"
 
@@ -71,7 +72,7 @@  add_globalpaths (Strings *paths)
   if (paths)
     {
       if (!global.path)
-	global.path = new Strings ();
+	global.path = d_gc_malloc<Strings> ();
 
       for (size_t i = 0; i < paths->length; i++)
 	{
@@ -98,7 +99,7 @@  add_filepaths (Strings *paths)
   if (paths)
     {
       if (!global.filePath)
-	global.filePath = new Strings ();
+	global.filePath = d_gc_malloc<Strings> ();
 
       for (size_t i = 0; i < paths->length; i++)
 	{
diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc
index be6330fbdfb..d20370e5d8a 100644
--- a/gcc/d/d-lang.cc
+++ b/gcc/d/d-lang.cc
@@ -26,12 +26,13 @@  along with GCC; see the file COPYING3.  If not see
 #include "dmd/errors.h"
 #include "dmd/expression.h"
 #include "dmd/hdrgen.h"
+#include "dmd/id.h"
 #include "dmd/identifier.h"
 #include "dmd/json.h"
 #include "dmd/mangle.h"
-#include "dmd/mars.h"
 #include "dmd/module.h"
 #include "dmd/mtype.h"
+#include "dmd/root/file.h"
 #include "dmd/target.h"
 
 #include "opts.h"
@@ -53,7 +54,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "input.h"
 
 #include "d-tree.h"
-#include "id.h"
+#include "d-frontend.h"
 
 
 /* Array of D frontend type/decl nodes.  */
@@ -83,10 +84,6 @@  d_option;
 /* List of modules being compiled.  */
 static Modules builtin_modules;
 
-/* Module where `C main' is defined, compiled in if needed.  */
-static Module *entrypoint_module = NULL;
-static Module *entrypoint_root_module = NULL;
-
 /* The current and global binding level in effect.  */
 struct binding_level *current_binding_level;
 struct binding_level *global_binding_level;
@@ -202,7 +199,7 @@  deps_write (Module *module, obstack *buffer)
 	deps_write_string (d_option.deps_target[i], buffer, column);
     }
   else
-    deps_write_string (module->objfile->name->str, buffer, column);
+    deps_write_string (module->objfile.toChars (), buffer, column);
 
   obstack_1grow (buffer, ':');
   column++;
@@ -212,7 +209,7 @@  deps_write (Module *module, obstack *buffer)
     {
       Module *depmod = modlist.pop ();
 
-      const char *modstr = depmod->srcfile->name->str;
+      const char *modstr = depmod->srcfile.toChars ();
 
       /* Skip modules that have already been looked at.  */
       if (seen_modules.add (modstr))
@@ -238,9 +235,7 @@  deps_write (Module *module, obstack *buffer)
 	  Module *m = depmod->aimports[i];
 
 	  /* Ignore compiler-generated modules.  */
-	  if ((m->ident == Identifier::idPool ("__entrypoint")
-	       || m->ident == Identifier::idPool ("__main"))
-	      && m->parent == NULL)
+	  if (m->ident == Identifier::idPool ("__main") && m->parent == NULL)
 	    continue;
 
 	  /* Don't search system installed modules, this includes
@@ -251,9 +246,9 @@  deps_write (Module *module, obstack *buffer)
 		  && m->parent == NULL)
 		continue;
 
-	      if (m->md && m->md->packages)
+	      if (m->md && m->md->packages.length)
 		{
-		  Identifier *package = (*m->md->packages)[0];
+		  Identifier *package = m->md->packages.ptr[0];
 
 		  if (package == Identifier::idPool ("core")
 		      || package == Identifier::idPool ("std")
@@ -291,27 +286,15 @@  deps_write (Module *module, obstack *buffer)
 static void
 d_init_options (unsigned int, cl_decoded_option *decoded_options)
 {
+  /* Initialize the D runtime.  */
+  rt_init ();
+//  gc_disable ();
+
   /* Set default values.  */
   global._init ();
 
   global.vendor = lang_hooks.name;
   global.params.argv0 = xstrdup (decoded_options[0].arg);
-  global.params.link = true;
-  global.params.useAssert = CHECKENABLEdefault;
-  global.params.useInvariants = CHECKENABLEdefault;
-  global.params.useIn = CHECKENABLEdefault;
-  global.params.useOut = CHECKENABLEdefault;
-  global.params.useArrayBounds = CHECKENABLEdefault;
-  global.params.useSwitchError = CHECKENABLEdefault;
-  global.params.checkAction = CHECKACTION_D;
-  global.params.useModuleInfo = true;
-  global.params.useTypeInfo = true;
-  global.params.useExceptions = true;
-  global.params.useInline = false;
-  global.params.obj = true;
-  global.params.hdrStripPlainFunctions = true;
-  global.params.betterC = false;
-  global.params.allInst = false;
   global.params.errorLimit = flag_max_errors;
 
   /* Default extern(C++) mangling to C++14.  */
@@ -320,9 +303,10 @@  d_init_options (unsigned int, cl_decoded_option *decoded_options)
   /* Warnings and deprecations are disabled by default.  */
   global.params.useDeprecated = DIAGNOSTICinform;
   global.params.warnings = DIAGNOSTICoff;
+  global.params.messageStyle = MESSAGESTYLEgnu;
 
-  global.params.imppath = new Strings ();
-  global.params.fileImppath = new Strings ();
+  global.params.imppath = d_gc_malloc<Strings> ();
+  global.params.fileImppath = d_gc_malloc<Strings> ();
 
   /* Extra GDC-specific options.  */
   d_option.fonly = NULL;
@@ -462,6 +446,11 @@  d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
 	: (value == 1) ? CHECKENABLEsafeonly : CHECKENABLEoff;
       break;
 
+    case OPT_fcheckaction_:
+      global.params.checkAction = (value == 0) ? CHECKACTION_D
+	: (value == 1) ? CHECKACTION_halt : CHECKACTION_context;
+      break;
+
     case OPT_fdebug:
       global.params.debuglevel = value ? 1 : 0;
       break;
@@ -480,7 +469,7 @@  d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
       if (Identifier::isValidIdentifier (CONST_CAST (char *, arg)))
 	{
 	  if (!global.params.debugids)
-	    global.params.debugids = new Strings ();
+	    global.params.debugids = d_gc_malloc<Strings> ();
 	  global.params.debugids->push (arg);
 	  break;
 	}
@@ -510,6 +499,16 @@  d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
       global.params.betterC = !value;
       break;
 
+    case OPT_fdump_c___spec_:
+      if (global.params.doCxxHdrGeneration == CxxHeaderMode::none)
+	global.params.doCxxHdrGeneration = CxxHeaderMode::silent;
+      global.params.cxxhdrname = arg;
+      break;
+
+    case OPT_fdump_c___spec_verbose:
+      global.params.doCxxHdrGeneration = CxxHeaderMode::verbose;
+      break;
+
     case OPT_fdump_d_original:
       global.params.vcg_ast = value;
       break;
@@ -518,6 +517,22 @@  d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
       global.params.useExceptions = value;
       break;
 
+    case OPT_fextern_std_:
+      switch (value)
+	{
+	case CppStdRevisionCpp98:
+	case CppStdRevisionCpp11:
+	case CppStdRevisionCpp14:
+	case CppStdRevisionCpp17:
+	case CppStdRevisionCpp20:
+	  global.params.cplusplus = (CppStdRevision) value;
+	  break;
+
+	default:
+	  error ("bad argument for %<-fextern-std%>: %qs", arg);
+	}
+      break;
+
     case OPT_fignore_unknown_pragmas:
       global.params.ignoreUnsupportedPragmas = value;
       break;
@@ -552,35 +567,115 @@  d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
       global.params.useIn = value ? CHECKENABLEon : CHECKENABLEoff;
       break;
 
+    case OPT_fpreview_all:
+      global.params.ehnogc = value;
+      global.params.useDIP25 = FeatureState::enabled;
+      global.params.useDIP1000 = FeatureState::enabled;
+      global.params.useDIP1021 = value;
+      global.params.dtorFields = FeatureState::enabled;
+      global.params.fieldwise = value;
+      global.params.fixAliasThis = value;
+      global.params.previewIn = value;
+      global.params.fix16997 = value;
+      global.params.markdown = value;
+      global.params.noSharedAccess = value;
+      global.params.rvalueRefParam = value;
+      global.params.inclusiveInContracts = value;
+      global.params.shortenedMethods = value;
+      break;
+
+    case OPT_fpreview_dip1000:
+      global.params.useDIP1000 = FeatureState::enabled;
+      break;
+
+    case OPT_fpreview_dip1008:
+      global.params.ehnogc = value;
+      break;
+
+    case OPT_fpreview_dip1021:
+      global.params.useDIP1021 = value;
+      break;
+
+    case OPT_fpreview_dip25:
+      global.params.useDIP25 = FeatureState::enabled;
+      break;
+
+    case OPT_fpreview_dtorfields:
+      global.params.dtorFields = FeatureState::enabled;
+      break;
+
+    case OPT_fpreview_fieldwise:
+      global.params.fieldwise = value;
+      break;
+
+    case OPT_fpreview_fixaliasthis:
+      global.params.fixAliasThis = value;
+      break;
+
+    case OPT_fpreview_in:
+      global.params.previewIn = value;
+      break;
+
+    case OPT_fpreview_inclusiveincontracts:
+      global.params.inclusiveInContracts = value;
+      break;
+
+    case OPT_fpreview_intpromote:
+      global.params.fix16997 = value;
+      break;
+
+    case OPT_fpreview_nosharedaccess:
+      global.params.noSharedAccess = value;
+      break;
+
+    case OPT_fpreview_rvaluerefparam:
+      global.params.rvalueRefParam = value;
+      break;
+
+    case OPT_fpreview_shortenedmethods:
+      global.params.shortenedMethods = value;
+      break;
+
     case OPT_frelease:
       global.params.release = value;
       break;
 
-    case OPT_frtti:
-      global.params.useTypeInfo = value;
+    case OPT_frevert_all:
+      global.params.useDIP25 = FeatureState::disabled;
+      global.params.markdown = !value;
+      global.params.dtorFields = FeatureState::disabled;
       break;
 
-    case OPT_fswitch_errors:
-      global.params.useSwitchError = value ? CHECKENABLEon : CHECKENABLEoff;
+    case OPT_frevert_dip25:
+      global.params.useDIP25 = FeatureState::disabled;
       break;
 
-    case OPT_ftransition_all:
-      global.params.vtls = value;
-      global.params.vfield = value;
-      global.params.vcomplex = value;
+    case OPT_frevert_dtorfields:
+      global.params.dtorFields = FeatureState::disabled;
+      break;
+
+    case OPT_frevert_markdown:
+      global.params.markdown = !value;
       break;
 
-    case OPT_ftransition_complex:
-      global.params.vcomplex = value;
+    case OPT_frtti:
+      global.params.useTypeInfo = value;
       break;
 
-    case OPT_ftransition_dip1000:
-      global.params.vsafe = value;
-      global.params.useDIP25 = value;
+    case OPT_fsave_mixins_:
+      global.params.mixinFile = arg;
+      global.params.mixinOut = d_gc_malloc<OutBuffer> ();
       break;
 
-    case OPT_ftransition_dip25:
-      global.params.useDIP25 = value;
+    case OPT_fswitch_errors:
+      global.params.useSwitchError = value ? CHECKENABLEon : CHECKENABLEoff;
+      break;
+
+    case OPT_ftransition_all:
+      global.params.vfield = value;
+      global.params.vgc = value;
+      global.params.vmarkdown= value;
+      global.params.vtls = value;
       break;
 
     case OPT_ftransition_field:
@@ -591,6 +686,14 @@  d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
       global.params.vgc = value;
       break;
 
+    case OPT_ftransition_vmarkdown:
+      global.params.vmarkdown = value;
+      break;
+
+    case OPT_ftransition_templates:
+      global.params.vtemplates = value;
+      break;
+
     case OPT_ftransition_tls:
       global.params.vtls = value;
       break;
@@ -613,7 +716,7 @@  d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
       if (Identifier::isValidIdentifier (CONST_CAST (char *, arg)))
 	{
 	  if (!global.params.versionids)
-	    global.params.versionids = new Strings ();
+	    global.params.versionids = d_gc_malloc<Strings> ();
 	  global.params.versionids->push (arg);
 	  break;
 	}
@@ -804,6 +907,14 @@  d_post_options (const char ** fn)
       global.params.checkAction = CHECKACTION_C;
     }
 
+  /* Enabling DIP1021 implies DIP1000.  */
+  if (global.params.useDIP1021)
+    global.params.useDIP1000 = FeatureState::enabled;
+
+  /* Enabling DIP1000 implies DIP25.  */
+  if (global.params.useDIP1000 == FeatureState::enabled)
+    global.params.useDIP25 = FeatureState::enabled;
+
   /* Keep in sync with existing -fbounds-check flag.  */
   flag_bounds_check = (global.params.useArrayBounds == CHECKENABLEon);
 
@@ -828,6 +939,7 @@  d_post_options (const char ** fn)
   global.params.symdebug = write_symbols != NO_DEBUG;
   global.params.useInline = flag_inline_functions;
   global.params.showColumns = flag_show_column;
+  global.params.printErrorContext = flag_diagnostics_show_caret;
 
   if (global.params.useInline)
     global.params.hdrStripPlainFunctions = false;
@@ -872,17 +984,6 @@  d_add_builtin_module (Module *m)
   builtin_modules.push (m);
 }
 
-/* Record the entrypoint module ENTRY which will be compiled in the current
-   compilation.  ROOT is the module scope where this was requested from.  */
-
-void
-d_add_entrypoint_module (Module *entry, Module *root)
-{
-  /* We are emitting this straight to object file.  */
-  entrypoint_module = entry;
-  entrypoint_root_module = root;
-}
-
 /* Implements the lang_hooks.parse_file routine for language D.  */
 
 static void
@@ -891,7 +992,7 @@  d_parse_file (void)
   if (global.params.verbose)
     {
       message ("binary    %s", global.params.argv0.ptr);
-      message ("version   %s", global.version.ptr);
+      message ("version   %s", global.versionChars ());
 
       if (global.versionids)
 	{
@@ -955,16 +1056,16 @@  d_parse_file (void)
 
 	  /* Handling stdin, generate a unique name for the module.  */
 	  Module *m = Module::create (in_fnames[i],
-				      Identifier::generateId ("__stdin"),
+				      Identifier::idPool ("__stdin"),
 				      global.params.doDocComments,
 				      global.params.doHdrGeneration);
 	  modules.push (m);
 
 	  /* Overwrite the source file for the module, the one created by
 	     Module::create would have a forced a `.d' suffix.  */
-	  m->srcfile = File::create ("<stdin>");
-	  m->srcfile->len = len;
-	  m->srcfile->buffer = buffer;
+	  m->srcBuffer = FileBuffer::create ();
+	  m->srcBuffer->data.length = len;
+	  m->srcBuffer->data.ptr = buffer;
 	}
       else
 	{
@@ -1011,15 +1112,16 @@  d_parse_file (void)
     }
 
   /* Load the module containing D main.  */
+  Module *main_module = NULL;
   if (global.params.addMain)
     {
       unsigned errors = global.startGagging ();
-      Module *m = Module::load (Loc (), NULL, Identifier::idPool ("__main"));
+      main_module = Module::load (Loc (), NULL, Identifier::idPool ("__main"));
 
       if (!global.endGagging (errors))
 	{
-	  m->importedFrom = m;
-	  modules.push (m);
+	  main_module->importedFrom = main_module;
+	  modules.push (main_module);
 	}
     }
 
@@ -1038,7 +1140,7 @@  d_parse_file (void)
       for (size_t i = 0; i < modules.length; i++)
 	{
 	  Module *m = modules[i];
-	  if (d_option.fonly && m != Module::rootModule)
+	  if (m->isHdrFile || (d_option.fonly && m != Module::rootModule))
 	    continue;
 
 	  if (global.params.verbose)
@@ -1203,7 +1305,7 @@  d_parse_file (void)
       if (name && (name[0] != '-' || name[1] != '\0'))
 	{
 	  const char *nameext
-	    = FileName::defaultExt (name, global.json_ext.ptr);
+	    = FileName::defaultExt (name, json_ext.ptr);
 	  json_stream = fopen (nameext, "w");
 	  if (!json_stream)
 	    {
@@ -1245,22 +1347,25 @@  d_parse_file (void)
 	}
     }
 
+  /* Generate C++ header files.  */
+  if (global.params.doCxxHdrGeneration != CxxHeaderMode::none)
+    genCppHdrFiles (modules);
+
+  if (global.errors)
+    goto had_errors;
+
   for (size_t i = 0; i < modules.length; i++)
     {
       Module *m = modules[i];
-      if (d_option.fonly && m != Module::rootModule)
+      if ((m->isHdrFile && m != main_module)
+	  || (d_option.fonly && m != Module::rootModule))
 	continue;
 
       if (global.params.verbose)
 	message ("code      %s", m->toChars ());
 
       if (!flag_syntax_only)
-	{
-	  if ((entrypoint_module != NULL) && (m == entrypoint_root_module))
-	    build_decl_tree (entrypoint_module);
-
-	  build_decl_tree (m);
-	}
+	build_decl_tree (m);
     }
 
   /* And end the main input file, if the debug writer wants it.  */
@@ -1272,16 +1377,37 @@  d_parse_file (void)
      exit with an error status.  */
   errorcount += (global.errors + global.warnings);
 
+  /* We want to write the mixin expansion file also on error.  */
+  if (global.params.mixinOut)
+    {
+      FILE *mixin_stream = fopen (global.params.mixinFile, "w");
+
+      if (mixin_stream)
+	{
+	  OutBuffer *buf = global.params.mixinOut;
+	  fprintf (mixin_stream, "%s", buf->peekChars ());
+
+	  if (ferror (mixin_stream) || fclose (mixin_stream))
+	    fatal_error (input_location, "closing mixin file %s: %m",
+			 global.params.mixinFile);
+	}
+      else
+	{
+	  fatal_error (input_location, "opening mixin file %s: %m",
+		       global.params.mixinFile);
+	}
+    }
+
   /* Remove generated .di files on error.  */
   if (errorcount && dump_headers)
     {
       for (size_t i = 0; i < modules.length; i++)
 	{
 	  Module *m = modules[i];
-	  if (d_option.fonly && m != Module::rootModule)
+	  if (m->isHdrFile || (d_option.fonly && m != Module::rootModule))
 	    continue;
 
-	  remove (m->hdrfile->toChars ());
+	  remove (m->hdrfile.toChars ());
 	}
     }
 
@@ -1406,7 +1532,7 @@  d_type_promotes_to (tree type)
   /* Promotions are only applied on unnamed function arguments for declarations
      with `extern(C)' or `extern(C++)' linkage.  */
   if (cfun && DECL_LANG_FRONTEND (cfun->decl)
-      && DECL_LANG_FRONTEND (cfun->decl)->linkage != LINKd)
+      && DECL_LANG_FRONTEND (cfun->decl)->linkage != LINK::d)
     {
       /* In [type/integer-promotions], integer promotions are conversions of the
 	 following types:
@@ -1559,7 +1685,8 @@  d_types_compatible_p (tree x, tree y)
 	return true;
 
       /* Type system allows implicit conversion between.  */
-      if (tx->implicitConvTo (ty) || ty->implicitConvTo (tx))
+      if (tx->implicitConvTo (ty) != MATCH::nomatch
+	  || ty->implicitConvTo (tx) != MATCH::nomatch)
 	return true;
     }
 
diff --git a/gcc/d/d-longdouble.cc b/gcc/d/d-longdouble.cc
index 471544ef79a..27c8d17a065 100644
--- a/gcc/d/d-longdouble.cc
+++ b/gcc/d/d-longdouble.cc
@@ -30,12 +30,6 @@  along with GCC; see the file COPYING3.  If not see
 #include "longdouble.h"
 
 
-/* Constant real values 0, 1, -1 and 0.5.  */
-real_t CTFloat::zero;
-real_t CTFloat::one;
-real_t CTFloat::minusone;
-real_t CTFloat::half;
-
 /* Truncate longdouble to the highest precision supported by target.  */
 
 longdouble
diff --git a/gcc/d/d-system.h b/gcc/d/d-system.h
index a6a9fccc6b8..d7a0079ecf3 100644
--- a/gcc/d/d-system.h
+++ b/gcc/d/d-system.h
@@ -26,60 +26,8 @@ 
 #endif
 #include "system.h"
 
-/* Used by the dmd front-end to determine if we have POSIX-style IO.  */
-#define POSIX (__linux__ || __GLIBC__ || __gnu_hurd__ || __APPLE__ \
-	       || __FreeBSD__ || __NetBSD__ || __OpenBSD__ || __DragonFly__ \
-	       || __sun || __unix__)
-
 /* Forward assert invariants to gcc_assert.  */
 #undef assert
 #define assert(EXPR) gcc_assert(EXPR)
 
-/* Use libiberty's lrealpath to avoid portability problems.  */
-#undef realpath
-#define realpath(a, b) lrealpath((a))
-
-/* Forward ctype.h macros used by the dmd front-end to safe-ctype.h.  */
-#undef isalpha
-#define isalpha(c) ISALPHA(c)
-#undef isalnum
-#define isalnum(c) ISALNUM(c)
-#undef isdigit
-#define isdigit(c) ISDIGIT(c)
-#undef islower
-#define islower(c) ISLOWER(c)
-#undef isprint
-#define isprint(c) ISPRINT(c)
-#undef isspace
-#define isspace(c) ISSPACE(c)
-#undef isupper
-#define isupper(c) ISUPPER(c)
-#undef isxdigit
-#define isxdigit(c) ISXDIGIT(c)
-#undef tolower
-#define tolower(c) TOLOWER(c)
-
-/* Forward _mkdir on MinGW to mkdir in system.h.  */
-#ifdef _WIN32
-#undef _mkdir
-#define _mkdir(p) mkdir(p, 0)
-#endif
-
-/* Define any missing _MAX and _MIN macros.  */
-#ifndef INT32_MAX
-# define INT32_MAX INTTYPE_MAXIMUM (int32_t)
-#endif
-#ifndef INT32_MIN
-# define INT32_MIN INTTYPE_MINIMUM (int32_t)
-#endif
-#ifndef INT64_MIN
-# define INT64_MIN INTTYPE_MINIMUM (int64_t)
-#endif
-#ifndef UINT32_MAX
-# define UINT32_MAX INTTYPE_MAXIMUM (uint32_t)
-#endif
-#ifndef UINT64_MAX
-# define UINT64_MAX INTTYPE_MAXIMUM (uint64_t)
-#endif
-
 #endif  /* GCC_D_SYSTEM_H  */
diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc
index 1488bcebb2c..21417dddf78 100644
--- a/gcc/d/d-target.cc
+++ b/gcc/d/d-target.cc
@@ -35,6 +35,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "tm.h"
 #include "tm_p.h"
 #include "target.h"
+#include "calls.h"
 
 #include "d-tree.h"
 #include "d-target.h"
@@ -42,8 +43,6 @@  along with GCC; see the file COPYING3.  If not see
 /* Implements the Target interface defined by the front end.
    Used for retrieving target-specific information.  */
 
-Target target;
-
 /* Internal key handlers for `__traits(getTargetInfo)'.  */
 static tree d_handle_target_cpp_std (void);
 static tree d_handle_target_cpp_runtime_library (void);
@@ -89,9 +88,6 @@  define_float_constants (T &f, tree type)
   /* Floating-point NaN.  */
   real_nan (&f.nan.rv (), "", 1, mode);
 
-  /* Signalling floating-point NaN.  */
-  real_nan (&f.snan.rv (), "", 0, mode);
-
   /* Floating-point +Infinity if the target supports infinities.  */
   real_inf (&f.infinity.rv ());
 
@@ -142,19 +138,19 @@  Target::_init (const Param &)
   /* Define what type to use for size_t, ptrdiff_t.  */
   if (this->ptrsize == 8)
     {
-      global.params.isLP64 = true;
-      Type::tsize_t = Type::basic[Tuns64];
-      Type::tptrdiff_t = Type::basic[Tint64];
+      this->isLP64 = true;
+      Type::tsize_t = Type::basic[(int)TY::Tuns64];
+      Type::tptrdiff_t = Type::basic[(int)TY::Tint64];
     }
   else if (this->ptrsize == 4)
     {
-      Type::tsize_t = Type::basic[Tuns32];
-      Type::tptrdiff_t = Type::basic[Tint32];
+      Type::tsize_t = Type::basic[(int)TY::Tuns32];
+      Type::tptrdiff_t = Type::basic[(int)TY::Tint32];
     }
   else if (this->ptrsize == 2)
     {
-      Type::tsize_t = Type::basic[Tuns16];
-      Type::tptrdiff_t = Type::basic[Tint16];
+      Type::tsize_t = Type::basic[(int)TY::Tuns16];
+      Type::tptrdiff_t = Type::basic[(int)TY::Tint16];
     }
   else
     sorry ("D does not support pointers on this target.");
@@ -164,15 +160,7 @@  Target::_init (const Param &)
   /* Set-up target C ABI.  */
   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.");
+  this->c.wchar_tsize = (WCHAR_TYPE_SIZE / BITS_PER_UNIT);
 
   /* Set-up target C++ ABI.  */
   this->cpp.reverseOverloads = false;
@@ -182,6 +170,12 @@  Target::_init (const Param &)
   /* Set-up target Objective-C ABI.  */
   this->objc.supported = false;
 
+  /* Set-up environmental settings.  */
+  this->obj_ext = "o";
+  this->lib_ext = "a";
+  this->dll_ext = "so";
+  this->run_noext = true;
+
   /* Initialize all compile-time properties for floating-point types.
      Should ensure that our real_t type is able to represent real_value.  */
   gcc_assert (sizeof (real_t) >= sizeof (real_value));
@@ -273,7 +267,7 @@  Target::isVectorTypeSupported (int sz, Type *type)
     type = Type::tuns8;
 
   /* No support for non-trivial types, complex types, or booleans.  */
-  if (!type->isTypeBasic () || type->iscomplex () || type->ty == Tbool)
+  if (!type->isTypeBasic () || type->iscomplex () || type->ty == TY::Tbool)
     return 2;
 
   /* In [simd/vector extensions], which vector types are supported depends on
@@ -293,9 +287,9 @@  Target::isVectorTypeSupported (int sz, Type *type)
    Returns true if the operation is supported or type is not a vector.  */
 
 bool
-Target::isVectorOpSupported (Type *type, TOK op, Type *)
+Target::isVectorOpSupported (Type *type, unsigned op, Type *)
 {
-  if (type->ty != Tvector)
+  if (type->ty != TY::Tvector)
     return true;
 
   /* Don't support if type is non-scalar, such as __vector(void[]).  */
@@ -322,18 +316,10 @@  Target::isVectorOpSupported (Type *type, TOK op, Type *)
       /* Logical operators must have a result type of bool.  */
       return false;
 
-    case TOKue:
-    case TOKlg:
-    case TOKule:
-    case TOKul:
-    case TOKuge:
-    case TOKug:
     case TOKle:
     case TOKlt:
     case TOKge:
     case TOKgt:
-    case TOKleg:
-    case TOKunord:
     case TOKequal:
     case TOKnotequal:
     case TOKidentity:
@@ -379,7 +365,8 @@  TargetCPP::thunkMangle (FuncDeclaration *fd, int offset)
 const char *
 TargetCPP::typeMangle (Type *type)
 {
-  if (type->isTypeBasic () || type->ty == Tvector || type->ty == Tstruct)
+  if (type->isTypeBasic () || type->ty == TY::Tvector
+      || type->ty == TY::Tstruct)
     {
       tree ctype = build_ctype (type);
       return targetm.mangle_type (ctype);
@@ -400,14 +387,14 @@  TargetCPP::parameterType (Parameter *arg)
   else if (arg->storageClass & STClazy)
     {
       /* Mangle as delegate.  */
-      Type *td = TypeFunction::create (NULL, t, VARARGnone, LINKd);
-      td = TypeDelegate::create (td);
-      t = t->merge2 ();
+      TypeFunction *tf = TypeFunction::create (NULL, t, VARARGnone, LINK::d);
+      TypeDelegate *td = TypeDelegate::create (tf);
+      t = td->merge2 ();
     }
 
   /* Could be a va_list, which we mangle as a pointer.  */
   Type *tvalist = target.va_listType (Loc (), NULL);
-  if (t->ty == Tsarray && tvalist->ty == Tsarray)
+  if (t->ty == TY::Tsarray && tvalist->ty == TY::Tsarray)
     {
       Type *tb = t->toBasetype ()->mutableOf ();
       if (tb == tvalist)
@@ -450,10 +437,10 @@  Target::systemLinkage (void)
       /* In [attribute/linkage], `System' is the same as `Windows' on Windows
 	 platforms, and `C' on other platforms.  */
       if (link_system)
-	return LINKwindows;
+	return LINK::windows;
     }
 
-  return LINKc;
+  return LINK::c;
 }
 
 /* Generate a TypeTuple of the equivalent types used to determine if a
@@ -477,12 +464,12 @@  Target::isReturnOnStack (TypeFunction *tf, bool)
   /* Need the back-end type to determine this, but this is called from the
      frontend before semantic processing is finished.  An accurate value
      is not currently needed anyway.  */
-  if (tf->isref)
+  if (tf->isref ())
     return false;
 
   Type *tn = tf->next->toBasetype ();
 
-  return (tn->ty == Tstruct || tn->ty == Tsarray);
+  return (tn->ty == TY::Tstruct || tn->ty == TY::Tsarray);
 }
 
 /* Add all target info in HANDLERS to D_TARGET_INFO_TABLE for use by
@@ -575,12 +562,49 @@  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).  */
+/* Returns true if the callee invokes destructors for arguments.  */
+
+bool
+Target::isCalleeDestroyingArgs (TypeFunction *tf)
+{
+  return tf->linkage == LINK::d;
+}
+
+/* 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;
 }
+
+/* Decides whether an `in' parameter of the specified POD type PARAM_TYPE is to
+   be passed by reference or by valie.  This is used only when compiling with
+   `-fpreview=in' enabled.  */
+
+bool
+Target::preferPassByRef (Type *param_type)
+{
+  if (param_type->size () == SIZE_INVALID)
+    return false;
+
+  tree type = build_ctype (param_type);
+
+  /* Prefer a `ref' if the type is an aggregate, and its size is greater than
+     its alignment.  */
+  if (AGGREGATE_TYPE_P (type)
+      && (!valid_constant_size_p (TYPE_SIZE_UNIT (type))
+	  || compare_tree_int (TYPE_SIZE_UNIT (type), TYPE_ALIGN (type)) > 0))
+    return true;
+
+  /* If the back-end is always going to pass this by invisible reference.  */
+  if (pass_by_reference (NULL, function_arg_info (type, true)))
+    return true;
+
+  /* If returning the parameter means the caller will do RVO.  */
+  if (targetm.calls.return_in_memory (type, NULL_TREE))
+    return true;
+
+  return false;
+}
diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h
index 9b90ca530e6..328b6b861d2 100644
--- a/gcc/d/d-tree.h
+++ b/gcc/d/d-tree.h
@@ -617,7 +617,6 @@  extern void add_import_paths (const char *, const char *, bool);
 
 /* In d-lang.cc.  */
 extern void d_add_builtin_module (Module *);
-extern void d_add_entrypoint_module (Module *, Module *);
 extern d_tree_node_structure_enum d_tree_node_structure (lang_tree_node *);
 extern struct lang_type *build_lang_type (Type *);
 extern struct lang_decl *build_lang_decl (Declaration *);
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index 9c9205fa349..e28a581a7ec 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -106,9 +106,9 @@  gcc_attribute_p (Dsymbol *decl)
 {
   ModuleDeclaration *md = decl->getModule ()->md;
 
-  if (md && md->packages && md->packages->length == 1)
+  if (md && md->packages.length == 1)
     {
-      if (!strcmp ((*md->packages)[0]->toChars (), "gcc")
+      if (!strcmp (md->packages.ptr[0]->toChars (), "gcc")
 	  && !strcmp (md->id->toChars (), "attributes"))
 	return true;
     }
@@ -116,6 +116,59 @@  gcc_attribute_p (Dsymbol *decl)
   return false;
 }
 
+/* Subroutine of pragma declaration visitor for marking the function in the
+   defined in SYM as a global constructor or destructor.  If ISCTOR is true,
+   then we're applying pragma(crt_constructor).  */
+
+static int
+apply_pragma_crt (Dsymbol *sym, bool isctor)
+{
+  AttribDeclaration *ad = sym->isAttribDeclaration ();
+  if (ad != NULL)
+    {
+      int nested = 0;
+
+      /* Walk all declarations of the attribute scope.  */
+      Dsymbols *ds = ad->include (NULL);
+      if (ds)
+	{
+	  for (size_t i = 0; i < ds->length; i++)
+	    nested += apply_pragma_crt ((*ds)[i], isctor);
+	}
+
+      return nested;
+    }
+
+  FuncDeclaration *fd = sym->isFuncDeclaration ();
+  if (fd != NULL)
+    {
+      tree decl = get_decl_tree (fd);
+
+      /* Apply flags to the function.  */
+      if (isctor)
+	{
+	  DECL_STATIC_CONSTRUCTOR (decl) = 1;
+	  decl_init_priority_insert (decl, DEFAULT_INIT_PRIORITY);
+	}
+      else
+	{
+	  DECL_STATIC_DESTRUCTOR (decl) = 1;
+	  decl_fini_priority_insert (decl, DEFAULT_INIT_PRIORITY);
+	}
+
+      if (fd->linkage != LINK::c)
+	{
+	  error_at (make_location_t (fd->loc),
+		    "must be %<extern(C)%> for %<pragma(%s)%>",
+		    isctor ? "crt_constructor" : "crt_destructor");
+	}
+
+      return 1;
+    }
+
+  return 0;
+}
+
 /* Implements the visitor interface to lower all Declaration AST classes
    emitted from the D Front-end to GCC trees.
    All visit methods accept one parameter D, which holds the frontend AST
@@ -246,19 +299,31 @@  public:
   }
 
   /* Pragmas are a way to pass special information to the compiler and to add
-     vendor specific extensions to D.  We don't do anything here, yet.  */
+     vendor specific extensions to D.  */
 
   void visit (PragmaDeclaration *d)
   {
-    if (!global.params.ignoreUnsupportedPragmas)
+    if (d->ident == Identifier::idPool ("lib")
+	|| d->ident == Identifier::idPool ("startaddress"))
       {
-	if (d->ident == Identifier::idPool ("lib")
-	    || d->ident == Identifier::idPool ("startaddress"))
+	if (!global.params.ignoreUnsupportedPragmas)
 	  {
 	    warning_at (make_location_t (d->loc), OPT_Wunknown_pragmas,
 			"pragma(%s) not implemented", d->ident->toChars ());
 	  }
       }
+    else if (d->ident == Identifier::idPool ("crt_constructor")
+	     || d->ident == Identifier::idPool ("crt_destructor"))
+      {
+	/* Handle pragma(crt_constructor) and pragma(crt_destructor).  Apply
+	   flag to indicate that the functions enclosed should run automatically
+	   at the beginning or end of execution.  */
+	bool isctor = (d->ident == Identifier::idPool ("crt_constructor"));
+
+	if (apply_pragma_crt (d, isctor) > 1)
+	  error_at (make_location_t (d->loc),
+		    "can only apply to a single declaration");
+      }
 
     visit ((AttribDeclaration *) d);
   }
@@ -311,14 +376,14 @@  public:
        nested members.  Only applies to classes or structs.  */
     Type *tb = fd->type->nextOf ()->baseElemOf ();
 
-    while (tb->ty == Tarray || tb->ty == Tpointer)
+    while (tb->ty == TY::Tarray || tb->ty == TY::Tpointer)
       tb = tb->nextOf ()->baseElemOf ();
 
     TemplateInstance *ti = NULL;
 
-    if (tb->ty == Tstruct)
+    if (tb->ty == TY::Tstruct)
       ti = tb->isTypeStruct ()->sym->isInstantiated ();
-    else if (tb->ty == Tclass)
+    else if (tb->ty == TY::Tclass)
       ti = tb->isTypeClass ()->sym->isInstantiated ();
 
     /* Return type is instantiated from this template declaration, walk over
@@ -360,7 +425,7 @@  public:
     if (d->semanticRun >= PASSobj)
       return;
 
-    if (d->type->ty == Terror)
+    if (d->type->ty == TY::Terror)
       {
 	error_at (make_location_t (d->loc),
 		  "had semantic errors when compiling");
@@ -447,7 +512,8 @@  public:
 	    if (fd2->isFuture ())
 	      continue;
 
-	    if (fd->leastAsSpecialized (fd2) || fd2->leastAsSpecialized (fd))
+	    if (fd->leastAsSpecialized (fd2) != MATCH::nomatch
+		|| fd2->leastAsSpecialized (fd) != MATCH::nomatch)
 	      {
 		error_at (make_location_t (fd->loc), "use of %qs",
 			  fd->toPrettyChars ());
@@ -474,7 +540,7 @@  public:
     if (d->semanticRun >= PASSobj)
       return;
 
-    if (d->type->ty == Terror)
+    if (d->type->ty == TY::Terror)
       {
 	error_at (make_location_t (d->loc),
 		  "had semantic errors when compiling");
@@ -495,7 +561,8 @@  public:
 
     /* Generate C symbols.  */
     d->csym = get_classinfo_decl (d);
-    d->vtblsym = get_vtable_decl (d);
+    Dsymbol *vtblsym = d->vtblSymbol ();
+    vtblsym->csym = get_vtable_decl (d);
     tree sinit = aggregate_initializer_decl (d);
 
     /* Generate static initializer.  */
@@ -527,9 +594,9 @@  public:
 	  }
       }
 
-    DECL_INITIAL (d->vtblsym)
-      = build_constructor (TREE_TYPE (d->vtblsym), elms);
-    d_finish_decl (d->vtblsym);
+    DECL_INITIAL (vtblsym->csym)
+      = build_constructor (TREE_TYPE (vtblsym->csym), elms);
+    d_finish_decl (vtblsym->csym);
 
     /* Add this decl to the current binding level.  */
     tree ctype = TREE_TYPE (build_ctype (d->type));
@@ -547,7 +614,7 @@  public:
     if (d->semanticRun >= PASSobj)
       return;
 
-    if (d->type->ty == Terror)
+    if (d->type->ty == TY::Terror)
       {
 	error_at (make_location_t (d->loc),
 		  "had semantic errors when compiling");
@@ -590,7 +657,7 @@  public:
     if (d->semanticRun >= PASSobj)
       return;
 
-    if (d->errors || d->type->ty == Terror)
+    if (d->errors || d->type->ty == TY::Terror)
       {
 	error_at (make_location_t (d->loc),
 		  "had semantic errors when compiling");
@@ -629,7 +696,7 @@  public:
     if (d->semanticRun >= PASSobj)
       return;
 
-    if (d->type->ty == Terror)
+    if (d->type->ty == TY::Terror)
       {
 	error_at (make_location_t (d->loc),
 		  "had semantic errors when compiling");
@@ -695,7 +762,7 @@  public:
 
 	/* Frontend should have already caught this.  */
 	gcc_assert (!integer_zerop (size)
-		    || d->type->toBasetype ()->ty == Tsarray);
+		    || d->type->toBasetype ()->ty == TY::Tsarray);
 
 	d_finish_decl (decl);
 
@@ -770,7 +837,7 @@  public:
     /* Check if any errors occurred when running semantic.  */
     if (TypeFunction *tf = d->type->isTypeFunction ())
       {
-	if (tf->next == NULL || tf->next->ty == Terror)
+	if (tf->next == NULL || tf->next->ty == TY::Terror)
 	  return;
       }
 
@@ -1183,6 +1250,17 @@  get_symbol_decl (Declaration *decl)
     }
   else if (TREE_CODE (decl->csym) == FUNCTION_DECL)
     {
+      /* Dual-context functions require the code generation to build an array
+	 for the context pointer of the function, making the delicate task of
+	 tracking which context to follow when encountering a non-local symbol,
+	 and so are a not planned to be supported.  */
+      if (fd->needThis () && !fd->isMember2 ())
+	{
+	  fatal_error (make_location_t (fd->loc),
+		       "function requires a dual-context, which is not yet "
+		       "supported by GDC");
+	}
+
       /* The real function type may differ from its declaration.  */
       tree fntype = TREE_TYPE (decl->csym);
       tree newfntype = NULL_TREE;
@@ -1238,9 +1316,9 @@  get_symbol_decl (Declaration *decl)
 
       /* In [pragma/inline], functions decorated with `pragma(inline)' affects
 	 whether they are inlined or not.  */
-      if (fd->inlining == PINLINEalways)
+      if (fd->inlining == PINLINE::always)
 	DECL_DECLARED_INLINE_P (decl->csym) = 1;
-      else if (fd->inlining == PINLINEnever)
+      else if (fd->inlining == PINLINE::never)
 	DECL_UNINLINABLE (decl->csym) = 1;
 
       /* Function was declared `naked'.  */
@@ -1254,13 +1332,6 @@  get_symbol_decl (Declaration *decl)
       if (fd->generated)
 	DECL_ARTIFICIAL (decl->csym) = 1;
 
-      /* Vector array operations are always compiler generated.  */
-      if (fd->isArrayOp)
-	{
-	  DECL_ARTIFICIAL (decl->csym) = 1;
-	  DECL_DECLARED_INLINE_P (decl->csym) = 1;
-	}
-
       /* Ensure and require contracts are lexically nested in the function they
 	 part of, but are always publicly callable.  */
       if (fd->ident == Identifier::idPool ("ensure")
@@ -1271,7 +1342,7 @@  get_symbol_decl (Declaration *decl)
 	DECL_FINAL_P (decl->csym) = 1;
 
       /* Function is of type `noreturn' or `typeof(*null)'.  */
-      if (fd->type->nextOf ()->ty == Tnoreturn)
+      if (fd->type->nextOf ()->ty == TY::Tnoreturn)
 	TREE_THIS_VOLATILE (decl->csym) = 1;
 
       /* Check whether this function is expanded by the frontend.  */
@@ -1298,10 +1369,10 @@  get_symbol_decl (Declaration *decl)
   if (decl->storage_class & STCvolatile)
     TREE_THIS_VOLATILE (decl->csym) = 1;
 
-  /* Protection attributes are used by the debugger.  */
-  if (decl->protection.kind == Prot::private_)
+  /* Visibility attributes are used by the debugger.  */
+  if (decl->visibility.kind == Visibility::private_)
     TREE_PRIVATE (decl->csym) = 1;
-  else if (decl->protection.kind == Prot::protected_)
+  else if (decl->visibility.kind == Visibility::protected_)
     TREE_PROTECTED (decl->csym) = 1;
 
   /* Likewise, so could the deprecated attribute.  */
@@ -1794,7 +1865,7 @@  make_thunk (FuncDeclaration *decl, int offset)
      forcing a D local thunk to be emitted.  */
   const char *ident;
 
-  if (decl->linkage == LINKcpp)
+  if (decl->linkage == LINK::cpp)
     ident = target.cpp.thunkMangle (decl, offset);
   else
     {
@@ -1810,7 +1881,9 @@  make_thunk (FuncDeclaration *decl, int offset)
   SET_DECL_ASSEMBLER_NAME (thunk, DECL_NAME (thunk));
 
   d_keep (thunk);
-  free (CONST_CAST (char *, ident));
+
+  if (decl->linkage != LINK::cpp)
+    free (CONST_CAST (char *, ident));
 
   if (!DECL_EXTERNAL (function))
     finish_thunk (thunk, function);
@@ -1989,26 +2062,27 @@  d_mark_needed (tree decl)
 tree
 get_vtable_decl (ClassDeclaration *decl)
 {
-  if (decl->vtblsym)
-    return decl->vtblsym;
+  if (decl->vtblsym && decl->vtblsym->csym)
+    return decl->vtblsym->csym;
 
   tree ident = mangle_internal_decl (decl, "__vtbl", "Z");
   /* Note: Using a static array type for the VAR_DECL, the DECL_INITIAL value
      will have a different type.  However the back-end seems to accept this.  */
   tree type = build_ctype (Type::tvoidptr->sarrayOf (decl->vtbl.length));
 
-  decl->vtblsym = declare_extern_var (ident, type);
-  DECL_LANG_SPECIFIC (decl->vtblsym) = build_lang_decl (NULL);
+  Dsymbol *vtblsym = decl->vtblSymbol ();
+  vtblsym->csym = declare_extern_var (ident, type);
+  DECL_LANG_SPECIFIC (vtblsym->csym) = build_lang_decl (NULL);
 
   /* Class is a reference, want the record type.  */
-  DECL_CONTEXT (decl->vtblsym) = TREE_TYPE (build_ctype (decl->type));
-  TREE_READONLY (decl->vtblsym) = 1;
-  DECL_VIRTUAL_P (decl->vtblsym) = 1;
+  DECL_CONTEXT (vtblsym->csym) = TREE_TYPE (build_ctype (decl->type));
+  TREE_READONLY (vtblsym->csym) = 1;
+  DECL_VIRTUAL_P (vtblsym->csym) = 1;
 
-  SET_DECL_ALIGN (decl->vtblsym, TARGET_VTABLE_ENTRY_ALIGN);
-  DECL_USER_ALIGN (decl->vtblsym) = true;
+  SET_DECL_ALIGN (vtblsym->csym, TARGET_VTABLE_ENTRY_ALIGN);
+  DECL_USER_ALIGN (vtblsym->csym) = true;
 
-  return decl->vtblsym;
+  return vtblsym->csym;
 }
 
 /* Helper function of build_class_instance.  Find the field inside aggregate
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index ea21bd5a8a1..31680564bdd 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -249,7 +249,7 @@  public:
     tree t1 = build_expr (e->e1);
     tree t2 = build_expr (e->e2);
 
-    if (e->type->ty != Tvoid)
+    if (e->type->ty != TY::Tvoid)
       {
 	t1 = convert_expr (t1, e->e1->type, e->type);
 	t2 = convert_expr (t2, e->e2->type, e->type);
@@ -268,8 +268,8 @@  public:
     Type *tb1 = e->e1->type->toBasetype ();
     Type *tb2 = e->e2->type->toBasetype ();
 
-    if ((tb1->ty == Tsarray || tb1->ty == Tarray)
-	&& (tb2->ty == Tsarray || tb2->ty == Tarray))
+    if ((tb1->ty == TY::Tsarray || tb1->ty == TY::Tarray)
+	&& (tb2->ty == TY::Tsarray || tb2->ty == TY::Tarray))
       {
 	/* For static and dynamic arrays, identity is defined as referring to
 	   the same array elements and the same number of elements.  */
@@ -278,7 +278,7 @@  public:
 	this->result_ = d_convert (build_ctype (e->type),
 				   build_boolop (code, t1, t2));
       }
-    else if (tb1->isfloating () && tb1->ty != Tvector)
+    else if (tb1->isfloating () && tb1->ty != TY::Tvector)
       {
 	/* For floating-point values, identity is defined as the bits in the
 	   operands being identical.  */
@@ -333,8 +333,8 @@  public:
     Type *tb2 = e->e2->type->toBasetype ();
     tree_code code = (e->op == TOKequal) ? EQ_EXPR : NE_EXPR;
 
-    if ((tb1->ty == Tsarray || tb1->ty == Tarray)
-	&& (tb2->ty == Tsarray || tb2->ty == Tarray))
+    if ((tb1->ty == TY::Tsarray || tb1->ty == TY::Tarray)
+	&& (tb2->ty == TY::Tsarray || tb2->ty == TY::Tarray))
       {
 	/* For static and dynamic arrays, equality is defined as the lengths of
 	   the arrays matching, and all the elements are equal.  */
@@ -346,8 +346,9 @@  public:
 		e1.length == e2.length && memcmp(e1.ptr, e2.ptr, size) == 0;
 	    Or when generating a NE expression:
 		e1.length != e2.length || memcmp(e1.ptr, e2.ptr, size) != 0;  */
-	if ((t1elem->isintegral () || t1elem->ty == Tvoid
-	     || (t1elem->ty == Tstruct && !t1elem->isTypeStruct ()->sym->xeq))
+	if ((t1elem->isintegral () || t1elem->ty == TY::Tvoid
+	     || (t1elem->ty == TY::Tstruct
+		 && !t1elem->isTypeStruct ()->sym->xeq))
 	    && t1elem->ty == t2elem->ty)
 	  {
 	    tree t1 = d_array_convert (e->e1);
@@ -368,7 +369,7 @@  public:
 
 	    /* Compare arrays using memcmp if possible, otherwise for structs,
 	       each field is compared inline.  */
-	    if (t1elem->ty != Tstruct
+	    if (t1elem->ty != TY::Tstruct
 		|| identity_compare_p (t1elem->isTypeStruct ()->sym))
 	      {
 		tree size = size_mult_expr (t1len, size_int (t1elem->size ()));
@@ -398,7 +399,7 @@  public:
 	    /* Finally, check if lengths of both arrays match if dynamic.
 	       The frontend should have already guaranteed that static arrays
 	       have same size.  */
-	    if (tb1->ty == Tsarray && tb2->ty == Tsarray)
+	    if (tb1->ty == TY::Tsarray && tb2->ty == TY::Tsarray)
 	      gcc_assert (tb1->size () == tb2->size ());
 	    else
 	      {
@@ -444,7 +445,7 @@  public:
 
 	this->result_ = build_struct_comparison (code, ts->sym, t1, t2);
       }
-    else if (tb1->ty == Taarray && tb2->ty == Taarray)
+    else if (tb1->ty == TY::Taarray && tb2->ty == TY::Taarray)
       {
 	/* Use _aaEqual() for associative arrays.  */
 	tree result = build_libcall (LIBCALL_AAEQUAL, e->type, 3,
@@ -518,23 +519,14 @@  public:
 	gcc_unreachable ();
       }
 
-    if ((tb1->ty == Tsarray || tb1->ty == Tarray)
-	&& (tb2->ty == Tsarray || tb2->ty == Tarray))
+    /* For static and dynamic arrays, the relational op is turned into a
+       library call.  It is not lowered during codegen.  */
+    if ((tb1->ty == TY::Tsarray || tb1->ty == TY::Tarray)
+	&& (tb2->ty == TY::Tsarray || tb2->ty == TY::Tarray))
       {
-	/* For static and dynamic arrays, the result of the relational op is
-	   the result of the operator applied to the first non-equal element
-	   of the array.  If two arrays compare equal, but are of different
-	   lengths, the shorter array compares as less than the longer.  */
-	Type *telem = tb1->nextOf ()->toBasetype ();
-
-	tree call = build_libcall (LIBCALL_ADCMP2, Type::tint32, 3,
-				   d_array_convert (e->e1),
-				   d_array_convert (e->e2),
-				   build_typeinfo (e->loc, telem->arrayOf ()));
-	result = build_boolop (code, call, integer_zero_node);
-
-	this->result_ = d_convert (build_ctype (e->type), result);
-	return;
+	error ("cannot handle comparison of type %<%s == %s%>",
+	       tb1->toChars (), tb2->toChars ());
+	gcc_unreachable ();
       }
 
     /* Simple comparison.  */
@@ -550,7 +542,7 @@  public:
   {
     tree_code code = (e->op == TOKandand) ? TRUTH_ANDIF_EXPR : TRUTH_ORIF_EXPR;
 
-    if (e->e2->type->toBasetype ()->ty != Tvoid)
+    if (e->e2->type->toBasetype ()->ty != TY::Tvoid)
       {
 	tree t1 = build_expr (e->e1);
 	tree t2 = build_expr (e->e2);
@@ -618,7 +610,8 @@  public:
 	   The front-end rewrites `(p1 - p2)' into `(p1 - p2) / stride'.  */
 	if (MinExp *me = e->e1->isMinExp ())
 	  {
-	    if (me->e1->type->ty == Tpointer && me->e2->type->ty == Tpointer
+	    if (me->e1->type->ty == TY::Tpointer
+		&& me->e2->type->ty == TY::Tpointer
 		&& e->e2->op == TOKint64)
 	      {
 		code = EXACT_DIV_EXPR;
@@ -678,7 +671,7 @@  public:
     Type *tb2 = e->e2->type->toBasetype ();
     Type *etype;
 
-    if (tb1->ty == Tarray || tb1->ty == Tsarray)
+    if (tb1->ty == TY::Tarray || tb1->ty == TY::Tsarray)
       etype = tb1->nextOf ();
     else
       etype = tb2->nextOf ();
@@ -839,13 +832,13 @@  public:
     tree ptr = d_save_expr (build_address (lhs));
     tree result = NULL_TREE;
 
-    if (tb1->ty == Tarray && tb2->ty == Tdchar
-	&& (etype->ty == Tchar || etype->ty == Twchar))
+    if (tb1->ty == TY::Tarray && tb2->ty == TY::Tdchar
+	&& (etype->ty == TY::Tchar || etype->ty == TY::Twchar))
       {
 	/* Append a dchar to a char[] or wchar[]:
 	   The assignment is handled by the D run-time library, so only
 	   need to call `_d_arrayappend[cw]d(&e1, e2)'  */
-	libcall_fn libcall = (etype->ty == Tchar)
+	libcall_fn libcall = (etype->ty == TY::Tchar)
 	  ? LIBCALL_ARRAYAPPENDCD : LIBCALL_ARRAYAPPENDWD;
 
 	result = build_libcall (libcall, e->type, 2,
@@ -853,9 +846,9 @@  public:
       }
     else
       {
-	gcc_assert (tb1->ty == Tarray || tb2->ty == Tsarray);
+	gcc_assert (tb1->ty == TY::Tarray || tb2->ty == TY::Tsarray);
 
-	if ((tb2->ty == Tarray || tb2->ty == Tsarray)
+	if ((tb2->ty == TY::Tarray || tb2->ty == TY::Tsarray)
 	    && same_type_p (etype, tb2->nextOf ()->toBasetype ()))
 	  {
 	    /* Append an array to another array:
@@ -917,23 +910,9 @@  public:
     /* Look for array.length = n;  */
     if (e->e1->op == TOKarraylength)
       {
-	/* Assignment to an array's length property; resize the array.  */
-	ArrayLengthExp *ale = e->e1->isArrayLengthExp ();
-	tree newlength = convert_expr (build_expr (e->e2), e->e2->type,
-				       Type::tsize_t);
-	tree ptr = build_address (build_expr (ale->e1));
-
-	/* Don't want the basetype for the element type.  */
-	Type *etype = ale->e1->type->toBasetype ()->nextOf ();
-	libcall_fn libcall = etype->isZeroInit ()
-	  ? LIBCALL_ARRAYSETLENGTHT : LIBCALL_ARRAYSETLENGTHIT;
-
-	tree result = build_libcall (libcall, ale->e1->type, 3,
-				     build_typeinfo (ale->loc, ale->e1->type),
-				     newlength, ptr);
-
-	this->result_ = d_array_length (result);
-	return;
+	/* This case should have been rewritten to `_d_arraysetlengthT` in the
+	   semantic phase.  */
+	gcc_unreachable ();
       }
 
     /* Look for array[] = n;  */
@@ -947,13 +926,17 @@  public:
 	bool postblit = needs_postblit (etype) && lvalue_p (e->e2);
 	bool destructor = needs_dtor (etype);
 
-	if (e->memset & blockAssign)
+	if (e->memset == MemorySet::blockAssign)
 	  {
 	    /* Set a range of elements to one value.  */
-	    tree t1 = d_save_expr (build_expr (e->e1));
+	    tree t1 = build_expr (e->e1);
 	    tree t2 = build_expr (e->e2);
 	    tree result;
 
+	    /* Extract any array bounds checks from the slice expression.  */
+	    tree init = stabilize_expr (&t1);
+	    t1 = d_save_expr (t1);
+
 	    if ((postblit || destructor) && e->op != TOKblit)
 	      {
 		libcall_fn libcall = (e->op == TOKconstruct)
@@ -962,15 +945,12 @@  public:
 		Type *tm = etype->unSharedOf ()->mutableOf ();
 		tree ti = build_typeinfo (e->loc, tm);
 
-		tree result = build_libcall (libcall, Type::tvoid, 4,
-					     d_array_ptr (t1),
-					     build_address (t2),
-					     d_array_length (t1), ti);
-		this->result_ = compound_expr (result, t1);
-		return;
+		result = build_libcall (libcall, Type::tvoid, 4,
+					d_array_ptr (t1),
+					build_address (t2),
+					d_array_length (t1), ti);
 	      }
-
-	    if (integer_zerop (t2))
+	    else if (integer_zerop (t2))
 	      {
 		tree size = size_mult_expr (d_array_length (t1),
 					    size_int (etype->size ()));
@@ -980,12 +960,13 @@  public:
 	      result = build_array_set (d_array_ptr (t1),
 					d_array_length (t1), t2);
 
+	    result = compound_expr (init, result);
 	    this->result_ = compound_expr (result, t1);
 	  }
 	else
 	  {
 	    /* Perform a memcpy operation.  */
-	    gcc_assert (e->e2->type->ty != Tpointer);
+	    gcc_assert (e->e2->type->ty != TY::Tpointer);
 
 	    if (!postblit && !destructor)
 	      {
@@ -1056,7 +1037,7 @@  public:
       }
 
     /* Look for reference initializations.  */
-    if (e->memset & referenceInit)
+    if (e->memset == MemorySet::referenceInit)
       {
 	gcc_assert (e->op == TOKconstruct || e->op == TOKblit);
 	gcc_assert (e->e1->op == TOKvar);
@@ -1082,7 +1063,7 @@  public:
     tree_code modifycode = (e->op == TOKconstruct) ? INIT_EXPR : MODIFY_EXPR;
 
     /* Look for struct assignment.  */
-    if (tb1->ty == Tstruct)
+    if (tb1->ty == TY::Tstruct)
       {
 	tree t1 = build_expr (e->e1);
 	tree t2 = convert_for_assignment (build_expr (e->e2, false, true),
@@ -1136,7 +1117,7 @@  public:
       }
 
     /* Look for static array assignment.  */
-    if (tb1->ty == Tsarray)
+    if (tb1->ty == TY::Tsarray)
       {
 	/* Look for array = 0.  */
 	if (e->e2->op == TOKint64)
@@ -1148,7 +1129,7 @@  public:
 	  }
 
 	Type *etype = tb1->nextOf ();
-	gcc_assert (e->e2->type->toBasetype ()->ty == Tsarray);
+	gcc_assert (e->e2->type->toBasetype ()->ty == TY::Tsarray);
 
 	/* Determine if we need to run postblit.  */
 	bool postblit = needs_postblit (etype);
@@ -1171,7 +1152,8 @@  public:
 	    return;
 	  }
 
-	Type *arrtype = (e->type->ty == Tsarray) ? etype->arrayOf () : e->type;
+	Type *arrtype = (e->type->ty == TY::Tsarray)
+	  ? etype->arrayOf () : e->type;
 	tree result;
 
 	if (e->op == TOKconstruct)
@@ -1198,7 +1180,7 @@  public:
 	  }
 
 	/* Cast the libcall result back to a static array.  */
-	if (e->type->ty == Tsarray)
+	if (e->type->ty == TY::Tsarray)
 	  result = indirect_ref (build_ctype (e->type),
 				 d_array_ptr (result));
 
@@ -1243,7 +1225,7 @@  public:
   {
     Type *tb1 = e->e1->type->toBasetype ();
 
-    if (tb1->ty == Taarray)
+    if (tb1->ty == TY::Taarray)
       {
 	/* Get the key for the associative array.  */
 	Type *tkey = tb1->isTypeAArray ()->index->toBasetype ();
@@ -1289,7 +1271,7 @@  public:
 	tree ptr = convert_expr (array, tb1, tb1->nextOf ()->pointerTo ());
 
 	tree length = NULL_TREE;
-	if (tb1->ty != Tpointer)
+	if (tb1->ty != TY::Tpointer)
 	  length = get_array_length (array, tb1);
 	else
 	  gcc_assert (e->lengthVar == NULL);
@@ -1304,7 +1286,7 @@  public:
 
 	/* If it's a static array and the index is constant, the front end has
 	   already checked the bounds.  */
-	if (tb1->ty != Tpointer)
+	if (tb1->ty != TY::Tpointer)
 	  index = build_bounds_index_condition (e, index, length);
 
 	/* Index the .ptr.  */
@@ -1330,7 +1312,7 @@  public:
 
   void visit (ArrayLengthExp *e)
   {
-    if (e->e1->type->toBasetype ()->ty == Tarray)
+    if (e->e1->type->toBasetype ()->ty == TY::Tarray)
       this->result_ = d_array_length (build_expr (e->e1));
     else
       {
@@ -1364,13 +1346,13 @@  public:
   {
     Type *tb = e->type->toBasetype ();
     Type *tb1 = e->e1->type->toBasetype ();
-    gcc_assert (tb->ty == Tarray || tb->ty == Tsarray);
+    gcc_assert (tb->ty == TY::Tarray || tb->ty == TY::Tsarray);
 
     /* Use convert-to-dynamic-array code if possible.  */
     if (!e->lwr)
       {
 	tree result = build_expr (e->e1);
-	if (e->e1->type->toBasetype ()->ty == Tsarray)
+	if (e->e1->type->toBasetype ()->ty == TY::Tsarray)
 	  result = convert_expr (result, e->e1->type, e->type);
 
 	this->result_ = result;
@@ -1386,7 +1368,7 @@  public:
 
     /* Our array is already a SAVE_EXPR if necessary, so we don't make length
        a SAVE_EXPR which is, at most, a COMPONENT_REF on top of array.  */
-    if (tb1->ty != Tpointer)
+    if (tb1->ty != TY::Tpointer)
       length = get_array_length (array, tb1);
     else
       gcc_assert (e->lengthVar == NULL);
@@ -1415,13 +1397,13 @@  public:
 
     /* Nothing more to do for static arrays, their bounds checking has been
        done at compile-time.  */
-    if (tb->ty == Tsarray)
+    if (tb->ty == TY::Tsarray)
       {
 	this->result_ = indirect_ref (build_ctype (e->type), ptr);
 	return;
       }
     else
-      gcc_assert (tb->ty == Tarray);
+      gcc_assert (tb->ty == TY::Tarray);
 
     /* Generate bounds checking code.  */
     tree newlength = build_bounds_slice_condition (e, lwr_tree, upr_tree,
@@ -1440,7 +1422,7 @@  public:
     tree result = build_expr (e->e1, this->constp_, this->literalp_);
 
     /* Just evaluate e1 if it has any side effects.  */
-    if (tbtype->ty == Tvoid)
+    if (tbtype->ty == TY::Tvoid)
       this->result_ = build_nop (build_ctype (tbtype), result);
     else
       this->result_ = convert_for_rvalue (result, ebtype, tbtype);
@@ -1453,7 +1435,7 @@  public:
     tree t1 = build_expr (e->e1);
     Type *tb1 = e->e1->type->toBasetype ();
 
-    if (tb1->ty == Tclass)
+    if (tb1->ty == TY::Tclass)
       {
 	/* For class object references, if there is a destructor for that class,
 	   the destructor is called for the object instance.  */
@@ -1480,7 +1462,7 @@  public:
 	t1 = build_address (t1);
 	this->result_ = build_libcall (libcall, Type::tvoid, 1, t1);
       }
-    else if (tb1->ty == Tarray)
+    else if (tb1->ty == TY::Tarray)
       {
 	/* For dynamic arrays, the garbage collector is called to immediately
 	   release the memory.  */
@@ -1498,7 +1480,7 @@  public:
 	this->result_ = build_libcall (LIBCALL_DELARRAYT, Type::tvoid, 2,
 				       build_address (t1), ti);
       }
-    else if (tb1->ty == Tpointer)
+    else if (tb1->ty == TY::Tpointer)
       {
 	/* For pointers to a struct instance, if the struct has overloaded
 	   operator delete, then that operator is called.  */
@@ -1533,7 +1515,7 @@  public:
   void visit (RemoveExp *e)
   {
     /* Check that the array is actually an associative array.  */
-    if (e->e1->type->toBasetype ()->ty == Taarray)
+    if (e->e1->type->toBasetype ()->ty == TY::Taarray)
       {
 	Type *tb = e->e1->type->toBasetype ();
 	Type *tkey = tb->isTypeAArray ()->index->toBasetype ();
@@ -1569,7 +1551,7 @@  public:
   void visit (ComExp *e)
   {
     TY ty1 = e->e1->type->toBasetype ()->ty;
-    gcc_assert (ty1 != Tarray && ty1 != Tsarray);
+    gcc_assert (ty1 != TY::Tarray && ty1 != TY::Tsarray);
 
     this->result_ = fold_build1 (BIT_NOT_EXPR, build_ctype (e->type),
 				 build_expr (e->e1));
@@ -1580,7 +1562,7 @@  public:
   void visit (NegExp *e)
   {
     TY ty1 = e->e1->type->toBasetype ()->ty;
-    gcc_assert (ty1 != Tarray && ty1 != Tsarray);
+    gcc_assert (ty1 != TY::Tarray && ty1 != TY::Tsarray);
 
     tree type = build_ctype (e->type);
     tree expr = build_expr (e->e1);
@@ -1630,7 +1612,7 @@  public:
     /* Produce better code by converting *(#record + n) to
        COMPONENT_REFERENCE.  Otherwise, the variable will always be
        allocated in memory because its address is taken.  */
-    if (tnext && tnext->ty == Tstruct)
+    if (tnext && tnext->ty == TY::Tstruct)
       {
 	StructDeclaration *sd = tnext->isTypeStruct ()->sym;
 
@@ -1716,7 +1698,7 @@  public:
 	gcc_assert (var->isFuncDeclaration () && !var->needThis ());
       }
 
-    if (e1b->op == TOKdotvar && tb->ty != Tdelegate)
+    if (e1b->op == TOKdotvar && tb->ty != TY::Tdelegate)
       {
 	DotVarExp *dve = e1b->isDotVarExp ();
 
@@ -1775,7 +1757,7 @@  public:
 		/* C++ constructors return void, even though front-end semantic
 		   treats them as implicitly returning `this'.  Set returnvalue
 		   to override the result of this expression.  */
-		if (fd->isCtorDeclaration () && fd->linkage == LINKcpp)
+		if (fd->isCtorDeclaration () && fd->linkage == LINK::cpp)
 		  {
 		    thisexp = d_save_expr (thisexp);
 		    returnvalue = thisexp;
@@ -1805,7 +1787,7 @@  public:
 
 	extract_from_method_call (callee, callee, object);
       }
-    else if (tb->ty == Tdelegate)
+    else if (tb->ty == TY::Tdelegate)
       {
 	/* Delegate call, extract .object and .funcptr from var.  */
 	callee = d_save_expr (callee);
@@ -1850,7 +1832,7 @@  public:
     if (returnvalue != NULL_TREE)
       exp = compound_expr (exp, returnvalue);
 
-    if (tf->isref)
+    if (tf->isref ())
       exp = build_deref (exp);
 
     /* Some library calls are defined to return a generic type.
@@ -1888,7 +1870,7 @@  public:
     tree fndecl;
     tree object;
 
-    if (e->func->isNested ())
+    if (e->func->isNested () && !e->func->isThis ())
       {
 	if (e->e1->op == TOKnull)
 	  object = build_expr (e->e1);
@@ -1909,12 +1891,12 @@  public:
 	object = build_expr (e->e1);
 
 	/* Want reference to `this' object.  */
-	if (e->e1->type->ty != Tclass && e->e1->type->ty != Tpointer)
+	if (e->e1->type->ty != TY::Tclass && e->e1->type->ty != TY::Tpointer)
 	  object = build_address (object);
 
 	/* Object reference could be the outer `this' field of a class or
 	   closure of type `void*'.  Cast it to the right type.  */
-	if (e->e1->type->ty == Tclass)
+	if (e->e1->type->ty == TY::Tclass)
 	  object = d_convert (build_ctype (e->e1->type), object);
 
 	fndecl = get_symbol_decl (e->func);
@@ -1958,7 +1940,7 @@  public:
 	  {
 	    tree object = build_expr (e->e1);
 
-	    if (e->e1->type->toBasetype ()->ty != Tstruct)
+	    if (e->e1->type->toBasetype ()->ty != TY::Tstruct)
 	      object = build_deref (object);
 
 	    this->result_ = component_ref (object, get_symbol_decl (vd));
@@ -2005,7 +1987,7 @@  public:
 	  {
 	    /* If the condition is a D class or struct object with an invariant,
 	       call it if the condition result is true.  */
-	    if (tb1->ty == Tclass)
+	    if (tb1->ty == TY::Tclass)
 	      {
 		ClassDeclaration *cd = tb1->isClassHandle ();
 		if (!cd->isInterfaceDeclaration () && !cd->isCPPclass ())
@@ -2015,7 +1997,8 @@  public:
 						 Type::tvoid, 1, arg);
 		  }
 	      }
-	    else if (tb1->ty == Tpointer && tb1->nextOf ()->ty == Tstruct)
+	    else if (tb1->ty == TY::Tpointer
+		     && tb1->nextOf ()->ty == TY::Tstruct)
 	      {
 		StructDeclaration *sd = tb1->nextOf ()->isTypeStruct ()->sym;
 		if (sd->inv != NULL)
@@ -2093,7 +2076,7 @@  public:
     else if (Expression *tid = isExpression (e->obj))
       {
 	Type *type = tid->type->toBasetype ();
-	assert (type->ty == Tclass);
+	assert (type->ty == TY::Tclass);
 
 	/* Generate **classptr to get the classinfo.  */
 	tree ci = build_expr (tid);
@@ -2117,7 +2100,7 @@  public:
     Type *ftype = e->type->toBasetype ();
 
     /* This check is for lambda's, remove `vthis' as function isn't nested.  */
-    if (e->fd->tok == TOKreserved && ftype->ty == Tpointer)
+    if (e->fd->tok == TOKreserved && ftype->ty == TY::Tpointer)
       {
 	e->fd->tok = TOKfunction;
 	e->fd->vthis = NULL;
@@ -2226,7 +2209,7 @@  public:
 	tree init = NULL_TREE;
 
 	if (var && (var->isConst () || var->isImmutable ())
-	    && e->type->toBasetype ()->ty != Tsarray && var->_init)
+	    && e->type->toBasetype ()->ty != TY::Tsarray && var->_init)
 	  {
 	    if (var->inuse)
 	      error_at (make_location_t (e->loc), "recursive reference %qs",
@@ -2279,7 +2262,7 @@  public:
 	result = get_decl_tree (fd->vthis);
       }
 
-    if (e->type->ty == Tstruct)
+    if (e->type->ty == TY::Tstruct)
       result = build_deref (result);
 
     this->result_ = result;
@@ -2293,10 +2276,7 @@  public:
     Type *tb = e->type->toBasetype ();
     tree result;
 
-    if (e->allocator)
-      gcc_assert (e->newargs);
-
-    if (tb->ty == Tclass)
+    if (tb->ty == TY::Tclass)
       {
 	/* Allocating a new class.  */
 	tb = e->newtype->toBasetype ();
@@ -2315,20 +2295,13 @@  public:
 	    new_call = build_nop (type, build_address (var));
 	    setup_exp = modify_expr (var, aggregate_initializer_decl (cd));
 	  }
-	else if (e->allocator)
-	  {
-	    /* Call class allocator, and copy the initializer into memory.  */
-	    new_call = d_build_call_expr (e->allocator, NULL_TREE, e->newargs);
-	    new_call = d_save_expr (new_call);
-	    new_call = build_nop (type, new_call);
-	    setup_exp = modify_expr (build_deref (new_call),
-				     aggregate_initializer_decl (cd));
-	  }
 	else
 	  {
 	    /* Generate: _d_newclass()  */
 	    tree arg = build_address (get_classinfo_decl (cd));
-	    new_call = build_libcall (LIBCALL_NEWCLASS, tb, 1, arg);
+	    libcall_fn libcall = (global.params.ehnogc && e->thrownew)
+	      ? LIBCALL_NEWTHROW : LIBCALL_NEWCLASS;
+	    new_call = build_libcall (libcall, tb, 1, arg);
 	  }
 
 	/* Set the context pointer for nested classes.  */
@@ -2340,13 +2313,15 @@  public:
 	    if (e->thisexp)
 	      {
 		ClassDeclaration *tcd = e->thisexp->type->isClassHandle ();
-		Dsymbol *outer = cd->toParent2 ();
-		int offset = 0;
+		/* The class or function we're nested in.  */
+		Dsymbol *outer = cd->toParentLocal ();
 
 		value = build_expr (e->thisexp);
+
 		if (outer != tcd)
 		  {
 		    ClassDeclaration *ocd = outer->isClassDeclaration ();
+		    int offset = 0;
 		    gcc_assert (ocd->isBaseOf (tcd, &offset));
 		    /* Could just add offset...  */
 		    value = convert_expr (value, e->thisexp->type, ocd->type);
@@ -2375,7 +2350,8 @@  public:
 	if (e->argprefix)
 	  result = compound_expr (build_expr (e->argprefix), result);
       }
-    else if (tb->ty == Tpointer && tb->nextOf ()->toBasetype ()->ty == Tstruct)
+    else if (tb->ty == TY::Tpointer
+	     && tb->nextOf ()->toBasetype ()->ty == TY::Tstruct)
       {
 	/* Allocating memory for a new struct.  */
 	Type *htype = e->newtype->toBasetype ();
@@ -2393,20 +2369,11 @@  public:
 	    return;
 	  }
 
-	if (e->allocator)
-	  {
-	    /* Call struct allocator.  */
-	    new_call = d_build_call_expr (e->allocator, NULL_TREE, e->newargs);
-	    new_call = build_nop (build_ctype (tb), new_call);
-	  }
-	else
-	  {
-	    /* Generate: _d_newitemT()  */
-	    libcall_fn libcall = htype->isZeroInit ()
-	      ? LIBCALL_NEWITEMT : LIBCALL_NEWITEMIT;
-	    tree arg = build_typeinfo (e->loc, e->newtype);
-	    new_call = build_libcall (libcall, tb, 1, arg);
-	  }
+	/* Generate: _d_newitemT()  */
+	libcall_fn libcall = htype->isZeroInit ()
+	  ? LIBCALL_NEWITEMT : LIBCALL_NEWITEMIT;
+	tree arg = build_typeinfo (e->loc, e->newtype);
+	new_call = build_libcall (libcall, tb, 1, arg);
 
 	if (e->member || !e->arguments)
 	  {
@@ -2449,13 +2416,12 @@  public:
 	if (e->argprefix)
 	  result = compound_expr (build_expr (e->argprefix), result);
       }
-    else if (tb->ty == Tarray)
+    else if (tb->ty == TY::Tarray)
       {
 	/* Allocating memory for a new D array.  */
 	tb = e->newtype->toBasetype ();
 	TypeDArray *tarray = tb->isTypeDArray ();
 
-	gcc_assert (!e->allocator);
 	gcc_assert (e->arguments && e->arguments->length >= 1);
 
 	if (e->arguments->length == 1)
@@ -2492,7 +2458,7 @@  public:
 		Expression *arg = (*e->arguments)[i];
 		CONSTRUCTOR_APPEND_ELT (elms, size_int (i), build_expr (arg));
 
-		gcc_assert (telem->ty == Tarray);
+		gcc_assert (telem->ty == TY::Tarray);
 		telem = telem->toBasetype ()->nextOf ();
 		gcc_assert (telem);
 	      }
@@ -2517,7 +2483,7 @@  public:
 	if (e->argprefix)
 	  result = compound_expr (build_expr (e->argprefix), result);
       }
-    else if (tb->ty == Tpointer)
+    else if (tb->ty == TY::Tpointer)
       {
 	/* Allocating memory for a new pointer.  */
 	TypePointer *tpointer = tb->isTypePointer ();
@@ -2576,15 +2542,15 @@  public:
 
     switch (e->type->toBasetype ()->ty)
       {
-      case Tcomplex32:
+      case TY::Tcomplex32:
 	tnext = (TypeBasic *) Type::tfloat32;
 	break;
 
-      case Tcomplex64:
+      case TY::Tcomplex64:
 	tnext = (TypeBasic *) Type::tfloat64;
 	break;
 
-      case Tcomplex80:
+      case TY::Tcomplex80:
 	tnext = (TypeBasic *) Type::tfloat80;
 	break;
 
@@ -2605,7 +2571,7 @@  public:
     Type *tb = e->type->toBasetype ();
     tree type = build_ctype (e->type);
 
-    if (tb->ty == Tsarray)
+    if (tb->ty == TY::Tsarray)
       {
 	/* Turn the string into a constructor for the static array.  */
 	vec <constructor_elt, va_gc> *elms = NULL;
@@ -2635,7 +2601,7 @@  public:
 	TREE_TYPE (value) = make_array_type (tb->nextOf (), length + 1);
 	value = build_address (value);
 
-	if (tb->ty == Tarray)
+	if (tb->ty == TY::Tarray)
 	  value = d_array_value (type, size_int (e->len), value);
 
 	TREE_CONSTANT (value) = 1;
@@ -2674,15 +2640,16 @@  public:
     Type *tb = e->type->toBasetype ();
 
     /* Implicitly convert void[n] to ubyte[n].  */
-    if (tb->ty == Tsarray && tb->nextOf ()->toBasetype ()->ty == Tvoid)
+    if (tb->ty == TY::Tsarray && tb->nextOf ()->toBasetype ()->ty == TY::Tvoid)
       tb = Type::tuns8->sarrayOf (tb->isTypeSArray ()->dim->toUInteger ());
 
-    gcc_assert (tb->ty == Tarray || tb->ty == Tsarray || tb->ty == Tpointer);
+    gcc_assert (tb->ty == TY::Tarray || tb->ty == TY::Tsarray
+		|| tb->ty == TY::Tpointer);
 
     /* Handle empty array literals.  */
     if (e->elements->length == 0)
       {
-	if (tb->ty == Tarray)
+	if (tb->ty == TY::Tarray)
 	  this->result_ = d_array_value (build_ctype (e->type),
 					 size_int (0), null_pointer_node);
 	else
@@ -2732,15 +2699,15 @@  public:
     tree type = build_ctype (e->type);
 
     /* Nothing else to do for static arrays.  */
-    if (tb->ty == Tsarray || this->constp_)
+    if (tb->ty == TY::Tsarray || this->constp_)
       {
 	/* Can't take the address of the constructor, so create an anonymous
 	   static symbol, and then refer to it.  */
-	if (tb->ty != Tsarray)
+	if (tb->ty != TY::Tsarray)
 	  {
 	    tree decl = build_artificial_decl (TREE_TYPE (ctor), ctor, "A");
 	    ctor = build_address (decl);
-	    if (tb->ty == Tarray)
+	    if (tb->ty == TY::Tarray)
 	      ctor = d_array_value (type, size_int (e->elements->length), ctor);
 
 	    d_pushdecl (decl);
@@ -2789,7 +2756,7 @@  public:
 	/* Return the array pointed to by MEM.  */
 	result = compound_expr (result, mem);
 
-	if (tb->ty == Tarray)
+	if (tb->ty == TY::Tarray)
 	  result = d_array_value (type, size_int (e->elements->length), result);
 
 	this->result_ = compound_expr (saved_elems, result);
@@ -2882,7 +2849,7 @@  public:
     gcc_assert (e->elements->length <= e->sd->fields.length);
 
     Type *tb = e->type->toBasetype ();
-    gcc_assert (tb->ty == Tstruct);
+    gcc_assert (tb->ty == TY::Tstruct);
 
     for (size_t i = 0; i < e->elements->length; i++)
       {
@@ -2895,7 +2862,7 @@  public:
 	Type *ftype = field->type->toBasetype ();
 	tree value = NULL_TREE;
 
-	if (ftype->ty == Tsarray && !same_type_p (type, ftype))
+	if (ftype->ty == TY::Tsarray && !same_type_p (type, ftype))
 	  {
 	    /* Initialize a static array with a single element.  */
 	    tree elem = build_expr (exp, this->constp_, true);
@@ -3126,7 +3093,7 @@  build_return_dtor (Expression *e, Type *type, TypeFunction *tf)
   tree result = build_expr (e);
 
   /* Convert for initializing the DECL_RESULT.  */
-  if (tf->isref)
+  if (tf->isref ())
     {
       /* If we are returning a reference, take the address.  */
       result = convert_expr (result, e->type, type);
diff --git a/gcc/d/imports.cc b/gcc/d/imports.cc
index 2288843c61a..740a020321c 100644
--- a/gcc/d/imports.cc
+++ b/gcc/d/imports.cc
@@ -68,7 +68,7 @@  public:
   void visit (Module *m)
   {
     Loc loc = (m->md != NULL) ? m->md->loc
-      : Loc (m->srcfile->toChars (), 1, 0);
+      : Loc (m->srcfile.toChars (), 1, 0);
 
     m->isym = build_decl (make_location_t (loc), NAMESPACE_DECL,
 			  get_identifier (m->toPrettyChars ()),
@@ -130,11 +130,11 @@  public:
 	/* Type imports should really be part of their own visit method.  */
 	if (type != NULL)
 	  {
-	    if (type->ty == Tenum)
+	    if (type->ty == TY::Tenum)
 	      dsym = type->isTypeEnum ()->sym;
-	    else if (type->ty == Tstruct)
+	    else if (type->ty == TY::Tstruct)
 	      dsym = type->isTypeStruct ()->sym;
-	    else if (type->ty == Tclass)
+	    else if (type->ty == TY::Tclass)
 	      dsym = type->isTypeClass ()->sym;
 	  }
       }
diff --git a/gcc/d/intrinsics.cc b/gcc/d/intrinsics.cc
index 539dc0c1f37..b14b0ca5111 100644
--- a/gcc/d/intrinsics.cc
+++ b/gcc/d/intrinsics.cc
@@ -20,9 +20,9 @@  along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 
 #include "dmd/declaration.h"
+#include "dmd/expression.h"
 #include "dmd/identifier.h"
 #include "dmd/mangle.h"
-#include "dmd/mangle.h"
 #include "dmd/module.h"
 #include "dmd/template.h"
 
@@ -76,12 +76,12 @@  static const intrinsic_decl intrinsic_decls[] =
 void
 maybe_set_intrinsic (FuncDeclaration *decl)
 {
-  if (!decl->ident || decl->builtin != BUILTINunknown)
+  if (!decl->ident || decl->builtin != BUILTIN::unknown)
     return;
 
   /* The builtin flag is updated only if we can evaluate the intrinsic
      at compile-time.  Such as the math or bitop intrinsics.  */
-  decl->builtin = BUILTINunimp;
+  decl->builtin = BUILTIN::unimp;
 
   /* Check if it's a compiler intrinsic.  We only require that any
      internally recognised intrinsics are declared in a module with
@@ -177,12 +177,12 @@  maybe_set_intrinsic (FuncDeclaration *decl)
 		 built-in function.  It could be `int pow(int, int)'.  */
 	      tree rettype = TREE_TYPE (TREE_TYPE (decl->csym));
 	      if (mathfn_built_in (rettype, BUILT_IN_POW) != NULL_TREE)
-		decl->builtin = BUILTINgcc;
+		decl->builtin = BUILTIN::gcc;
 	      break;
 	    }
 
 	    default:
-	      decl->builtin = BUILTINgcc;
+	      decl->builtin = BUILTIN::gcc;
 	      break;
 	    }
 
diff --git a/gcc/d/intrinsics.def b/gcc/d/intrinsics.def
index f5af2a5fe5c..1f350f3c236 100644
--- a/gcc/d/intrinsics.def
+++ b/gcc/d/intrinsics.def
@@ -77,12 +77,12 @@  DEF_D_BUILTIN (INTRINSIC_POPCNT32, BUILT_IN_NONE, "popcnt", "core.bitop",
 DEF_D_BUILTIN (INTRINSIC_POPCNT64, BUILT_IN_NONE, "popcnt", "core.bitop",
 	       "FNaNbNiNfmZi")
 
-DEF_D_BUILTIN (INTRINSIC_ROL, BUILT_IN_NONE, "rol", "core.bitop", "FNaI1TkZI1T")
+DEF_D_BUILTIN (INTRINSIC_ROL, BUILT_IN_NONE, "rol", "core.bitop", "FNa@1TkZ@1T")
 DEF_D_BUILTIN (INTRINSIC_ROL_TIARG, BUILT_IN_NONE, "rol", "core.bitop",
-	       "FNaI1TZI1T")
-DEF_D_BUILTIN (INTRINSIC_ROR, BUILT_IN_NONE, "ror", "core.bitop", "FNaI1TkZI1T")
+	       "FNa@1TZ@1T")
+DEF_D_BUILTIN (INTRINSIC_ROR, BUILT_IN_NONE, "ror", "core.bitop", "FNa@1TkZ@1T")
 DEF_D_BUILTIN (INTRINSIC_ROR_TIARG, BUILT_IN_NONE, "ror", "core.bitop",
-	       "FNaI1TZI1T")
+	       "FNa@1TZ@1T")
 
 /* core.volatile intrinsics.  */
 
@@ -183,75 +183,74 @@  DEF_D_BUILTIN (INTRINSIC_SQRT, BUILT_IN_SQRT, "sqrt", "core.math",
 DEF_D_BUILTIN (INTRINSIC_SQRTL, BUILT_IN_SQRTL, "sqrt", "core.math",
 	       "FNaNbNiNfeZe")
 DEF_D_BUILTIN (INTRINSIC_TOPRECF, BUILT_IN_NONE, "toPrec", "core.math",
-	       "FfZI1T")
-DEF_D_BUILTIN (INTRINSIC_TOPREC, BUILT_IN_NONE, "toPrec", "core.math", "FdZI1T")
+	       "FfZ@1T")
+DEF_D_BUILTIN (INTRINSIC_TOPREC, BUILT_IN_NONE, "toPrec", "core.math", "FdZ@1T")
 DEF_D_BUILTIN (INTRINSIC_TOPRECL, BUILT_IN_NONE, "toPrec", "core.math",
-	       "FeZI1T")
+	       "FeZ@1T")
 
 /* std.math intrinsics.  */
 
-DEF_CTFE_BUILTIN (INTRINSIC_TAN, BUILT_IN_TANL, "tan", "std.math",
+DEF_CTFE_BUILTIN (INTRINSIC_TAN, BUILT_IN_TANL, "tan", "std.math.trigonometry",
 		  "FNaNbNiNeeZe")
-DEF_CTFE_BUILTIN (INTRINSIC_ISNAN, BUILT_IN_ISNAN, "isNaN", "std.math",
-		  "FNaNbNiNeI1XZb")
+
+DEF_CTFE_BUILTIN (INTRINSIC_ISNAN, BUILT_IN_ISNAN, "isNaN", "std.math.traits",
+		  "FNaNbNiNe@1XZb")
 DEF_CTFE_BUILTIN (INTRINSIC_ISINFINITY, BUILT_IN_ISINF, "isInfinity",
-		  "std.math", "FNaNbNiNeI1XZb")
-DEF_CTFE_BUILTIN (INTRINSIC_ISFINITE, BUILT_IN_ISFINITE, "isFinite", "std.math",
-		  "FNaNbNiNeI1XZb")
+		  "std.math.traits", "FNaNbNiNe@1XZb")
+DEF_CTFE_BUILTIN (INTRINSIC_ISFINITE, BUILT_IN_ISFINITE, "isFinite",
+		  "std.math.traits", "FNaNbNiNe@1XZb")
+DEF_CTFE_BUILTIN (INTRINSIC_COPYSIGN, BUILT_IN_NONE, "copysign",
+		  "std.math.traits", "FNaNbNiNe@1R@1XZ@1R")
+DEF_CTFE_BUILTIN (INTRINSIC_COPYSIGNI, BUILT_IN_NONE, "copysign",
+		  "std.math.traits", "FNaNbNiNe@1X@1RZ@1R")
 
-DEF_CTFE_BUILTIN (INTRINSIC_EXP, BUILT_IN_EXPL, "exp", "std.math",
-		  "FNaNbNiNeeZe")
-DEF_CTFE_BUILTIN (INTRINSIC_EXPM1, BUILT_IN_EXPM1L, "expm1", "std.math",
-		  "FNaNbNiNeeZe")
-DEF_CTFE_BUILTIN (INTRINSIC_EXP2, BUILT_IN_EXP2L, "exp2", "std.math",
+DEF_CTFE_BUILTIN (INTRINSIC_EXP, BUILT_IN_EXPL, "exp", "std.math.exponential",
 		  "FNaNbNiNeeZe")
-
-DEF_CTFE_BUILTIN (INTRINSIC_LOG, BUILT_IN_LOGL, "log", "std.math",
-		  "FNaNbNiNfeZe")
-DEF_CTFE_BUILTIN (INTRINSIC_LOG2, BUILT_IN_LOG2L, "log2", "std.math",
-		  "FNaNbNiNfeZe")
-DEF_CTFE_BUILTIN (INTRINSIC_LOG10, BUILT_IN_LOG10L, "log10", "std.math",
+DEF_CTFE_BUILTIN (INTRINSIC_EXPM1, BUILT_IN_EXPM1L, "expm1",
+		  "std.math.exponential", "FNaNbNiNeeZe")
+DEF_CTFE_BUILTIN (INTRINSIC_EXP2, BUILT_IN_EXP2L, "exp2",
+		  "std.math.exponential", "FNaNbNiNeeZe")
+DEF_CTFE_BUILTIN (INTRINSIC_LOG, BUILT_IN_LOGL, "log", "std.math.exponential",
 		  "FNaNbNiNfeZe")
+DEF_CTFE_BUILTIN (INTRINSIC_LOG2, BUILT_IN_LOG2L, "log2",
+		  "std.math.exponential", "FNaNbNiNfeZe")
+DEF_CTFE_BUILTIN (INTRINSIC_LOG10, BUILT_IN_LOG10L, "log10",
+		  "std.math.exponential", "FNaNbNiNfeZe")
+DEF_CTFE_BUILTIN (INTRINSIC_POW, BUILT_IN_NONE, "pow", "std.math.exponential",
+		  "FNaNbNiNe@1F@1GZ@")
 
-DEF_CTFE_BUILTIN (INTRINSIC_ROUND, BUILT_IN_ROUNDL, "round", "std.math",
-		  "FNbNiNeeZe")
-DEF_CTFE_BUILTIN (INTRINSIC_FLOORF, BUILT_IN_FLOORF, "floor", "std.math",
-		  "FNaNbNiNefZf")
-DEF_CTFE_BUILTIN (INTRINSIC_FLOOR, BUILT_IN_FLOOR, "floor", "std.math",
+DEF_CTFE_BUILTIN (INTRINSIC_ROUND, BUILT_IN_ROUNDL, "round",
+		  "std.math.rounding", "FNaNbNiNeeZe")
+DEF_CTFE_BUILTIN (INTRINSIC_FLOORF, BUILT_IN_FLOORF, "floor",
+		  "std.math.rounding", "FNaNbNiNefZf")
+DEF_CTFE_BUILTIN (INTRINSIC_FLOOR, BUILT_IN_FLOOR, "floor", "std.math.rounding",
 		  "FNaNbNiNedZd")
-DEF_CTFE_BUILTIN (INTRINSIC_FLOORL, BUILT_IN_FLOORL, "floor", "std.math",
-		  "FNaNbNiNeeZe")
-DEF_CTFE_BUILTIN (INTRINSIC_CEILF, BUILT_IN_CEILF, "ceil", "std.math",
+DEF_CTFE_BUILTIN (INTRINSIC_FLOORL, BUILT_IN_FLOORL, "floor",
+		  "std.math.rounding", "FNaNbNiNeeZe")
+DEF_CTFE_BUILTIN (INTRINSIC_CEILF, BUILT_IN_CEILF, "ceil", "std.math.rounding",
 		  "FNaNbNiNefZf")
-DEF_CTFE_BUILTIN (INTRINSIC_CEIL, BUILT_IN_CEIL, "ceil", "std.math",
+DEF_CTFE_BUILTIN (INTRINSIC_CEIL, BUILT_IN_CEIL, "ceil", "std.math.rounding",
 		  "FNaNbNiNedZd")
-DEF_CTFE_BUILTIN (INTRINSIC_CEILL, BUILT_IN_CEILL, "ceil", "std.math",
+DEF_CTFE_BUILTIN (INTRINSIC_CEILL, BUILT_IN_CEILL, "ceil", "std.math.rounding",
 		  "FNaNbNiNeeZe")
+DEF_CTFE_BUILTIN (INTRINSIC_TRUNC, BUILT_IN_TRUNCL, "trunc",
+		  "std.math.rounding", "FNaNbNiNeeZe")
 
-DEF_CTFE_BUILTIN (INTRINSIC_TRUNC, BUILT_IN_TRUNCL, "trunc", "std.math",
-		  "FNbNiNeeZe")
-DEF_CTFE_BUILTIN (INTRINSIC_FMIN, BUILT_IN_FMINL, "fmin", "std.math",
+DEF_CTFE_BUILTIN (INTRINSIC_FMIN, BUILT_IN_FMINL, "fmin", "std.math.operations",
 		  "FNaNbNiNfeeZe")
-DEF_CTFE_BUILTIN (INTRINSIC_FMAX, BUILT_IN_FMAXL, "fmax", "std.math",
+DEF_CTFE_BUILTIN (INTRINSIC_FMAX, BUILT_IN_FMAXL, "fmax", "std.math.operations",
 		  "FNaNbNiNfeeZe")
-DEF_CTFE_BUILTIN (INTRINSIC_COPYSIGN, BUILT_IN_NONE, "copysign", "std.math",
-		  "FNaNbNiNeI1RI1XZI1R")
-DEF_CTFE_BUILTIN (INTRINSIC_COPYSIGNI, BUILT_IN_NONE, "copysign", "std.math",
-		  "FNaNbNiNeI1XI1RZI1R")
-
-DEF_CTFE_BUILTIN (INTRINSIC_POW, BUILT_IN_NONE, "pow", "std.math",
-		  "FNaNbNiNeI1FI1GZ@")
-DEF_CTFE_BUILTIN (INTRINSIC_FMA, BUILT_IN_FMAL, "fma", "std.math",
+DEF_CTFE_BUILTIN (INTRINSIC_FMA, BUILT_IN_FMAL, "fma", "std.math.operations",
 		  "FNaNbNiNfeeeZe")
 
 /* core.stdc.stdarg intrinsics.  */
 
 DEF_D_BUILTIN (INTRINSIC_VA_ARG, BUILT_IN_NONE, "va_arg", "core.stdc.stdarg",
-	       "FKI7va_listKI1TZv")
+	       "FK@7va_listK@1TZv")
 DEF_D_BUILTIN (INTRINSIC_C_VA_ARG, BUILT_IN_NONE, "va_arg", "core.stdc.stdarg",
-	       "FKI7va_listZI1T")
+	       "FK@7va_listZ@1T")
 DEF_D_BUILTIN (INTRINSIC_VASTART, BUILT_IN_NONE, "va_start", "core.stdc.stdarg",
-	       "FJI7va_listKI1TZv")
+	       "FJ@7va_listK@1TZv")
 
 #undef DEF_D_BUILTIN
 #undef DEF_CTFE_BUILTIN
diff --git a/gcc/d/lang.opt b/gcc/d/lang.opt
index ded218fc5e3..f7f90fb08c3 100644
--- a/gcc/d/lang.opt
+++ b/gcc/d/lang.opt
@@ -209,6 +209,40 @@  fbuiltin
 D Var(flag_no_builtin, 0)
 ; Documented in C
 
+fcheck=assert
+D Alias(fassert)
+
+fcheck=bounds
+D Alias(fbounds-check)
+
+fcheck=in
+D Alias(fpreconditions)
+
+fcheck=invariant
+D Alias(finvariants)
+
+fcheck=out
+D Alias(fpostconditions)
+
+fcheck=switch
+D Alias(fswitch-errors)
+
+fcheckaction=
+D Joined RejectNegative Enum(check_action) Var(flag_check_action)
+-fcheckaction=[throw,halt,context]	Behavior on contract failure.
+
+Enum
+Name(check_action) Type(int) UnknownError(unknown checkaction setting %qs)
+
+EnumValue
+Enum(check_action) String(throw) Value(0)
+
+EnumValue
+Enum(check_action) String(halt) Value(1)
+
+EnumValue
+Enum(check_action) String(context) Value(2)
+
 fdebug
 D
 Compile in debug code.
@@ -237,10 +271,43 @@  fdruntime
 D
 Assume that standard D runtime libraries and \"D main\" exist.
 
+fdump-c++-spec-verbose
+D RejectNegative
+Add comments for ignored declarations in the generated C++ header.
+
+fdump-c++-spec=
+D RejectNegative Joined
+-fdump-cxx-spec=<filename>	Write all declarations as C++ code to <file>.
+
 fdump-d-original
 D
 Display the frontend AST after parsing and semantic passes.
 
+fextern-std=
+D Joined RejectNegative Enum(extern_stdcpp) Var(flag_extern_stdcpp)
+-fextern-std=<standard>	Set C++ name mangling compatibility with <standard>.
+
+Enum
+Name(extern_stdcpp) Type(int) UnknownError(unknown C++ standard %qs)
+
+EnumValue
+Enum(extern_stdcpp) String(c++98) Value(199711)
+
+EnumValue
+Enum(extern_stdcpp) String(c++03) Value(199711)
+
+EnumValue
+Enum(extern_stdcpp) String(c++11) Value(201103)
+
+EnumValue
+Enum(extern_stdcpp) String(c++14) Value(201402)
+
+EnumValue
+Enum(extern_stdcpp) String(c++17) Value(201703)
+
+EnumValue
+Enum(extern_stdcpp) String(c++20) Value(202002)
+
 fignore-unknown-pragmas
 D
 Ignore unsupported pragmas.
@@ -273,33 +340,97 @@  fpreconditions
 D Var(flag_preconditions)
 Generate code for precondition contracts.
 
+fpreview=all
+D RejectNegative
+Turn on all upcoming D language features.
+
+fpreview=dip1000
+D RejectNegative
+Implement DIP1000: Scoped pointers.
+
+fpreview=dip1008
+D RejectNegative
+Implement DIP1008: Allow exceptions in @nogc code.
+
+fpreview=dip1021
+D RejectNegative
+Implement DIP1021: Mutable function arguments.
+
+fpreview=dip25
+D RejectNegative
+Implement DIP25: Sealed references.
+
+fpreview=dtorfields
+D RejectNegative
+Destruct fields of partially constructed objects.
+
+fpreview=fieldwise
+D RejectNegative
+Use field-wise comparisons for struct equality.
+
+fpreview=fixaliasthis
+D RejectNegative
+When a symbol is resolved, check alias this scope before going to upper scopes.
+
+fpreview=in
+D RejectNegative
+Implement 'in' parameters to mean scope const.
+
+fpreview=inclusiveincontracts
+D RejectNegative
+Implement 'in' contracts of overridden methods to be a superset of parent contract.
+
+fpreview=intpromote
+D RejectNegative
+Use C-style integral promotion for unary '+', '-' and '~'.
+
+fpreview=nosharedaccess
+D RejectNegative
+Disable access to shared memory objects.
+
+fpreview=rvaluerefparam
+D RejectNegative
+Enable rvalue arguments to ref parameters.
+
+fpreview=shortenedmethods
+D RejectNegative
+Allow use of '=>' for methods and top-level functions in addition to lambdas.
+
 frelease
 D
 Compile release version.
 
+frevert=all
+D RejectNegative
+Turn off all revertable D language features.
+
+frevert=dip25
+D RejectNegative
+Revert DIP25: Sealed references.
+
+frevert=dtorfields
+D RejectNegative
+Don't destruct fields of partially constructed objects.
+
+frevert=markdown
+D RejectNegative
+Disable Markdown replacements in Ddoc.
+
 frtti
 D
 ; Documented in C
 
+fsave-mixins=
+D Joined RejectNegative
+-fsave-mixins=<filename>	Expand and save mixins to file specified by <filename>.
+
 fswitch-errors
 D Var(flag_switch_errors)
 Generate code for switches without a default case.
 
 ftransition=all
 D RejectNegative
-List information on all language changes.
-
-ftransition=complex
-D RejectNegative
-List all usages of complex or imaginary types.
-
-ftransition=dip1000
-D RejectNegative
-Implement DIP1000: Scoped pointers (experimental).
-
-ftransition=dip25
-D RejectNegative
-Implement DIP25: Sealed references (experimental).
+List information on all D language transitions.
 
 ftransition=field
 D RejectNegative
@@ -309,10 +440,18 @@  ftransition=nogc
 D RejectNegative
 List all hidden GC allocations.
 
+ftransition=templates
+D RejectNegative
+List statistics on template instantiations.
+
 ftransition=tls
 D RejectNegative
 List all variables going into thread local storage.
 
+ftransition=vmarkdown
+D RejectNegative
+List instances of Markdown replacements in Ddoc.
+
 funittest
 D
 Compile in unittest code.
diff --git a/gcc/d/modules.cc b/gcc/d/modules.cc
index 8786344d954..06eb5ae3424 100644
--- a/gcc/d/modules.cc
+++ b/gcc/d/modules.cc
@@ -125,7 +125,7 @@  static Module *current_module_decl;
    by both module initialization and dso handlers.  */
 
 static FuncDeclaration *
-get_internal_fn (tree ident, const Prot &prot)
+get_internal_fn (tree ident, const Visibility &visibility)
 {
   Module *mod = current_module_decl;
   const char *name = IDENTIFIER_POINTER (ident);
@@ -142,9 +142,9 @@  get_internal_fn (tree ident, const Prot &prot)
   FuncDeclaration *fd = FuncDeclaration::genCfunc (NULL, Type::tvoid,
 						   Identifier::idPool (name));
   fd->generated = true;
-  fd->loc = Loc (mod->srcfile->toChars (), 1, 0);
+  fd->loc = Loc (mod->srcfile.toChars (), 1, 0);
   fd->parent = mod;
-  fd->protection = prot;
+  fd->visibility = visibility;
   fd->semanticRun = PASSsemantic3done;
 
   return fd;
@@ -156,7 +156,9 @@  get_internal_fn (tree ident, const Prot &prot)
 static tree
 build_internal_fn (tree ident, tree expr)
 {
-  FuncDeclaration *fd = get_internal_fn (ident, Prot (Prot::private_));
+  Visibility visibility;
+  visibility.kind = Visibility::private_;
+  FuncDeclaration *fd = get_internal_fn (ident, visibility);
   tree decl = get_symbol_decl (fd);
 
   tree old_context = start_function (fd);
@@ -338,8 +340,9 @@  build_dso_cdtor_fn (bool ctor_p)
 	}
     }
    */
-  FuncDeclaration *fd = get_internal_fn (get_identifier (name),
-					 Prot (Prot::public_));
+  Visibility visibility;
+  visibility.kind = Visibility::public_;
+  FuncDeclaration *fd = get_internal_fn (get_identifier (name), visibility);
   tree decl = get_symbol_decl (fd);
 
   TREE_PUBLIC (decl) = 1;
@@ -740,7 +743,8 @@  build_module_tree (Module *decl)
       /* Associate the module info symbol with a mock module.  */
       const char *name = concat (GDC_PREFIX ("modtest__"),
 				 decl->ident->toChars (), NULL);
-      Module *tm = Module::create (decl->arg, Identifier::idPool (name), 0, 0);
+      Module *tm = Module::create (decl->arg.ptr, Identifier::idPool (name),
+				   0, 0);
       Dsymbols members;
 
       /* Setting parent puts module in the same package as the current, to
@@ -780,9 +784,7 @@  build_module_tree (Module *decl)
 
   /* Default behavior is to always generate module info because of templates.
      Can be switched off for not compiling against runtime library.  */
-  if (global.params.useModuleInfo
-      && Module::moduleinfo != NULL
-      && decl->ident != Identifier::idPool ("__entrypoint"))
+  if (global.params.useModuleInfo && Module::moduleinfo != NULL)
     {
       if (mi.ctors || mi.ctorgates)
 	decl->sctor = build_funcs_gates_fn (get_identifier ("*__modctor"),
diff --git a/gcc/d/runtime.def b/gcc/d/runtime.def
index 0296233f4e2..fdff6db0626 100644
--- a/gcc/d/runtime.def
+++ b/gcc/d/runtime.def
@@ -34,6 +34,8 @@  along with GCC; see the file COPYING3.  If not see
 		3, LCT_ ## T1, LCT_ ## T2, LCT_ ## T3
 #define P4(T1, T2, T3, T4) \
 		4, LCT_ ## T1, LCT_ ## T2, LCT_ ## T3, LCT_ ## T4
+#define P5(T1, T2, T3, T4, T5)  \
+		5, LCT_ ## T1, LCT_ ## T2, LCT_ ## T3, LCT_ ## T4, LCT_ ## T5
 #define RT(T1)	LCT_ ## T1
 
 /* Used when an assert() contract fails.  */
@@ -51,9 +53,15 @@  DEF_D_RUNTIME (UNITTEST_MSG, "_d_unittest_msg", RT(VOID),
 /* Used when an array index outside the bounds of its range.  */
 DEF_D_RUNTIME (ARRAYBOUNDSP, "_d_arrayboundsp", RT(VOID),
 	       P2(IMMUTABLE_CHARPTR, UINT), ECF_NORETURN)
+DEF_D_RUNTIME (ARRAYBOUNDS_SLICEP, "_d_arraybounds_slicep", RT(VOID),
+	       P5(IMMUTABLE_CHARPTR, UINT, SIZE_T, SIZE_T, SIZE_T),
+	       ECF_NORETURN)
+DEF_D_RUNTIME (ARRAYBOUNDS_INDEXP, "_d_arraybounds_indexp", RT(VOID),
+	       P4(IMMUTABLE_CHARPTR, UINT, SIZE_T, SIZE_T), ECF_NORETURN)
 
 /* Used when calling new on a class.  */
 DEF_D_RUNTIME (NEWCLASS, "_d_newclass", RT(OBJECT), P1(CONST_CLASSINFO), 0)
+DEF_D_RUNTIME (NEWTHROW, "_d_newThrowable", RT(OBJECT), P1(CONST_CLASSINFO), 0)
 
 /* Used when calling delete on a class or interface.  */
 DEF_D_RUNTIME (DELCLASS, "_d_delclass", RT(VOID), P1(VOIDPTR), 0)
@@ -104,13 +112,6 @@  DEF_D_RUNTIME (DELARRAYT, "_d_delarray_t", RT(VOID),
    arrays.  Such as an array of structs or classes.  */
 DEF_D_RUNTIME (ADEQ2, "_adEq2", RT(INT),
 	       P3(ARRAY_VOID, ARRAY_VOID, CONST_TYPEINFO), 0)
-DEF_D_RUNTIME (ADCMP2, "_adCmp2", RT(INT),
-	       P3(ARRAY_VOID, ARRAY_VOID, CONST_TYPEINFO), 0)
-
-/* Used when casting from one array type to another where the index type
-   sizes differ.  Such as from int[] to short[].  */
-DEF_D_RUNTIME (ARRAYCAST, "_d_arraycast", RT(ARRAY_VOID),
-	       P3(SIZE_T, SIZE_T, ARRAY_VOID), 0)
 
 /* Used for (array.length = n) expressions.  The `i' variant is for when the
    initializer is nonzero.  */
@@ -206,23 +207,10 @@  DEF_D_RUNTIME (CXA_END_CATCH, "__cxa_end_catch", RT(VOID), P0(), 0)
 DEF_D_RUNTIME (INVARIANT, "_D9invariant12_d_invariantFC6ObjectZv", RT(VOID),
 	       P1(OBJECT), 0)
 
-/* Used when performing a switch/cases on a string.  The `u' and `d' variants
-   are for UTF-16 and UTF-32 strings respectively.  */
-DEF_D_RUNTIME (SWITCH_STRING, "_d_switch_string", RT(INT),
-	       P2(ARRAY_STRING, STRING), 0)
-DEF_D_RUNTIME (SWITCH_USTRING, "_d_switch_ustring", RT(INT),
-	       P2(ARRAY_WSTRING, WSTRING), 0)
-DEF_D_RUNTIME (SWITCH_DSTRING, "_d_switch_dstring", RT(INT),
-	       P2(ARRAY_DSTRING, DSTRING), 0)
-
-/* Used when throwing an error that a switch statement has no default case,
-   and yet none of the existing cases matched.  */
-DEF_D_RUNTIME (SWITCH_ERROR, "_d_switch_error", RT(VOID), P2(STRING, UINT),
-	       ECF_NORETURN)
-
 #undef P0
 #undef P1
 #undef P2
 #undef P3
 #undef P4
+#undef P5
 #undef RT
diff --git a/gcc/d/toir.cc b/gcc/d/toir.cc
index 1c9da101f39..55d63f89cb7 100644
--- a/gcc/d/toir.cc
+++ b/gcc/d/toir.cc
@@ -413,18 +413,6 @@  public:
 		else
 		  error_at (location, "cannot %<goto%> into %<catch%> block");
 	      }
-	    else if (s->isCaseStatement ())
-	      {
-		location = make_location_t (s->loc);
-		error_at (location, "case cannot be in different "
-			  "%<try%> block level from %<switch%>");
-	      }
-	    else if (s->isDefaultStatement ())
-	      {
-		location = make_location_t (s->loc);
-		error_at (location, "default cannot be in different "
-			  "%<try%> block level from %<switch%>");
-	      }
 	    else
 	      gcc_unreachable ();
 	  }
@@ -709,7 +697,8 @@  public:
       {
 	/* The break label may actually be some levels up.
 	   eg: on a try/finally wrapping a loop.  */
-	LabelStatement *label = this->func_->searchLabel (s->ident)->statement;
+	LabelDsymbol *sym = this->func_->searchLabel (s->ident, s->loc);
+	LabelStatement *label = sym->statement;
 	gcc_assert (label != NULL);
 	Statement *stmt = label->statement->getRelatedLabeled ();
 	this->do_jump (this->lookup_bc_label (stmt, bc_break));
@@ -725,7 +714,8 @@  public:
   {
     if (s->ident)
       {
-	LabelStatement *label = this->func_->searchLabel (s->ident)->statement;
+	LabelDsymbol *sym = this->func_->searchLabel (s->ident, s->loc);
+	LabelStatement *label = sym->statement;
 	gcc_assert (label != NULL);
 	this->do_jump (this->lookup_bc_label (label->statement,
 					      bc_continue));
@@ -759,7 +749,7 @@  public:
     if (this->is_return_label (s->ident))
       sym = this->func_->returnLabel;
     else
-      sym = this->func_->searchLabel (s->ident);
+      sym = this->func_->searchLabel (s->ident, s->loc);
 
     /* If no label found, there was an error.  */
     tree label = this->define_label (sym->statement, sym->ident);
@@ -784,69 +774,9 @@  public:
     tree condition = build_expr_dtor (s->condition);
     Type *condtype = s->condition->type->toBasetype ();
 
-    /* A switch statement on a string gets turned into a library call,
-       which does a binary lookup on list of string cases.  */
-    if (s->condition->type->isString ())
-      {
-	Type *etype = condtype->nextOf ()->toBasetype ();
-	libcall_fn libcall;
-
-	switch (etype->ty)
-	  {
-	  case Tchar:
-	    libcall = LIBCALL_SWITCH_STRING;
-	    break;
-
-	  case Twchar:
-	    libcall = LIBCALL_SWITCH_USTRING;
-	    break;
-
-	  case Tdchar:
-	    libcall = LIBCALL_SWITCH_DSTRING;
-	    break;
-
-	  default:
-	    ::error ("switch statement value must be an array of "
-		     "some character type, not %s", etype->toChars ());
-	    gcc_unreachable ();
-	  }
-
-	/* Apparently the backend is supposed to sort and set the indexes
-	   on the case array, have to change them to be usable.  */
-	Type *satype = condtype->sarrayOf (s->cases->length);
-	vec <constructor_elt, va_gc> *elms = NULL;
-
-	s->cases->sort ();
-
-	for (size_t i = 0; i < s->cases->length; i++)
-	  {
-	    CaseStatement *cs = (*s->cases)[i];
-	    cs->index = i;
-
-	    if (cs->exp->op != TOKstring)
-	      s->error ("case '%s' is not a string", cs->exp->toChars ());
-	    else
-	      {
-		tree exp = build_expr (cs->exp, true);
-		CONSTRUCTOR_APPEND_ELT (elms, size_int (i), exp);
-	      }
-	  }
-
-	/* Build static declaration to reference constructor.  */
-	tree ctor = build_constructor (build_ctype (satype), elms);
-	tree decl = build_artificial_decl (TREE_TYPE (ctor), ctor);
-	TREE_READONLY (decl) = 1;
-	d_pushdecl (decl);
-	rest_of_decl_compilation (decl, 1, 0);
-
-	/* Pass it as a dynamic array.  */
-	decl = d_array_value (build_ctype (condtype->arrayOf ()),
-			      size_int (s->cases->length),
-			      build_address (decl));
-
-	condition = build_libcall (libcall, Type::tint32, 2, decl, condition);
-      }
-    else if (!condtype->isscalar ())
+    /* A switch statement on a string gets turned into a library call.
+       It is not lowered during codegen.  */
+    if (!condtype->isscalar ())
       {
 	error ("cannot handle switch condition of type %s",
 	       condtype->toChars ());
@@ -992,7 +922,10 @@  public:
 
   void visit (SwitchErrorStatement *s)
   {
-    add_stmt (build_assert_call (s->loc, LIBCALL_SWITCH_ERROR));
+    /* A throw SwitchError statement gets turned into a library call.
+       The call is wrapped in the enclosed expression.  */
+    gcc_assert (s->exp != NULL);
+    add_stmt (build_expr (s->exp));
   }
 
   /* A return statement exits the current function and supplies its return
@@ -1000,7 +933,7 @@  public:
 
   void visit (ReturnStatement *s)
   {
-    if (s->exp == NULL || s->exp->type->toBasetype ()->ty == Tvoid)
+    if (s->exp == NULL || s->exp->type->toBasetype ()->ty == TY::Tvoid)
       {
 	/* Return has no value.  */
 	add_stmt (return_expr (NULL_TREE));
@@ -1012,7 +945,7 @@  public:
       ? this->func_->tintro->nextOf () : tf->nextOf ();
 
     if ((this->func_->isMain () || this->func_->isCMain ())
-	&& type->toBasetype ()->ty == Tvoid)
+	&& type->toBasetype ()->ty == TY::Tvoid)
       type = Type::tint32;
 
     if (this->func_->shidden)
@@ -1020,7 +953,7 @@  public:
 	/* Returning by hidden reference, store the result into the retval decl.
 	   The result returned then becomes the retval reference itself.  */
 	tree decl = DECL_RESULT (get_symbol_decl (this->func_));
-	gcc_assert (!tf->isref);
+	gcc_assert (!tf->isref ());
 
 	/* If returning via NRVO, just refer to the DECL_RESULT; this differs
 	   from using NULL_TREE in that it indicates that we care about the
@@ -1096,7 +1029,7 @@  public:
 
 	add_stmt (return_expr (decl));
       }
-    else if (tf->next->ty == Tnoreturn)
+    else if (tf->next->ty == TY::Tnoreturn)
       {
 	/* Returning an expression that has no value, but has a side effect
 	   that should never return.  */
@@ -1514,7 +1447,7 @@  public:
 
     /* If the function has been annotated with `pragma(inline)', then mark
        the asm expression as being inline as well.  */
-    if (this->func_->inlining == PINLINEalways)
+    if (this->func_->inlining == PINLINE::always)
       ASM_INLINE_P (exp) = 1;
 
     add_stmt (exp);
diff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc
index fd8c746a307..065f6b3de80 100644
--- a/gcc/d/typeinfo.cc
+++ b/gcc/d/typeinfo.cc
@@ -39,6 +39,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "stor-layout.h"
 
 #include "d-tree.h"
+#include "d-frontend.h"
 #include "d-target.h"
 
 
@@ -110,37 +111,37 @@  get_typeinfo_kind (Type *type)
 
   switch (type->ty)
     {
-    case Tpointer:
+    case TY::Tpointer:
       return TK_POINTER_TYPE;
 
-    case  Tarray:
+    case TY::Tarray:
       return TK_ARRAY_TYPE;
 
-    case Tsarray:
+    case TY::Tsarray:
       return TK_STATICARRAY_TYPE;
 
-    case Taarray:
+    case TY::Taarray:
       return TK_ASSOCIATIVEARRAY_TYPE;
 
-    case Tstruct:
+    case TY::Tstruct:
       return TK_STRUCT_TYPE;
 
-    case Tvector:
+    case TY::Tvector:
       return TK_VECTOR_TYPE;
 
-    case Tenum:
+    case TY::Tenum:
       return TK_ENUMERAL_TYPE;
 
-    case Tfunction:
+    case TY::Tfunction:
       return TK_FUNCTION_TYPE;
 
-    case Tdelegate:
+    case TY::Tdelegate:
       return TK_DELEGATE_TYPE;
 
-    case Ttuple:
+    case TY::Ttuple:
       return TK_TYPELIST_TYPE;
 
-    case Tclass:
+    case TY::Tclass:
       if (type->isTypeClass ()->sym->isInterfaceDeclaration ())
 	return TK_INTERFACE_TYPE;
       else
@@ -216,7 +217,7 @@  make_frontend_typeinfo (Identifier *ident, ClassDeclaration *base = NULL)
 	    = ClassDeclaration::create (loc, Identifier::idPool ("Object"),
 					NULL, NULL, true);
 	  object->parent = object_module;
-	  object->members = new Dsymbols;
+	  object->members = d_gc_malloc<Dsymbols> ();
 	  object->storage_class |= STCtemp;
 	}
 
@@ -228,7 +229,7 @@  make_frontend_typeinfo (Identifier *ident, ClassDeclaration *base = NULL)
   ClassDeclaration *tinfo = ClassDeclaration::create (loc, ident, NULL, NULL,
 						      true);
   tinfo->parent = object_module;
-  tinfo->members = new Dsymbols;
+  tinfo->members = d_gc_malloc<Dsymbols> ();
   dsymbolSemantic (tinfo, object_module->_scope);
   tinfo->baseClass = base;
   /* This is a compiler generated class, and shouldn't be mistaken for being
@@ -836,7 +837,7 @@  public:
 	/* Name of the class declaration.  */
 	const char *name = cd->ident->toChars ();
 	if (!(strlen (name) > 9 && memcmp (name, "TypeInfo_", 9) == 0))
-	  name = cd->toPrettyChars ();
+	  name = cd->toPrettyChars (true);
 	this->layout_string (name);
 
 	/* The vtable of the class declaration.  */
@@ -857,7 +858,7 @@  public:
 	this->layout_field (base);
 
 	/* void *destructor;  */
-	tree dtor = (cd->dtor) ? build_address (get_symbol_decl (cd->dtor))
+	tree dtor = (cd->tidtor) ? build_address (get_symbol_decl (cd->tidtor))
 	  : null_pointer_node;
 	this->layout_field (dtor);
 
@@ -911,10 +912,7 @@  public:
 	this->layout_field (build_integer_cst (flags, d_uint_type));
 
 	/* void *deallocator;  */
-	tree ddtor = (cd->aggDelete)
-	  ? build_address (get_symbol_decl (cd->aggDelete))
-	  : null_pointer_node;
-	this->layout_field (ddtor);
+	this->layout_field (null_pointer_node);
 
 	/* OffsetTypeInfo[] m_offTi;  (not implemented)  */
 	this->layout_field (null_array_node);
@@ -942,7 +940,7 @@  public:
 	this->layout_field (null_array_node);
 
 	/* Name of the interface declaration.  */
-	this->layout_string (cd->toPrettyChars ());
+	this->layout_string (cd->toPrettyChars (true));
 
 	/* No vtable for interface declaration.  */
 	this->layout_field (null_array_node);
@@ -1024,7 +1022,7 @@  public:
   /* Layout of TypeInfo_Struct is:
 	void **__vptr;
 	void *__monitor;
-	string name;
+	string mangledName;
 	void[] m_init;
 	hash_t function(in void*) xtoHash;
 	bool function(in void*, in void*) xopEquals;
@@ -1047,8 +1045,8 @@  public:
     if (!sd->members)
       return;
 
-    /* Name of the struct declaration.  */
-    this->layout_string (sd->toPrettyChars ());
+    /* Mangled name of the struct declaration.  */
+    this->layout_string (ti->deco);
 
     /* Default initializer for struct.  */
     tree ptr = (sd->zeroInit) ? null_pointer_node
@@ -1064,7 +1062,7 @@  public:
     if (sd->xhash)
       {
 	TypeFunction *tf = sd->xhash->type->toTypeFunction ();
-	if (!tf->isnothrow || tf->trust == TRUSTsystem)
+	if (!tf->isnothrow () || tf->trust == TRUST::system)
 	  {
 	    warning (sd->xhash->loc, "toHash() must be declared as "
 		     "extern (D) size_t toHash() const nothrow @safe, "
@@ -1096,7 +1094,7 @@  public:
     this->layout_field (build_integer_cst (m_flags, d_uint_type));
 
     /* void function(void*) xdtor;  */
-    tree dtor = (sd->dtor) ? build_address (get_symbol_decl (sd->dtor))
+    tree dtor = (sd->tidtor) ? build_address (get_symbol_decl (sd->tidtor))
       : null_pointer_node;
     this->layout_field (dtor);
 
@@ -1298,17 +1296,17 @@  layout_classinfo_interfaces (ClassDeclaration *decl)
 static bool
 builtin_typeinfo_p (Type *type)
 {
-  if (type->isTypeBasic () || type->ty == Tclass || type->ty == Tnull)
+  if (type->isTypeBasic () || type->ty == TY::Tclass || type->ty == TY::Tnull)
     return !type->mod;
 
-  if (type->ty == Tarray)
+  if (type->ty == TY::Tarray)
     {
       /* Strings are so common, make them builtin.  */
       Type *next = type->nextOf ();
       return !type->mod
 	&& ((next->isTypeBasic () != NULL && !next->mod)
-	    || (next->ty == Tchar && next->mod == MODimmutable)
-	    || (next->ty == Tchar && next->mod == MODconst));
+	    || (next->ty == TY::Tchar && next->mod == MODimmutable)
+	    || (next->ty == TY::Tchar && next->mod == MODconst));
     }
 
   return false;
@@ -1361,7 +1359,7 @@  get_typeinfo_decl (TypeInfoDeclaration *decl)
   if (decl->csym)
     return decl->csym;
 
-  gcc_assert (decl->tinfo->ty != Terror);
+  gcc_assert (decl->tinfo->ty != TY::Terror);
 
   TypeInfoDeclVisitor v = TypeInfoDeclVisitor ();
   decl->accept (&v);
@@ -1436,7 +1434,7 @@  check_typeinfo_type (const Loc &loc, Scope *sc)
 tree
 build_typeinfo (const Loc &loc, Type *type)
 {
-  gcc_assert (type->ty != Terror);
+  gcc_assert (type->ty != TY::Terror);
   check_typeinfo_type (loc, NULL);
   create_typeinfo (type, NULL);
   return build_address (get_typeinfo_decl (type->vtinfo));
diff --git a/gcc/d/types.cc b/gcc/d/types.cc
index fc8a1330696..db500ee2efe 100644
--- a/gcc/d/types.cc
+++ b/gcc/d/types.cc
@@ -94,7 +94,7 @@  bool
 valist_array_p (Type *type)
 {
   Type *tvalist = target.va_listType (Loc (), NULL);
-  if (tvalist->ty == Tsarray)
+  if (tvalist->ty == TY::Tsarray)
     {
       Type *tb = type->toBasetype ();
       if (same_type_p (tb, tvalist))
@@ -170,7 +170,7 @@  make_array_type (Type *type, unsigned HOST_WIDE_INT size)
 {
   /* In [arrays/void-arrays], void arrays can also be static, the length is
      specified in bytes.  */
-  if (type->toBasetype ()->ty == Tvoid)
+  if (type->toBasetype ()->ty == TY::Tvoid)
     type = Type::tuns8;
 
   /* In [arrays/static-arrays], a static array with a dimension of 0 is allowed,
@@ -546,9 +546,9 @@  merge_aggregate_types (Type *type, tree deco)
 {
   AggregateDeclaration *sym;
 
-  if (type->ty == Tstruct)
+  if (type->ty == TY::Tstruct)
     sym = type->isTypeStruct ()->sym;
-  else if (type->ty == Tclass)
+  else if (type->ty == TY::Tclass)
     sym = type->isTypeClass ()->sym;
   else
     gcc_unreachable ();
@@ -646,31 +646,31 @@  public:
 
     switch (t->ty)
       {
-      case Tvoid:	  t->ctype = void_type_node; break;
-      case Tbool:	  t->ctype = d_bool_type; break;
-      case Tint8:	  t->ctype = d_byte_type; break;
-      case Tuns8:	  t->ctype = d_ubyte_type; break;
-      case Tint16:	  t->ctype = d_short_type; break;
-      case Tuns16:	  t->ctype = d_ushort_type; break;
-      case Tint32:	  t->ctype = d_int_type; break;
-      case Tuns32:	  t->ctype = d_uint_type; break;
-      case Tint64:	  t->ctype = d_long_type; break;
-      case Tuns64:	  t->ctype = d_ulong_type; break;
-      case Tint128:	  t->ctype = d_cent_type; break;
-      case Tuns128:	  t->ctype = d_ucent_type; break;
-      case Tfloat32:	  t->ctype = float_type_node; break;
-      case Tfloat64:	  t->ctype = double_type_node; break;
-      case Tfloat80:	  t->ctype = long_double_type_node; break;
-      case Timaginary32:  t->ctype = ifloat_type_node; break;
-      case Timaginary64:  t->ctype = idouble_type_node; break;
-      case Timaginary80:  t->ctype = ireal_type_node; break;
-      case Tcomplex32:	  t->ctype = complex_float_type_node; break;
-      case Tcomplex64:	  t->ctype = complex_double_type_node; break;
-      case Tcomplex80:	  t->ctype = complex_long_double_type_node; break;
-      case Tchar:	  t->ctype = char8_type_node; break;
-      case Twchar:	  t->ctype = char16_type_node; break;
-      case Tdchar:	  t->ctype = char32_type_node; break;
-      default:		  gcc_unreachable ();
+      case TY::Tvoid:	     t->ctype = void_type_node; break;
+      case TY::Tbool:	     t->ctype = d_bool_type; break;
+      case TY::Tint8:	     t->ctype = d_byte_type; break;
+      case TY::Tuns8:	     t->ctype = d_ubyte_type; break;
+      case TY::Tint16:	     t->ctype = d_short_type; break;
+      case TY::Tuns16:	     t->ctype = d_ushort_type; break;
+      case TY::Tint32:	     t->ctype = d_int_type; break;
+      case TY::Tuns32:	     t->ctype = d_uint_type; break;
+      case TY::Tint64:	     t->ctype = d_long_type; break;
+      case TY::Tuns64:	     t->ctype = d_ulong_type; break;
+      case TY::Tint128:	     t->ctype = d_cent_type; break;
+      case TY::Tuns128:	     t->ctype = d_ucent_type; break;
+      case TY::Tfloat32:     t->ctype = float_type_node; break;
+      case TY::Tfloat64:     t->ctype = double_type_node; break;
+      case TY::Tfloat80:     t->ctype = long_double_type_node; break;
+      case TY::Timaginary32: t->ctype = ifloat_type_node; break;
+      case TY::Timaginary64: t->ctype = idouble_type_node; break;
+      case TY::Timaginary80: t->ctype = ireal_type_node; break;
+      case TY::Tcomplex32:   t->ctype = complex_float_type_node; break;
+      case TY::Tcomplex64:   t->ctype = complex_double_type_node; break;
+      case TY::Tcomplex80:   t->ctype = complex_long_double_type_node; break;
+      case TY::Tchar:	     t->ctype = char8_type_node; break;
+      case TY::Twchar:	     t->ctype = char16_type_node; break;
+      case TY::Tdchar:	     t->ctype = char32_type_node; break;
+      default:		     gcc_unreachable ();
       }
 
     TYPE_NAME (t->ctype) = get_identifier (t->toChars ());
@@ -786,7 +786,7 @@  public:
     if (t->next != NULL)
       {
 	fntype = build_ctype (t->next);
-	if (t->isref)
+	if (t->isref ())
 	  fntype = build_reference_type (fntype);
       }
     else
@@ -800,7 +800,7 @@  public:
     /* Handle any special support for calling conventions.  */
     switch (t->linkage)
       {
-      case LINKwindows:
+      case LINK::windows:
 	{
 	  /* [attribute/linkage]
 
@@ -815,10 +815,10 @@  public:
 	  break;
 	}
 
-      case LINKc:
-      case LINKcpp:
-      case LINKd:
-      case LINKobjc:
+      case LINK::c:
+      case LINK::cpp:
+      case LINK::d:
+      case LINK::objc:
 	/* [abi/function-calling-conventions]
 
 	  The extern (C) and extern (D) calling convention matches
@@ -1013,8 +1013,8 @@  public:
     TYPE_CONTEXT (t->ctype) = d_decl_context (t->sym);
     build_type_decl (t->ctype, t->sym);
 
-    /* For structs with a user defined postblit or a destructor,
-       also set TREE_ADDRESSABLE on the type and all variants.
+    /* For structs with a user defined postblit, copy constructor, or a
+       destructor, also set TREE_ADDRESSABLE on the type and all variants.
        This will make the struct be passed around by reference.  */
     if (!t->sym->isPOD ())
       {
diff --git a/gcc/d/verstr.h b/gcc/d/verstr.h
deleted file mode 100644
index 0dd41eeaebe..00000000000
--- a/gcc/d/verstr.h
+++ /dev/null
@@ -1 +0,0 @@ 
-"2.076.1"