Merge from trunk revision 24ca97325cab7bc454c785d55f37120fe7ea6f74.
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a3e17e0..f3de0c1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,129 @@
+2022-02-15  Andrew MacLeod  <amacleod@redhat.com>
+
+	PR tree-optimization/104526
+	* gimple-range-fold.cc (fold_using_range::range_of_cond_expr): Call
+	new routine.
+	* gimple-range-gori.cc (range_def_chain::get_def_chain): Force a build
+	of dependency chain if there isn't one.
+	(gori_compute::condexpr_adjust): New.
+	* gimple-range-gori.h (class gori_compute): New prototype.
+
+2022-02-15  Richard Sandiford  <richard.sandiford@arm.com>
+
+	PR target/100874
+	* config/aarch64/aarch64-protos.h (aarch64_maxmin_plus_const):
+	Declare.
+	* config/aarch64/aarch64.cc (aarch64_maxmin_plus_const): New function.
+	* config/aarch64/aarch64.md (*aarch64_minmax_plus): New pattern.
+
+2022-02-15  Richard Sandiford  <richard.sandiford@arm.com>
+
+	* tree-vectorizer.h (vect_scalar_ops_slice): New struct.
+	(vect_scalar_ops_slice_hash): Likewise.
+	(vect_scalar_ops_slice::op): New function.
+	* tree-vect-slp.cc (vect_scalar_ops_slice::all_same_p): New function.
+	(vect_scalar_ops_slice_hash::hash): Likewise.
+	(vect_scalar_ops_slice_hash::equal): Likewise.
+	(vect_prologue_cost_for_slp): Check for duplicate vectors.
+	* config/aarch64/aarch64.cc
+	(aarch64_vector_costs::m_stp_sequence_cost): New member variable.
+	(aarch64_aligned_constant_offset_p): New function.
+	(aarch64_stp_sequence_cost): Likewise.
+	(aarch64_vector_costs::add_stmt_cost): Handle new STP heuristic.
+	(aarch64_vector_costs::finish_cost): Likewise.
+
+2022-02-15  Richard Sandiford  <richard.sandiford@arm.com>
+
+	* tree-vect-slp.cc (vect_bb_vectorization_profitable_p): Fix
+	use after free.
+
+2022-02-15  Richard Biener  <rguenther@suse.de>
+
+	PR tree-optimization/104543
+	* gimple-loop-jam.cc (unroll_jam_possible_p): Check outer loop exits
+	come after the inner loop.
+
+2022-02-15  Jakub Jelinek  <jakub@redhat.com>
+
+	PR target/104536
+	* config/i386/host-cygwin.cc (cygwin_gt_pch_get_address): Use
+	cannot instead of can%'t in diagnostics.  Formatting fixes.
+
+2022-02-15  Jakub Jelinek  <jakub@redhat.com>
+
+	PR middle-end/104522
+	* fold-const.h (native_interpret_real): Declare.
+	* fold-const.cc (native_interpret_real): No longer static.  Don't
+	perform MODE_COMPOSITE_P verification here.
+	(native_interpret_expr) <case REAL_TYPE>: But perform it here instead
+	for all modes.
+	* gimple-fold.cc (clear_padding_type): Call native_interpret_real
+	instead of native_interpret_expr.
+	* simplify-rtx.cc (simplify_immed_subreg): Perform the native_encode_rtx
+	and comparison verification for all FLOAT_MODE_P modes, not just
+	MODE_COMPOSITE_P.
+
+2022-02-15  Richard Biener  <rguenther@suse.de>
+
+	PR tree-optimization/104519
+	* fold-const.cc (multiple_of_p): Remove never true condition.
+	* tree-ssa-loop-niter.cc (number_of_iterations_ne): Use
+	the appropriate types for determining whether the difference
+	of final and base is a multiple of the step.
+
+2022-02-15  Jakub Jelinek  <jakub@redhat.com>
+
+	PR debug/104517
+	* omp-low.cc (task_cpyfns): New variable.
+	(delete_omp_context): Don't call finalize_task_copyfn from here.
+	(create_task_copyfn): Push task_stmt into task_cpyfns.
+	(execute_lower_omp): Call finalize_task_copyfn here on entries from
+	task_cpyfns vector and release the vector.
+
+2022-02-14  Martin Sebor  <msebor@redhat.com>
+
+	PR middle-end/104355
+	* doc/invoke.texi (-Warray-bounds): Update documentation.
+
+2022-02-14  Michael Meissner  <meissner@the-meissners.org>
+
+	PR target/104253
+	* config/rs6000/rs6000.cc (init_float128_ibm): Update the
+	conversion functions used to convert IFmode types.
+
+2022-02-14  Andrew Stubbs  <ams@codesourcery.com>
+
+	* config/gcn/gcn.cc (gcn_expand_reduc_scalar): Use force_reg.
+
+2022-02-14  Richard Biener  <rguenther@suse.de>
+
+	PR tree-optimization/104528
+	* tree-ssa.h (find_released_ssa_name): Declare.
+	* tree-ssa.cc (find_released_ssa_name): Export.
+	* cfgloop.cc (verify_loop_structure): Look for released
+	SSA names in loops nb_iterations.
+	* tree-ssa-dse.cc (pass_dse::execute): Release number of iteration
+	estimates.
+
+2022-02-14  Richard Biener  <rguenther@suse.de>
+
+	PR tree-optimization/104511
+	* tree-ssa-forwprop.cc (simplify_vector_constructor): Avoid
+	touching DFP <-> FP conversions.
+
+2022-02-14  Richard Biener  <rguenther@suse.de>
+
+	PR middle-end/104497
+	* gimplify.cc (gimplify_compound_lval): Make sure the
+	base is a non-register if needed and possible.
+
+2022-02-13  liuhongt  <hongtao.liu@intel.com>
+
+	PR target/103771
+	* match.pd (cond_expr_convert_p): New match.
+	* tree-vect-patterns.cc (gimple_cond_expr_convert_p): Declare.
+	(vect_recog_cond_expr_convert_pattern): New.
+
 2022-02-12  Jakub Jelinek  <jakub@redhat.com>
 
 	PR sanitizer/104449
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 35b6375..07f9f51 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20220213
+20220216
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 3e72eb7..cae3536 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,10 @@
+2022-02-13  Maciej W. Rozycki  <macro@orcam.me.uk>
+
+	PR ada/98724
+	PR ada/97504
+	* Makefile.rtl (LIBGNAT_TARGET_PAIRS) <alpha*-*-linux*>: Use
+	wraplf version of Aux_Long_Long_Float.
+
 2022-01-31  Pierre-Marie de Rodat  <derodat@adacore.com>
 
 	* doc/share/conf.py: Remove spurious call to ".decode()".
diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl
index 6d60aea..aaf853e 100644
--- a/gcc/ada/Makefile.rtl
+++ b/gcc/ada/Makefile.rtl
@@ -2559,6 +2559,7 @@
 ifeq ($(strip $(filter-out alpha% linux%,$(target_cpu) $(target_os))),)
   LIBGNAT_TARGET_PAIRS = \
   a-intnam.ads<libgnarl/a-intnam__linux.ads \
+  a-nallfl.ads<libgnat/a-nallfl__wraplf.ads \
   s-inmaop.adb<libgnarl/s-inmaop__posix.adb \
   s-intman.adb<libgnarl/s-intman__posix.adb \
   s-linux.ads<libgnarl/s-linux__alpha.ads \
diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog
index f5d1243..cab27465 100644
--- a/gcc/analyzer/ChangeLog
+++ b/gcc/analyzer/ChangeLog
@@ -1,3 +1,22 @@
+2022-02-15  David Malcolm  <dmalcolm@redhat.com>
+
+	PR analyzer/104524
+	* region-model-manager.cc
+	(region_model_manager::maybe_fold_sub_svalue): Only call
+	get_or_create_cast if type is non-NULL.
+
+2022-02-15  David Malcolm  <dmalcolm@redhat.com>
+
+	PR analyzer/102692
+	* exploded-graph.h (impl_region_model_context::get_stmt): New.
+	* region-model.cc: Include "gimple-ssa.h", "tree-phinodes.h",
+	"tree-ssa-operands.h", and "ssa-iterators.h".
+	(within_short_circuited_stmt_p): New.
+	(region_model::check_for_poison): Don't warn about uninit values
+	if within_short_circuited_stmt_p.
+	* region-model.h (region_model_context::get_stmt): New vfunc.
+	(noop_region_model_context::get_stmt): New.
+
 2022-02-11  David Malcolm  <dmalcolm@redhat.com>
 
 	PR analyzer/104274
diff --git a/gcc/analyzer/exploded-graph.h b/gcc/analyzer/exploded-graph.h
index 1854193..1f52725 100644
--- a/gcc/analyzer/exploded-graph.h
+++ b/gcc/analyzer/exploded-graph.h
@@ -90,6 +90,8 @@
 		       const state_machine **out_sm,
 		       unsigned *out_sm_idx) FINAL OVERRIDE;
 
+  const gimple *get_stmt () const OVERRIDE { return m_stmt; }
+
   exploded_graph *m_eg;
   log_user m_logger;
   exploded_node *m_enode_for_diag;
diff --git a/gcc/analyzer/region-model-manager.cc b/gcc/analyzer/region-model-manager.cc
index d7156c5..917af22 100644
--- a/gcc/analyzer/region-model-manager.cc
+++ b/gcc/analyzer/region-model-manager.cc
@@ -771,7 +771,7 @@
       if (unary->get_op () == NOP_EXPR
 	  || unary->get_op () == VIEW_CONVERT_EXPR)
 	if (tree cst = unary->get_arg ()->maybe_get_constant ())
-	  if (zerop (cst))
+	  if (zerop (cst) && type)
 	    {
 	      const svalue *cst_sval
 		= get_or_create_constant_svalue (cst);
@@ -786,7 +786,8 @@
 	/* If we have a concrete 1-byte access within the parent region... */
 	byte_range subregion_bytes (0, 0);
 	if (subregion->get_relative_concrete_byte_range (&subregion_bytes)
-	    && subregion_bytes.m_size_in_bytes == 1)
+	    && subregion_bytes.m_size_in_bytes == 1
+	    && type)
 	  {
 	    /* ...then attempt to get that char from the STRING_CST.  */
 	    HOST_WIDE_INT hwi_start_byte
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index e659cf0..69e8fa7 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -68,6 +68,10 @@
 #include "stor-layout.h"
 #include "attribs.h"
 #include "tree-object-size.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
+#include "tree-ssa-operands.h"
+#include "ssa-iterators.h"
 
 #if ENABLE_ANALYZER
 
@@ -829,6 +833,108 @@
     }
 }
 
+/* Workaround for discarding certain false positives from
+   -Wanalyzer-use-of-uninitialized-value
+   of the form:
+     ((A OR-IF B) OR-IF C)
+   and:
+     ((A AND-IF B) AND-IF C)
+   where evaluating B is redundant, but could involve simple accesses of
+   uninitialized locals.
+
+   When optimization is turned on the FE can immediately fold compound
+   conditionals.  Specifically, c_parser_condition parses this condition:
+     ((A OR-IF B) OR-IF C)
+   and calls c_fully_fold on the condition.
+   Within c_fully_fold, fold_truth_andor is called, which bails when
+   optimization is off, but if any optimization is turned on can convert the
+     ((A OR-IF B) OR-IF C)
+   into:
+     ((A OR B) OR_IF C)
+   for sufficiently simple B
+   i.e. the inner OR-IF becomes an OR.
+   At gimplification time the inner OR becomes BIT_IOR_EXPR (in gimplify_expr),
+   giving this for the inner condition:
+      tmp = A | B;
+      if (tmp)
+   thus effectively synthesizing a redundant access of B when optimization
+   is turned on, when compared to:
+      if (A) goto L1; else goto L4;
+  L1: if (B) goto L2; else goto L4;
+  L2: if (C) goto L3; else goto L4;
+   for the unoptimized case.
+
+   Return true if CTXT appears to be  handling such a short-circuitable stmt,
+   such as the def-stmt for B for the:
+      tmp = A | B;
+   case above, for the case where A is true and thus B would have been
+   short-circuited without optimization, using MODEL for the value of A.  */
+
+static bool
+within_short_circuited_stmt_p (const region_model *model,
+			       region_model_context *ctxt)
+{
+  gcc_assert (ctxt);
+  const gimple *curr_stmt = ctxt->get_stmt ();
+  if (curr_stmt == NULL)
+    return false;
+
+  /* We must have an assignment to a temporary of _Bool type.  */
+  const gassign *assign_stmt = dyn_cast <const gassign *> (curr_stmt);
+  if (!assign_stmt)
+    return false;
+  tree lhs = gimple_assign_lhs (assign_stmt);
+  if (TREE_TYPE (lhs) != boolean_type_node)
+    return false;
+  if (TREE_CODE (lhs) != SSA_NAME)
+    return false;
+  if (SSA_NAME_VAR (lhs) != NULL_TREE)
+    return false;
+
+  /* The temporary bool must be used exactly once: as the second arg of
+     a BIT_IOR_EXPR or BIT_AND_EXPR.  */
+  use_operand_p use_op;
+  gimple *use_stmt;
+  if (!single_imm_use (lhs, &use_op, &use_stmt))
+    return false;
+  const gassign *use_assign = dyn_cast <const gassign *> (use_stmt);
+  if (!use_assign)
+    return false;
+  enum tree_code op = gimple_assign_rhs_code (use_assign);
+  if (!(op == BIT_IOR_EXPR ||op == BIT_AND_EXPR))
+    return false;
+  if (!(gimple_assign_rhs1 (use_assign) != lhs
+	&& gimple_assign_rhs2 (use_assign) == lhs))
+    return false;
+
+  /* The first arg of the bitwise stmt must have a known value in MODEL
+     that implies that the value of the second arg doesn't matter, i.e.
+     1 for bitwise or, 0 for bitwise and.  */
+  tree other_arg = gimple_assign_rhs1 (use_assign);
+  /* Use a NULL ctxt here to avoid generating warnings.  */
+  const svalue *other_arg_sval = model->get_rvalue (other_arg, NULL);
+  tree other_arg_cst = other_arg_sval->maybe_get_constant ();
+  if (!other_arg_cst)
+    return false;
+  switch (op)
+    {
+    default:
+      gcc_unreachable ();
+    case BIT_IOR_EXPR:
+      if (zerop (other_arg_cst))
+	return false;
+      break;
+    case BIT_AND_EXPR:
+      if (!zerop (other_arg_cst))
+	return false;
+      break;
+    }
+
+  /* All tests passed.  We appear to be in a stmt that generates a boolean
+     temporary with a value that won't matter.  */
+  return true;
+}
+
 /* Check for SVAL being poisoned, adding a warning to CTXT.
    Return SVAL, or, if a warning is added, another value, to avoid
    repeatedly complaining about the same poisoned value in followup code.  */
@@ -852,6 +958,11 @@
 	  && is_empty_type (sval->get_type ()))
 	return sval;
 
+      /* Special case to avoid certain false positives.  */
+      if (pkind == POISON_KIND_UNINIT
+	  && within_short_circuited_stmt_p (this, ctxt))
+	  return sval;
+
       /* If we have an SSA name for a temporary, we don't want to print
 	 '<unknown>'.
 	 Poisoned values are shared by type, and so we can't reconstruct
diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h
index 46cf37e..c2c89a2 100644
--- a/gcc/analyzer/region-model.h
+++ b/gcc/analyzer/region-model.h
@@ -930,6 +930,9 @@
   virtual bool get_taint_map (sm_state_map **out_smap,
 			      const state_machine **out_sm,
 			      unsigned *out_sm_idx) = 0;
+
+  /* Get the current statement, if any.  */
+  virtual const gimple *get_stmt () const = 0;
 };
 
 /* A "do nothing" subclass of region_model_context.  */
@@ -980,6 +983,8 @@
   {
     return false;
   }
+
+  const gimple *get_stmt () const OVERRIDE { return NULL; }
 };
 
 /* A subclass of region_model_context for determining if operations fail
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 78f6f6f..340e2c0 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,9 @@
+2022-02-14  Richard Biener  <rguenther@suse.de>
+
+	PR c/104505
+	* c-pretty-print.cc (c_pretty_printer::postfix_expression): Handle
+	internal function calls.
+
 2022-02-11  Richard Biener  <rguenther@suse.de>
 
 	* c-attribs.cc (c_common_attribute_table): Add entry for
diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index bf0749b..7203d76 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -3174,7 +3174,11 @@
   else if (real1 && real2
 	   && (DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (primop0)))
 	       || DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (primop1)))))
-    return NULL_TREE;
+    {
+      type = *restype_ptr;
+      primop0 = op0;
+      primop1 = op1;
+    }
 
   else if (real1 && real2
 	   && (TYPE_PRECISION (TREE_TYPE (primop0))
diff --git a/gcc/c-family/c-omp.cc b/gcc/c-family/c-omp.cc
index f5314d6..cd9d866 100644
--- a/gcc/c-family/c-omp.cc
+++ b/gcc/c-family/c-omp.cc
@@ -353,8 +353,13 @@
     }
   bool save = in_late_binary_op;
   in_late_binary_op = true;
-  x = build_modify_expr (loc, blhs ? blhs : lhs, NULL_TREE, opcode,
-			 loc, rhs, NULL_TREE);
+  if ((opcode == MIN_EXPR || opcode == MAX_EXPR)
+      && build_binary_op (loc, LT_EXPR, blhs ? blhs : lhs, rhs,
+			  true) == error_mark_node)
+    x = error_mark_node;
+  else
+    x = build_modify_expr (loc, blhs ? blhs : lhs, NULL_TREE, opcode,
+			   loc, rhs, NULL_TREE);
   in_late_binary_op = save;
   if (x == error_mark_node)
     return error_mark_node;
diff --git a/gcc/c-family/c-pretty-print.cc b/gcc/c-family/c-pretty-print.cc
index ceedaea..dac1775 100644
--- a/gcc/c-family/c-pretty-print.cc
+++ b/gcc/c-family/c-pretty-print.cc
@@ -32,6 +32,7 @@
 #include "selftest.h"
 #include "langhooks.h"
 #include "options.h"
+#include "internal-fn.h"
 
 /* The pretty-printer code is primarily designed to closely follow
    (GNU) C and C++ grammars.  That is to be contrasted with spaghetti
@@ -1601,7 +1602,10 @@
       {
 	call_expr_arg_iterator iter;
 	tree arg;
-	postfix_expression (CALL_EXPR_FN (e));
+	if (CALL_EXPR_FN (e) != NULL_TREE)
+	  postfix_expression (CALL_EXPR_FN (e));
+	else
+	  pp_string (this, internal_fn_name (CALL_EXPR_IFN (e)));
 	pp_c_left_paren (this);
 	FOR_EACH_CALL_EXPR_ARG (arg, iter, e)
 	  {
diff --git a/gcc/cfgloop.cc b/gcc/cfgloop.cc
index 78fd6d5..5ffcc77 100644
--- a/gcc/cfgloop.cc
+++ b/gcc/cfgloop.cc
@@ -31,6 +31,8 @@
 #include "cfgloop.h"
 #include "gimple-iterator.h"
 #include "dumpfile.h"
+#include "tree-ssa.h"
+#include "tree-pretty-print.h"
 
 static void flow_loops_cfg_dump (FILE *);
 
@@ -1561,6 +1563,17 @@
 		err = 1;
 	      }
 	}
+
+      /* Check cached number of iterations for released SSA names.  */
+      tree ref;
+      if (loop->nb_iterations
+	  && (ref = walk_tree (&loop->nb_iterations,
+			       find_released_ssa_name, NULL, NULL)))
+	{
+	  error ("loop %d%'s number of iterations %qE references the"
+		 " released SSA name %qE", i, loop->nb_iterations, ref);
+	  err = 1;
+	}
     }
 
   /* Check irreducible loops.  */
diff --git a/gcc/combine.cc b/gcc/combine.cc
index c4c5444..8f06ee0 100644
--- a/gcc/combine.cc
+++ b/gcc/combine.cc
@@ -4223,10 +4223,12 @@
 	  for (rtx_insn *insn = NEXT_INSN (i3);
 	       !done
 	       && insn
-	       && NONDEBUG_INSN_P (insn)
+	       && INSN_P (insn)
 	       && BLOCK_FOR_INSN (insn) == this_basic_block;
 	       insn = NEXT_INSN (insn))
 	    {
+	      if (DEBUG_INSN_P (insn))
+		continue;
 	      struct insn_link *link;
 	      FOR_EACH_LOG_LINK (link, insn)
 		if (link->insn == i3 && link->regno == regno)
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 392efa0..d0e78d6 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -939,6 +939,7 @@
 				   aarch64_addr_query_type = ADDR_QUERY_M);
 machine_mode aarch64_select_cc_mode (RTX_CODE, rtx, rtx);
 rtx aarch64_gen_compare_reg (RTX_CODE, rtx, rtx);
+bool aarch64_maxmin_plus_const (rtx_code, rtx *, bool);
 rtx aarch64_load_tp (rtx);
 
 void aarch64_expand_compare_and_swap (rtx op[]);
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index e3f18fb..37ed22b 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -3781,6 +3781,110 @@
   return aarch64_gen_compare_reg (code, x, y);
 }
 
+/* Consider the operation:
+
+     OPERANDS[0] = CODE (OPERANDS[1], OPERANDS[2]) + OPERANDS[3]
+
+   where:
+
+   - CODE is [SU]MAX or [SU]MIN
+   - OPERANDS[2] and OPERANDS[3] are constant integers
+   - OPERANDS[3] is a positive or negative shifted 12-bit immediate
+   - all operands have mode MODE
+
+   Decide whether it is possible to implement the operation using:
+
+     SUBS <tmp>, OPERANDS[1], -OPERANDS[3]
+     or
+     ADDS <tmp>, OPERANDS[1], OPERANDS[3]
+
+   followed by:
+
+     <insn> OPERANDS[0], <tmp>, [wx]zr, <cond>
+
+   where <insn> is one of CSEL, CSINV or CSINC.  Return true if so.
+   If GENERATE_P is true, also update OPERANDS as follows:
+
+     OPERANDS[4] = -OPERANDS[3]
+     OPERANDS[5] = the rtl condition representing <cond>
+     OPERANDS[6] = <tmp>
+     OPERANDS[7] = 0 for CSEL, -1 for CSINV or 1 for CSINC.  */
+bool
+aarch64_maxmin_plus_const (rtx_code code, rtx *operands, bool generate_p)
+{
+  signop sgn = (code == UMAX || code == UMIN ? UNSIGNED : SIGNED);
+  rtx dst = operands[0];
+  rtx maxmin_op = operands[2];
+  rtx add_op = operands[3];
+  machine_mode mode = GET_MODE (dst);
+
+  /* max (x, y) - z == (x >= y + 1 ? x : y) - z
+		    == (x >= y ? x : y) - z
+		    == (x > y ? x : y) - z
+		    == (x > y - 1 ? x : y) - z
+
+     min (x, y) - z == (x <= y - 1 ? x : y) - z
+		    == (x <= y ? x : y) - z
+		    == (x < y ? x : y) - z
+		    == (x < y + 1 ? x : y) - z
+
+     Check whether z is in { y - 1, y, y + 1 } and pick the form(s) for
+     which x is compared with z.  Set DIFF to y - z.  Thus the supported
+     combinations are as follows, with DIFF being the value after the ":":
+
+     max (x, y) - z == x >= y + 1 ? x - (y + 1) : -1   [z == y + 1]
+		    == x >= y ? x - y : 0              [z == y]
+		    == x > y ? x - y : 0               [z == y]
+		    == x > y - 1 ? x - (y - 1) : 1     [z == y - 1]
+
+     min (x, y) - z == x <= y - 1 ? x - (y - 1) : 1    [z == y - 1]
+		    == x <= y ? x - y : 0              [z == y]
+		    == x < y ? x - y : 0               [z == y]
+		    == x < y + 1 ? x - (y + 1) : -1    [z == y + 1].  */
+  auto maxmin_val = rtx_mode_t (maxmin_op, mode);
+  auto add_val = rtx_mode_t (add_op, mode);
+  auto sub_val = wi::neg (add_val);
+  auto diff = wi::sub (maxmin_val, sub_val);
+  if (!(diff == 0
+	|| (diff == 1 && wi::gt_p (maxmin_val, sub_val, sgn))
+	|| (diff == -1 && wi::lt_p (maxmin_val, sub_val, sgn))))
+    return false;
+
+  if (!generate_p)
+    return true;
+
+  rtx_code cmp;
+  switch (code)
+    {
+    case SMAX:
+      cmp = diff == 1 ? GT : GE;
+      break;
+    case UMAX:
+      cmp = diff == 1 ? GTU : GEU;
+      break;
+    case SMIN:
+      cmp = diff == -1 ? LT : LE;
+      break;
+    case UMIN:
+      cmp = diff == -1 ? LTU : LEU;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  rtx cc = gen_rtx_REG (CCmode, CC_REGNUM);
+
+  operands[4] = immed_wide_int_const (sub_val, mode);
+  operands[5] = gen_rtx_fmt_ee (cmp, VOIDmode, cc, const0_rtx);
+  if (can_create_pseudo_p ())
+    operands[6] = gen_reg_rtx (mode);
+  else
+    operands[6] = dst;
+  operands[7] = immed_wide_int_const (diff, mode);
+
+  return true;
+}
+
+
 /* Build the SYMBOL_REF for __tls_get_addr.  */
 
 static GTY(()) rtx tls_get_addr_libfunc;
@@ -14932,6 +15036,31 @@
      - If M_VEC_FLAGS & VEC_ANY_SVE is nonzero then we're costing SVE code.  */
   unsigned int m_vec_flags = 0;
 
+  /* At the moment, we do not model LDP and STP in the vector and scalar costs.
+     This means that code such as:
+
+	a[0] = x;
+	a[1] = x;
+
+     will be costed as two scalar instructions and two vector instructions
+     (a scalar_to_vec and an unaligned_store).  For SLP, the vector form
+     wins if the costs are equal, because of the fact that the vector costs
+     include constant initializations whereas the scalar costs don't.
+     We would therefore tend to vectorize the code above, even though
+     the scalar version can use a single STP.
+
+     We should eventually fix this and model LDP and STP in the main costs;
+     see the comment in aarch64_sve_adjust_stmt_cost for some of the problems.
+     Until then, we look specifically for code that does nothing more than
+     STP-like operations.  We cost them on that basis in addition to the
+     normal latency-based costs.
+
+     If the scalar or vector code could be a sequence of STPs +
+     initialization, this variable counts the cost of the sequence,
+     with 2 units per instruction.  The variable is ~0U for other
+     kinds of code.  */
+  unsigned int m_stp_sequence_cost = 0;
+
   /* On some CPUs, SVE and Advanced SIMD provide the same theoretical vector
      throughput, such as 4x128 Advanced SIMD vs. 2x256 SVE.  In those
      situations, we try to predict whether an Advanced SIMD implementation
@@ -15724,6 +15853,104 @@
     }
 }
 
+/* Return true if STMT_INFO contains a memory access and if the constant
+   component of the memory address is aligned to SIZE bytes.  */
+static bool
+aarch64_aligned_constant_offset_p (stmt_vec_info stmt_info,
+				   poly_uint64 size)
+{
+  if (!STMT_VINFO_DATA_REF (stmt_info))
+    return false;
+
+  if (auto first_stmt = DR_GROUP_FIRST_ELEMENT (stmt_info))
+    stmt_info = first_stmt;
+  tree constant_offset = DR_INIT (STMT_VINFO_DATA_REF (stmt_info));
+  /* Needed for gathers & scatters, for example.  */
+  if (!constant_offset)
+    return false;
+
+  return multiple_p (wi::to_poly_offset (constant_offset), size);
+}
+
+/* Check if a scalar or vector stmt could be part of a region of code
+   that does nothing more than store values to memory, in the scalar
+   case using STP.  Return the cost of the stmt if so, counting 2 for
+   one instruction.  Return ~0U otherwise.
+
+   The arguments are a subset of those passed to add_stmt_cost.  */
+unsigned int
+aarch64_stp_sequence_cost (unsigned int count, vect_cost_for_stmt kind,
+			   stmt_vec_info stmt_info, tree vectype)
+{
+  /* Code that stores vector constants uses a vector_load to create
+     the constant.  We don't apply the heuristic to that case for two
+     main reasons:
+
+     - At the moment, STPs are only formed via peephole2, and the
+       constant scalar moves would often come between STRs and so
+       prevent STP formation.
+
+     - The scalar code also has to load the constant somehow, and that
+       isn't costed.  */
+  switch (kind)
+    {
+    case scalar_to_vec:
+      /* Count 2 insns for a GPR->SIMD dup and 1 insn for a FPR->SIMD dup.  */
+      return (FLOAT_TYPE_P (vectype) ? 2 : 4) * count;
+
+    case vec_construct:
+      if (FLOAT_TYPE_P (vectype))
+	/* Count 1 insn for the maximum number of FP->SIMD INS
+	   instructions.  */
+	return (vect_nunits_for_cost (vectype) - 1) * 2 * count;
+
+      /* Count 2 insns for a GPR->SIMD move and 2 insns for the
+	 maximum number of GPR->SIMD INS instructions.  */
+      return vect_nunits_for_cost (vectype) * 4 * count;
+
+    case vector_store:
+    case unaligned_store:
+      /* Count 1 insn per vector if we can't form STP Q pairs.  */
+      if (aarch64_sve_mode_p (TYPE_MODE (vectype)))
+	return count * 2;
+      if (aarch64_tune_params.extra_tuning_flags
+	  & AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS)
+	return count * 2;
+
+      if (stmt_info)
+	{
+	  /* Assume we won't be able to use STP if the constant offset
+	     component of the address is misaligned.  ??? This could be
+	     removed if we formed STP pairs earlier, rather than relying
+	     on peephole2.  */
+	  auto size = GET_MODE_SIZE (TYPE_MODE (vectype));
+	  if (!aarch64_aligned_constant_offset_p (stmt_info, size))
+	    return count * 2;
+	}
+      return CEIL (count, 2) * 2;
+
+    case scalar_store:
+      if (stmt_info && STMT_VINFO_DATA_REF (stmt_info))
+	{
+	  /* Check for a mode in which STP pairs can be formed.  */
+	  auto size = GET_MODE_SIZE (TYPE_MODE (aarch64_dr_type (stmt_info)));
+	  if (maybe_ne (size, 4) && maybe_ne (size, 8))
+	    return ~0U;
+
+	  /* Assume we won't be able to use STP if the constant offset
+	     component of the address is misaligned.  ??? This could be
+	     removed if we formed STP pairs earlier, rather than relying
+	     on peephole2.  */
+	  if (!aarch64_aligned_constant_offset_p (stmt_info, size))
+	    return ~0U;
+	}
+      return count;
+
+    default:
+      return ~0U;
+    }
+}
+
 unsigned
 aarch64_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind,
 				     stmt_vec_info stmt_info, tree vectype,
@@ -15747,6 +15974,14 @@
       m_analyzed_vinfo = true;
     }
 
+  /* Apply the heuristic described above m_stp_sequence_cost.  */
+  if (m_stp_sequence_cost != ~0U)
+    {
+      uint64_t cost = aarch64_stp_sequence_cost (count, kind,
+						 stmt_info, vectype);
+      m_stp_sequence_cost = MIN (m_stp_sequence_cost + cost, ~0U);
+    }
+
   /* Try to get a more accurate cost by looking at STMT_INFO instead
      of just looking at KIND.  */
   if (stmt_info && aarch64_use_new_vector_costs_p ())
@@ -16017,6 +16252,15 @@
     m_costs[vect_body] = adjust_body_cost (loop_vinfo, scalar_costs,
 					   m_costs[vect_body]);
 
+  /* Apply the heuristic described above m_stp_sequence_cost.  Prefer
+     the scalar code in the event of a tie, since there is more chance
+     of scalar code being optimized with surrounding operations.  */
+  if (!loop_vinfo
+      && scalar_costs
+      && m_stp_sequence_cost != ~0U
+      && m_stp_sequence_cost >= scalar_costs->m_stp_sequence_cost)
+    m_costs[vect_body] = 2 * scalar_costs->total_cost ();
+
   vector_costs::finish_cost (scalar_costs);
 }
 
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 3c72bda..5909184 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -4405,6 +4405,33 @@
   }
 )
 
+;; Implement MAX/MIN (A, B) - C using SUBS/ADDS followed by CSEL/CSINV/CSINC.
+;; See aarch64_maxmin_plus_const for details about the supported cases.
+(define_insn_and_split "*aarch64_minmax_plus"
+  [(set (match_operand:GPI 0 "register_operand" "=r")
+	(plus:GPI
+	  (MAXMIN:GPI
+	    (match_operand:GPI 1 "register_operand" "r")
+	    (match_operand:GPI 2 "const_int_operand"))
+	  (match_operand:GPI 3 "aarch64_plus_immediate")))
+   (clobber (reg:CC CC_REGNUM))]
+  "aarch64_maxmin_plus_const (<CODE>, operands, false)"
+  "#"
+  "&& 1"
+  [(parallel
+     [(set (reg:CC CC_REGNUM)
+	   (compare:CC (match_dup 1) (match_dup 4)))
+      (set (match_dup 6)
+	   (plus:GPI (match_dup 1) (match_dup 3)))])
+   (set (match_dup 0)
+	(if_then_else:GPI (match_dup 5) (match_dup 6) (match_dup 7)))]
+  {
+    if (!aarch64_maxmin_plus_const (<CODE>, operands, true))
+      gcc_unreachable ();
+  }
+  [(set_attr "length" "8")]
+)
+
 ;; -------------------------------------------------------------------
 ;; Logical operations
 ;; -------------------------------------------------------------------
@@ -4531,7 +4558,7 @@
 
 (define_split
   [(set (match_operand:GPI 0 "register_operand")
-	(LOGICAL:GPI
+	(LOGICAL_OR_PLUS:GPI
 	  (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand")
 			       (match_operand:QI 2 "aarch64_shift_imm_<mode>"))
 		   (match_operand:GPI 3 "const_int_operand"))
@@ -4544,16 +4571,23 @@
 	   && REGNO (operands[1]) == REGNO (operands[4])))
    && (trunc_int_for_mode (GET_MODE_MASK (GET_MODE (operands[4]))
 			   << INTVAL (operands[2]), <MODE>mode)
-       == INTVAL (operands[3]))"
+       == INTVAL (operands[3]))
+   && (<CODE> != PLUS
+       || (GET_MODE_MASK (GET_MODE (operands[4]))
+	   & INTVAL (operands[3])) == 0)"
   [(set (match_dup 5) (zero_extend:GPI (match_dup 4)))
-   (set (match_dup 0) (LOGICAL:GPI (ashift:GPI (match_dup 5) (match_dup 2))
-				   (match_dup 5)))]
-  "operands[5] = gen_reg_rtx (<MODE>mode);"
+   (set (match_dup 0) (match_dup 6))]
+  {
+    operands[5] = gen_reg_rtx (<MODE>mode);
+    rtx shift = gen_rtx_ASHIFT (<MODE>mode, operands[5], operands[2]);
+    rtx_code new_code = (<CODE> == PLUS ? IOR : <CODE>);
+    operands[6] = gen_rtx_fmt_ee (new_code, <MODE>mode, shift, operands[5]);
+  }
 )
 
 (define_split
   [(set (match_operand:GPI 0 "register_operand")
-	(LOGICAL:GPI
+	(LOGICAL_OR_PLUS:GPI
 	  (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand")
 			       (match_operand:QI 2 "aarch64_shift_imm_<mode>"))
 		   (match_operand:GPI 4 "const_int_operand"))
@@ -4562,11 +4596,17 @@
    && pow2_or_zerop (UINTVAL (operands[3]) + 1)
    && (trunc_int_for_mode (UINTVAL (operands[3])
 			   << INTVAL (operands[2]), <MODE>mode)
-       == INTVAL (operands[4]))"
+       == INTVAL (operands[4]))
+   && (<CODE> != PLUS
+       || (INTVAL (operands[4]) & INTVAL (operands[3])) == 0)"
   [(set (match_dup 5) (and:GPI (match_dup 1) (match_dup 3)))
-   (set (match_dup 0) (LOGICAL:GPI (ashift:GPI (match_dup 5) (match_dup 2))
-				   (match_dup 5)))]
-  "operands[5] = gen_reg_rtx (<MODE>mode);"
+   (set (match_dup 0) (match_dup 6))]
+  {
+    operands[5] = gen_reg_rtx (<MODE>mode);
+    rtx shift = gen_rtx_ASHIFT (<MODE>mode, operands[5], operands[2]);
+    rtx_code new_code = (<CODE> == PLUS ? IOR : <CODE>);
+    operands[6] = gen_rtx_fmt_ee (new_code, <MODE>mode, shift, operands[5]);
+  }
 )
 
 (define_split
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index 88067a3..e72fdf35 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -2122,6 +2122,9 @@
 ;; Code iterator for logical operations
 (define_code_iterator LOGICAL [and ior xor])
 
+;; LOGICAL with plus, for when | gets converted to +.
+(define_code_iterator LOGICAL_OR_PLUS [and ior xor plus])
+
 ;; LOGICAL without AND.
 (define_code_iterator LOGICAL_OR [ior xor])
 
diff --git a/gcc/config/gcn/gcn.cc b/gcc/config/gcn/gcn.cc
index 74819c6..402f025 100644
--- a/gcc/config/gcn/gcn.cc
+++ b/gcc/config/gcn/gcn.cc
@@ -4460,7 +4460,7 @@
      pair of lanes, then on every pair of results from the previous
      iteration (thereby effectively reducing every 4 lanes) and so on until
      all lanes are reduced.  */
-  rtx in, out = src;
+  rtx in, out = force_reg (mode, src);
   for (int i = 0, shift = 1; i < 6; i++, shift <<= 1)
     {
       rtx shift_val = gen_rtx_CONST_INT (VOIDmode, shift);
diff --git a/gcc/config/i386/host-cygwin.cc b/gcc/config/i386/host-cygwin.cc
index fcf6333..05ad3a8 100644
--- a/gcc/config/i386/host-cygwin.cc
+++ b/gcc/config/i386/host-cygwin.cc
@@ -51,18 +51,18 @@
 cygwin_gt_pch_get_address (size_t sz, int fd)
 {
   void *base;
-  off_t p = lseek(fd, 0, SEEK_CUR);
+  off_t p = lseek (fd, 0, SEEK_CUR);
 
   if (p == (off_t) -1)
-    fatal_error (input_location, "can%'t get position in PCH file: %m");
+    fatal_error (input_location, "cannot get position in PCH file: %m");
 
    /* Cygwin requires that the underlying file be at least
       as large as the requested mapping.  */
   if ((size_t) p < sz)
-  { 
-    if ( ftruncate (fd, sz) == -1 )
-      fatal_error (input_location, "can%'t extend PCH file: %m");
-  }
+    { 
+      if (ftruncate (fd, sz) == -1)
+	fatal_error (input_location, "cannot extend PCH file: %m");
+    }
 
   base = mmap (NULL, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
 
@@ -71,8 +71,8 @@
   else
     munmap (base, sz);
 
-  if (lseek (fd, p, SEEK_SET) == (off_t) -1 )
-    fatal_error (input_location, "can%'t set position in PCH file: %m");
+  if (lseek (fd, p, SEEK_SET) == (off_t) -1)
+    fatal_error (input_location, "cannot set position in PCH file: %m");
 
   return base;
 }
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index bc3ef072..e76c017 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -11018,6 +11018,12 @@
       set_conv_libfunc (trunc_optab, DDmode, mode, "__dpd_trunctfdd");
       set_conv_libfunc (sext_optab, TDmode, mode, "__dpd_extendtftd");
 
+      set_conv_libfunc (sfix_optab, DImode, mode, "__fixtfdi");
+      set_conv_libfunc (ufix_optab, DImode, mode, "__fixunstfdi");
+
+      set_conv_libfunc (sfloat_optab, mode, DImode, "__floatditf");
+      set_conv_libfunc (ufloat_optab, mode, DImode, "__floatunditf");
+
       if (TARGET_POWERPC64)
 	{
 	  set_conv_libfunc (sfix_optab, TImode, mode, "__fixtfti");
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1db66a7..90d4a79 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,19 @@
+2022-02-15  Jason Merrill  <jason@redhat.com>
+
+	PR c++/104107
+	PR c++/95036
+	* pt.cc (coerce_template_template_parms): Take full parms.
+	Avoid adding too much of outer_args.
+	(coerce_template_template_parm): Adjust.
+	(template_template_parm_bindings_ok_p): Adjust.
+	(convert_template_argument): Adjust.
+
+2022-02-14  Jakub Jelinek  <jakub@redhat.com>
+
+	PR c++/104513
+	* constexpr.cc (potential_constant_expression_1) <case GOTO_EXPR>:
+	Don't punt if returns (target).
+
 2022-02-11  Jakub Jelinek  <jakub@redhat.com>
 
 	PR c++/104472
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 87f3a7b..4716694 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -9065,6 +9065,14 @@
     case BIND_EXPR:
       return RECUR (BIND_EXPR_BODY (t), want_rval);
 
+    case NON_DEPENDENT_EXPR:
+      /* Treat NON_DEPENDENT_EXPR as non-constant: it's not handled by
+	 constexpr evaluation or tsubst, so fold_non_dependent_expr can't
+	 do anything useful with it.  And we shouldn't see it in a context
+	 where a constant expression is strictly required, hence the assert.  */
+      gcc_checking_assert (!(flags & tf_error));
+      return false;
+
     case CLEANUP_POINT_EXPR:
     case MUST_NOT_THROW_EXPR:
     case TRY_CATCH_EXPR:
@@ -9072,7 +9080,6 @@
     case EH_SPEC_BLOCK:
     case EXPR_STMT:
     case PAREN_EXPR:
-    case NON_DEPENDENT_EXPR:
       /* For convenience.  */
     case LOOP_EXPR:
     case EXIT_EXPR:
@@ -9363,8 +9370,8 @@
     case GOTO_EXPR:
       {
 	tree *target = &TREE_OPERAND (t, 0);
-	/* Gotos representing break and continue are OK.  */
-	if (breaks (target) || continues (target))
+	/* Gotos representing break, continue and cdtor return are OK.  */
+	if (breaks (target) || continues (target) || returns (target))
 	  {
 	    *jump_target = *target;
 	    return true;
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 1b18e2a..6dda660 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -7731,8 +7731,8 @@
 	 template <template <template <class> class> class TT>
 	 class C;  */
       {
-	tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
-	tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
+	tree parmparm = DECL_TEMPLATE_PARMS (parm);
+	tree argparm = DECL_TEMPLATE_PARMS (arg);
 
 	if (!coerce_template_template_parms
 	    (parmparm, argparm, complain, in_decl, outer_args))
@@ -8001,8 +8001,8 @@
    the parameters to A, and OUTER_ARGS contains A.  */
 
 static int
-coerce_template_template_parms (tree parm_parms,
-				tree arg_parms,
+coerce_template_template_parms (tree parm_parms_full,
+				tree arg_parms_full,
 				tsubst_flags_t complain,
 				tree in_decl,
 				tree outer_args)
@@ -8011,6 +8011,9 @@
   tree parm, arg;
   int variadic_p = 0;
 
+  tree parm_parms = INNERMOST_TEMPLATE_PARMS (parm_parms_full);
+  tree arg_parms = INNERMOST_TEMPLATE_PARMS (arg_parms_full);
+
   gcc_assert (TREE_CODE (parm_parms) == TREE_VEC);
   gcc_assert (TREE_CODE (arg_parms) == TREE_VEC);
 
@@ -8046,8 +8049,26 @@
 	 specialized as P, so they match.*/
       processing_template_decl_sentinel ptds (/*reset*/false);
       ++processing_template_decl;
+
       tree pargs = template_parms_level_to_args (parm_parms);
-      pargs = add_outermost_template_args (outer_args, pargs);
+
+      /* PARM, and thus the context in which we are passing ARG to it, may be
+	 at a deeper level than ARG; when trying to coerce to ARG_PARMS, we
+	 want to provide the right number of levels, so we reduce the number of
+	 levels in OUTER_ARGS before prepending them.  This is most important
+	 when ARG is a namespace-scope template, as in alias-decl-ttp2.C.
+
+	 ARG might also be deeper than PARM (ttp23).  In that case, we include
+	 all of OUTER_ARGS.  The missing levels seem potentially problematic,
+	 but I can't come up with a testcase that breaks.  */
+      if (int arg_outer_levs = TMPL_PARMS_DEPTH (arg_parms_full) - 1)
+	{
+	  auto x = make_temp_override (TREE_VEC_LENGTH (outer_args));
+	  if (TMPL_ARGS_DEPTH (outer_args) > arg_outer_levs)
+	    TREE_VEC_LENGTH (outer_args) = arg_outer_levs;
+	  pargs = add_to_template_args (outer_args, pargs);
+	}
+
       pargs = coerce_template_parms (arg_parms, pargs, NULL_TREE, tf_none,
 				     /*require_all*/true, /*use_default*/true);
       if (pargs != error_mark_node)
@@ -8186,16 +8207,16 @@
 	      /* Extract the template parameters from the template
 		 argument.  */
 	      if (TREE_CODE (targ) == TEMPLATE_DECL)
-		targ_parms = DECL_INNERMOST_TEMPLATE_PARMS (targ);
+		targ_parms = DECL_TEMPLATE_PARMS (targ);
 	      else if (TREE_CODE (targ) == TEMPLATE_TEMPLATE_PARM)
-		targ_parms = DECL_INNERMOST_TEMPLATE_PARMS (TYPE_NAME (targ));
+		targ_parms = DECL_TEMPLATE_PARMS (TYPE_NAME (targ));
 
 	      /* Verify that we can coerce the template template
 		 parameters from the template argument to the template
 		 parameter.  This requires an exact match.  */
 	      if (targ_parms
 		  && !coerce_template_template_parms
-		       (DECL_INNERMOST_TEMPLATE_PARMS (tparm),
+		       (DECL_TEMPLATE_PARMS (tparm),
 			targ_parms,
 			tf_none,
 			tparm,
@@ -8489,13 +8510,13 @@
 	    val = orig_arg;
 	  else
 	    {
-	      tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
+	      tree parmparm = DECL_TEMPLATE_PARMS (parm);
 	      tree argparm;
 
 	      /* Strip alias templates that are equivalent to another
 		 template.  */
 	      arg = get_underlying_template (arg);
-              argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
+	      argparm = DECL_TEMPLATE_PARMS (arg);
 
 	      if (coerce_template_template_parms (parmparm, argparm,
 						  complain, in_decl,
diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc
index 44a0db64..73b4766 100644
--- a/gcc/d/d-builtins.cc
+++ b/gcc/d/d-builtins.cc
@@ -543,7 +543,7 @@
 	   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) ? PURE::strong
+      tf->purity = DECL_PURE_P (decl) ? PURE::const_
 	: TREE_READONLY (decl) ? PURE::const_
 	: DECL_IS_NOVOPS (decl) ? PURE::weak
 	: !DECL_ASSEMBLER_NAME_SET_P (decl) ? PURE::weak
diff --git a/gcc/d/d-gimplify.cc b/gcc/d/d-gimplify.cc
index fbeb607..a98089b7 100644
--- a/gcc/d/d-gimplify.cc
+++ b/gcc/d/d-gimplify.cc
@@ -62,6 +62,18 @@
   return empty_aggregate_p (type);
 }
 
+/* Return TRUE if EXPR is a COMPONENT_REF to a bit-field declaration.  */
+
+static bool
+bit_field_ref (const_tree expr)
+{
+  if (TREE_CODE (expr) == COMPONENT_REF
+      && DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))
+    return true;
+
+  return false;
+}
+
 /* Gimplify assignment from an INIT_EXPR or MODIFY_EXPR.  */
 
 static gimplify_status
@@ -96,6 +108,13 @@
       return GS_OK;
     }
 
+  /* Same as above, but for bit-field assignments.  */
+  if (bit_field_ref (op0) && TREE_TYPE (op0) != TREE_TYPE (op1))
+    {
+      TREE_OPERAND (*expr_p, 1) = convert (TREE_TYPE (op0), op1);
+      return GS_OK;
+    }
+
   return GS_UNHANDLED;
 }
 
@@ -178,6 +197,54 @@
   return GS_OK;
 }
 
+/* Gimplify an unary expression node.  */
+
+static gimplify_status
+d_gimplify_unary_expr (tree *expr_p)
+{
+  tree op0 = TREE_OPERAND (*expr_p, 0);
+
+  if (error_operand_p (op0))
+    return GS_UNHANDLED;
+
+  /* Front end doesn't know that bit-field types are really different
+     from basic types, add an explicit conversion in unary expressions.  */
+  if (bit_field_ref (op0) && TREE_TYPE (op0) != TREE_TYPE (*expr_p))
+    {
+      TREE_OPERAND (*expr_p, 0) = convert (TREE_TYPE (*expr_p), op0);
+      return GS_OK;
+    }
+
+  return GS_UNHANDLED;
+}
+
+/* Gimplify a binary expression node.  */
+
+static gimplify_status
+d_gimplify_binary_expr (tree *expr_p)
+{
+  tree op0 = TREE_OPERAND (*expr_p, 0);
+  tree op1 = TREE_OPERAND (*expr_p, 1);
+
+  if (error_operand_p (op0) || error_operand_p (op1))
+    return GS_UNHANDLED;
+
+  /* Front end doesn't know that bit-field types are really different
+     from basic types, add an explicit conversion in binary expressions.  */
+  if (bit_field_ref (op0) || bit_field_ref (op1))
+    {
+      if (TREE_TYPE (op0) != TREE_TYPE (*expr_p))
+    	TREE_OPERAND (*expr_p, 0) = convert (TREE_TYPE (*expr_p), op0);
+
+      if (TREE_TYPE (op1) != TREE_TYPE (*expr_p))
+    	TREE_OPERAND (*expr_p, 1) = convert (TREE_TYPE (*expr_p), op1);
+
+      return GS_OK;
+    }
+
+  return GS_UNHANDLED;
+}
+
 /* Implements the lang_hooks.gimplify_expr routine for language D.
    Do gimplification of D specific expression trees in EXPR_P.  */
 
@@ -203,6 +270,10 @@
       gcc_unreachable ();
 
     default:
+      if (UNARY_CLASS_P (*expr_p) && !CONVERT_EXPR_P (*expr_p))
+	return d_gimplify_unary_expr (expr_p);
+      if (BINARY_CLASS_P (*expr_p))
+	return d_gimplify_binary_expr (expr_p);
       break;
     }
 
diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc
index 87cb48f6..02f7b74 100644
--- a/gcc/d/d-target.cc
+++ b/gcc/d/d-target.cc
@@ -161,6 +161,8 @@
   this->c.longsize = int_size_in_bytes (long_integer_type_node);
   this->c.long_doublesize = int_size_in_bytes (long_double_type_node);
   this->c.wchar_tsize = (WCHAR_TYPE_SIZE / BITS_PER_UNIT);
+  this->c.bitFieldStyle = targetm.ms_bitfield_layout_p (unknown_type_node)
+    ? TargetC::BitFieldStyle::MS : TargetC::BitFieldStyle::Gcc_Clang;
 
   /* Set-up target C++ ABI.  */
   this->cpp.reverseOverloads = false;
@@ -379,32 +381,21 @@
    ARG to an extern(C++) function.  */
 
 Type *
-TargetCPP::parameterType (Parameter *arg)
+TargetCPP::parameterType (Type *type)
 {
-  Type *t = arg->type->merge2 ();
-  if (arg->storageClass & (STCout | STCref))
-    t = t->referenceTo ();
-  else if (arg->storageClass & STClazy)
-    {
-      /* Mangle as delegate.  */
-      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 == TY::Tsarray && tvalist->ty == TY::Tsarray)
+  if (type->ty == TY::Tsarray && tvalist->ty == TY::Tsarray)
     {
-      Type *tb = t->toBasetype ()->mutableOf ();
+      Type *tb = type->toBasetype ()->mutableOf ();
       if (tb == tvalist)
 	{
-	  tb = t->nextOf ()->pointerTo ();
-	  t = tb->castMod (t->mod);
+	  tb = type->nextOf ()->pointerTo ();
+	  type = tb->castMod (type->mod);
 	}
     }
 
-  return t;
+  return type;
 }
 
 /* Checks whether TYPE is a vendor-specific fundamental type.  Stores the result
@@ -579,6 +570,14 @@
   return true;
 }
 
+/* Returns true if the target supports `pragma(linkerDirective)'.  */
+
+bool
+Target::supportsLinkerDirective (void) const
+{
+  return false;
+}
+
 /* 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.  */
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 5915706..91cdc9f 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-001bfd97b0e75423970260dac54f453be9b57f4c
+52844d4b1e9d6714bfd2e535f25a72074a046209
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/README.md b/gcc/d/dmd/README.md
index 6b91e22..f613ab2 100644
--- a/gcc/d/dmd/README.md
+++ b/gcc/d/dmd/README.md
@@ -33,6 +33,7 @@
 |-----------------------------------------------------------------------------|-----------------------------------------------------------------------|
 | [mars.d](https://github.com/dlang/dmd/blob/master/src/dmd/mars.d)           | The entry point. Contains `main`.                                     |
 | [cli.d](https://github.com/dlang/dmd/blob/master/src/dmd/cli.d)             | Define the command line interface                                     |
+| [dmdparams.d](https://github.com/dlang/dmd/blob/master/src/dmd/dmdparams.d) | DMD-specific parameters                                               |
 | [globals.d](https://github.com/dlang/dmd/blob/master/src/dmd/globals.d)     | Define a structure storing command line options                       |
 | [dinifile.d](https://github.com/dlang/dmd/blob/master/src/dmd/dinifile.d)   | Parse settings from .ini file (`sc.ini` / `dmd.conf`)                 |
 | [vsoptions.d](https://github.com/dlang/dmd/blob/master/src/dmd/vsoptions.d) | Detect the Microsoft Visual Studio toolchain for linking              |
diff --git a/gcc/d/dmd/access.d b/gcc/d/dmd/access.d
index 51ef049..59c77adf 100644
--- a/gcc/d/dmd/access.d
+++ b/gcc/d/dmd/access.d
@@ -51,15 +51,7 @@
 
     if (!symbolIsVisible(sc, smember))
     {
-        // when in @safe code or with -preview=dip1000
-        if (sc.flags & SCOPE.onlysafeaccess)
-        {
-            // if there is a func. ask for it's opinion of safety, and if it considers the access @safe accept it.
-            if (sc.func && !sc.func.setUnsafe())
-                return false;
-        }
-
-        ad.error(loc, "%s `%s` is not accessible%s", smember.kind(), smember.toChars(), (sc.flags & SCOPE.onlysafeaccess) ? " from `@safe` code".ptr : "".ptr);
+        ad.error(loc, "%s `%s` is not accessible", smember.kind(), smember.toChars());
         //printf("smember = %s %s, vis = %d, semanticRun = %d\n",
         //        smember.kind(), smember.toPrettyChars(), smember.visible() smember.semanticRun);
         return true;
diff --git a/gcc/d/dmd/astenums.d b/gcc/d/dmd/astenums.d
index 3e86cfa..ea10c4e 100644
--- a/gcc/d/dmd/astenums.d
+++ b/gcc/d/dmd/astenums.d
@@ -134,6 +134,8 @@
 
 }
 
+alias StorageClass = ulong;
+
 /********
  * Determine if it's the ambigous case of where `return` attaches to.
  * Params:
@@ -302,8 +304,7 @@
     impure      = 0,    // not pure at all
     fwdref      = 1,    // it's pure, but not known which level yet
     weak        = 2,    // no mutable globals are read or written
-    const_      = 3,    // parameters are values or const
-    strong      = 4,    // parameters are values or immutable
+    const_      = 3,    // parameters are values or const = strongly pure
 }
 
 // Whether alias this dependency is recursive or not
@@ -389,3 +390,43 @@
     C_,
 }
 
+/// A linkage attribute as defined by `extern(XXX)`
+///
+/// https://dlang.org/spec/attribute.html#linkage
+enum LINK : ubyte
+{
+    default_,
+    d,
+    c,
+    cpp,
+    windows,
+    objc,
+    system,
+}
+
+/// Whether to mangle an external aggregate as a struct or class, as set by `extern(C++, struct)`
+enum CPPMANGLE : ubyte
+{
+    def,      /// default
+    asStruct, /// `extern(C++, struct)`
+    asClass,  /// `extern(C++, class)`
+}
+
+/// Function match levels
+///
+/// https://dlang.org/spec/function.html#function-overloading
+enum MATCH : int
+{
+    nomatch,   /// no match
+    convert,   /// match with conversions
+    constant,  /// match with conversion to const
+    exact,     /// exact match
+}
+
+/// Inline setting as defined by `pragma(inline, XXX)`
+enum PINLINE : ubyte
+{
+    default_, /// as specified on the command line
+    never,    /// never inline
+    always,   /// always inline
+}
diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d
index 5d44760..cf9e9ce 100644
--- a/gcc/d/dmd/attrib.d
+++ b/gcc/d/dmd/attrib.d
@@ -43,6 +43,7 @@
 import dmd.mtype;
 import dmd.objc; // for objc.addSymbols
 import dmd.common.outbuffer;
+import dmd.root.array; // for each
 import dmd.target; // for target.systemLinkage
 import dmd.tokens;
 import dmd.visitor;
@@ -1519,3 +1520,60 @@
         }
     }
 }
+
+/**
+ * Returns `true` if the given symbol is a symbol declared in
+ * `core.attribute` and has the given identifier.
+ *
+ * This is used to determine if a symbol is a UDA declared in
+ * `core.attribute`.
+ *
+ * Params:
+ *  sym = the symbol to check
+ *  ident = the name of the expected UDA
+ */
+bool isCoreUda(Dsymbol sym, Identifier ident)
+{
+    if (sym.ident != ident || !sym.parent)
+        return false;
+
+    auto _module = sym.parent.isModule();
+    return _module && _module.isCoreModule(Id.attribute);
+}
+
+/**
+ * Iterates the UDAs attached to the given symbol.
+ *
+ * If `dg` returns `!= 0`, it will stop the iteration and return that
+ * value, otherwise it will return 0.
+ *
+ * Params:
+ *  sym = the symbol to get the UDAs from
+ *  sc = scope to use for semantic analysis of UDAs
+ *  dg = called once for each UDA. If `dg` returns `!= 0`, it will stop the
+ *      iteration and return that value, otherwise it will return `0`.
+ */
+int foreachUda(Dsymbol sym, Scope* sc, int delegate(Expression) dg)
+{
+    if (!sym.userAttribDecl)
+        return 0;
+
+    auto udas = sym.userAttribDecl.getAttributes();
+    arrayExpressionSemantic(udas, sc, true);
+
+    return udas.each!((uda) {
+        if (!uda.isTupleExp())
+            return 0;
+
+        auto exps = uda.isTupleExp().exps;
+
+        return exps.each!((e) {
+            assert(e);
+
+            if (auto result = dg(e))
+                return result;
+
+            return 0;
+        });
+    });
+}
diff --git a/gcc/d/dmd/blockexit.d b/gcc/d/dmd/blockexit.d
index c4a9577..5132a2d 100644
--- a/gcc/d/dmd/blockexit.d
+++ b/gcc/d/dmd/blockexit.d
@@ -110,8 +110,8 @@
                 }
                 if (s.exp.type && s.exp.type.toBasetype().isTypeNoreturn())
                     result = BE.halt;
-                if (canThrow(s.exp, func, mustNotThrow))
-                    result |= BE.throw_;
+
+                result |= canThrow(s.exp, func, mustNotThrow);
             }
         }
 
@@ -149,7 +149,7 @@
                             else if (!func.getModule().isCFile)
                             {
                                 const(char)* gototype = s.isCaseStatement() ? "case" : "default";
-                                s.deprecation("switch case fallthrough - use 'goto %s;' if intended", gototype);
+                                s.error("switch case fallthrough - use 'goto %s;' if intended", gototype);
                             }
                         }
                     }
@@ -214,8 +214,8 @@
                 result = BE.fallthru;
             if (result & BE.fallthru)
             {
-                if (canThrow(s.condition, func, mustNotThrow))
-                    result |= BE.throw_;
+                result |= canThrow(s.condition, func, mustNotThrow);
+
                 if (!(result & BE.break_) && s.condition.toBool().hasValue(true))
                     result &= ~BE.fallthru;
             }
@@ -233,8 +233,8 @@
             }
             if (s.condition)
             {
-                if (canThrow(s.condition, func, mustNotThrow))
-                    result |= BE.throw_;
+                result |= canThrow(s.condition, func, mustNotThrow);
+
                 const opt = s.condition.toBool();
                 if (opt.hasValue(true))
                     result &= ~BE.fallthru;
@@ -250,15 +250,15 @@
                     result |= BE.fallthru;
                 result |= r & ~(BE.fallthru | BE.break_ | BE.continue_);
             }
-            if (s.increment && canThrow(s.increment, func, mustNotThrow))
-                result |= BE.throw_;
+            if (s.increment)
+                result |= canThrow(s.increment, func, mustNotThrow);
         }
 
         override void visit(ForeachStatement s)
         {
             result = BE.fallthru;
-            if (canThrow(s.aggr, func, mustNotThrow))
-                result |= BE.throw_;
+            result |= canThrow(s.aggr, func, mustNotThrow);
+
             if (s._body)
                 result |= blockExit(s._body, func, mustNotThrow) & ~(BE.break_ | BE.continue_);
         }
@@ -273,8 +273,7 @@
         {
             //printf("IfStatement::blockExit(%p)\n", s);
             result = BE.none;
-            if (canThrow(s.condition, func, mustNotThrow))
-                result |= BE.throw_;
+            result |= canThrow(s.condition, func, mustNotThrow);
 
             const opt = s.condition.toBool();
             if (opt.hasValue(true))
@@ -313,8 +312,8 @@
         override void visit(SwitchStatement s)
         {
             result = BE.none;
-            if (canThrow(s.condition, func, mustNotThrow))
-                result |= BE.throw_;
+            result |= canThrow(s.condition, func, mustNotThrow);
+
             if (s._body)
             {
                 result |= blockExit(s._body, func, mustNotThrow);
@@ -357,8 +356,8 @@
         override void visit(ReturnStatement s)
         {
             result = BE.return_;
-            if (s.exp && canThrow(s.exp, func, mustNotThrow))
-                result |= BE.throw_;
+            if (s.exp)
+                result |= canThrow(s.exp, func, mustNotThrow);
         }
 
         override void visit(BreakStatement s)
@@ -380,8 +379,7 @@
         override void visit(WithStatement s)
         {
             result = BE.none;
-            if (canThrow(s.exp, func, mustNotThrow))
-                result = BE.throw_;
+            result |= canThrow(s.exp, func, mustNotThrow);
             result |= blockExit(s._body, func, mustNotThrow);
         }
 
@@ -483,19 +481,7 @@
                 return;
             }
 
-            Type t = s.exp.type.toBasetype();
-            ClassDeclaration cd = t.isClassHandle();
-            assert(cd);
-
-            if (cd == ClassDeclaration.errorException || ClassDeclaration.errorException.isBaseOf(cd, null))
-            {
-                result = BE.errthrow;
-                return;
-            }
-            if (mustNotThrow)
-                s.error("`%s` is thrown but not caught", s.exp.type.toChars());
-
-            result = BE.throw_;
+            result = checkThrow(s.loc, s.exp, mustNotThrow);
         }
 
         override void visit(GotoStatement s)
@@ -537,3 +523,32 @@
     s.accept(be);
     return be.result;
 }
+
+/++
+ + Checks whether `throw <exp>` throws an `Exception` or an `Error`
+ + and raises an error if this violates `nothrow`.
+ +
+ + Params:
+ +   loc          = location of the `throw`
+ +   exp          = expression yielding the throwable
+ +   mustNotThrow = inside of a `nothrow` scope?
+ +
+ + Returns: `BE.[err]throw` depending on the type of `exp`
+ +/
+BE checkThrow(ref const Loc loc, Expression exp, const bool mustNotThrow)
+{
+    import dmd.errors : error;
+
+    Type t = exp.type.toBasetype();
+    ClassDeclaration cd = t.isClassHandle();
+    assert(cd);
+
+    if (cd == ClassDeclaration.errorException || ClassDeclaration.errorException.isBaseOf(cd, null))
+    {
+        return BE.errthrow;
+    }
+    if (mustNotThrow)
+        loc.error("`%s` is thrown but not caught", exp.type.toChars());
+
+    return BE.throw_;
+}
diff --git a/gcc/d/dmd/canthrow.d b/gcc/d/dmd/canthrow.d
index e6eb0ac..faf427d 100644
--- a/gcc/d/dmd/canthrow.d
+++ b/gcc/d/dmd/canthrow.d
@@ -18,6 +18,7 @@
 import dmd.arraytypes;
 import dmd.attrib;
 import dmd.astenums;
+import dmd.blockexit : BE, checkThrow;
 import dmd.declaration;
 import dmd.dsymbol;
 import dmd.expression;
@@ -29,11 +30,28 @@
 import dmd.tokens;
 import dmd.visitor;
 
+/**
+ * Status indicating what kind of throwable might be caused by an expression.
+ *
+ * This is a subset of `BE` restricted to the values actually used by `canThrow`.
+ */
+enum CT : BE
+{
+    /// Never throws an `Exception` or `Throwable`
+    none = BE.none,
+
+    /// Might throw an `Exception`
+    exception = BE.throw_,
+
+    // Might throw an `Error`
+    error = BE.errthrow,
+}
+
 /********************************************
  * Returns true if the expression may throw exceptions.
  * If 'mustNotThrow' is true, generate an error if it throws
  */
-extern (C++) bool canThrow(Expression e, FuncDeclaration func, bool mustNotThrow)
+extern (C++) /* CT */ BE canThrow(Expression e, FuncDeclaration func, bool mustNotThrow)
 {
     //printf("Expression::canThrow(%d) %s\n", mustNotThrow, toChars());
     // stop walking if we determine this expression can throw
@@ -42,6 +60,7 @@
         alias visit = typeof(super).visit;
         FuncDeclaration func;
         bool mustNotThrow;
+        CT result;
 
     public:
         extern (D) this(FuncDeclaration func, bool mustNotThrow)
@@ -62,7 +81,7 @@
 
                     e.checkOverridenDtor(null, f, dd => dd.type.toTypeFunction().isnothrow, "not nothrow");
                 }
-                stop = true;  // if any function throws, then the whole expression throws
+                result |= CT.exception;
             }
         }
 
@@ -72,7 +91,7 @@
 
         override void visit(DeclarationExp de)
         {
-            stop = Dsymbol_canThrow(de.declaration, func, mustNotThrow);
+            result |= Dsymbol_canThrow(de.declaration, func, mustNotThrow);
         }
 
         override void visit(CallExp ce)
@@ -83,18 +102,27 @@
             if (global.errors && !ce.e1.type)
                 return; // error recovery
 
-            import dmd.id : Id;
-
-            if (ce.f && ce.f.ident == Id._d_delstruct)
+            if (ce.f && ce.arguments.dim > 0)
             {
-                // Only check if the dtor throws.
                 Type tb = (*ce.arguments)[0].type.toBasetype();
-                auto ts = tb.nextOf().baseElemOf().isTypeStruct();
-                if (ts)
+                auto tbNext = tb.nextOf();
+                if (tbNext)
                 {
-                    auto sd = ts.sym;
-                    if (sd.dtor)
-                        checkFuncThrows(ce, sd.dtor);
+                    auto ts = tbNext.baseElemOf().isTypeStruct();
+                    if (ts)
+                    {
+                        import dmd.id : Id;
+
+                        auto sd = ts.sym;
+                        if (sd.dtor && ce.f.ident == Id._d_delstruct)
+                            checkFuncThrows(ce, sd.dtor);
+                        else if (sd.postblit &&
+                            (ce.f.ident == Id._d_arrayctor || ce.f.ident == Id._d_arraysetctor))
+                        {
+                            checkFuncThrows(ce, sd.postblit);
+                            return;
+                        }
+                    }
                 }
             }
 
@@ -124,7 +152,7 @@
                     e1 = pe.e1;
                 ce.error("`%s` is not `nothrow`", e1.toChars());
             }
-            stop = true;
+            result |= CT.exception;
         }
 
         override void visit(NewExp ne)
@@ -187,6 +215,13 @@
                     checkFuncThrows(ae, postblit);
         }
 
+        override void visit(ThrowExp te)
+        {
+            const res = checkThrow(te.loc, te.e1, mustNotThrow);
+            assert((res & ~(CT.exception | CT.error)) == 0);
+            result |= res;
+        }
+
         override void visit(NewAnonClassExp)
         {
             assert(0); // should have been lowered by semantic()
@@ -194,18 +229,22 @@
     }
 
     scope CanThrow ct = new CanThrow(func, mustNotThrow);
-    return walkPostorder(e, ct);
+    walkPostorder(e, ct);
+    return ct.result;
 }
 
 /**************************************
  * Does symbol, when initialized, throw?
  * Mirrors logic in Dsymbol_toElem().
  */
-private bool Dsymbol_canThrow(Dsymbol s, FuncDeclaration func, bool mustNotThrow)
+private CT Dsymbol_canThrow(Dsymbol s, FuncDeclaration func, bool mustNotThrow)
 {
+    CT result;
+
     int symbolDg(Dsymbol s)
     {
-        return Dsymbol_canThrow(s, func, mustNotThrow);
+        result |= Dsymbol_canThrow(s, func, mustNotThrow);
+        return 0;
     }
 
     //printf("Dsymbol_toElem() %s\n", s.toChars());
@@ -225,20 +264,19 @@
             if (vd._init)
             {
                 if (auto ie = vd._init.isExpInitializer())
-                    if (canThrow(ie.exp, func, mustNotThrow))
-                        return true;
+                    result |= canThrow(ie.exp, func, mustNotThrow);
             }
             if (vd.needsScopeDtor())
-                return canThrow(vd.edtor, func, mustNotThrow);
+                result |= canThrow(vd.edtor, func, mustNotThrow);
         }
     }
     else if (auto ad = s.isAttribDeclaration())
     {
-        return ad.include(null).foreachDsymbol(&symbolDg) != 0;
+        ad.include(null).foreachDsymbol(&symbolDg);
     }
     else if (auto tm = s.isTemplateMixin())
     {
-        return tm.members.foreachDsymbol(&symbolDg) != 0;
+        tm.members.foreachDsymbol(&symbolDg);
     }
     else if (auto td = s.isTupleDeclaration())
     {
@@ -250,11 +288,10 @@
                 Expression eo = cast(Expression)o;
                 if (auto se = eo.isDsymbolExp())
                 {
-                    if (Dsymbol_canThrow(se.s, func, mustNotThrow))
-                        return true;
+                    result |= Dsymbol_canThrow(se.s, func, mustNotThrow);
                 }
             }
         }
     }
-    return false;
+    return result;
 }
diff --git a/gcc/d/dmd/constfold.d b/gcc/d/dmd/constfold.d
index 76e1d7f..16f7b2f 100644
--- a/gcc/d/dmd/constfold.d
+++ b/gcc/d/dmd/constfold.d
@@ -120,18 +120,13 @@
 {
     UnionExp ue = void;
     Loc loc = e1.loc;
+    // BUG: Should be replaced with e1.toBool().get(), but this is apparently
+    //      executed for some expressions that cannot be const-folded
+    //      To be fixed in another PR
     emplaceExp!(IntegerExp)(&ue, loc, e1.toBool().hasValue(false) ? 1 : 0, type);
     return ue;
 }
 
-private UnionExp Bool(Type type, Expression e1)
-{
-    UnionExp ue = void;
-    Loc loc = e1.loc;
-    emplaceExp!(IntegerExp)(&ue, loc, e1.toBool().hasValue(true) ? 1 : 0, type);
-    return ue;
-}
-
 UnionExp Add(const ref Loc loc, Type type, Expression e1, Expression e2)
 {
     UnionExp ue = void;
@@ -1093,19 +1088,14 @@
     }
     else if (tb.ty == Tbool)
     {
-        bool val = void;
         const opt = e1.toBool();
-        if (opt.hasValue(true))
-            val = true;
-        else if (opt.hasValue(false))
-            val = false;
-        else
+        if (opt.isEmpty())
         {
             cantExp(ue);
             return ue;
         }
 
-        emplaceExp!(IntegerExp)(&ue, loc, val, type);
+        emplaceExp!(IntegerExp)(&ue, loc, opt.get(), type);
     }
     else if (type.isintegral())
     {
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index 8d3f3b3..38a78a0 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -35,7 +35,8 @@
 {
     AST.Dsymbols* symbols;      // symbols declared in current scope
 
-    bool addFuncName;             /// add declaration of __func__ to function symbol table
+    bool addFuncName;           /// add declaration of __func__ to function symbol table
+    bool importBuiltins;        /// seen use of C compiler builtins, so import __builtins;
 
     extern (D) this(TARGET)(AST.Module _module, const(char)[] input, bool doDocComment,
                             const ref TARGET target)
@@ -72,7 +73,6 @@
     {
         //printf("cparseTranslationUnit()\n");
         symbols = new AST.Dsymbols();
-        addBuiltinDeclarations();
         while (1)
         {
             if (token.value == TOK.endOfFile)
@@ -82,6 +82,15 @@
                 auto ld = new AST.LinkDeclaration(token.loc, LINK.c, symbols);
                 wrap.push(ld);
 
+                if (importBuiltins)
+                {
+                    /* Seen references to C builtin functions.
+                     * Import their definitions
+                     */
+                    auto s = new AST.Import(Loc.initial, null, Id.builtins, null, false);
+                    wrap.push(s);
+                }
+
                 return wrap;
             }
 
@@ -596,6 +605,7 @@
      *    string-literal
      *    ( expression )
      *    generic-selection
+     *    __builtin_va_arg(assign_expression, type)
      */
     AST.Expression cparsePrimaryExp()
     {
@@ -606,9 +616,20 @@
         switch (token.value)
         {
         case TOK.identifier:
-            if (token.ident is Id.__func__)
+            const id = token.ident.toString();
+            if (id.length > 2 && id[0] == '_' && id[1] == '_')  // leading double underscore
             {
-                addFuncName = true;     // implicitly declare __func__
+                if (token.ident is Id.__func__)
+                {
+                    addFuncName = true;     // implicitly declare __func__
+                }
+                else if (token.ident is Id.builtin_va_arg)
+                {
+                    e = cparseBuiltin_va_arg();
+                    break;
+                }
+                else
+                    importBuiltins = true;  // probably one of those compiler extensions
             }
             e = new AST.IdentifierExp(loc, token.ident);
             nextToken();
@@ -1449,6 +1470,40 @@
         return cparseAssignExp();
     }
 
+    /*****************************
+     * gcc extension:
+     *    type __builtin_va_arg(assign-expression, type)
+     * Rewrite as `va_arg` template from `core.stdc.stdarg`:
+     *    va_arg!(type)(assign-expression);
+     * Lexer is on `__builtin_va_arg`
+     */
+    private AST.Expression cparseBuiltin_va_arg()
+    {
+        importBuiltins = true;  // need core.stdc.stdarg
+
+        nextToken();
+        check(TOK.leftParenthesis);
+
+        auto arguments = new AST.Expressions();
+        auto arg = cparseAssignExp();
+        arguments.push(arg);
+
+        check(TOK.comma);
+
+        auto t = cparseTypeName();
+        auto tiargs = new AST.Objects();
+        tiargs.push(t);
+
+        const loc = loc;
+        auto ti = new AST.TemplateInstance(loc, Id.va_arg, tiargs);
+        auto tie = new AST.ScopeExp(loc, ti);
+
+        AST.Expression e = new AST.CallExp(loc, tie, arguments);
+
+        check(TOK.rightParenthesis);
+        return e;
+    }
+
     //}
     /********************************************************************************/
     /********************************* Declaration Parser ***************************/
@@ -1481,6 +1536,14 @@
             return;
         }
 
+        if (token.value == TOK._import) // import declaration extension
+        {
+            auto a = parseImport();
+            if (a && a.length)
+                symbols.append(a);
+            return;
+        }
+
         auto symbolsSave = symbols;
         Specifier specifier;
         specifier.packalign = this.packalign;
@@ -1504,7 +1567,7 @@
              */
             auto stag = (tt.tok == TOK.struct_) ? new AST.StructDeclaration(tt.loc, tt.id, false) :
                         (tt.tok == TOK.union_)  ? new AST.UnionDeclaration(tt.loc, tt.id) :
-                                                  new AST.EnumDeclaration(tt.loc, tt.id, AST.Type.tint32);
+                                                  new AST.EnumDeclaration(tt.loc, tt.id, tt.base);
             stag.members = tt.members;
             if (!symbols)
                 symbols = new AST.Dsymbols();
@@ -1550,26 +1613,18 @@
                 case TOK.semicolon:
                 case TOK.asm_:
                 case TOK.__attribute__:
-                    /* This is a data definition, there cannot now be a
-                     * function definition.
-                     */
-                    first = false;
                     if (token.value == TOK.asm_)
                         asmname = cparseSimpleAsmExpr();
                     if (token.value == TOK.__attribute__)
                     {
                         cparseGnuAttributes(specifier);
                         if (token.value == TOK.leftCurly)
-                        {
-                            error("attributes should be specified before the function definition");
-                            auto t = &token;
-                            if (skipBraces(t))
-                            {
-                                token = *t;
-                                return;
-                            }
-                        }
+                            break;              // function definition
                     }
+                    /* This is a data definition, there cannot now be a
+                     * function definition.
+                     */
+                    first = false;
                     break;
 
                 default:
@@ -1636,6 +1691,30 @@
                         isalias = false;
                     }
                 }
+                else if (auto tt = dt.isTypeTag())
+                {
+                    if (tt.id || tt.tok == TOK.enum_)
+                    {
+                        /* `struct tag;` and `struct tag { ... };`
+                         * always result in a declaration in the current scope
+                         */
+                        auto stag = (tt.tok == TOK.struct_) ? new AST.StructDeclaration(tt.loc, tt.id, false) :
+                                    (tt.tok == TOK.union_)  ? new AST.UnionDeclaration(tt.loc, tt.id) :
+                                                              new AST.EnumDeclaration(tt.loc, tt.id, tt.base);
+                        stag.members = tt.members;
+                        tt.members = null;
+                        if (!symbols)
+                            symbols = new AST.Dsymbols();
+                        symbols.push(stag);
+                        if (tt.tok == TOK.enum_)
+                        {
+                            if (!tt.members)
+                                error(tt.loc, "`enum %s` has no members", stag.toChars());
+                            isalias = false;
+                            s = new AST.AliasDeclaration(token.loc, id, stag);
+                        }
+                    }
+                }
                 if (isalias)
                     s = new AST.AliasDeclaration(token.loc, id, dt);
             }
@@ -1768,6 +1847,7 @@
             if (pl.varargs != AST.VarArg.none && pl.length)
                 error("function identifier-list cannot end with `...`");
             ft.parameterList.varargs = AST.VarArg.variadic;     // but C11 allows extra arguments
+            importBuiltins = true;                              // will need __va_list_tag
             auto plLength = pl.length;
             if (symbols.length != plLength)
                 error("%d identifiers does not match %d declarations", cast(int)plLength, cast(int)symbols.length);
@@ -2230,8 +2310,14 @@
             case TKW.xcomplex | TKW.xdouble:               t = AST.Type.tcomplex64; break;
             case TKW.xcomplex | TKW.xlong | TKW.xdouble:   t = realType(RTFlags.complex); break;
 
-            case TKW.xident:                    t = new AST.TypeIdentifier(loc, previd);
+            case TKW.xident:
+            {
+                const idx = previd.toString();
+                if (idx.length > 2 && idx[0] == '_' && idx[1] == '_')  // leading double underscore
+                    importBuiltins = true;  // probably one of those compiler extensions
+                t = new AST.TypeIdentifier(loc, previd);
                 break;
+            }
 
             case TKW.xtag:
                 break;          // t is already set
@@ -2599,6 +2685,7 @@
         if (token.value == TOK.rightParenthesis)        // func()
         {
             nextToken();
+            importBuiltins = true;                              // will need __va_list_tag
             return AST.ParameterList(parameters, AST.VarArg.variadic, varargsStc);
         }
 
@@ -2613,6 +2700,7 @@
             {
                 if (parameters.length == 0)     // func(...)
                     error("named parameter required before `...`");
+                importBuiltins = true;          // will need __va_list_tag
                 varargs = AST.VarArg.variadic;  // C-style variadics
                 nextToken();
                 check(TOK.rightParenthesis);
@@ -3011,6 +3099,17 @@
             nextToken();
         }
 
+        /* clang extension: add optional base type after the identifier
+         * https://en.cppreference.com/w/cpp/language/enum
+         *   enum Identifier : Type
+         */
+        AST.Type base = AST.Type.tint32;  // C11 6.7.2.2-4 implementation defined default base type
+        if (token.value == TOK.colon)
+        {
+            nextToken();
+            base = cparseTypeName();
+        }
+
         AST.Dsymbols* members;
         if (token.value == TOK.leftCurly)
         {
@@ -3084,7 +3183,7 @@
          * redeclaration, or reference to existing declaration.
          * Defer to the semantic() pass with a TypeTag.
          */
-        return new AST.TypeTag(loc, TOK.enum_, tag, members);
+        return new AST.TypeTag(loc, TOK.enum_, tag, base, members);
     }
 
     /*************************************
@@ -3124,17 +3223,14 @@
         if (token.value == TOK.leftCurly)
         {
             nextToken();
-            auto symbolsSave = symbols;
-            symbols = new AST.Dsymbols();
+            members = new AST.Dsymbols();          // so `members` will be non-null even with 0 members
             while (token.value != TOK.rightCurly)
             {
-                cparseStructDeclaration();
+                cparseStructDeclaration(members);
 
                 if (token.value == TOK.endOfFile)
                     break;
             }
-            members = symbols;          // `members` will be non-null even with 0 members
-            symbols = symbolsSave;
             check(TOK.rightCurly);
 
             if ((*members).length == 0) // C11 6.7.2.1-8
@@ -3152,7 +3248,7 @@
          * redeclaration, or reference to existing declaration.
          * Defer to the semantic() pass with a TypeTag.
          */
-        return new AST.TypeTag(loc, structOrUnion, tag, members);
+        return new AST.TypeTag(loc, structOrUnion, tag, null, members);
     }
 
     /*************************************
@@ -3169,18 +3265,19 @@
      * struct-declarator:
      *    declarator
      *    declarator (opt) : constant-expression
+     * Params:
+     *    members = where to put the fields (members)
      */
-    void cparseStructDeclaration()
+    void cparseStructDeclaration(AST.Dsymbols* members)
     {
         //printf("cparseStructDeclaration()\n");
         if (token.value == TOK._Static_assert)
         {
             auto s = cparseStaticAssert();
-            symbols.push(s);
+            members.push(s);
             return;
         }
 
-        auto symbolsSave = symbols;
         Specifier specifier;
         specifier.packalign = this.packalign;
         auto tspec = cparseSpecifierQualifierList(LVL.member, specifier);
@@ -3209,10 +3306,8 @@
                  * the containing struct
                  */
                 auto ad = new AST.AnonDeclaration(tt.loc, tt.tok == TOK.union_, tt.members);
-                if (!symbols)
-                    symbols = new AST.Dsymbols();
                 auto s = applySpecifier(ad, specifier);
-                symbols.push(s);
+                members.push(s);
                 return;
             }
             if (!tt.id && !tt.members)
@@ -3270,18 +3365,14 @@
             if (token.value == TOK.__attribute__)
                 cparseGnuAttributes(specifier);
 
-            AST.Dsymbol s = null;
-            symbols = symbolsSave;
-            if (!symbols)
-                symbols = new AST.Dsymbols;     // lazilly create it
-
             if (!tspec && !specifier.scw && !specifier.mod)
                 error("specifier-qualifier-list required");
             else if (width)
             {
                 if (specifier.alignExps)
                     error("no alignment-specifier for bit field declaration"); // C11 6.7.5-2
-                s = new AST.BitFieldDeclaration(width.loc, dt, id, width);
+                auto s = new AST.BitFieldDeclaration(width.loc, dt, id, width);
+                members.push(s);
             }
             else if (id)
             {
@@ -3291,11 +3382,10 @@
                 // declare the symbol
                 // Give member variables an implicit void initializer
                 auto initializer = new AST.VoidInitializer(token.loc);
-                s = new AST.VarDeclaration(token.loc, dt, id, initializer, specifiersToSTC(LVL.member, specifier));
+                AST.Dsymbol s = new AST.VarDeclaration(token.loc, dt, id, initializer, specifiersToSTC(LVL.member, specifier));
                 s = applySpecifier(s, specifier);
+                members.push(s);
             }
-            if (s !is null)
-                symbols.push(s);
 
             switch (token.value)
             {
@@ -4391,39 +4481,5 @@
         return s;
     }
 
-    /***********************************
-     * Add global target-dependent builtin declarations.
-     */
-    private void addBuiltinDeclarations()
-    {
-        void genBuiltinFunc(Identifier id, AST.VarArg va)
-        {
-            auto tva_list = new AST.TypeIdentifier(Loc.initial, Id.builtin_va_list);
-            auto parameters = new AST.Parameters();
-            parameters.push(new AST.Parameter(STC.parameter | STC.ref_, tva_list, null, null, null));
-            auto pl = AST.ParameterList(parameters, va, 0);
-            auto tf = new AST.TypeFunction(pl, AST.Type.tvoid, LINK.c, 0);
-            auto s = new AST.FuncDeclaration(Loc.initial, Loc.initial, id, AST.STC.static_, tf, false);
-            symbols.push(s);
-        }
-
-        /* void __builtin_va_start(__builtin_va_list, ...);
-         * The second argument is supposed to be of any type, so fake it with the ...
-         */
-        genBuiltinFunc(Id.builtin_va_start, AST.VarArg.variadic);
-
-        /* void __builtin_va_end(__builtin_va_list);
-         */
-        genBuiltinFunc(Id.builtin_va_end, AST.VarArg.none);
-
-        /* struct __va_list_tag
-         * {
-         *    uint, uint, void*, void*
-         * }
-         */
-        auto s = new AST.StructDeclaration(Loc.initial, Id.va_list_tag, false);
-        symbols.push(s);
-    }
-
     //}
 }
diff --git a/gcc/d/dmd/cppmangle.d b/gcc/d/dmd/cppmangle.d
index 7cb2092..986b53f 100644
--- a/gcc/d/dmd/cppmangle.d
+++ b/gcc/d/dmd/cppmangle.d
@@ -1315,7 +1315,18 @@
 
         foreach (n, fparam; parameterList)
         {
-            Type t = target.cpp.parameterType(fparam);
+            Type t = fparam.type.merge2();
+            if (fparam.isReference())
+                t = t.referenceTo();
+            else if (fparam.storageClass & STC.lazy_)
+            {
+                // Mangle as delegate
+                auto tf = new TypeFunction(ParameterList(), t, LINK.d);
+                auto td = new TypeDelegate(tf);
+                t = td.merge();
+            }
+            else if (Type cpptype = target.cpp.parameterType(t))
+                t = cpptype;
             if (t.ty == Tsarray)
             {
                 // Static arrays in D are passed by value; no counterpart in C++
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index 4a80d17..91b3861 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -858,11 +858,8 @@
              * convert to immutable
              */
             if (e.f &&
-                (global.params.useDIP1000 != FeatureState.enabled ||        // lots of legacy code breaks with the following purity check
-                 e.f.isPure() >= PURE.strong ||
-                 // Special case exemption for Object.dup() which we assume is implemented correctly
-                 e.f.ident == Id.dup &&
-                 e.f.toParent2() == ClassDeclaration.object.toParent()) &&
+                // lots of legacy code breaks with the following purity check
+                (global.params.useDIP1000 != FeatureState.enabled || e.f.isPure() >= PURE.const_) &&
                  e.f.isReturnIsolated() // check isReturnIsolated last, because it is potentially expensive.
                )
             {
@@ -2245,9 +2242,12 @@
                 ex = ex.castTo(sc, totuple ? (*totuple.arguments)[i].type : t);
                 (*te.exps)[i] = ex;
             }
+            if (totuple)
+                te.type = totuple;
             result = te;
 
-            /* Questionable behavior: In here, result.type is not set to t.
+            /* Questionable behavior: In here, result.type is not set to t
+             *  if target type is not a tuple of same length.
              * Therefoe:
              *  TypeTuple!(int, int) values;
              *  auto values2 = cast(long)values;
diff --git a/gcc/d/dmd/dclass.d b/gcc/d/dmd/dclass.d
index 1fb4779..ce463c0 100644
--- a/gcc/d/dmd/dclass.d
+++ b/gcc/d/dmd/dclass.d
@@ -446,6 +446,7 @@
             *poffset = 0;
         while (cd)
         {
+            assert(cd.baseClass || cd.semanticRun >= PASS.semanticdone || cd.isInterfaceDeclaration());
             if (this == cd.baseClass)
                 return true;
 
diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d
index aa143d4..494b60f 100644
--- a/gcc/d/dmd/declaration.d
+++ b/gcc/d/dmd/declaration.d
@@ -1048,7 +1048,6 @@
     uint endlinnum;                 // line number of end of scope that this var lives in
     uint offset;
     uint sequenceNumber;            // order the variables are declared
-    __gshared uint nextSequenceNumber;   // the counter for sequenceNumber
     structalign_t alignment;
 
     // When interpreting, these point to the value (NULL if value not determinable)
@@ -1099,7 +1098,6 @@
         this._init = _init;
         ctfeAdrOnStack = AdrOnStackNone;
         this.storage_class = storage_class;
-        sequenceNumber = ++nextSequenceNumber;
     }
 
     static VarDeclaration create(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
@@ -1657,12 +1655,10 @@
         // Sequence numbers work when there are no special VarDeclaration's involved
         if (!((this.storage_class | v.storage_class) & special))
         {
-            // FIXME: VarDeclaration's for parameters are created in semantic3, so
-            //        they will have a greater sequence number than local variables.
-            //        Hence reverse the result for mixed comparisons.
-            const exp = this.isParameter() == v.isParameter();
+            assert(this.sequenceNumber != this.sequenceNumber.init);
+            assert(v.sequenceNumber != v.sequenceNumber.init);
 
-            return (this.sequenceNumber < v.sequenceNumber) == exp;
+            return (this.sequenceNumber < v.sequenceNumber);
         }
 
         // Assume that semantic produces temporaries according to their lifetime
diff --git a/gcc/d/dmd/denum.d b/gcc/d/dmd/denum.d
index dd6dd41..90e48f8 100644
--- a/gcc/d/dmd/denum.d
+++ b/gcc/d/dmd/denum.d
@@ -16,6 +16,7 @@
 
 import core.stdc.stdio;
 
+import dmd.astenums;
 import dmd.attrib;
 import dmd.gluelayer;
 import dmd.declaration;
@@ -60,7 +61,7 @@
     extern (D) this(const ref Loc loc, Identifier ident, Type memtype)
     {
         super(loc, ident);
-        //printf("EnumDeclaration() %s\n", toChars());
+        //printf("EnumDeclaration() %p %s : %s\n", this, toChars(), memtype.toChars());
         type = new TypeEnum(this);
         this.memtype = memtype;
         visibility = Visibility(Visibility.Kind.undefined);
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index fb8ed9b..b55b981 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -99,7 +99,15 @@
 
     Expression result = interpret(e, null);
 
-    result = copyRegionExp(result);
+    // Report an error if the expression contained a `ThrowException` and
+    // hence generated an uncaught exception
+    if (auto tee = result.isThrownExceptionExp())
+    {
+        tee.generateUncaughtError();
+        result = CTFEExp.cantexp;
+    }
+    else
+        result = copyRegionExp(result);
 
     if (!CTFEExp.isCantExp(result))
         result = scrubReturnValue(e.loc, result);
@@ -1601,14 +1609,20 @@
             istate.start = null;
         }
 
-        incUsageCtfe(istate, s.loc);
+        interpretThrow(s.exp, s.loc);
+    }
 
-        Expression e = interpretRegion(s.exp, istate);
+    /// Interpret `throw <exp>` found at the specified location `loc`
+    private void interpretThrow(Expression exp, const ref Loc loc)
+    {
+        incUsageCtfe(istate, loc);
+
+        Expression e = interpretRegion(exp, istate);
         if (exceptionOrCant(e))
             return;
 
         assert(e.op == EXP.classReference);
-        result = ctfeEmplaceExp!ThrownExceptionExp(s.loc, e.isClassReferenceExp());
+        result = ctfeEmplaceExp!ThrownExceptionExp(loc, e.isClassReferenceExp());
     }
 
     override void visit(ScopeGuardStatement s)
@@ -6149,6 +6163,15 @@
         return;
     }
 
+    override void visit(ThrowExp te)
+    {
+        debug (LOG)
+        {
+            printf("%s ThrowExpression::interpret()\n", e.loc.toChars());
+        }
+        interpretThrow(te.e1, te.loc);
+    }
+
     override void visit(PtrExp e)
     {
         debug (LOG)
diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d
index 07ebc27..2a3777b 100644
--- a/gcc/d/dmd/dscope.d
+++ b/gcc/d/dmd/dscope.d
@@ -59,7 +59,6 @@
     compile       = 0x0100,   /// inside __traits(compile)
     ignoresymbolvisibility    = 0x0200,   /// ignore symbol visibility
                                           /// https://issues.dlang.org/show_bug.cgi?id=15907
-    onlysafeaccess = 0x0400,  /// unsafe access is not allowed for @safe code
     Cfile         = 0x0800,   /// C semantics apply
     free          = 0x8000,   /// is on free list
 
@@ -74,7 +73,7 @@
 /// Flags that are carried along with a scope push()
 private enum PersistentFlags =
     SCOPE.contract | SCOPE.debug_ | SCOPE.ctfe | SCOPE.compile | SCOPE.constraint |
-    SCOPE.noaccesscheck | SCOPE.onlysafeaccess | SCOPE.ignoresymbolvisibility |
+    SCOPE.noaccesscheck | SCOPE.ignoresymbolvisibility |
     SCOPE.printf | SCOPE.scanf | SCOPE.Cfile;
 
 struct Scope
diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d
index c4b3380..7823351 100644
--- a/gcc/d/dmd/dsymbol.d
+++ b/gcc/d/dmd/dsymbol.d
@@ -2345,7 +2345,7 @@
 Dsymbol handleTagSymbols(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsymbol sds)
 {
     enum log = false;
-    if (log) printf("handleTagSymbols('%s')\n", s.toChars());
+    if (log) printf("handleTagSymbols('%s') add %p existing %p\n", s.toChars(), s, s2);
     auto sd = s.isScopeDsymbol(); // new declaration
     auto sd2 = s2.isScopeDsymbol(); // existing declaration
 
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index 387dfe3..1cb167a 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -356,6 +356,8 @@
         if (sc && sc.inunion && sc.inunion.isAnonDeclaration())
             dsym.overlapped = true;
 
+        dsym.sequenceNumber = global.varSequenceNumber++;
+
         Scope* scx = null;
         if (dsym._scope)
         {
@@ -1636,7 +1638,7 @@
 
         // Should be merged with PragmaStatement
         //printf("\tPragmaDeclaration::semantic '%s'\n", pd.toChars());
-        if (target.mscoff)
+        if (target.supportsLinkerDirective())
         {
             if (pd.ident == Id.linkerDirective)
             {
@@ -2177,7 +2179,7 @@
         {
             /* C11 6.7.2.2
              */
-            ed.memtype = Type.tint32; // C11 6.7.2.2-4 implementation defined
+            assert(ed.memtype);
             int nextValue = 0;        // C11 6.7.2.2-3 first member value defaults to 0
 
             void emSemantic(EnumMember em, ref int nextValue)
@@ -3457,9 +3459,11 @@
                     }
                 }
 
-                /* These quirky conditions mimic what VC++ appears to do
+                /* These quirky conditions mimic what happens when virtual
+                   inheritance is implemented by producing a virtual base table
+                   with offsets to each of the virtual bases.
                  */
-                if (target.mscoff && cd.classKind == ClassKind.cpp &&
+                if (target.cpp.splitVBasetable && cd.classKind == ClassKind.cpp &&
                     cd.baseClass && cd.baseClass.vtbl.dim)
                 {
                     /* if overriding an interface function, then this is not
@@ -3557,7 +3561,7 @@
                             goto Lintro;
                     }
 
-                    if (fdv.isDeprecated)
+                    if (fdv.isDeprecated && !funcdecl.isDeprecated)
                         deprecation(funcdecl.loc, "`%s` is overriding the deprecated method `%s`",
                                     funcdecl.toPrettyChars, fdv.toPrettyChars);
 
@@ -3646,11 +3650,17 @@
                         funcdecl.tintro = fdv.tintro;
                     else if (!funcdecl.type.equals(fdv.type))
                     {
+                        auto tnext = funcdecl.type.nextOf();
+                        if (auto handle = tnext.isClassHandle())
+                        {
+                            if (handle.semanticRun < PASS.semanticdone && !handle.isBaseInfoComplete())
+                                handle.dsymbolSemantic(null);
+                        }
                         /* Only need to have a tintro if the vptr
                          * offsets differ
                          */
                         int offset;
-                        if (fdv.type.nextOf().isBaseOf(funcdecl.type.nextOf(), &offset))
+                        if (fdv.type.nextOf().isBaseOf(tnext, &offset))
                         {
                             funcdecl.tintro = fdv.type;
                         }
@@ -3812,7 +3822,8 @@
                     deprecation(funcdecl.loc,
                                 "`%s` cannot be annotated with `@disable` because it is overriding a function in the base class",
                                 funcdecl.toPrettyChars);
-                if (funcdecl.isDeprecated)
+
+                if (funcdecl.isDeprecated && !(funcdecl.foverrides.length && funcdecl.foverrides[0].isDeprecated))
                     deprecation(funcdecl.loc,
                                 "`%s` cannot be marked as `deprecated` because it is overriding a function in the base class",
                                 funcdecl.toPrettyChars);
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index c0d17f7..9fe8472 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -6223,114 +6223,62 @@
      */
     final bool needsCodegen()
     {
-        if (!minst)
+        // minst is finalized after the 1st invocation.
+        // tnext and tinst are only needed for the 1st invocation and
+        // cleared for further invocations.
+        TemplateInstance tnext = this.tnext;
+        TemplateInstance tinst = this.tinst;
+        this.tnext = null;
+        this.tinst = null;
+
+        if (errors || (inst && inst.isDiscardable()))
         {
-            // If this is a speculative instantiation,
-            // 1. do codegen if ancestors really needs codegen.
-            // 2. become non-speculative if siblings are not speculative
-
-            TemplateInstance tnext = this.tnext;
-            TemplateInstance tinst = this.tinst;
-            // At first, disconnect chain first to prevent infinite recursion.
-            this.tnext = null;
-            this.tinst = null;
-
-            // Determine necessity of tinst before tnext.
-            if (tinst && tinst.needsCodegen())
-            {
-                minst = tinst.minst; // cache result
-                if (global.params.allInst && minst)
-                {
-                    return true;
-                }
-                assert(minst);
-                assert(minst.isRoot() || minst.rootImports());
-                return true;
-            }
-            if (tnext && (tnext.needsCodegen() || tnext.minst))
-            {
-                minst = tnext.minst; // cache result
-                if (global.params.allInst && minst)
-                {
-                    return true;
-                }
-                assert(minst);
-                return minst.isRoot() || minst.rootImports();
-            }
-
-            // Elide codegen because this is really speculative.
+            minst = null; // mark as speculative
             return false;
         }
 
         if (global.params.allInst)
         {
-            return true;
-        }
+            // Do codegen if there is an instantiation from a root module, to maximize link-ability.
 
-        if (isDiscardable())
-        {
-            return false;
-        }
-
-        /* Even when this is reached to the codegen pass,
-         * a non-root nested template should not generate code,
-         * due to avoid ODR violation.
-         */
-        if (enclosing && enclosing.inNonRoot())
-        {
-            if (tinst)
-            {
-                auto r = tinst.needsCodegen();
-                minst = tinst.minst; // cache result
-                return r;
-            }
-            if (tnext)
-            {
-                auto r = tnext.needsCodegen();
-                minst = tnext.minst; // cache result
-                return r;
-            }
-            return false;
-        }
-
-        if (global.params.useUnitTests)
-        {
-            // Prefer instantiations from root modules, to maximize link-ability.
-            if (minst.isRoot())
+            // Do codegen if `this` is instantiated from a root module.
+            if (minst && minst.isRoot())
                 return true;
 
-            TemplateInstance tnext = this.tnext;
-            TemplateInstance tinst = this.tinst;
-            this.tnext = null;
-            this.tinst = null;
-
+            // Do codegen if the ancestor needs it.
             if (tinst && tinst.needsCodegen())
             {
                 minst = tinst.minst; // cache result
                 assert(minst);
-                assert(minst.isRoot() || minst.rootImports());
+                assert(minst.isRoot());
                 return true;
             }
-            if (tnext && tnext.needsCodegen())
+
+            // Do codegen if a sibling needs it.
+            if (tnext)
             {
-                minst = tnext.minst; // cache result
-                assert(minst);
-                assert(minst.isRoot() || minst.rootImports());
-                return true;
+                if (tnext.needsCodegen())
+                {
+                    minst = tnext.minst; // cache result
+                    assert(minst);
+                    assert(minst.isRoot());
+                    return true;
+                }
+                else if (!minst && tnext.minst)
+                {
+                    minst = tnext.minst; // cache result from non-speculative sibling
+                    return false;
+                }
             }
 
-            // https://issues.dlang.org/show_bug.cgi?id=2500 case
-            if (minst.rootImports())
-                return true;
-
-            // Elide codegen because this is not included in root instances.
+            // Elide codegen because there's no instantiation from any root modules.
             return false;
         }
         else
         {
-            // Prefer instantiations from non-root module, to minimize object code size.
+            // Prefer instantiations from non-root modules, to minimize object code size.
 
-            /* If a TemplateInstance is ever instantiated by non-root modules,
+            /* If a TemplateInstance is ever instantiated from a non-root module,
              * we do not have to generate code for it,
              * because it will be generated when the non-root module is compiled.
              *
@@ -6341,22 +6289,51 @@
              * or the compilation of B do the actual instantiation?
              *
              * See https://issues.dlang.org/show_bug.cgi?id=2500.
+             *
+             * => Elide codegen if there is at least one instantiation from a non-root module
+             *    which doesn't import any root modules.
              */
-            if (!minst.isRoot() && !minst.rootImports())
-                return false;
 
-            TemplateInstance tnext = this.tnext;
-            this.tnext = null;
-
-            if (tnext && !tnext.needsCodegen() && tnext.minst)
+            // If the ancestor isn't speculative,
+            // 1. do codegen if the ancestor needs it
+            // 2. elide codegen if the ancestor doesn't need it (non-root instantiation of ancestor incl. subtree)
+            if (tinst)
             {
-                minst = tnext.minst; // cache result
-                assert(!minst.isRoot());
-                return false;
+                const needsCodegen = tinst.needsCodegen(); // sets tinst.minst
+                if (tinst.minst) // not speculative
+                {
+                    minst = tinst.minst; // cache result
+                    return needsCodegen;
+                }
             }
 
-            // Do codegen because this is not included in non-root instances.
-            return true;
+            // Elide codegen if `this` doesn't need it.
+            if (minst && !minst.isRoot() && !minst.rootImports())
+                return false;
+
+            // Elide codegen if a (non-speculative) sibling doesn't need it.
+            if (tnext)
+            {
+                const needsCodegen = tnext.needsCodegen(); // sets tnext.minst
+                if (tnext.minst) // not speculative
+                {
+                    if (!needsCodegen)
+                    {
+                        minst = tnext.minst; // cache result
+                        assert(!minst.isRoot() && !minst.rootImports());
+                        return false;
+                    }
+                    else if (!minst)
+                    {
+                        minst = tnext.minst; // cache result from non-speculative sibling
+                        return true;
+                    }
+                }
+            }
+
+            // Unless `this` is still speculative (=> all further siblings speculative too),
+            // do codegen because we found no guaranteed-codegen'd non-root instantiation.
+            return minst !is null;
         }
     }
 
@@ -7311,7 +7288,7 @@
                 if ((td && td.literal) || (ti && ti.enclosing) || (d && !d.isDataseg() && !(d.storage_class & STC.manifest) && (!d.isFuncDeclaration() || d.isFuncDeclaration().isNested()) && !isTemplateMixin()))
                 {
                     Dsymbol dparent = sa.toParent2();
-                    if (!dparent)
+                    if (!dparent || dparent.isModule)
                         goto L1;
                     else if (!enclosing)
                         enclosing = dparent;
@@ -7370,13 +7347,6 @@
     {
         Module mi = minst; // instantiated . inserted module
 
-        if (global.params.useUnitTests)
-        {
-            // Turn all non-root instances to speculative
-            if (mi && !mi.isRoot())
-                mi = null;
-        }
-
         //printf("%s.appendToModuleMember() enclosing = %s mi = %s\n",
         //    toPrettyChars(),
         //    enclosing ? enclosing.toPrettyChars() : null,
diff --git a/gcc/d/dmd/dtoh.d b/gcc/d/dmd/dtoh.d
index dbc21b3..5871ada 100644
--- a/gcc/d/dmd/dtoh.d
+++ b/gcc/d/dmd/dtoh.d
@@ -16,6 +16,7 @@
 import core.stdc.ctype;
 
 import dmd.astcodegen;
+import dmd.astenums;
 import dmd.arraytypes;
 import dmd.attrib;
 import dmd.dsymbol;
diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d
index e60ee9c..d2a9060 100644
--- a/gcc/d/dmd/escape.d
+++ b/gcc/d/dmd/escape.d
@@ -691,11 +691,8 @@
             }
 
             // If va's lifetime encloses v's, then error
-            if (va &&
-                (va.enclosesLifetimeOf(v) && !(v.storage_class & (STC.parameter | STC.temp)) ||
-                 // va is class reference
-                 ae.e1.isDotVarExp() && va.type.toBasetype().isTypeClass() && (va.enclosesLifetimeOf(v) ||
-                 !va.isScope()) ||
+            if (va && !va.isDataseg() &&
+                (va.enclosesLifetimeOf(v) && !(v.storage_class & STC.temp) ||
                  vaIsRef ||
                  va.isReference() && !(v.storage_class & (STC.parameter | STC.temp))) &&
                 fd.setUnsafe())
@@ -768,7 +765,6 @@
         }
     }
 
-ByRef:
     foreach (VarDeclaration v; er.byref)
     {
         if (log) printf("byref: %s\n", v.toChars());
@@ -797,8 +793,7 @@
 
         // If va's lifetime encloses v's, then error
         if (va &&
-            (va.enclosesLifetimeOf(v) && !(v.isParameter() && v.isRef()) ||
-             va.isDataseg()) &&
+            (va.enclosesLifetimeOf(v) || (va.isRef() && !(va.storage_class & STC.temp)) || va.isDataseg()) &&
             fd.setUnsafe())
         {
             if (!gag)
@@ -807,26 +802,6 @@
             continue;
         }
 
-        if (va && v.isReference())
-        {
-            Dsymbol pva = va.toParent2();
-            for (Dsymbol pv = p; pv; )
-            {
-                pv = pv.toParent2();
-                if (pva == pv)  // if v is nested inside pva
-                {
-                    if (fd.setUnsafe())
-                    {
-                        if (!gag)
-                            error(ae.loc, "reference `%s` assigned to `%s` with longer lifetime", v.toChars(), va.toChars());
-                        result = true;
-                        continue ByRef;
-                    }
-                    break;
-                }
-            }
-        }
-
         if (!(va && va.isScope()))
             notMaybeScope(v);
 
@@ -1323,7 +1298,9 @@
                     msg = "returning `%s` escapes a reference to parameter `%s`";
                     supplemental = vsr == ScopeRef.Ref_ReturnScope
                                               ? "perhaps remove `scope` parameter annotation so `return` applies to `ref`"
-                                              : "perhaps annotate the parameter with `return`";
+                                              : v.ident is Id.This
+                                                    ? "perhaps annotate the function with `return`"
+                                                    : "perhaps annotate the parameter with `return`";
                 }
                 else
                 {
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index 523015e..4258e9b 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -25,7 +25,6 @@
 import dmd.astenums;
 import dmd.ast_node;
 import dmd.gluelayer;
-import dmd.canthrow;
 import dmd.constfold;
 import dmd.ctfeexpr;
 import dmd.ctorflow;
@@ -466,7 +465,17 @@
              */
             auto tmp = copyToTemp(STC.rvalue, "__copytmp", e);
             if (sd.hasCopyCtor && destinationType)
-                tmp.type = destinationType;
+            {
+                // https://issues.dlang.org/show_bug.cgi?id=22619
+                // If the destination type is inout we can preserve it
+                // only if inside an inout function; if we are not inside
+                // an inout function, then we will preserve the type of
+                // the source
+                if (destinationType.hasWild && !(sc.func.storage_class & STC.wild))
+                    tmp.type = e.type;
+                else
+                    tmp.type = destinationType;
+            }
             tmp.storage_class |= STC.nodtor;
             tmp.dsymbolSemantic(sc);
             Expression de = new DeclarationExp(e.loc, tmp);
@@ -4681,6 +4690,31 @@
 }
 
 /***********************************************************
+ * `throw <e1>` as proposed by DIP 1034.
+ *
+ * Replacement for the deprecated `ThrowStatement` that can be nested
+ * in other expression.
+ */
+extern (C++) final class ThrowExp : UnaExp
+{
+    extern (D) this(const ref Loc loc, Expression e)
+    {
+        super(loc, EXP.throw_, __traits(classInstanceSize, ThrowExp), e);
+        this.type = Type.tnoreturn;
+    }
+
+    override ThrowExp syntaxCopy()
+    {
+        return new ThrowExp(loc, e1.syntaxCopy());
+    }
+
+    override void accept(Visitor v)
+    {
+        v.visit(this);
+    }
+}
+
+/***********************************************************
  */
 extern (C++) final class DotIdExp : UnaExp
 {
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index f848cce..18ef90a 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -48,7 +48,9 @@
 void expandTuples(Expressions *exps);
 bool isTrivialExp(Expression *e);
 bool hasSideEffect(Expression *e, bool assumeImpureCalls = false);
-bool canThrow(Expression *e, FuncDeclaration *func, bool mustNotThrow);
+
+enum BE : int32_t;
+BE canThrow(Expression *e, FuncDeclaration *func, bool mustNotThrow);
 
 typedef unsigned char OwnedBy;
 enum
@@ -742,6 +744,14 @@
     void accept(Visitor *v) { v->visit(this); }
 };
 
+class ThrowExp : public UnaExp
+{
+public:
+    ThrowExp *syntaxCopy();
+
+    void accept(Visitor *v) { v->visit(this); }
+};
+
 class DotIdExp : public UnaExp
 {
 public:
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index 1008606..6eda688 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -3604,16 +3604,21 @@
                 {
                     if (!cdthis)
                     {
+                        if (!sc.hasThis)
+                        {
+                            string msg = "cannot construct " ~
+                            (cd.isAnonymous ? "anonymous nested class" : "nested class `%s`") ~
+                            " because no implicit `this` reference to outer class" ~
+                            (cdn.isAnonymous ? "" : " `%s`") ~ " is available\0";
+
+                            exp.error(msg.ptr, cd.toChars, cdn.toChars);
+                            return setError();
+                        }
+
                         // Supply an implicit 'this' and try again
                         exp.thisexp = new ThisExp(exp.loc);
                         for (Dsymbol sp = sc.parent; 1; sp = sp.toParentLocal())
                         {
-                            if (!sp)
-                            {
-                                exp.error("outer class `%s` `this` needed to `new` nested class `%s`",
-                                    cdn.toChars(), cd.toChars());
-                                return setError();
-                            }
                             ClassDeclaration cdp = sp.isClassDeclaration();
                             if (!cdp)
                                 continue;
@@ -5702,12 +5707,6 @@
                     || global.params.useDeprecated != DiagnosticReporting.error;
                 const bool preventAliasThis = e.targ.hasDeprecatedAliasThis && !deprecationAllowed;
 
-                // baseClass might not be set if either targ or tspec is forward referenced.
-                if (auto tc = e.targ.isTypeClass())
-                    tc.sym.dsymbolSemantic(null);
-                if (auto tc = e.tspec.isTypeClass())
-                    tc.sym.dsymbolSemantic(null);
-
                 if (preventAliasThis && e.targ.ty == Tstruct)
                 {
                     if ((cast(TypeStruct) e.targ).implicitConvToWithoutAliasThis(e.tspec))
@@ -6396,6 +6395,16 @@
             : Expression.combine(temporariesPrefix, exp).expressionSemantic(sc);
     }
 
+    override void visit(ThrowExp te)
+    {
+        import dmd.statementsem;
+
+        if (StatementSemanticVisitor.throwSemantic(te.loc, te.e1, sc))
+            result = te;
+        else
+            setError();
+    }
+
     override void visit(DotIdExp exp)
     {
         static if (LOGSEMANTIC)
@@ -6913,6 +6922,18 @@
             exp.error("cannot take address of `%s`", exp.e1.toChars());
             return setError();
         }
+        if (auto dve = exp.e1.isDotVarExp())
+        {
+            /* https://issues.dlang.org/show_bug.cgi?id=22749
+             * Error about taking address of any bit-field, regardless of
+             * whether SCOPE.Cfile is set.
+             */
+            if (auto bf = dve.var.isBitFieldDeclaration())
+            {
+                exp.error("cannot take address of bit-field `%s`", bf.toChars());
+                return setError();
+            }
+        }
 
         bool hasOverloads;
         if (auto f = isFuncAddress(exp, &hasOverloads))
@@ -7511,6 +7532,17 @@
         // https://issues.dlang.org/show_bug.cgi?id=19954
         if (exp.e1.type.ty == Ttuple)
         {
+            if (exp.to)
+            {
+                if (TypeTuple tt = exp.to.isTypeTuple())
+                {
+                    if (exp.e1.type.implicitConvTo(tt))
+                    {
+                        result = exp.e1.castTo(sc, tt);
+                        return;
+                    }
+                }
+            }
             TupleExp te = exp.e1.isTupleExp();
             if (te.exps.dim == 1)
                 exp.e1 = (*te.exps)[0];
@@ -7531,7 +7563,7 @@
 
         if (exp.to.ty == Ttuple)
         {
-            exp.error("cannot cast `%s` to tuple type `%s`", exp.e1.toChars(), exp.to.toChars());
+            exp.error("cannot cast `%s` of type `%s` to tuple type `%s`", exp.e1.toChars(), exp.e1.type.toChars(), exp.to.toChars());
             return setError();
         }
 
@@ -8016,7 +8048,7 @@
                 Expression el = new ArrayLengthExp(exp.loc, exp.e1);
                 el = el.expressionSemantic(sc);
                 el = el.optimize(WANTvalue);
-                if (el.op == EXP.int64)
+                if (el.op == EXP.int64 && t1b.ty == Tsarray)
                 {
                     // Array length is known at compile-time. Upper is in bounds if it fits length.
                     dinteger_t length = el.toInteger();
@@ -9894,7 +9926,6 @@
                 Expression id = new IdentifierExp(exp.loc, Id.empty);
                 id = new DotIdExp(exp.loc, id, Id.object);
                 id = new DotIdExp(exp.loc, id, func);
-                id = id.expressionSemantic(sc);
 
                 auto arguments = new Expressions();
                 arguments.push(new CastExp(ae.loc, ae.e1, ae.e1.type.nextOf.arrayOf).expressionSemantic(sc));
@@ -11355,7 +11386,8 @@
             return setError();
         }
 
-        EXP cmpop;
+
+        EXP cmpop = exp.op;
         if (auto e = exp.op_overload(sc, &cmpop))
         {
             if (!e.type.isscalar() && e.type.equals(exp.e1.type))
@@ -11365,6 +11397,38 @@
             }
             if (e.op == EXP.call)
             {
+
+                if (t1.ty == Tclass && t2.ty == Tclass)
+                {
+                    // Lower to object.__cmp(e1, e2)
+                    Expression cl = new IdentifierExp(exp.loc, Id.empty);
+                    cl = new DotIdExp(exp.loc, cl, Id.object);
+                    cl = new DotIdExp(exp.loc, cl, Id.__cmp);
+                    cl = cl.expressionSemantic(sc);
+
+                    auto arguments = new Expressions();
+                    // Check if op_overload found a better match by calling e2.opCmp(e1)
+                    // If the operands were swapped, then the result must be reversed
+                    // e1.opCmp(e2) == -e2.opCmp(e1)
+                    // cmpop takes care of this
+                    if (exp.op == cmpop)
+                    {
+                        arguments.push(exp.e1);
+                        arguments.push(exp.e2);
+                    }
+                    else
+                    {
+                        // Use better match found by op_overload
+                        arguments.push(exp.e2);
+                        arguments.push(exp.e1);
+                    }
+
+                    cl = new CallExp(exp.loc, cl, arguments);
+                    cl = new CmpExp(cmpop, exp.loc, cl, new IntegerExp(0));
+                    result = cl.expressionSemantic(sc);
+                    return;
+                }
+
                 e = new CmpExp(cmpop, exp.loc, e, IntegerExp.literal!0);
                 e = e.expressionSemantic(sc);
             }
@@ -11372,6 +11436,7 @@
             return;
         }
 
+
         if (Expression ex = typeCombine(exp, sc))
         {
             result = ex;
@@ -13213,7 +13278,16 @@
     if (em.errors)
         return ErrorExp.get();
     Expression e = new VarExp(loc, em);
-    return e.expressionSemantic(sc);
+    e = e.expressionSemantic(sc);
+    if (!(sc.flags & SCOPE.Cfile) && em.isCsymbol())
+    {
+        /* C11 types them as int. But if in D file,
+         * type qualified names as the enum
+         */
+        e.type = em.parent.isEnumDeclaration().type;
+        assert(e.type);
+    }
+    return e;
 }
 
 
@@ -13245,6 +13319,8 @@
         case EXP.assign:
         case EXP.construct:
         case EXP.blit:
+            if (sc.flags & SCOPE.Cfile)
+                return exp;
             // Things like:
             //  if (a = b) ...
             // are usually mistakes.
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index b5148be..f3aeb0f 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -3052,7 +3052,7 @@
         // all of overloads are templates
         if (td)
         {
-            .error(loc, "%s `%s.%s` cannot deduce function from argument types `!(%s)%s`",
+            .error(loc, "none of the overloads of %s `%s.%s` are callable using argument types `!(%s)%s`",
                    td.kind(), td.parent.toPrettyChars(), td.ident.toChars(),
                    tiargsBuf.peekChars(), fargsBuf.peekChars());
 
diff --git a/gcc/d/dmd/globals.d b/gcc/d/dmd/globals.d
index 22ccddd..eccd1ee 100644
--- a/gcc/d/dmd/globals.d
+++ b/gcc/d/dmd/globals.d
@@ -327,6 +327,7 @@
     Array!Identifier* debugids;   /// command line debug versions and predefined versions
 
     bool hasMainFunction; /// Whether a main function has already been compiled in (for -main switch)
+    uint varSequenceNumber = 1; /// Relative lifetime of `VarDeclaration` within a function, used for `scope` checks
 
     enum recursionLimit = 500; /// number of recursive template expansions before abort
 
@@ -614,48 +615,5 @@
     }
 }
 
-/// A linkage attribute as defined by `extern(XXX)`
-///
-/// https://dlang.org/spec/attribute.html#linkage
-enum LINK : ubyte
-{
-    default_,
-    d,
-    c,
-    cpp,
-    windows,
-    objc,
-    system,
-}
-
-/// Whether to mangle an external aggregate as a struct or class, as set by `extern(C++, struct)`
-enum CPPMANGLE : ubyte
-{
-    def,      /// default
-    asStruct, /// `extern(C++, struct)`
-    asClass,  /// `extern(C++, class)`
-}
-
-/// Function match levels
-///
-/// https://dlang.org/spec/function.html#function-overloading
-enum MATCH : int
-{
-    nomatch,   /// no match
-    convert,   /// match with conversions
-    constant,  /// match with conversion to const
-    exact,     /// exact match
-}
-
-/// Inline setting as defined by `pragma(inline, XXX)`
-enum PINLINE : ubyte
-{
-    default_, /// as specified on the command line
-    never,    /// never inline
-    always,   /// always inline
-}
-
-alias StorageClass = ulong;
-
 /// Collection of global state
 extern (C++) __gshared Global global;
diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h
index 4e76967..49fa5b9 100644
--- a/gcc/d/dmd/globals.h
+++ b/gcc/d/dmd/globals.h
@@ -290,6 +290,7 @@
     Array<class Identifier*>* debugids;   // command line debug versions and predefined versions
 
     bool hasMainFunction;
+    unsigned varSequenceNumber;
 
     /* Start gagging. Return the current number of gagged errors
      */
diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d
index 6fc86c3..43b63f1 100644
--- a/gcc/d/dmd/hdrgen.d
+++ b/gcc/d/dmd/hdrgen.d
@@ -2364,6 +2364,12 @@
         buf.writeByte(')');
     }
 
+    override void visit(ThrowExp e)
+    {
+        buf.writestring("throw ");
+        expToBuffer(e.e1, PREC.unary, buf, hgs);
+    }
+
     override void visit(DotIdExp e)
     {
         expToBuffer(e.e1, PREC.primary, buf, hgs);
@@ -3896,6 +3902,11 @@
         buf.writeByte(' ');
         if (t.id)
             buf.writestring(t.id.toChars());
+        if (t.base.ty != TY.Tint32)
+        {
+            buf.writestring(" : ");
+            visitWithMask(t.base, t.mod, buf, hgs);
+        }
     }
 
     void visitTuple(TypeTuple t)
diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d
index cef1b8e..7f51e92 100644
--- a/gcc/d/dmd/id.d
+++ b/gcc/d/dmd/id.d
@@ -478,6 +478,7 @@
     { "hasCopyConstructor" },
     { "isCopyable" },
     { "toType" },
+    { "parameters" },
 
     // For C++ mangling
     { "allocator" },
@@ -507,12 +508,11 @@
     { "__func__" },
     { "noreturn" },
     { "__pragma", "pragma" },
+    { "builtins", "__builtins" },
     { "builtin_va_list", "__builtin_va_list" },
-    { "builtin_va_start", "__builtin_va_start" },
     { "builtin_va_arg", "__builtin_va_arg" },
-    { "builtin_va_copy", "__builtin_va_copy" },
-    { "builtin_va_end", "__builtin_va_end" },
     { "va_list_tag", "__va_list_tag" },
+    { "va_arg" },
     { "pack" },
     { "show" },
     { "push" },
diff --git a/gcc/d/dmd/json.d b/gcc/d/dmd/json.d
index ba2dd17..3183c8d 100644
--- a/gcc/d/dmd/json.d
+++ b/gcc/d/dmd/json.d
@@ -302,8 +302,7 @@
             //property(name, "impure");
             break;
         case PURE.weak:     return property(name, "weak");
-        case PURE.const_:   return property(name, "const");
-        case PURE.strong:   return property(name, "strong");
+        case PURE.const_:   return property(name, "strong");
         case PURE.fwdref:   return property(name, "fwdref");
         }
     }
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index 0257faa..fefad28 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -230,6 +230,57 @@
     return ty == Tchar || ty == Twchar || ty == Tdchar;
 }
 
+/************************************
+ * Determine mutability of indirections in (ref) t.
+ *
+ * Returns: When the type has any mutable indirections, returns 0.
+ * When all indirections are immutable, returns 2.
+ * Otherwise, when the type has const/inout indirections, returns 1.
+ *
+ * Params:
+ *      isref = if true, check `ref t`; otherwise, check just `t`
+ *      t = the type that is being checked
+ */
+int mutabilityOfType(bool isref, Type t)
+{
+    if (isref)
+    {
+        if (t.mod & MODFlags.immutable_)
+            return 2;
+        if (t.mod & (MODFlags.const_ | MODFlags.wild))
+            return 1;
+        return 0;
+    }
+
+    t = t.baseElemOf();
+
+    if (!t.hasPointers() || t.mod & MODFlags.immutable_)
+        return 2;
+
+    /* Accept immutable(T)[] and immutable(T)* as being strongly pure
+     */
+    if (t.ty == Tarray || t.ty == Tpointer)
+    {
+        Type tn = t.nextOf().toBasetype();
+        if (tn.mod & MODFlags.immutable_)
+            return 2;
+        if (tn.mod & (MODFlags.const_ | MODFlags.wild))
+            return 1;
+    }
+
+    /* The rest of this is too strict; fix later.
+     * For example, the only pointer members of a struct may be immutable,
+     * which would maintain strong purity.
+     * (Just like for dynamic arrays and pointers above.)
+     */
+    if (t.mod & (MODFlags.const_ | MODFlags.wild))
+        return 1;
+
+    /* Should catch delegates and function pointers, and fold in their purity
+     */
+    return 0;
+}
+
 /****************
  * dotExp() bit flags
  */
@@ -4217,54 +4268,11 @@
         if (tf.purity != PURE.fwdref)
             return;
 
-        /* Determine purity level based on mutability of t
-         * and whether it is a 'ref' type or not.
-         */
-        static PURE purityOfType(bool isref, Type t)
-        {
-            if (isref)
-            {
-                if (t.mod & MODFlags.immutable_)
-                    return PURE.strong;
-                if (t.mod & (MODFlags.const_ | MODFlags.wild))
-                    return PURE.const_;
-                return PURE.weak;
-            }
-
-            t = t.baseElemOf();
-
-            if (!t.hasPointers() || t.mod & MODFlags.immutable_)
-                return PURE.strong;
-
-            /* Accept immutable(T)[] and immutable(T)* as being strongly pure
-             */
-            if (t.ty == Tarray || t.ty == Tpointer)
-            {
-                Type tn = t.nextOf().toBasetype();
-                if (tn.mod & MODFlags.immutable_)
-                    return PURE.strong;
-                if (tn.mod & (MODFlags.const_ | MODFlags.wild))
-                    return PURE.const_;
-            }
-
-            /* The rest of this is too strict; fix later.
-             * For example, the only pointer members of a struct may be immutable,
-             * which would maintain strong purity.
-             * (Just like for dynamic arrays and pointers above.)
-             */
-            if (t.mod & (MODFlags.const_ | MODFlags.wild))
-                return PURE.const_;
-
-            /* Should catch delegates and function pointers, and fold in their purity
-             */
-            return PURE.weak;
-        }
-
-        purity = PURE.strong; // assume strong until something weakens it
+        purity = PURE.const_; // assume strong until something weakens it
 
         /* Evaluate what kind of purity based on the modifiers for the parameters
          */
-    Lloop: foreach (i, fparam; tf.parameterList)
+        foreach (i, fparam; tf.parameterList)
         {
             Type t = fparam.type;
             if (!t)
@@ -4275,33 +4283,11 @@
                 purity = PURE.weak;
                 break;
             }
-            switch (purityOfType((fparam.storageClass & STC.ref_) != 0, t))
-            {
-                case PURE.weak:
-                    purity = PURE.weak;
-                    break Lloop; // since PURE.weak, no need to check further
-
-                case PURE.const_:
-                    purity = PURE.const_;
-                    continue;
-
-                case PURE.strong:
-                    continue;
-
-                default:
-                    assert(0);
-            }
+            const pref = (fparam.storageClass & STC.ref_) != 0;
+            if (mutabilityOfType(pref, t) == 0)
+                purity = PURE.weak;
         }
 
-        if (purity > PURE.weak && tf.nextOf())
-        {
-            /* Adjust purity based on mutability of return type.
-             * https://issues.dlang.org/show_bug.cgi?id=15862
-             */
-            const purity2 = purityOfType(tf.isref, tf.nextOf());
-            if (purity2 < purity)
-                purity = purity2;
-        }
         tf.purity = purity;
     }
 
@@ -6306,10 +6292,7 @@
 
     extern (D) MATCH implicitConvToWithoutAliasThis(Type to)
     {
-        MATCH m = constConv(to);
-        if (m > MATCH.nomatch)
-            return m;
-
+        // Run semantic before checking whether class is convertible
         ClassDeclaration cdto = to.isClassHandle();
         if (cdto)
         {
@@ -6318,11 +6301,15 @@
                 cdto.dsymbolSemantic(null);
             if (sym.semanticRun < PASS.semanticdone && !sym.isBaseInfoComplete())
                 sym.dsymbolSemantic(null);
-            if (cdto.isBaseOf(sym, null) && MODimplicitConv(mod, to.mod))
-            {
-                //printf("'to' is base\n");
-                return MATCH.convert;
-            }
+        }
+        MATCH m = constConv(to);
+        if (m > MATCH.nomatch)
+            return m;
+
+        if (cdto && cdto.isBaseOf(sym, null) && MODimplicitConv(mod, to.mod))
+        {
+            //printf("'to' is base\n");
+            return MATCH.convert;
         }
         return MATCH.nomatch;
     }
@@ -6373,6 +6360,9 @@
 
     override MOD deduceWild(Type t, bool isRef)
     {
+        // If sym is forward referenced:
+        if (sym.semanticRun < PASS.semanticdone && !sym.isBaseInfoComplete())
+            sym.dsymbolSemantic(null);
         ClassDeclaration cd = t.isClassHandle();
         if (cd && (sym == cd || cd.isBaseOf(sym, null)))
             return Type.deduceWild(t, isRef);
@@ -6760,19 +6750,21 @@
     Loc loc;                /// location of declaration
     TOK tok;                /// TOK.struct_, TOK.union_, TOK.enum_
     Identifier id;          /// tag name identifier
+    Type base;              /// base type for enums otherwise null
     Dsymbols* members;      /// members of struct, null if none
 
     Type resolved;          /// type after semantic() in case there are more others
                             /// pointing to this instance, which can happen with
                             ///   struct S { int a; } s1, *s2;
 
-    extern (D) this(const ref Loc loc, TOK tok, Identifier id, Dsymbols* members)
+    extern (D) this(const ref Loc loc, TOK tok, Identifier id, Type base, Dsymbols* members)
     {
         //printf("TypeTag %p\n", this);
         super(Ttag);
         this.loc = loc;
         this.tok = tok;
         this.id = id;
+        this.base = base;
         this.members = members;
     }
 
diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h
index fde5027..cb60236 100644
--- a/gcc/d/dmd/mtype.h
+++ b/gcc/d/dmd/mtype.h
@@ -553,7 +553,6 @@
     fwdref = 1,     // it's pure, but not known which level yet
     weak = 2,       // no mutable globals are read or written
     const_ = 3,     // parameters are values or const
-    strong = 4      // parameters are values or immutable
 };
 
 class Parameter : public ASTNode
diff --git a/gcc/d/dmd/nogc.d b/gcc/d/dmd/nogc.d
index ed3f832..f25e779 100644
--- a/gcc/d/dmd/nogc.d
+++ b/gcc/d/dmd/nogc.d
@@ -71,6 +71,7 @@
         if (!e.f)
             return;
 
+        // Treat lowered hook calls as their original expressions.
         auto fd = stripHookTraceImpl(e.f);
         if (fd.ident == Id._d_arraysetlengthT)
         {
diff --git a/gcc/d/dmd/nspace.d b/gcc/d/dmd/nspace.d
index 29f920a..40f2676 100644
--- a/gcc/d/dmd/nspace.d
+++ b/gcc/d/dmd/nspace.d
@@ -48,6 +48,7 @@
 
 import dmd.aggregate;
 import dmd.arraytypes;
+import dmd.astenums;
 import dmd.dscope;
 import dmd.dsymbol;
 import dmd.dsymbolsem;
diff --git a/gcc/d/dmd/objc.d b/gcc/d/dmd/objc.d
index 6d283e1..9e92212 100644
--- a/gcc/d/dmd/objc.d
+++ b/gcc/d/dmd/objc.d
@@ -818,64 +818,6 @@
         expression.errorSupplemental("`tupleof` is not available for members " ~
             "of Objective-C classes. Please use the Objective-C runtime instead");
     }
-
-extern(D) private:
-
-    /**
-     * Returns `true` if the given symbol is a symbol declared in
-     * `core.attribute` and has the given identifier.
-     *
-     * This is used to determine if a symbol is a UDA declared in
-     * `core.attribute`.
-     *
-     * Params:
-     *  sd = the symbol to check
-     *  ident = the name of the expected UDA
-     */
-    bool isCoreUda(ScopeDsymbol sd, Identifier ident) const
-    {
-        if (sd.ident != ident || !sd.parent)
-            return false;
-
-        auto _module = sd.parent.isModule();
-        return _module && _module.isCoreModule(Id.attribute);
-    }
-
-    /**
-     * Iterates the UDAs attached to the given function declaration.
-     *
-     * If `dg` returns `!= 0`, it will stop the iteration and return that
-     * value, otherwise it will return 0.
-     *
-     * Params:
-     *  fd = the function declaration to get the UDAs from
-     *  dg = called once for each UDA. If `dg` returns `!= 0`, it will stop the
-     *      iteration and return that value, otherwise it will return `0`.
-     */
-    int foreachUda(FuncDeclaration fd, Scope* sc, int delegate(Expression) dg) const
-    {
-        if (!fd.userAttribDecl)
-            return 0;
-
-        auto udas = fd.userAttribDecl.getAttributes();
-        arrayExpressionSemantic(udas, sc, true);
-
-        return udas.each!((uda) {
-            if (!uda.isTupleExp())
-                return 0;
-
-            auto exps = uda.isTupleExp().exps;
-
-            return exps.each!((e) {
-                assert(e);
-
-                if (auto result = dg(e))
-                    return result;
-
-                return 0;
-            });
-        });
-    }
 }
 
 /*
diff --git a/gcc/d/dmd/opover.d b/gcc/d/dmd/opover.d
index c932d043..5d6128b 100644
--- a/gcc/d/dmd/opover.d
+++ b/gcc/d/dmd/opover.d
@@ -853,11 +853,11 @@
                         {
                             // Rewrite (e1 op e2) as e2.opfunc(e1)
                             result = build_overload(e.loc, sc, e.e2, e.e1, m.lastf ? m.lastf : s);
+                            // When reversing operands of comparison operators,
+                            // need to reverse the sense of the op
+                            if (pop)
+                                *pop = reverseRelation(e.op);
                         }
-                        // When reversing operands of comparison operators,
-                        // need to reverse the sense of the op
-                        if (pop)
-                            *pop = reverseRelation(e.op);
                         return;
                     }
                 }
@@ -1052,7 +1052,7 @@
                 e.e2 = new DotIdExp(e.loc, e.e2, Id._tupleof);
 
                 auto sc2 = sc.push();
-                sc2.flags = (sc2.flags & ~SCOPE.onlysafeaccess) | SCOPE.noaccesscheck;
+                sc2.flags |= SCOPE.noaccesscheck;
                 result = e.expressionSemantic(sc2);
                 sc2.pop();
 
diff --git a/gcc/d/dmd/optimize.d b/gcc/d/dmd/optimize.d
index 5864fa2..5b4ebd7 100644
--- a/gcc/d/dmd/optimize.d
+++ b/gcc/d/dmd/optimize.d
@@ -1130,8 +1130,8 @@
             const e1Opt = e.e1.toBool();
             if (e.e2.isConst())
             {
-                bool n1 = e1Opt.hasValue(true);
-                bool n2 = e.e2.toBool().hasValue(true);
+                bool n1 = e1Opt.get();
+                bool n2 = e.e2.toBool().get();
                 ret = new IntegerExp(e.loc, oror ? (n1 || n2) : (n1 && n2), e.type);
             }
             else if (e1Opt.hasValue(!oror))
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index 700f3c5..63afeb2 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -128,6 +128,7 @@
     EXP.new_ : PREC.unary,
     EXP.newAnonymousClass : PREC.unary,
     EXP.cast_ : PREC.unary,
+    EXP.throw_ : PREC.unary,
 
     EXP.vector : PREC.unary,
     EXP.pow : PREC.pow,
@@ -443,6 +444,13 @@
         }
 
         decldefs = parseDeclDefs(0, &lastDecl);
+
+        if (token.value == TOK.rightCurly)
+        {
+            error(token.loc, "unmatched closing brace");
+            goto Lerr;
+        }
+
         if (token.value != TOK.endOfFile)
         {
             error(token.loc, "unrecognized declaration");
@@ -643,7 +651,43 @@
                 goto Lerror;
 
             case TOK.unittest_:
-                if (global.params.useUnitTests || global.params.doDocComments || global.params.doHdrGeneration)
+                /**
+                 * Ignore unittests in non-root modules.
+                 *
+                 * This mainly means that unittests *inside templates* are only
+                 * ever instantiated if the module lexically declaring the
+                 * template is one of the root modules.
+                 *
+                 * E.g., compiling some project with `-unittest` does NOT
+                 * compile and later run any unittests in instantiations of
+                 * templates declared in other libraries.
+                 *
+                 * Declaring unittests *inside* templates is considered an anti-
+                 * pattern. In almost all cases, the unittests don't depend on
+                 * the template parameters, but instantiate the template with
+                 * fixed arguments (e.g., Nullable!T unittests instantiating
+                 * Nullable!int), so compiling and running identical tests for
+                 * each template instantiation is hardly desirable.
+                 * But adding a unittest right below some function being tested
+                 * is arguably good for locality, so unittests end up inside
+                 * templates.
+                 * To make sure a template's unittests are run, it should be
+                 * instantiated in the same module, e.g., some module-level
+                 * unittest.
+                 *
+                 * Another reason for ignoring unittests in templates from non-
+                 * root modules is for template codegen culling via
+                 * TemplateInstance.needsCodegen(). If the compiler decides not
+                 * to emit some Nullable!bool because there's an existing
+                 * instantiation in some non-root module, it has no idea whether
+                 * that module was compiled with -unittest too, and so whether
+                 * Nullable!int (instantiated in some unittest inside the
+                 * Nullable template) can be culled too. By ignoring unittests
+                 * in non-root modules, the compiler won't consider any
+                 * template instantiations in these unittests as candidates for
+                 * further codegen culling.
+                 */
+                if (mod.isRoot() && (global.params.useUnitTests || global.params.doDocComments || global.params.doHdrGeneration))
                 {
                     s = parseUnitTest(pAttrs);
                     if (*pLastDecl)
@@ -1530,6 +1574,8 @@
 
             case TOK.return_:
                 stc = STC.return_;
+                if (peekNext() == TOK.scope_)
+                    stc |= STC.returnScope;     // recognize `return scope`
                 break;
 
             case TOK.scope_:
@@ -2880,7 +2926,7 @@
         StorageClass varargsStc;
 
         // Attributes allowed for ...
-        enum VarArgsStc = STC.const_ | STC.immutable_ | STC.shared_ | STC.scope_ | STC.return_;
+        enum VarArgsStc = STC.const_ | STC.immutable_ | STC.shared_ | STC.scope_ | STC.return_ | STC.returnScope;
 
         check(TOK.leftParenthesis);
         while (1)
@@ -2988,6 +3034,8 @@
 
                 case TOK.return_:
                     stc = STC.return_;
+                    if (peekNext() == TOK.scope_)
+                        stc |= STC.returnScope;
                     goto L2;
                 L2:
                     storageClass = appendStorageClass(storageClass, stc);
@@ -3491,7 +3539,7 @@
         return baseclasses;
     }
 
-    private AST.Dsymbols* parseImport()
+    AST.Dsymbols* parseImport()
     {
         auto decldefs = new AST.Dsymbols();
         Identifier aliasid = null;
@@ -4453,7 +4501,6 @@
     private AST.Dsymbols* parseDeclarations(bool autodecl, PrefixAttributes!AST* pAttrs, const(char)* comment)
     {
         StorageClass storage_class = STC.undefined_;
-        TOK tok = TOK.reserved;
         LINK link = linkage;
         Loc linkloc = this.linkLoc;
         bool setAlignment = false;
@@ -4464,245 +4511,22 @@
         if (!comment)
             comment = token.blockComment.ptr;
 
-        /* Look for AliasAssignment:
-         *   identifier = type;
+        /* Look for AliasReassignment
          */
         if (token.value == TOK.identifier && peekNext() == TOK.assign)
-        {
-            const loc = token.loc;
-            auto ident = token.ident;
-            nextToken();
-            nextToken();        // advance past =
-            auto t = parseType();
-            AST.Dsymbol s = new AST.AliasAssign(loc, ident, t, null);
-            check(TOK.semicolon);
-            addComment(s, comment);
-            auto a = new AST.Dsymbols();
-            a.push(s);
-            return a;
-        }
+            return parseAliasReassignment(comment);
 
+        /* Declarations that start with `alias`
+         */
+        bool isAliasDeclaration = false;
         if (token.value == TOK.alias_)
         {
-            const loc = token.loc;
-            tok = token.value;
-            nextToken();
-
-            /* Look for:
-             *   alias identifier this;
-             */
-            if (token.value == TOK.identifier && peekNext() == TOK.this_)
-            {
-                auto s = new AST.AliasThis(loc, token.ident);
-                nextToken();
-                check(TOK.this_);
-                check(TOK.semicolon);
-                auto a = new AST.Dsymbols();
-                a.push(s);
-                addComment(s, comment);
+            if (auto a = parseAliasDeclarations(comment))
                 return a;
-            }
-            version (none)
-            {
-                /* Look for:
-                 *  alias this = identifier;
-                 */
-                if (token.value == TOK.this_ && peekNext() == TOK.assign && peekNext2() == TOK.identifier)
-                {
-                    check(TOK.this_);
-                    check(TOK.assign);
-                    auto s = new AliasThis(loc, token.ident);
-                    nextToken();
-                    check(TOK.semicolon);
-                    auto a = new Dsymbols();
-                    a.push(s);
-                    addComment(s, comment);
-                    return a;
-                }
-            }
-            /* Look for:
-             *  alias identifier = type;
-             *  alias identifier(...) = type;
+            /* Handle these later:
+             *   alias StorageClasses type ident;
              */
-            if (token.value == TOK.identifier && hasOptionalParensThen(peek(&token), TOK.assign))
-            {
-                auto a = new AST.Dsymbols();
-                while (1)
-                {
-                    auto ident = token.ident;
-                    nextToken();
-                    AST.TemplateParameters* tpl = null;
-                    if (token.value == TOK.leftParenthesis)
-                        tpl = parseTemplateParameterList();
-                    check(TOK.assign);
-
-                    bool hasParsedAttributes;
-                    void parseAttributes()
-                    {
-                        if (hasParsedAttributes) // only parse once
-                            return;
-                        hasParsedAttributes = true;
-                        udas = null;
-                        storage_class = STC.undefined_;
-                        link = linkage;
-                        linkloc = this.linkLoc;
-                        setAlignment = false;
-                        ealign = null;
-                        parseStorageClasses(storage_class, link, setAlignment, ealign, udas, linkloc);
-                    }
-
-                    if (token.value == TOK.at)
-                        parseAttributes;
-
-                    AST.Declaration v;
-                    AST.Dsymbol s;
-
-                    // try to parse function type:
-                    // TypeCtors? BasicType ( Parameters ) MemberFunctionAttributes
-                    bool attributesAppended;
-                    const StorageClass funcStc = parseTypeCtor();
-                    Token* tlu = &token;
-                    Token* tk;
-                    if (token.value != TOK.function_ &&
-                        token.value != TOK.delegate_ &&
-                        isBasicType(&tlu) && tlu &&
-                        tlu.value == TOK.leftParenthesis)
-                    {
-                        AST.Type tret = parseBasicType();
-                        auto parameterList = parseParameterList(null);
-
-                        parseAttributes();
-                        if (udas)
-                            error("user-defined attributes not allowed for `alias` declarations");
-
-                        attributesAppended = true;
-                        storage_class = appendStorageClass(storage_class, funcStc);
-                        AST.Type tf = new AST.TypeFunction(parameterList, tret, link, storage_class);
-                        v = new AST.AliasDeclaration(loc, ident, tf);
-                    }
-                    else if (token.value == TOK.function_ ||
-                        token.value == TOK.delegate_ ||
-                        token.value == TOK.leftParenthesis &&
-                            skipAttributes(peekPastParen(&token), &tk) &&
-                            (tk.value == TOK.goesTo || tk.value == TOK.leftCurly) ||
-                        token.value == TOK.leftCurly ||
-                        token.value == TOK.identifier && peekNext() == TOK.goesTo ||
-                        token.value == TOK.ref_ && peekNext() == TOK.leftParenthesis &&
-                            skipAttributes(peekPastParen(peek(&token)), &tk) &&
-                            (tk.value == TOK.goesTo || tk.value == TOK.leftCurly)
-                       )
-                    {
-                        // function (parameters) { statements... }
-                        // delegate (parameters) { statements... }
-                        // (parameters) { statements... }
-                        // (parameters) => expression
-                        // { statements... }
-                        // identifier => expression
-                        // ref (parameters) { statements... }
-                        // ref (parameters) => expression
-
-                        s = parseFunctionLiteral();
-
-                        if (udas !is null)
-                        {
-                            if (storage_class != 0)
-                                error("Cannot put a storage-class in an alias declaration.");
-                            // parseAttributes shouldn't have set these variables
-                            assert(link == linkage && !setAlignment && ealign is null);
-                            auto tpl_ = cast(AST.TemplateDeclaration) s;
-                            assert(tpl_ !is null && tpl_.members.dim == 1);
-                            auto fd = cast(AST.FuncLiteralDeclaration) (*tpl_.members)[0];
-                            auto tf = cast(AST.TypeFunction) fd.type;
-                            assert(tf.parameterList.parameters.dim > 0);
-                            auto as = new AST.Dsymbols();
-                            (*tf.parameterList.parameters)[0].userAttribDecl = new AST.UserAttributeDeclaration(udas, as);
-                        }
-
-                        v = new AST.AliasDeclaration(loc, ident, s);
-                    }
-                    else
-                    {
-                        parseAttributes();
-                        // type
-                        if (udas)
-                            error("user-defined attributes not allowed for `%s` declarations", Token.toChars(tok));
-
-                        auto t = parseType();
-
-                        // Disallow meaningless storage classes on type aliases
-                        if (storage_class)
-                        {
-                            // Don't raise errors for STC that are part of a function/delegate type, e.g.
-                            // `alias F = ref pure nothrow @nogc @safe int function();`
-                            auto tp = t.isTypePointer;
-                            const isFuncType = (tp && tp.next.isTypeFunction) || t.isTypeDelegate;
-                            const remStc = isFuncType ? (storage_class & ~STC.FUNCATTR) : storage_class;
-
-                            if (remStc)
-                            {
-                                OutBuffer buf;
-                                AST.stcToBuffer(&buf, remStc);
-                                // @@@DEPRECATED_2.093@@@
-                                // Deprecated in 2020-07, can be made an error in 2.103
-                                deprecation("storage class `%s` has no effect in type aliases", buf.peekChars());
-                            }
-                        }
-
-                        v = new AST.AliasDeclaration(loc, ident, t);
-                    }
-                    if (!attributesAppended)
-                        storage_class = appendStorageClass(storage_class, funcStc);
-                    v.storage_class = storage_class;
-
-                    s = v;
-                    if (tpl)
-                    {
-                        auto a2 = new AST.Dsymbols();
-                        a2.push(s);
-                        auto tempdecl = new AST.TemplateDeclaration(loc, ident, tpl, null, a2);
-                        s = tempdecl;
-                    }
-                    if (link != linkage)
-                    {
-                        auto a2 = new AST.Dsymbols();
-                        a2.push(s);
-                        s = new AST.LinkDeclaration(linkloc, link, a2);
-                    }
-                    a.push(s);
-
-                    switch (token.value)
-                    {
-                    case TOK.semicolon:
-                        nextToken();
-                        addComment(s, comment);
-                        break;
-
-                    case TOK.comma:
-                        nextToken();
-                        addComment(s, comment);
-                        if (token.value != TOK.identifier)
-                        {
-                            error("identifier expected following comma, not `%s`", token.toChars());
-                            break;
-                        }
-                        if (peekNext() != TOK.assign && peekNext() != TOK.leftParenthesis)
-                        {
-                            error("`=` expected following identifier");
-                            nextToken();
-                            break;
-                        }
-                        continue;
-
-                    default:
-                        error("semicolon expected to close `%s` declaration", Token.toChars(tok));
-                        break;
-                    }
-                    break;
-                }
-                return a;
-            }
-
-            // alias StorageClasses type ident;
+            isAliasDeclaration = true;
         }
 
         AST.Type ts;
@@ -4839,7 +4663,7 @@
             else if (!isThis && (t != AST.Type.terror))
                 error("no identifier for declarator `%s`", t.toChars());
 
-            if (tok == TOK.alias_)
+            if (isAliasDeclaration)
             {
                 AST.Declaration v;
                 AST.Initializer _init = null;
@@ -4852,7 +4676,7 @@
                  */
 
                 if (udas)
-                    error("user-defined attributes not allowed for `%s` declarations", Token.toChars(tok));
+                    error("user-defined attributes not allowed for `alias` declarations");
 
                 if (token.value == TOK.assign)
                 {
@@ -4901,7 +4725,7 @@
                     continue;
 
                 default:
-                    error("semicolon expected to close `%s` declaration", Token.toChars(tok));
+                    error("semicolon expected to close `alias` declaration");
                     break;
                 }
             }
@@ -5018,7 +4842,15 @@
                     continue;
 
                 default:
-                    error("semicolon expected, not `%s`", token.toChars());
+                    if (loc.linnum != token.loc.linnum)
+                    {
+                        error("semicolon needed to end declaration of `%s`, instead of `%s`", v.toChars(), token.toChars());
+                        errorSupplemental(loc, "`%s` declared here", v.toChars());
+                    }
+                    else
+                    {
+                        error("semicolon needed to end declaration of `%s` instead of `%s`", v.toChars(), token.toChars());
+                    }
                     break;
                 }
             }
@@ -5027,6 +4859,271 @@
         return a;
     }
 
+    /********************************
+     * Parse AliasReassignment:
+     *   identifier = type;
+     * Parser is sitting on the identifier.
+     * https://dlang.org/spec/declaration.html#alias-reassignment
+     * Params:
+     *  comment = if not null, comment to attach to symbol
+     * Returns:
+     *  array of symbols
+     */
+    private AST.Dsymbols* parseAliasReassignment(const(char)* comment)
+    {
+        const loc = token.loc;
+        auto ident = token.ident;
+        nextToken();
+        nextToken();        // advance past =
+        auto t = parseType();
+        AST.Dsymbol s = new AST.AliasAssign(loc, ident, t, null);
+        check(TOK.semicolon);
+        addComment(s, comment);
+        auto a = new AST.Dsymbols();
+        a.push(s);
+        return a;
+    }
+
+    /********************************
+     * Parse declarations that start with `alias`
+     * Parser is sitting on the `alias`.
+     * https://dlang.org/spec/declaration.html#alias
+     * Params:
+     *  comment = if not null, comment to attach to symbol
+     * Returns:
+     *  array of symbols
+     */
+    private AST.Dsymbols* parseAliasDeclarations(const(char)* comment)
+    {
+        const loc = token.loc;
+        nextToken();
+        Loc linkloc = this.linkLoc;
+        AST.Expressions* udas;
+        LINK link = linkage;
+        StorageClass storage_class = STC.undefined_;
+        AST.Expression ealign;
+        bool setAlignment = false;
+
+        /* Look for:
+         *   alias Identifier this;
+         * https://dlang.org/spec/class.html#alias-this
+         */
+        if (token.value == TOK.identifier && peekNext() == TOK.this_)
+        {
+            auto s = new AST.AliasThis(loc, token.ident);
+            nextToken();
+            check(TOK.this_);
+            check(TOK.semicolon);
+            auto a = new AST.Dsymbols();
+            a.push(s);
+            addComment(s, comment);
+            return a;
+        }
+        version (none)
+        {
+            /* Look for:
+             *  alias this = identifier;
+             */
+            if (token.value == TOK.this_ && peekNext() == TOK.assign && peekNext2() == TOK.identifier)
+            {
+                check(TOK.this_);
+                check(TOK.assign);
+                auto s = new AliasThis(loc, token.ident);
+                nextToken();
+                check(TOK.semicolon);
+                auto a = new Dsymbols();
+                a.push(s);
+                addComment(s, comment);
+                return a;
+            }
+        }
+        /* Look for:
+         *  alias identifier = type;
+         *  alias identifier(...) = type;
+         * https://dlang.org/spec/declaration.html#alias
+         */
+        if (token.value == TOK.identifier && hasOptionalParensThen(peek(&token), TOK.assign))
+        {
+            auto a = new AST.Dsymbols();
+            while (1)
+            {
+                auto ident = token.ident;
+                nextToken();
+                AST.TemplateParameters* tpl = null;
+                if (token.value == TOK.leftParenthesis)
+                    tpl = parseTemplateParameterList();
+                check(TOK.assign);
+
+                bool hasParsedAttributes;
+                void parseAttributes()
+                {
+                    if (hasParsedAttributes) // only parse once
+                        return;
+                    hasParsedAttributes = true;
+                    udas = null;
+                    storage_class = STC.undefined_;
+                    link = linkage;
+                    linkloc = this.linkLoc;
+                    setAlignment = false;
+                    ealign = null;
+                    parseStorageClasses(storage_class, link, setAlignment, ealign, udas, linkloc);
+                }
+
+                if (token.value == TOK.at)
+                    parseAttributes;
+
+                AST.Declaration v;
+                AST.Dsymbol s;
+
+                // try to parse function type:
+                // TypeCtors? BasicType ( Parameters ) MemberFunctionAttributes
+                bool attributesAppended;
+                const StorageClass funcStc = parseTypeCtor();
+                Token* tlu = &token;
+                Token* tk;
+                if (token.value != TOK.function_ &&
+                    token.value != TOK.delegate_ &&
+                    isBasicType(&tlu) && tlu &&
+                    tlu.value == TOK.leftParenthesis)
+                {
+                    AST.Type tret = parseBasicType();
+                    auto parameterList = parseParameterList(null);
+
+                    parseAttributes();
+                    if (udas)
+                        error("user-defined attributes not allowed for `alias` declarations");
+
+                    attributesAppended = true;
+                    storage_class = appendStorageClass(storage_class, funcStc);
+                    AST.Type tf = new AST.TypeFunction(parameterList, tret, link, storage_class);
+                    v = new AST.AliasDeclaration(loc, ident, tf);
+                }
+                else if (token.value == TOK.function_ ||
+                    token.value == TOK.delegate_ ||
+                    token.value == TOK.leftParenthesis &&
+                        skipAttributes(peekPastParen(&token), &tk) &&
+                        (tk.value == TOK.goesTo || tk.value == TOK.leftCurly) ||
+                    token.value == TOK.leftCurly ||
+                    token.value == TOK.identifier && peekNext() == TOK.goesTo ||
+                    token.value == TOK.ref_ && peekNext() == TOK.leftParenthesis &&
+                        skipAttributes(peekPastParen(peek(&token)), &tk) &&
+                        (tk.value == TOK.goesTo || tk.value == TOK.leftCurly)
+                   )
+                {
+                    // function (parameters) { statements... }
+                    // delegate (parameters) { statements... }
+                    // (parameters) { statements... }
+                    // (parameters) => expression
+                    // { statements... }
+                    // identifier => expression
+                    // ref (parameters) { statements... }
+                    // ref (parameters) => expression
+
+                    s = parseFunctionLiteral();
+
+                    if (udas !is null)
+                    {
+                        if (storage_class != 0)
+                            error("Cannot put a storage-class in an alias declaration.");
+                        // parseAttributes shouldn't have set these variables
+                        assert(link == linkage && !setAlignment && ealign is null);
+                        auto tpl_ = cast(AST.TemplateDeclaration) s;
+                        assert(tpl_ !is null && tpl_.members.dim == 1);
+                        auto fd = cast(AST.FuncLiteralDeclaration) (*tpl_.members)[0];
+                        auto tf = cast(AST.TypeFunction) fd.type;
+                        assert(tf.parameterList.parameters.dim > 0);
+                        auto as = new AST.Dsymbols();
+                        (*tf.parameterList.parameters)[0].userAttribDecl = new AST.UserAttributeDeclaration(udas, as);
+                    }
+
+                    v = new AST.AliasDeclaration(loc, ident, s);
+                }
+                else
+                {
+                    parseAttributes();
+                    // type
+                    if (udas)
+                        error("user-defined attributes not allowed for alias declarations");
+
+                    auto t = parseType();
+
+                    // Disallow meaningless storage classes on type aliases
+                    if (storage_class)
+                    {
+                        // Don't raise errors for STC that are part of a function/delegate type, e.g.
+                        // `alias F = ref pure nothrow @nogc @safe int function();`
+                        auto tp = t.isTypePointer;
+                        const isFuncType = (tp && tp.next.isTypeFunction) || t.isTypeDelegate;
+                        const remStc = isFuncType ? (storage_class & ~STC.FUNCATTR) : storage_class;
+
+                        if (remStc)
+                        {
+                            OutBuffer buf;
+                            AST.stcToBuffer(&buf, remStc);
+                            // @@@DEPRECATED_2.093@@@
+                            // Deprecated in 2020-07, can be made an error in 2.103
+                            deprecation("storage class `%s` has no effect in type aliases", buf.peekChars());
+                        }
+                    }
+
+                    v = new AST.AliasDeclaration(loc, ident, t);
+                }
+                if (!attributesAppended)
+                    storage_class = appendStorageClass(storage_class, funcStc);
+                v.storage_class = storage_class;
+
+                s = v;
+                if (tpl)
+                {
+                    auto a2 = new AST.Dsymbols();
+                    a2.push(s);
+                    auto tempdecl = new AST.TemplateDeclaration(loc, ident, tpl, null, a2);
+                    s = tempdecl;
+                }
+                if (link != linkage)
+                {
+                    auto a2 = new AST.Dsymbols();
+                    a2.push(s);
+                    s = new AST.LinkDeclaration(linkloc, link, a2);
+                }
+                a.push(s);
+
+                switch (token.value)
+                {
+                case TOK.semicolon:
+                    nextToken();
+                    addComment(s, comment);
+                    break;
+
+                case TOK.comma:
+                    nextToken();
+                    addComment(s, comment);
+                    if (token.value != TOK.identifier)
+                    {
+                        error("identifier expected following comma, not `%s`", token.toChars());
+                        break;
+                    }
+                    if (peekNext() != TOK.assign && peekNext() != TOK.leftParenthesis)
+                    {
+                        error("`=` expected following identifier");
+                        nextToken();
+                        break;
+                    }
+                    continue;
+
+                default:
+                    error("semicolon expected to close `alias` declaration");
+                    break;
+                }
+                break;
+            }
+            return a;
+        }
+
+        // alias StorageClasses type ident;
+        return null;
+    }
+
     private AST.Dsymbol parseFunctionLiteral()
     {
         const loc = token.loc;
@@ -5390,6 +5487,7 @@
         check(TOK.leftParenthesis);
 
         auto parameters = new AST.Parameters();
+        Identifier lastai;
         while (1)
         {
             Identifier ai = null;
@@ -5465,8 +5563,9 @@
             if (token.value == TOK.identifier)
             {
                 const tv = peekNext();
-                if (tv == TOK.comma || tv == TOK.semicolon)
+                if (tv == TOK.comma || tv == TOK.semicolon || tv == TOK.rightParenthesis)
                 {
+                    lastai = token.ident;
                     ai = token.ident;
                     at = null; // infer argument type
                     nextToken();
@@ -5486,7 +5585,17 @@
             }
             break;
         }
-        check(TOK.semicolon);
+        if (token.value != TOK.semicolon)
+        {
+            error("missing `; expression` before `)` of `foreach`");
+            nextToken();
+            if (lastai && parameters.length >= 2)
+            {
+                errorSupplemental(loc, "perhaps the `;` goes before `%s`", lastai.toChars());
+            }
+            return null;
+        }
+        nextToken();
 
         AST.Expression aggr = parseExpression();
         if (token.value == TOK.slice && parameters.dim == 1)
@@ -8473,6 +8582,7 @@
                 e = new AST.FuncExp(loc, s);
                 break;
             }
+
         default:
             error("expression expected, not `%s`", token.toChars());
         Lerr:
@@ -8766,6 +8876,17 @@
                 e = parsePostExp(e);
                 break;
             }
+        case TOK.throw_:
+            {
+                nextToken();
+                // Deviation from the DIP:
+                // Parse AssignExpression instead of Expression to avoid conflicts for comma
+                // separated lists, e.g. function arguments
+                AST.Expression exp = parseAssignExp();
+                e = new AST.ThrowExp(loc, exp);
+                break;
+            }
+
         default:
             e = parsePrimaryExp();
             e = parsePostExp(e);
diff --git a/gcc/d/dmd/parsetimevisitor.d b/gcc/d/dmd/parsetimevisitor.d
index d3e3086..7d5e19d 100644
--- a/gcc/d/dmd/parsetimevisitor.d
+++ b/gcc/d/dmd/parsetimevisitor.d
@@ -220,6 +220,7 @@
     void visit(AST.CallExp e) { visit(cast(AST.UnaExp)e); }
     void visit(AST.DotIdExp e) { visit(cast(AST.UnaExp)e); }
     void visit(AST.AssertExp e) { visit(cast(AST.UnaExp)e); }
+    void visit(AST.ThrowExp e) { visit(cast(AST.UnaExp)e); }
     void visit(AST.ImportExp e) { visit(cast(AST.UnaExp)e); }
     void visit(AST.DotTemplateInstanceExp e) { visit(cast(AST.UnaExp)e); }
     void visit(AST.ArrayExp e) { visit(cast(AST.UnaExp)e); }
diff --git a/gcc/d/dmd/root/README.md b/gcc/d/dmd/root/README.md
index b393c12..464f338 100644
--- a/gcc/d/dmd/root/README.md
+++ b/gcc/d/dmd/root/README.md
@@ -13,6 +13,7 @@
 | [hash.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/hash.d)               | Calculate a hash for a byte array                                                          |
 | [longdouble.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/longdouble.d)   | 80-bit floating point number implementation in case they are not natively supported        |
 | [man.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/man.d)                 | Opens an online manual page                                                                |
+| [optional.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/optional.d)       | Implementation of an 'Optional' type                                                       |
 | [port.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/port.d)               | Portable routines for functions that have different implementations on different platforms |
 | [region.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/region.d)           | A region allocator                                                                         |
 | [response.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/response.d)       | Parse command line arguments from response files                                           |
diff --git a/gcc/d/dmd/root/optional.d b/gcc/d/dmd/root/optional.d
index bb8150f..f2f7389 100644
--- a/gcc/d/dmd/root/optional.d
+++ b/gcc/d/dmd/root/optional.d
@@ -1,5 +1,5 @@
 /**
- * Optional implementation.
+ * Implementation of an 'Optional' type
  *
  * Copyright:   Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved
  * Authors:     $(LINK2 https://www.digitalmars.com, Walter Bright)
diff --git a/gcc/d/dmd/sideeffect.d b/gcc/d/dmd/sideeffect.d
index d365049..5691f3b 100644
--- a/gcc/d/dmd/sideeffect.d
+++ b/gcc/d/dmd/sideeffect.d
@@ -94,8 +94,9 @@
  * Determine if the call of f, or function type or delegate type t1, has any side effects.
  * Returns:
  *      0   has any side effects
- *      1   nothrow + constant purity
- *      2   nothrow + strong purity
+ *      1   nothrow + strongly pure
+ *      2   nothrow + strongly pure + only immutable indirections in the return
+ *          type
  */
 int callSideEffectLevel(FuncDeclaration f)
 {
@@ -106,15 +107,18 @@
         return 0;
     assert(f.type.ty == Tfunction);
     TypeFunction tf = cast(TypeFunction)f.type;
-    if (tf.isnothrow)
+    if (!tf.isnothrow)
+        return 0;
+    final switch (f.isPure())
     {
-        PURE purity = f.isPure();
-        if (purity == PURE.strong)
-            return 2;
-        if (purity == PURE.const_)
-            return 1;
+    case PURE.impure:
+    case PURE.fwdref:
+    case PURE.weak:
+        return 0;
+
+    case PURE.const_:
+        return mutabilityOfType(tf.isref, tf.next) == 2 ? 2 : 1;
     }
-    return 0;
 }
 
 int callSideEffectLevel(Type t)
@@ -141,10 +145,9 @@
             purity = PURE.const_;
     }
 
-    if (purity == PURE.strong)
-        return 2;
     if (purity == PURE.const_)
-        return 1;
+        return mutabilityOfType(tf.isref, tf.next) == 2 ? 2 : 1;
+
     return 0;
 }
 
@@ -178,6 +181,7 @@
     case EXP.remove:
     case EXP.assert_:
     case EXP.halt:
+    case EXP.throw_:
     case EXP.delete_:
     case EXP.new_:
     case EXP.newAnonymousClass:
diff --git a/gcc/d/dmd/statement.d b/gcc/d/dmd/statement.d
index be568f5..8b271f8 100644
--- a/gcc/d/dmd/statement.d
+++ b/gcc/d/dmd/statement.d
@@ -21,7 +21,6 @@
 import dmd.astenums;
 import dmd.ast_node;
 import dmd.gluelayer;
-import dmd.canthrow;
 import dmd.cond;
 import dmd.dclass;
 import dmd.declaration;
diff --git a/gcc/d/dmd/statement.h b/gcc/d/dmd/statement.h
index dfb65a1..66eddd8 100644
--- a/gcc/d/dmd/statement.h
+++ b/gcc/d/dmd/statement.h
@@ -45,7 +45,7 @@
 
 /* How a statement exits; this is returned by blockExit()
  */
-enum BE
+enum BE : int32_t
 {
     BEnone =     0,
     BEfallthru = 1,
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index faeba114..1f7f3e4 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -122,8 +122,10 @@
  * Returns:
  *  `e` or ErrorExp.
  */
-private Expression checkAssignmentAsCondition(Expression e)
+private Expression checkAssignmentAsCondition(Expression e, Scope* sc)
 {
+    if (sc.flags & SCOPE.Cfile)
+        return e;
     auto ec = lastComma(e);
     if (ec.op == EXP.assign)
     {
@@ -148,7 +150,7 @@
     return v.result;
 }
 
-private extern (C++) final class StatementSemanticVisitor : Visitor
+package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
 {
     alias visit = Visitor.visit;
 
@@ -550,7 +552,7 @@
             (cast(DotIdExp)ds.condition).noderef = true;
 
         // check in syntax level
-        ds.condition = checkAssignmentAsCondition(ds.condition);
+        ds.condition = checkAssignmentAsCondition(ds.condition, sc);
 
         ds.condition = ds.condition.expressionSemantic(sc);
         ds.condition = resolveProperties(sc, ds.condition);
@@ -623,7 +625,7 @@
                 (cast(DotIdExp)fs.condition).noderef = true;
 
             // check in syntax level
-            fs.condition = checkAssignmentAsCondition(fs.condition);
+            fs.condition = checkAssignmentAsCondition(fs.condition, sc);
 
             fs.condition = fs.condition.expressionSemantic(sc);
             fs.condition = resolveProperties(sc, fs.condition);
@@ -1867,7 +1869,7 @@
          */
 
         // check in syntax level
-        ifs.condition = checkAssignmentAsCondition(ifs.condition);
+        ifs.condition = checkAssignmentAsCondition(ifs.condition, sc);
 
         auto sym = new ScopeDsymbol();
         sym.parent = sc.scopesym;
@@ -3732,44 +3734,61 @@
          */
 
         //printf("ThrowStatement::semantic()\n");
+        if (throwSemantic(ts.loc, ts.exp, sc))
+            result = ts;
+        else
+            setError();
 
+    }
+
+    /**
+     * Run semantic on `throw <exp>`.
+     *
+     * Params:
+     *   loc = location of the `throw`
+     *   exp = value to be thrown
+     *   sc  = enclosing scope
+     *
+     * Returns: true if the `throw` is valid, or false if an error was found
+     */
+    extern(D) static bool throwSemantic(const ref Loc loc, ref Expression exp, Scope* sc)
+    {
         if (!global.params.useExceptions)
         {
-            ts.error("Cannot use `throw` statements with -betterC");
-            return setError();
+            loc.error("Cannot use `throw` statements with -betterC");
+            return false;
         }
 
         if (!ClassDeclaration.throwable)
         {
-            ts.error("Cannot use `throw` statements because `object.Throwable` was not declared");
-            return setError();
+            loc.error("Cannot use `throw` statements because `object.Throwable` was not declared");
+            return false;
         }
 
-        FuncDeclaration fd = sc.parent.isFuncDeclaration();
-        fd.hasReturnExp |= 2;
+        if (FuncDeclaration fd = sc.parent.isFuncDeclaration())
+            fd.hasReturnExp |= 2;
 
-        if (ts.exp.op == EXP.new_)
+        if (exp.op == EXP.new_)
         {
-            NewExp ne = cast(NewExp)ts.exp;
+            NewExp ne = cast(NewExp) exp;
             ne.thrownew = true;
         }
 
-        ts.exp = ts.exp.expressionSemantic(sc);
-        ts.exp = resolveProperties(sc, ts.exp);
-        ts.exp = checkGC(sc, ts.exp);
-        if (ts.exp.op == EXP.error)
-            return setError();
+        exp = exp.expressionSemantic(sc);
+        exp = resolveProperties(sc, exp);
+        exp = checkGC(sc, exp);
+        if (exp.op == EXP.error)
+            return false;
 
-        checkThrowEscape(sc, ts.exp, false);
+        checkThrowEscape(sc, exp, false);
 
-        ClassDeclaration cd = ts.exp.type.toBasetype().isClassHandle();
+        ClassDeclaration cd = exp.type.toBasetype().isClassHandle();
         if (!cd || ((cd != ClassDeclaration.throwable) && !ClassDeclaration.throwable.isBaseOf(cd, null)))
         {
-            ts.error("can only throw class objects derived from `Throwable`, not type `%s`", ts.exp.type.toChars());
-            return setError();
+            loc.error("can only throw class objects derived from `Throwable`, not type `%s`", exp.type.toChars());
+            return false;
         }
-
-        result = ts;
+        return true;
     }
 
     override void visit(DebugStatement ds)
diff --git a/gcc/d/dmd/staticcond.d b/gcc/d/dmd/staticcond.d
index 6ff166a..0cbdd96 100644
--- a/gcc/d/dmd/staticcond.d
+++ b/gcc/d/dmd/staticcond.d
@@ -109,18 +109,16 @@
         e = e.ctfeInterpret();
 
         const opt = e.toBool();
-        if (opt.hasValue(true))
-            return true;
-        else if (opt.hasValue(false))
+        if (opt.isEmpty())
         {
-            if (negatives)
-                negatives.push(before);
+            e.error("expression `%s` is not constant", e.toChars());
+            errors = true;
             return false;
         }
 
-        e.error("expression `%s` is not constant", e.toChars());
-        errors = true;
-        return false;
+        if (negatives && !opt.get())
+            negatives.push(before);
+        return opt.get();
     }
     return impl(e);
 }
diff --git a/gcc/d/dmd/target.d b/gcc/d/dmd/target.d
index 619304d..e954625 100644
--- a/gcc/d/dmd/target.d
+++ b/gcc/d/dmd/target.d
@@ -61,8 +61,8 @@
     import dmd.dscope : Scope;
     import dmd.expression : Expression;
     import dmd.func : FuncDeclaration;
-    import dmd.globals : LINK, Loc, d_int64;
-    import dmd.astenums : TY;
+    import dmd.globals : Loc, d_int64;
+    import dmd.astenums : LINK, TY;
     import dmd.mtype : Type, TypeFunction, TypeTuple;
     import dmd.root.ctfloat : real_t;
     import dmd.statement : Statement;
@@ -119,7 +119,7 @@
     const(char)[] lib_ext;    /// extension for static library files
     const(char)[] dll_ext;    /// extension for dynamic library files
     bool run_noext;           /// allow -run sources without extensions
-    bool mscoff = false;      // for Win32: write MsCoff object files instead of OMF
+    bool omfobj = false;      // for Win32: write OMF object files instead of MsCoff
     /**
      * Values representing all properties for floating point types
      */
@@ -293,6 +293,13 @@
      *      `false` if the target backend handles synchronizing monitors.
      */
     extern (C++) bool libraryObjectMonitors(FuncDeclaration fd, Statement fbody);
+
+    /**
+     * Returns true if the target supports `pragma(linkerDirective)`.
+     * Returns:
+     *      `false` if the target does not support `pragma(linkerDirective)`.
+     */
+    extern (C++) bool supportsLinkerDirective() const;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -340,7 +347,7 @@
     import dmd.dsymbol : Dsymbol;
     import dmd.dclass : ClassDeclaration;
     import dmd.func : FuncDeclaration;
-    import dmd.mtype : Parameter, Type;
+    import dmd.mtype : Type;
 
     enum Runtime : ubyte
     {
@@ -354,6 +361,7 @@
     bool reverseOverloads;    /// set if overloaded functions are grouped and in reverse order (such as in dmc and cl)
     bool exceptions;          /// set if catching C++ exceptions is supported
     bool twoDtorInVtable;     /// target C++ ABI puts deleting and non-deleting destructor into vtable
+    bool splitVBasetable;     /// set if C++ ABI uses separate tables for virtual functions and virtual bases
     bool wrapDtorInExternD;   /// set if C++ dtors require a D wrapper to be callable from runtime
     Runtime runtime;          /// vendor of the C++ runtime to link against
 
@@ -398,13 +406,13 @@
 
     /**
      * Get the type that will really be used for passing the given argument
-     * to an `extern(C++)` function.
+     * to an `extern(C++)` function, or `null` if unhandled.
      * Params:
-     *      p = parameter to be passed.
+     *      t = type to be passed.
      * Returns:
-     *      `Type` to use for parameter `p`.
+     *      `Type` to use for type `t`.
      */
-    extern (C++) Type parameterType(Parameter p);
+    extern (C++) Type parameterType(Type t);
 
     /**
      * Checks whether type is a vendor-specific fundamental type.
diff --git a/gcc/d/dmd/target.h b/gcc/d/dmd/target.h
index 9c879de..fdae14c 100644
--- a/gcc/d/dmd/target.h
+++ b/gcc/d/dmd/target.h
@@ -20,7 +20,6 @@
 class Dsymbol;
 class Expression;
 class FuncDeclaration;
-class Parameter;
 class Statement;
 class Type;
 class TypeTuple;
@@ -92,6 +91,7 @@
     bool reverseOverloads;    // with dmc and cl, overloaded functions are grouped and in reverse order
     bool exceptions;          // set if catching C++ exceptions is supported
     bool twoDtorInVtable;     // target C++ ABI puts deleting and non-deleting destructor into vtable
+    bool splitVBasetable;     // set if C++ ABI uses separate tables for virtual functions and virtual bases
     bool wrapDtorInExternD;   // set if C++ dtors require a D wrapper to be callable from runtime
     Runtime runtime;
 
@@ -99,7 +99,7 @@
     const char *typeInfoMangle(ClassDeclaration *cd);
     const char *thunkMangle(FuncDeclaration *fd, int offset);
     const char *typeMangle(Type *t);
-    Type *parameterType(Parameter *p);
+    Type *parameterType(Type *p);
     bool fundamentalType(const Type *t, bool& isFundamental);
     unsigned derivedClassOffset(ClassDeclaration *baseClass);
 };
@@ -160,7 +160,7 @@
     DString lib_ext;    /// extension for static library files
     DString dll_ext;    /// extension for dynamic library files
     bool run_noext;     /// allow -run sources without extensions
-    bool mscoff;        /// for Win32: write COFF object files instead of OMF
+    bool omfobj;        /// for Win32: write OMF object files instead of COFF
 
     template <typename T>
     struct FPTypeProperties
@@ -205,6 +205,7 @@
     Expression *getTargetInfo(const char* name, const Loc& loc);
     bool isCalleeDestroyingArgs(TypeFunction* tf);
     bool libraryObjectMonitors(FuncDeclaration *fd, Statement *fbody);
+    bool supportsLinkerDirective() const;
     void addPredefinedGlobalIdentifiers() const;
 };
 
diff --git a/gcc/d/dmd/template.h b/gcc/d/dmd/template.h
index 95cd349..42517f6 100644
--- a/gcc/d/dmd/template.h
+++ b/gcc/d/dmd/template.h
@@ -284,6 +284,7 @@
     Identifier *getIdent();
     hash_t toHash();
 
+    bool isDiscardable();
     bool needsCodegen();
 
     TemplateInstance *isTemplateInstance() { return this; }
diff --git a/gcc/d/dmd/tokens.d b/gcc/d/dmd/tokens.d
index 5830dbb..20b8711 100644
--- a/gcc/d/dmd/tokens.d
+++ b/gcc/d/dmd/tokens.d
@@ -278,6 +278,7 @@
     _Thread_local,
 
     // C only extended keywords
+    _import,
     __cdecl,
     __declspec,
     __attribute__,
@@ -585,6 +586,7 @@
     TOK._Thread_local,
 
     // C only extended keywords
+    TOK._import,
     TOK.__cdecl,
     TOK.__declspec,
     TOK.__attribute__,
@@ -615,7 +617,7 @@
                        restrict, return_, int16, signed, sizeof_, static_, struct_, switch_, typedef_,
                        union_, unsigned, void_, volatile, while_, asm_,
                        _Alignas, _Alignof, _Atomic, _Bool, _Complex, _Generic, _Imaginary, _Noreturn,
-                       _Static_assert, _Thread_local, __cdecl, __declspec, __attribute__ ];
+                       _Static_assert, _Thread_local, _import, __cdecl, __declspec, __attribute__ ];
 
         foreach (kw; Ckwds)
             tab[kw] = cast(TOK) kw;
@@ -891,6 +893,7 @@
         TOK._Thread_local  : "_Thread_local",
 
         // C only extended keywords
+        TOK._import       : "__import",
         TOK.__cdecl        : "__cdecl",
         TOK.__declspec     : "__declspec",
         TOK.__attribute__  : "__attribute__",
diff --git a/gcc/d/dmd/tokens.h b/gcc/d/dmd/tokens.h
index 0a00ae7..a7c9aa5 100644
--- a/gcc/d/dmd/tokens.h
+++ b/gcc/d/dmd/tokens.h
@@ -287,6 +287,7 @@
     _Thread_local_,
 
     // C only extended keywords
+    _import,
     cdecl,
     declspec,
     attribute__,
diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d
index ae8ab9b..ec86bc5 100644
--- a/gcc/d/dmd/traits.d
+++ b/gcc/d/dmd/traits.d
@@ -150,6 +150,7 @@
         "hasPostblit",
         "hasCopyConstructor",
         "isCopyable",
+        "parameters"
     ];
 
     StringTable!(bool)* stringTable = cast(StringTable!(bool)*) &traitsStringTable;
@@ -998,7 +999,7 @@
                 e.error("`bool` expected as third argument of `__traits(getOverloads)`, not `%s` of type `%s`", b.toChars(), b.type.toChars());
                 return ErrorExp.get();
             }
-            includeTemplates = b.toBool().hasValue(true);
+            includeTemplates = b.toBool().get();
         }
 
         StringExp se = ex.toStringExp();
@@ -2090,7 +2091,43 @@
         auto tup = new TupleExp(e.loc, exps);
         return tup.expressionSemantic(sc);
     }
+    //https://issues.dlang.org/show_bug.cgi?id=22291
+    if (e.ident == Id.parameters)
+    {
+        //No args are valid
+        if (e.args)
+        {
+            char[] contents = cast(char[]) e.args.toString();
+            contents = contents[1..$];
+            contents[$-1] = '\0';
+            e.error("`__traits(parameters)` cannot have arguments, but `%s` was supplied", contents.ptr);
+            return ErrorExp.get();
+        }
 
+        if (sc.func is null)
+        {
+            e.error("`__traits(parameters)` may only be used inside a function");
+            return ErrorExp.get();
+        }
+        assert(sc.func && sc.parent.isFuncDeclaration());
+        auto tf = sc.parent.isFuncDeclaration.type.isTypeFunction();
+        assert(tf);
+        auto exps = new Expressions(0);
+        int addParameterDG(size_t idx, Parameter x)
+        {
+            assert(x.ident);
+            exps.push(new IdentifierExp(e.loc, x.ident));
+            return 0;
+        }
+        /*
+            This is required since not all "parameters" actually have a name
+            until they (tuples) are expanded e.g. an anonymous tuple parameter's
+            contents get given names but not the tuple itself.
+        */
+        Parameter._foreach(tf.parameterList.parameters, &addParameterDG);
+        auto tup = new TupleExp(e.loc, exps);
+        return tup.expressionSemantic(sc);
+    }
     static const(char)[] trait_search_fp(const(char)[] seed, out int cost)
     {
         //printf("trait_search_fp('%s')\n", seed);
diff --git a/gcc/d/dmd/transitivevisitor.d b/gcc/d/dmd/transitivevisitor.d
index 0479d5a..8b6ca65 100644
--- a/gcc/d/dmd/transitivevisitor.d
+++ b/gcc/d/dmd/transitivevisitor.d
@@ -1141,6 +1141,12 @@
         }
     }
 
+    override void visit(AST.ThrowExp e)
+    {
+        //printf("Visiting ThrowExp\n");
+        e.e1.accept(this);
+    }
+
 // Template Parameter
 //===========================================================
 
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index 34b363d..e11f1f7 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -2062,7 +2062,7 @@
             switch (mtype.tok)
             {
                 case TOK.enum_:
-                    auto ed = new EnumDeclaration(mtype.loc, mtype.id, Type.tint32);
+                    auto ed = new EnumDeclaration(mtype.loc, mtype.id, mtype.base);
                     declare(ed);
                     mtype.resolved = visitEnum(new TypeEnum(ed));
                     break;
@@ -3940,7 +3940,7 @@
 
             e = new TupleExp(e.loc, e0, exps);
             Scope* sc2 = sc.push();
-            sc2.flags |= global.params.useDIP1000 == FeatureState.enabled ? SCOPE.onlysafeaccess : SCOPE.noaccesscheck;
+            sc2.flags |= SCOPE.noaccesscheck;
             e = e.expressionSemantic(sc2);
             sc2.pop();
             return e;
@@ -4201,7 +4201,7 @@
 
             e = new TupleExp(e.loc, e0, exps);
             Scope* sc2 = sc.push();
-            sc2.flags |= global.params.useDIP1000 == FeatureState.enabled ? SCOPE.onlysafeaccess : SCOPE.noaccesscheck;
+            sc2.flags |= SCOPE.noaccesscheck;
             e = e.expressionSemantic(sc2);
             sc2.pop();
             return e;
diff --git a/gcc/d/dmd/visitor.h b/gcc/d/dmd/visitor.h
index 5bad56b..5d6b94c 100644
--- a/gcc/d/dmd/visitor.h
+++ b/gcc/d/dmd/visitor.h
@@ -220,6 +220,7 @@
 class MixinExp;
 class ImportExp;
 class AssertExp;
+class ThrowExp;
 class DotIdExp;
 class DotTemplateExp;
 class DotVarExp;
@@ -511,6 +512,7 @@
     virtual void visit(CallExp *e) { visit((UnaExp *)e); }
     virtual void visit(DotIdExp *e) { visit((UnaExp *)e); }
     virtual void visit(AssertExp *e) { visit((UnaExp *)e); }
+    virtual void visit(ThrowExp *e) { visit((UnaExp *)e); }
     virtual void visit(ImportExp *e) { visit((UnaExp *)e); }
     virtual void visit(DotTemplateInstanceExp *e) { visit((UnaExp *)e); }
     virtual void visit(ArrayExp *e) { visit((UnaExp *)e); }
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index f8d6876..dd7ebc8 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -1186,6 +1186,14 @@
     this->result_ = build_assign (modifycode, t1, t2);
   }
 
+  /* Build a throw expression.  */
+
+  void visit (ThrowExp *e)
+  {
+    tree arg = build_expr_dtor (e->e1);
+    this->result_ = build_libcall (LIBCALL_THROW, Type::tvoid, 1, arg);
+  }
+
   /* Build a postfix expression.  */
 
   void visit (PostExp *e)
diff --git a/gcc/d/types.cc b/gcc/d/types.cc
index 4b6d245..8ae6ea1 100644
--- a/gcc/d/types.cc
+++ b/gcc/d/types.cc
@@ -274,6 +274,72 @@
   TYPE_FIELDS (type) = chainon (TYPE_FIELDS (type), field);
 }
 
+/* Build a bit-field integer type for the given WIDTH and UNSIGNEDP.  */
+
+static tree
+d_build_bitfield_integer_type (unsigned HOST_WIDE_INT width, int unsignedp)
+{
+  /* Same as d_type_for_size, but uses exact match for size.  */
+  if (width == TYPE_PRECISION (d_byte_type))
+    return unsignedp ? d_ubyte_type : d_byte_type;
+
+  if (width == TYPE_PRECISION (d_short_type))
+    return unsignedp ? d_ushort_type : d_short_type;
+
+  if (width == TYPE_PRECISION (d_int_type))
+    return unsignedp ? d_uint_type : d_int_type;
+
+  if (width == TYPE_PRECISION (d_long_type))
+    return unsignedp ? d_ulong_type : d_long_type;
+
+  if (width == TYPE_PRECISION (d_cent_type))
+    return unsignedp ? d_ucent_type : d_cent_type;
+
+  for (int i = 0; i < NUM_INT_N_ENTS; i ++)
+    {
+      if (int_n_enabled_p[i] && width == int_n_data[i].bitsize)
+	{
+	  if (unsignedp)
+	    return int_n_trees[i].unsigned_type;
+	  else
+	    return int_n_trees[i].signed_type;
+	}
+    }
+
+  return build_nonstandard_integer_type (width, unsignedp);
+}
+
+/* Adds BITFIELD into the aggregate TYPE at OFFSET+BITOFFSET.  */
+
+static void
+insert_aggregate_bitfield (tree type, tree bitfield, size_t width,
+			   size_t offset, size_t bitoffset)
+{
+  DECL_FIELD_CONTEXT (bitfield) = type;
+  SET_DECL_OFFSET_ALIGN (bitfield, TYPE_ALIGN (TREE_TYPE (bitfield)));
+  DECL_SIZE (bitfield) = bitsize_int (width);
+  DECL_FIELD_OFFSET (bitfield) = size_int (offset);
+  DECL_FIELD_BIT_OFFSET (bitfield) = bitsize_int (bitoffset);
+
+  TREE_ADDRESSABLE (bitfield) = TYPE_SHARED (TREE_TYPE (bitfield));
+
+  DECL_BIT_FIELD (bitfield) = 1;
+  DECL_BIT_FIELD_TYPE (bitfield) = TREE_TYPE (bitfield);
+
+  layout_decl (bitfield, 0);
+
+  /* Give bit-field its proper type after layout_decl.  */
+  tree orig_type = DECL_BIT_FIELD_TYPE (bitfield);
+  if (width != TYPE_PRECISION (orig_type))
+    {
+      TREE_TYPE (bitfield)
+    	= d_build_bitfield_integer_type (width, TYPE_UNSIGNED (orig_type));
+      SET_DECL_MODE (bitfield, TYPE_MODE (TREE_TYPE (bitfield)));
+    }
+
+  TYPE_FIELDS (type) = chainon (TYPE_FIELDS (type), bitfield);
+}
+
 /* For all decls in the FIELDS chain, adjust their field offset by OFFSET.
    This is done as the frontend puts fields into the outer struct, and so
    their offset is from the beginning of the aggregate.
@@ -356,7 +422,16 @@
 	      tree field = create_field_decl (declaration_type (var), ident,
 					      inherited_p, inherited_p);
 	      apply_user_attributes (var, field);
-	      insert_aggregate_field (context, field, var->offset);
+
+	      if (BitFieldDeclaration *bf = var->isBitFieldDeclaration ())
+		{
+		  /* Bit-fields come from an ImportC context, and require the
+		     field be correctly adjusted.  */
+		  insert_aggregate_bitfield (context, field, bf->fieldWidth,
+					     bf->offset, bf->bitOffset);
+		}
+	      else
+  		insert_aggregate_field (context, field, var->offset);
 
 	      /* Because the front-end shares field decls across classes, don't
 		 create the corresponding back-end symbol unless we are adding
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index b49ba22..e1a00c8 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -5641,8 +5641,10 @@
 
 The effectiveness of some warnings depends on optimizations also being
 enabled. For example @option{-Wsuggest-final-types} is more effective
-with link-time optimization and @option{-Wmaybe-uninitialized} does not
-warn at all unless optimization is enabled.
+with link-time optimization and some instances of other warnings may
+not be issued at all unless optimization is enabled.  While optimization
+in general improves the efficacy of control and data flow sensitive
+warnings, in some cases it may also cause false positives.
 
 @table @gcctabopt
 @item -Wpedantic
@@ -7691,20 +7693,22 @@
 @itemx -Warray-bounds=@var{n}
 @opindex Wno-array-bounds
 @opindex Warray-bounds
-This option is only active when @option{-ftree-vrp} is active
-(default for @option{-O2} and above). It warns about subscripts to arrays
-that are always out of bounds. This warning is enabled by @option{-Wall}.
+Warn about out of bounds subscripts or offsets into arrays.  This warning
+is enabled by @option{-Wall}.  It is more effective when @option{-ftree-vrp}
+is active (the default for @option{-O2} and above) but a subset of instances
+are issued even without optimization.
 
 @table @gcctabopt
 @item -Warray-bounds=1
-This is the warning level of @option{-Warray-bounds} and is enabled
+This is the default warning level of @option{-Warray-bounds} and is enabled
 by @option{-Wall}; higher levels are not, and must be explicitly requested.
 
 @item -Warray-bounds=2
-This warning level also warns about out of bounds access for
-arrays at the end of a struct and for arrays accessed through
-pointers. This warning level may give a larger number of
-false positives and is deactivated by default.
+This warning level also warns about out of bounds accesses to trailing
+struct members of one-element array types (@pxref{Zero Length}) and about
+the intermediate results of pointer arithmetic that may yield out of bounds
+values.  This warning level may give a larger number of false positives and
+is deactivated by default.
 @end table
 
 @item -Warray-compare
diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index 386d573..7b21240 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -8643,7 +8643,7 @@
    the buffer PTR of length LEN as a REAL_CST of type TYPE.
    If the buffer cannot be interpreted, return NULL_TREE.  */
 
-static tree
+tree
 native_interpret_real (tree type, const unsigned char *ptr, int len)
 {
   scalar_float_mode mode = SCALAR_FLOAT_TYPE_MODE (type);
@@ -8694,19 +8694,7 @@
     }
 
   real_from_target (&r, tmp, mode);
-  tree ret = build_real (type, r);
-  if (MODE_COMPOSITE_P (mode))
-    {
-      /* For floating point values in composite modes, punt if this folding
-	 doesn't preserve bit representation.  As the mode doesn't have fixed
-	 precision while GCC pretends it does, there could be valid values that
-	 GCC can't really represent accurately.  See PR95450.  */
-      unsigned char buf[24];
-      if (native_encode_expr (ret, buf, total_bytes, 0) != total_bytes
-	  || memcmp (ptr, buf, total_bytes) != 0)
-	ret = NULL_TREE;
-    }
-  return ret;
+  return build_real (type, r);
 }
 
 
@@ -8824,7 +8812,23 @@
       return native_interpret_int (type, ptr, len);
 
     case REAL_TYPE:
-      return native_interpret_real (type, ptr, len);
+      if (tree ret = native_interpret_real (type, ptr, len))
+	{
+	  /* For floating point values in composite modes, punt if this
+	     folding doesn't preserve bit representation.  As the mode doesn't
+	     have fixed precision while GCC pretends it does, there could be
+	     valid values that GCC can't really represent accurately.
+	     See PR95450.  Even for other modes, e.g. x86 XFmode can have some
+	     bit combinationations which GCC doesn't preserve.  */
+	  unsigned char buf[24];
+	  scalar_float_mode mode = SCALAR_FLOAT_TYPE_MODE (type);
+	  int total_bytes = GET_MODE_SIZE (mode);
+	  if (native_encode_expr (ret, buf, total_bytes, 0) != total_bytes
+	      || memcmp (ptr, buf, total_bytes) != 0)
+	    return NULL_TREE;
+	  return ret;
+	}
+      return NULL_TREE;
 
     case FIXED_POINT_TYPE:
       return native_interpret_fixed (type, ptr, len);
@@ -14208,11 +14212,7 @@
 	      && multiple_of_p (type, TREE_OPERAND (top, 2), bottom, nowrap));
 
     case INTEGER_CST:
-      if (TREE_CODE (bottom) != INTEGER_CST
-	  || integer_zerop (bottom)
-	  || (TYPE_UNSIGNED (type)
-	      && (tree_int_cst_sgn (top) < 0
-		  || tree_int_cst_sgn (bottom) < 0)))
+      if (TREE_CODE (bottom) != INTEGER_CST || integer_zerop (bottom))
 	return 0;
       return wi::multiple_of_p (wi::to_widest (top), wi::to_widest (bottom),
 				SIGNED);
diff --git a/gcc/fold-const.h b/gcc/fold-const.h
index f217598..926c775 100644
--- a/gcc/fold-const.h
+++ b/gcc/fold-const.h
@@ -36,6 +36,7 @@
 extern int native_encode_initializer (tree, unsigned char *, int,
 				      int off = -1, unsigned char * = nullptr);
 extern tree native_interpret_expr (tree, const unsigned char *, int);
+extern tree native_interpret_real (tree, const unsigned char *, int);
 extern bool can_native_interpret_type_p (tree);
 extern tree native_interpret_aggregate (tree, const unsigned char *, int, int);
 extern tree find_bitfield_repr_type (int, int);
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 4a1e6c6..4a1371b 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,27 @@
+2022-02-15  Tobias Burnus  <tobias@codesourcery.com>
+
+	* trans-openmp.cc (gfc_trans_omp_depobj): Fix to alloc/ptr dummy
+	and for c_ptr.
+
+2022-02-15  Tobias Burnus  <tobias@codesourcery.com>
+
+	* trans-openmp.cc (gfc_trans_omp_clauses, gfc_trans_omp_depobj):
+	Depend on the proper addr, for ptr/alloc depend on pointee.
+
+2022-02-14  Harald Anlauf  <anlauf@gmx.de>
+
+	PR fortran/104211
+	* expr.cc (find_array_section): Replace assertion by error
+	recovery when encountering bad array constructor.
+
+2022-02-13  Mikael Morin  <mikael@gcc.gnu.org>
+
+	PR fortran/104228
+	* resolve.cc (resolve_assoc_var): Also create a new character
+	length for non-dummy associate targets.
+	* trans-stmt.cc (trans_associate_var): Initialize character length
+	even if no temporary is used for the associate variable.
+
 2022-02-10  Roger Sayle  <roger@nextmovesoftware.com>
 	    Tobias Burnus  <tobias@codesourcery.com>
 
diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc
index ed82a94..c9c0ba4 100644
--- a/gcc/fortran/expr.cc
+++ b/gcc/fortran/expr.cc
@@ -1718,7 +1718,13 @@
 	}
 
       cons = gfc_constructor_lookup (base, limit);
-      gcc_assert (cons);
+      if (cons == NULL)
+	{
+	  gfc_error ("Error in array constructor referenced at %L",
+		     &ref->u.ar.where);
+	  t = false;
+	  goto cleanup;
+	}
       gfc_constructor_append_expr (&expr->value.constructor,
 				   gfc_copy_expr (cons->expr), NULL);
     }
diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc
index 0eba0b3..4d56a771 100644
--- a/gcc/fortran/trans-openmp.cc
+++ b/gcc/fortran/trans-openmp.cc
@@ -2881,15 +2881,14 @@
 		  tree decl = gfc_trans_omp_variable (n->sym, false);
 		  if (gfc_omp_privatize_by_reference (decl))
 		    decl = build_fold_indirect_ref (decl);
-		  if (n->u.depend_op == OMP_DEPEND_DEPOBJ
-		      && POINTER_TYPE_P (TREE_TYPE (decl)))
-		    decl = build_fold_indirect_ref (decl);
 		  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
 		    {
 		      decl = gfc_conv_descriptor_data_get (decl);
 		      gcc_assert (POINTER_TYPE_P (TREE_TYPE (decl)));
 		      decl = build_fold_indirect_ref (decl);
 		    }
+		  else if (n->sym->attr.allocatable || n->sym->attr.pointer)
+		    decl = build_fold_indirect_ref (decl);
 		  else if (DECL_P (decl))
 		    TREE_ADDRESSABLE (decl) = 1;
 		  OMP_CLAUSE_DECL (node) = decl;
@@ -5508,12 +5507,46 @@
   if (n)
     {
       tree var;
-      if (n->expr)
-        var = gfc_convert_expr_to_tree (&block, n->expr);
+      if (n->expr && n->expr->ref->u.ar.type != AR_FULL)
+	{
+	  gfc_init_se (&se, NULL);
+	  if (n->expr->ref->u.ar.type == AR_ELEMENT)
+	    {
+	      gfc_conv_expr_reference (&se, n->expr);
+	      var = se.expr;
+	    }
+	  else
+	    {
+	      gfc_conv_expr_descriptor (&se, n->expr);
+	      var = gfc_conv_array_data (se.expr);
+	    }
+	  gfc_add_block_to_block (&block, &se.pre);
+	  gfc_add_block_to_block (&block, &se.post);
+	  gcc_assert (POINTER_TYPE_P (TREE_TYPE (var)));
+	}
       else
-	var = gfc_get_symbol_decl (n->sym);
-      if (!POINTER_TYPE_P (TREE_TYPE (var)))
-        var = gfc_build_addr_expr (NULL, var);
+	{
+	  var = gfc_get_symbol_decl (n->sym);
+	  if (POINTER_TYPE_P (TREE_TYPE (var))
+	      && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (var))))
+	    var = build_fold_indirect_ref (var);
+	  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (var)))
+	    {
+	      var = gfc_conv_descriptor_data_get (var);
+	      gcc_assert (POINTER_TYPE_P (TREE_TYPE (var)));
+	    }
+	  else if ((n->sym->attr.allocatable || n->sym->attr.pointer)
+		   && n->sym->attr.dummy)
+	    var = build_fold_indirect_ref (var);
+	  else if (!POINTER_TYPE_P (TREE_TYPE (var))
+		   || (n->sym->ts.f90_type == BT_VOID
+		       && !POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (var)))
+		       && !GFC_ARRAY_TYPE_P (TREE_TYPE (TREE_TYPE (var)))))
+	    {
+	      TREE_ADDRESSABLE (var) = 1;
+	      var = gfc_build_addr_expr (NULL, var);
+	    }
+	}
       depobj = save_expr (depobj);
       tree r = build_fold_indirect_ref_loc (loc, depobj);
       gfc_add_expr_to_block (&block,
diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
index d9b1a44..16f02c2 100644
--- a/gcc/gimple-fold.cc
+++ b/gcc/gimple-fold.cc
@@ -4807,10 +4807,10 @@
 	clear_padding_flush (buf, false);
       if (clear_padding_real_needs_padding_p (type))
 	{
-	  /* Use native_interpret_expr + native_encode_expr to figure out
+	  /* Use native_interpret_real + native_encode_expr to figure out
 	     which bits are padding.  */
 	  memset (buf->buf + buf->size, ~0, sz);
-	  tree cst = native_interpret_expr (type, buf->buf + buf->size, sz);
+	  tree cst = native_interpret_real (type, buf->buf + buf->size, sz);
 	  gcc_assert (cst && TREE_CODE (cst) == REAL_CST);
 	  int len = native_encode_expr (cst, buf->buf + buf->size, sz);
 	  gcc_assert (len > 0 && (size_t) len == (size_t) sz);
diff --git a/gcc/gimple-loop-jam.cc b/gcc/gimple-loop-jam.cc
index d9a7772..e33dd90 100644
--- a/gcc/gimple-loop-jam.cc
+++ b/gcc/gimple-loop-jam.cc
@@ -198,7 +198,8 @@
   if (!empty_block_p (loop->latch))
     return false;
 
-  if (!single_exit (loop))
+  edge exit;
+  if (!(exit = single_exit (loop)))
     return false;
 
   /* We need a perfect nest.  Quick check for adjacent inner loops.  */
@@ -259,7 +260,12 @@
   n = get_loop_body_with_size (outer, bbs, n_basic_blocks_for_fn (cfun));
 
   for (i = 0; i < n; i++)
-    if (bbs[i]->loop_father == outer && bb_prevents_fusion_p (bbs[i]))
+    if (bbs[i]->loop_father == outer
+	&& (bb_prevents_fusion_p (bbs[i])
+	    /* Outer loop exits must come after the inner loop, otherwise
+	       we'll put the outer loop exit into the fused inner loop.  */
+	    || (loop_exits_from_bb_p (outer, bbs[i])
+		&& !dominated_by_p (CDI_DOMINATORS, bbs[i], exit->src))))
       break;
   free (bbs);
   if (i != n)
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 5133a43..2fc8376 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -1270,6 +1270,18 @@
   src.get_operand (range1, op1);
   src.get_operand (range2, op2);
 
+  // Try to see if there is a dependence between the COND and either operand
+  if (src.gori ())
+    if (src.gori ()->condexpr_adjust (range1, range2, s, cond, op1, op2, src))
+      if (dump_file && (dump_flags & TDF_DETAILS))
+	{
+	  fprintf (dump_file, "Possible COND_EXPR adjustment. Range op1 : ");
+	  range1.dump(dump_file);
+	  fprintf (dump_file, " and Range op2: ");
+	  range2.dump(dump_file);
+	  fprintf (dump_file, "\n");
+	}
+
   // If the condition is known, choose the appropriate expression.
   if (cond_range.singleton_p ())
     {
diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index 3e53283..311214c 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -334,7 +334,7 @@
   unsigned v = SSA_NAME_VERSION (name);
 
   // If it has already been processed, just return the cached value.
-  if (has_def_chain (name))
+  if (has_def_chain (name) && m_def_chain[v].bm)
     return m_def_chain[v].bm;
 
   // No definition chain for default defs.
@@ -1303,6 +1303,100 @@
   return false;
 }
 
+// Given COND ? OP1 : OP2 with ranges R1 for OP1 and R2 for OP2, Use gori
+// to further resolve R1 and R2 if there are any dependencies between
+// OP1 and COND or OP2 and COND.  All values can are to be calculated using SRC
+// as the origination source location for operands..
+// Effectively, use COND an the edge condition and solve for OP1 on the true
+// edge and OP2 on the false edge.
+
+bool
+gori_compute::condexpr_adjust (irange &r1, irange &r2, gimple *, tree cond,
+			       tree op1, tree op2, fur_source &src)
+{
+  int_range_max tmp, cond_true, cond_false;
+  tree ssa1 = gimple_range_ssa_p (op1);
+  tree ssa2 = gimple_range_ssa_p (op2);
+  if (!ssa1 && !ssa2)
+    return false;
+  if (!COMPARISON_CLASS_P (cond))
+    return false;
+  tree type = TREE_TYPE (TREE_OPERAND (cond, 0));
+  if (!range_compatible_p (type, TREE_TYPE (TREE_OPERAND (cond, 1))))
+    return false;
+  range_operator *hand = range_op_handler (TREE_CODE (cond), type);
+  if (!hand)
+    return false;
+
+  tree c1 = gimple_range_ssa_p (TREE_OPERAND (cond, 0));
+  tree c2 = gimple_range_ssa_p (TREE_OPERAND (cond, 1));
+
+  // Only solve if there is one SSA name in the condition.
+  if ((!c1 && !c2) || (c1 && c2))
+    return false;
+
+  // Pick up the current values of each part of the condition.
+  int_range_max cl, cr;
+  src.get_operand (cl, TREE_OPERAND (cond, 0));
+  src.get_operand (cr, TREE_OPERAND (cond, 1));
+
+  tree cond_name = c1 ? c1 : c2;
+  gimple *def_stmt = SSA_NAME_DEF_STMT (cond_name);
+
+  // Evaluate the value of COND_NAME on the true and false edges, using either
+  // the op1 or op2 routines based on its location.
+  if (c1)
+    {
+      if (!hand->op1_range (cond_false, type, m_bool_zero, cr))
+	return false;
+      if (!hand->op1_range (cond_true, type, m_bool_one, cr))
+	return false;
+      cond_false.intersect (cl);
+      cond_true.intersect (cl);
+    }
+  else
+    {
+      if (!hand->op2_range (cond_false, type, m_bool_zero, cl))
+	return false;
+      if (!hand->op2_range (cond_true, type, m_bool_one, cl))
+	return false;
+      cond_false.intersect (cr);
+      cond_true.intersect (cr);
+    }
+
+  unsigned idx;
+  if ((idx = tracer.header ("cond_expr evaluation : ")))
+    {
+      fprintf (dump_file, " range1 = ");
+      r1.dump (dump_file);
+      fprintf (dump_file, ", range2 = ");
+      r1.dump (dump_file);
+      fprintf (dump_file, "\n");
+    }
+
+   // Now solve for SSA1 or SSA2 if they are in the dependency chain.
+   if (ssa1 && in_chain_p (ssa1, cond_name))
+    {
+      if (compute_operand_range (tmp, def_stmt, cond_true, ssa1, src))
+	r1.intersect (tmp);
+    }
+  if (ssa2 && in_chain_p (ssa2, cond_name))
+    {
+      if (compute_operand_range (tmp, def_stmt, cond_false, ssa2, src))
+	r2.intersect (tmp);
+    }
+  if (idx)
+    {
+      tracer.print (idx, "outgoing: range1 = ");
+      r1.dump (dump_file);
+      fprintf (dump_file, ", range2 = ");
+      r1.dump (dump_file);
+      fprintf (dump_file, "\n");
+      tracer.trailer (idx, "cond_expr", true, cond_name, cond_true);
+    }
+  return true;
+}
+
 // Dump what is known to GORI computes to listing file F.
 
 void
diff --git a/gcc/gimple-range-gori.h b/gcc/gimple-range-gori.h
index b799a84..605884e 100644
--- a/gcc/gimple-range-gori.h
+++ b/gcc/gimple-range-gori.h
@@ -158,6 +158,8 @@
 public:
   gori_compute (int not_executable_flag = 0);
   bool outgoing_edge_range_p (irange &r, edge e, tree name, range_query &q);
+  bool condexpr_adjust (irange &r1, irange &r2, gimple *s, tree cond, tree op1,
+			tree op2, fur_source &src);
   bool has_edge_range_p (tree name, basic_block bb = NULL);
   bool has_edge_range_p (tree name, edge e);
   void dump (FILE *f);
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 7d8850e..f570daa 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -250,6 +250,7 @@
 static hash_map<tree, tree> *oacc_declare_returns;
 static enum gimplify_status gimplify_expr (tree *, gimple_seq *, gimple_seq *,
 					   bool (*) (tree), fallback_t, bool);
+static void prepare_gimple_addressable (tree *, gimple_seq *);
 
 /* Shorter alias name for the above function for use in gimplify.cc
    only.  */
@@ -3122,10 +3123,12 @@
      gimplified before gimplifying the size expressions.
 
      So we do this in three steps.  First we deal with variable
-     bounds, sizes, and positions, then we gimplify the base,
-     then we deal with the annotations for any variables in the
-     components and any indices, from left to right.  */
+     bounds, sizes, and positions, then we gimplify the base and
+     ensure it is memory if needed, then we deal with the annotations
+     for any variables in the components and any indices, from left
+     to right.  */
 
+  bool need_non_reg = false;
   for (i = expr_stack.length () - 1; i >= 0; i--)
     {
       tree t = expr_stack[i];
@@ -3161,6 +3164,7 @@
 		  TREE_OPERAND (t, 3) = elmt_size;
 		}
 	    }
+	  need_non_reg = true;
 	}
       else if (TREE_CODE (t) == COMPONENT_REF)
 	{
@@ -3182,6 +3186,7 @@
 		  TREE_OPERAND (t, 2) = offset;
 		}
 	    }
+	  need_non_reg = true;
 	}
     }
 
@@ -3192,6 +3197,12 @@
 			fallback | fb_lvalue);
   ret = MIN (ret, tret);
 
+  /* Step 2a: if we have component references we do not support on
+     registers then make sure the base isn't a register.  Of course
+     we can only do so if an rvalue is OK.  */
+  if (need_non_reg && (fallback & fb_rvalue))
+    prepare_gimple_addressable (p, pre_p);
+
   /* Step 3: gimplify size expressions and the indices and operands of
      ARRAY_REF.  During this loop we also remove any useless conversions.  */
 
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index dd94ab3..f50a60b7 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -1,3 +1,10 @@
+2022-02-13  Ian Lance Taylor  <iant@golang.org>
+
+	* gospec.cc: Revert 2022-02-09 change:
+	(RTLIB, RT_LIBRARY): Don't define.
+	(lang_specific_driver): Don't add -lrt if linking statically
+	on GNU/Linux.
+
 2022-02-09  Ian Lance Taylor  <iant@golang.org>
 
 	* gospec.cc (RTLIB, RT_LIBRARY): Define.
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 745132a..3742414 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-0af68c0552341a44f1fb12301f9eff954b9dde88
+3742e8a154bfec805054b4ebf0809f12dc7694da
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc
index 0652084..77176ef 100644
--- a/gcc/omp-low.cc
+++ b/gcc/omp-low.cc
@@ -191,6 +191,7 @@
 static bitmap task_shared_vars;
 static bitmap global_nonaddressable_vars;
 static vec<omp_context *> taskreg_contexts;
+static vec<gomp_task *> task_cpyfns;
 
 static void scan_omp (gimple_seq *, omp_context *);
 static tree scan_omp_1_op (tree *, int *, void *);
@@ -1082,9 +1083,6 @@
 	DECL_ABSTRACT_ORIGIN (t) = NULL;
     }
 
-  if (is_task_ctx (ctx))
-    finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
-
   if (ctx->task_reduction_map)
     {
       ctx->task_reductions.release ();
@@ -11951,6 +11949,7 @@
   size_t looptempno = 0;
 
   child_fn = gimple_omp_task_copy_fn (task_stmt);
+  task_cpyfns.safe_push (task_stmt);
   child_cfun = DECL_STRUCT_FUNCTION (child_fn);
   gcc_assert (child_cfun->cfg == NULL);
   DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
@@ -14475,6 +14474,10 @@
       && (TREE_CODE (TREE_TYPE (DECL_ARGUMENTS (current_function_decl)))
 	  == POINTER_TYPE))
     remove_member_access_dummy_vars (DECL_INITIAL (current_function_decl));
+
+  for (auto task_stmt : task_cpyfns)
+    finalize_task_copyfn (task_stmt);
+  task_cpyfns.release ();
   return 0;
 }
 
diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
index bd176e8..85ad990 100644
--- a/gcc/simplify-rtx.cc
+++ b/gcc/simplify-rtx.cc
@@ -7302,7 +7302,7 @@
   else if (!native_encode_rtx (innermode, x, buffer, first_byte, inner_bytes))
     return NULL_RTX;
   rtx ret = native_decode_rtx (outermode, buffer, 0);
-  if (ret && MODE_COMPOSITE_P (outermode))
+  if (ret && FLOAT_MODE_P (outermode))
     {
       auto_vec<target_unit, 128> buffer2 (buffer_bytes);
       if (!native_encode_rtx (outermode, ret, buffer2, 0, buffer_bytes))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d50556d..5230f00 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,155 @@
+2022-02-15  Peter Bergner  <bergner@linux.ibm.com>
+
+	* gcc.target/powerpc/htm-1.c: Retry intermittent failing tbegins.
+
+2022-02-15  Andrew MacLeod  <amacleod@redhat.com>
+
+	PR tree-optimization/104526
+	* gcc.dg/pr104526.c: New.
+
+2022-02-15  David Malcolm  <dmalcolm@redhat.com>
+
+	PR analyzer/104524
+	* gcc.dg/analyzer/pr104524.c: New test.
+
+2022-02-15  David Malcolm  <dmalcolm@redhat.com>
+
+	PR analyzer/102692
+	* gcc.dg/analyzer/pr102692-2.c: New test.
+	* gcc.dg/analyzer/pr102692.c: Remove xfail.  Remove -O2 from
+	options and move to...
+	* gcc.dg/analyzer/torture/pr102692.c: ...here.
+
+2022-02-15  Tobias Burnus  <tobias@codesourcery.com>
+
+	* gfortran.dg/gomp/depend-4.f90: Add VALUE test, update scan test.
+	* gfortran.dg/gomp/depend-5.f90: Fix scan tree for -m32.
+	* gfortran.dg/gomp/depend-6.f90: New test.
+
+2022-02-15  Richard Sandiford  <richard.sandiford@arm.com>
+
+	* gcc.target/aarch64/max_plus_1.c: New test.
+	* gcc.target/aarch64/max_plus_2.c: Likewise.
+	* gcc.target/aarch64/max_plus_3.c: Likewise.
+	* gcc.target/aarch64/max_plus_4.c: Likewise.
+	* gcc.target/aarch64/max_plus_5.c: Likewise.
+	* gcc.target/aarch64/max_plus_6.c: Likewise.
+	* gcc.target/aarch64/max_plus_7.c: Likewise.
+	* gcc.target/aarch64/min_plus_1.c: Likewise.
+	* gcc.target/aarch64/min_plus_2.c: Likewise.
+	* gcc.target/aarch64/min_plus_3.c: Likewise.
+	* gcc.target/aarch64/min_plus_4.c: Likewise.
+	* gcc.target/aarch64/min_plus_5.c: Likewise.
+	* gcc.target/aarch64/min_plus_6.c: Likewise.
+	* gcc.target/aarch64/min_plus_7.c: Likewise.
+
+2022-02-15  Richard Sandiford  <richard.sandiford@arm.com>
+
+	* gcc.target/aarch64/store_v2vec_lanes.c: Add -fno-tree-vectorize.
+
+2022-02-15  Richard Sandiford  <richard.sandiford@arm.com>
+
+	* gcc.target/aarch64/shl-combine-2.c: New test.
+	* gcc.target/aarch64/shl-combine-3.c: Likewise.
+	* gcc.target/aarch64/shl-combine-4.c: Likewise.
+	* gcc.target/aarch64/shl-combine-5.c: Likewise.
+	* gcc.target/aarch64/xtn-combine-1.c: Likewise.
+	* gcc.target/aarch64/xtn-combine-2.c: Likewise.
+	* gcc.target/aarch64/xtn-combine-3.c: Likewise.
+	* gcc.target/aarch64/xtn-combine-4.c: Likewise.
+	* gcc.target/aarch64/xtn-combine-5.c: Likewise.
+	* gcc.target/aarch64/xtn-combine-6.c: Likewise.
+
+2022-02-15  Richard Sandiford  <richard.sandiford@arm.com>
+
+	* gcc.target/aarch64/ldp_stp_5.c: Require -mstrict-align.
+	* gcc.target/aarch64/ldp_stp_14.h,
+	* gcc.target/aarch64/ldp_stp_14.c: New test.
+	* gcc.target/aarch64/ldp_stp_15.c: Likewise.
+	* gcc.target/aarch64/ldp_stp_16.c: Likewise.
+	* gcc.target/aarch64/ldp_stp_17.c: Likewise.
+	* gcc.target/aarch64/ldp_stp_18.c: Likewise.
+	* gcc.target/aarch64/ldp_stp_19.c: Likewise.
+
+2022-02-15  Richard Biener  <rguenther@suse.de>
+
+	PR tree-optimization/104543
+	* gcc.dg/torture/pr104543.c: New testcase.
+
+2022-02-15  Tobias Burnus  <tobias@codesourcery.com>
+
+	* gfortran.dg/gomp/depend-4.f90: New test.
+	* gfortran.dg/gomp/depend-5.f90: New test.
+
+2022-02-15  Jakub Jelinek  <jakub@redhat.com>
+
+	PR middle-end/104522
+	* gcc.dg/pr104522.c: New test.
+
+2022-02-15  Richard Biener  <rguenther@suse.de>
+
+	PR tree-optimization/104519
+	* gcc.dg/torture/pr104519.c: New testcase.
+
+2022-02-15  Jakub Jelinek  <jakub@redhat.com>
+
+	PR debug/104517
+	* gcc.dg/gomp/pr104517.c: New test.
+
+2022-02-15  Jason Merrill  <jason@redhat.com>
+
+	PR c++/104107
+	PR c++/95036
+	* g++.dg/cpp0x/alias-decl-ttp2.C: New test.
+	* g++.dg/cpp1z/ttp2.C: New test.
+
+2022-02-14  Michael Meissner  <meissner@the-meissners.org>
+
+	PR target/104253
+	* gcc.target/powerpc/pr104253.c: New test.
+
+2022-02-14  Harald Anlauf  <anlauf@gmx.de>
+
+	PR fortran/104211
+	* gfortran.dg/pr104211.f90: New test.
+
+2022-02-14  Jakub Jelinek  <jakub@redhat.com>
+
+	PR c++/104513
+	* g++.dg/cpp1y/constexpr-104513.C: New test.
+	* g++.dg/cpp2a/constexpr-dtor12.C: New test.
+
+2022-02-14  Richard Biener  <rguenther@suse.de>
+
+	PR tree-optimization/104528
+	* gfortran.dg/pr104528.f: New testcase.
+
+2022-02-14  Richard Biener  <rguenther@suse.de>
+
+	PR tree-optimization/104511
+	* gcc.dg/pr104511.c: New testcase.
+
+2022-02-14  Richard Biener  <rguenther@suse.de>
+
+	PR c/104505
+	* c-c++-common/pr104505.c: New testcase.
+
+2022-02-14  Richard Biener  <rguenther@suse.de>
+
+	PR middle-end/104497
+	* c-c++-common/torture/pr104497.c: New testcase.
+
+2022-02-13  Mikael Morin  <mikael@gcc.gnu.org>
+
+	PR fortran/104228
+	* gfortran.dg/asan/associate_58.f90: New test.
+	* gfortran.dg/asan/associate_59.f90: New test.
+
+2022-02-13  liuhongt  <hongtao.liu@intel.com>
+
+	* gcc.target/i386/pr103771-2.c: New test.
+	* gcc.target/i386/pr103771-3.c: New test.
+
 2022-02-12  Jakub Jelinek  <jakub@redhat.com>
 
 	PR sanitizer/104449
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-31.c b/gcc/testsuite/c-c++-common/gomp/atomic-31.c
new file mode 100644
index 0000000..9ec3140
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-31.c
@@ -0,0 +1,11 @@
+/* c/104531 */
+/* { dg-do compile } */
+
+int x;
+
+void
+foo (_Complex int y)
+{
+  #pragma omp atomic compare	/* { dg-error "invalid operands" } */
+  x = x > y ? y : x;
+}
diff --git a/gcc/testsuite/c-c++-common/pr104505.c b/gcc/testsuite/c-c++-common/pr104505.c
new file mode 100644
index 0000000..7fa3d84
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr104505.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+typedef char __attribute__((__vector_size__ (8))) U;
+typedef short __attribute__((__vector_size__ (16))) V;
+
+U u;
+
+void
+foo (V v)
+{
+  u = __builtin_shufflevector (u, u, __builtin_convertvector (v, U)); /* { dg-error "invalid element index" } */
+}
diff --git a/gcc/testsuite/c-c++-common/torture/pr104497.c b/gcc/testsuite/c-c++-common/torture/pr104497.c
new file mode 100644
index 0000000..c63fc02
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/pr104497.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+typedef int __attribute__((vector_size(16))) vec_t;
+
+vec_t src, inv, res;
+
+void test(int i)
+{
+    vec_t y={0};
+    y[i] = (i & 1 ? inv : src)[i];
+    res = y;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-ttp2.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-ttp2.C
new file mode 100644
index 0000000..230b277
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-ttp2.C
@@ -0,0 +1,25 @@
+// PR c++/104107
+// { dg-do compile { target c++11 } }
+
+template<int targ_id, typename t_parameter,
+	 template<typename T, const T&> class tt_w_data>
+struct tt_main {
+  static t_parameter m_parameter;
+  template<template<typename T, const T&> class t_data>
+    using t_make = t_data<t_parameter, m_parameter>;
+  using t_data = t_make<tt_w_data>;
+};
+
+template<int targ_id, typename t_parameter,
+	 template<typename T, const T&> class tt_w_data>
+t_parameter tt_main<targ_id, t_parameter, tt_w_data>::m_parameter;
+
+template<typename T, const T&> struct P {};
+struct t_parameter {};
+
+using toto = tt_main<0, t_parameter, P>;
+
+int main() {
+  toto t;
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-104513.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-104513.C
new file mode 100644
index 0000000..4fa78a3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-104513.C
@@ -0,0 +1,10 @@
+// PR c++/104513
+// { dg-do compile { target c++14 } }
+
+struct A {
+  int a1;
+  short a2, a3;
+  long a4;
+  constexpr A() : a1(42), a2(42), a3(42), a4(42) { return; }
+};
+constexpr A a;
diff --git a/gcc/testsuite/g++.dg/cpp1z/ttp2.C b/gcc/testsuite/g++.dg/cpp1z/ttp2.C
new file mode 100644
index 0000000..1f161e5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/ttp2.C
@@ -0,0 +1,21 @@
+// PR c++/95036
+// { dg-do compile { target c++17 } }
+
+namespace a {
+template <int b> struct c { static constexpr int d = b; };
+template <bool, typename e = void> using f = e;
+template <typename e, e...> struct g;
+template <typename> struct array;
+} // namespace a
+template <template <class> class h> struct i {
+  template <template <class, auto...> class, class = void> struct n;
+  template <class j> struct n<h, j> : a::c<true> {};
+  template <template <class> class k, class = a::f<n<k>::d>> void function();
+};
+template <template <class> class... l> struct derived : i<l>... {
+  using i<l>::function...;
+};
+int main() {
+  derived<a::array, a::g> m;
+  m.function<a::array>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor12.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor12.C
new file mode 100644
index 0000000..19f9099b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor12.C
@@ -0,0 +1,13 @@
+// PR c++/104513
+// { dg-do compile { target c++20 } }
+
+struct S {
+  constexpr S () : s (nullptr) {}
+  constexpr ~S () { delete s; }
+  int *s;
+};
+struct T : S {
+  constexpr T () : S () {}
+  constexpr ~T () { s = new int (42); return; }
+};
+constexpr T t;
diff --git a/gcc/testsuite/g++.dg/template/non-dependent21.C b/gcc/testsuite/g++.dg/template/non-dependent21.C
new file mode 100644
index 0000000..89900837
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/non-dependent21.C
@@ -0,0 +1,9 @@
+// PR c++/104507
+
+extern const char *_k_errmsg[];
+
+template<class>
+const char* DoFoo(int __r, int __s) {
+  const char* n = _k_errmsg[(bool)__r && __s ? 1 : 2];
+  return n;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr102692-2.c b/gcc/testsuite/gcc.dg/analyzer/pr102692-2.c
new file mode 100644
index 0000000..c72fde2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/pr102692-2.c
@@ -0,0 +1,22 @@
+/* { dg-additional-options "-O1" } */
+
+struct Lisp_Overlay
+{
+  struct Lisp_Overlay *next;
+};
+
+void
+test_1 (struct Lisp_Overlay *tail, long prev)
+{
+  long end;
+  if (!tail || end < prev || !tail->next) /* { dg-warning "use of uninitialized value 'end'" } */
+    return;
+}
+
+void
+test_2 (struct Lisp_Overlay *tail, long prev)
+{
+  long end;
+  if (tail && end < prev && !tail->next) /* { dg-warning "use of uninitialized value 'end'" } */
+    return;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr104524.c b/gcc/testsuite/gcc.dg/analyzer/pr104524.c
new file mode 100644
index 0000000..875098c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/pr104524.c
@@ -0,0 +1,9 @@
+int src[1];
+
+int
+main (int c, char **a)
+{
+  __builtin_memcpy (*a, src, c);
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr102692.c b/gcc/testsuite/gcc.dg/analyzer/torture/pr102692.c
similarity index 94%
rename from gcc/testsuite/gcc.dg/analyzer/pr102692.c
rename to gcc/testsuite/gcc.dg/analyzer/torture/pr102692.c
index c8993c8..a6c6bc4 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr102692.c
+++ b/gcc/testsuite/gcc.dg/analyzer/torture/pr102692.c
@@ -1,4 +1,4 @@
-/* { dg-additional-options "-O2 -Wno-analyzer-too-complex" } */
+/* { dg-additional-options "-Wno-analyzer-too-complex" } */
 /* TODO: remove the need for -Wno-analyzer-too-complex.  */
 
 struct lisp;
@@ -73,7 +73,7 @@
       parent = tail;
       tail = tail->next;
     }
-  if (!tail || end < prev || !tail->next) /* { dg-bogus "use of uninitialized value 'end'" "uninit" { xfail *-*-* } } */
+  if (!tail || end < prev || !tail->next) /* { dg-bogus "use of uninitialized value 'end'" "uninit" } */
     /* { dg-bogus "dereference of NULL 'tail'" "null deref" { target *-*-* } .-1 } */
     return;
   right_pair = parent;
diff --git a/gcc/testsuite/gcc.dg/dfp/pr104510.c b/gcc/testsuite/gcc.dg/dfp/pr104510.c
new file mode 100644
index 0000000..85f4e97
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/pr104510.c
@@ -0,0 +1,12 @@
+/* PR c/104510 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+float f;
+_Decimal64 d;
+
+int
+foo (void)
+{
+  return d > (_Decimal32) (_Decimal64) f;
+}
diff --git a/gcc/testsuite/gcc.dg/gomp/pr104517.c b/gcc/testsuite/gcc.dg/gomp/pr104517.c
new file mode 100644
index 0000000..efb3175
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/pr104517.c
@@ -0,0 +1,54 @@
+/* PR debug/104517 */
+/* { dg-do compile } */
+/* { dg-options "-O1 -fcompare-debug -fopenmp -fno-tree-ter -save-temps" } */
+
+enum {
+  omp_default_mem_alloc,
+  omp_large_cap_mem_alloc,
+  omp_const_mem_alloc,
+  omp_high_bw_mem_alloc
+} omp_allocator_handle_t;
+
+int t, bar_nte, bar_tl, bar_i3, bar_dd;
+
+#pragma omp threadprivate(t)
+#pragma omp declare target
+int f, l, ll, r, r2;
+#pragma omp end declare target
+
+void
+bar (int *idp, int s, int nth, int g, int nta, int fi, int pp, int *q,
+     int ntm)
+{
+  int p = 0, i2 = 0, i1 = 0, m = 0, d = 0;
+
+#pragma omp target parallel for                               \
+  device(p) firstprivate (f) allocate (f) in_reduction(+:r2)
+  for (int i = 0; i < 4; i++)
+    ll++;
+
+#pragma omp target parallel for                                         \
+  device(d) map (m)                                                     \
+  if (target: p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \
+  if (parallel: i2) reduction(+:r) num_threads (nth) linear (ll)        \
+  schedule(static) collapse(1) nowait depend(inout: d) allocate (f)     \
+  in_reduction(+:r2)
+  for (int i = 0; i < 4; i++)
+    ll++;
+
+#pragma omp taskloop simd firstprivate(f) lastprivate(s) grainsize(g) \
+  collapse(1) untied if (i1) final(fi) mergeable nogroup              \
+  priority(pp) linear(ll) aligned(q) allocate(f)
+  for (int i = 0; i < 4; i++)
+    ll++;
+
+#pragma omp taskloop simd firstprivate(f) lastprivate(s) num_tasks(nta) \
+  collapse(1) if (i1) final(fi) priority(pp) safelen(8) simdlen(4)      \
+  linear(ll) aligned(q) nontemporal(ntm) order(concurrent) allocate(f)
+  for (int i = 0; i < 4; i++)
+    ll++;
+
+#pragma omp parallel master firstprivate(f) shared(nth) proc_bind(spread) \
+  copyin(t) allocate(f)
+  ;
+}
diff --git a/gcc/testsuite/gcc.dg/pr104511.c b/gcc/testsuite/gcc.dg/pr104511.c
new file mode 100644
index 0000000..ad5430c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr104511.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target dfp } } */
+/* { dg-options "-O -Wno-psabi" } */
+
+typedef _Float64 __attribute__((__vector_size__ (32))) F;
+typedef _Decimal32 __attribute__((__vector_size__ (16))) D;
+
+extern void bar (void);
+
+D g;
+void
+foo (F f)
+{
+  D d = __builtin_convertvector (f, D);
+  bar ();
+  g = d;
+}
diff --git a/gcc/testsuite/gcc.dg/pr104522.c b/gcc/testsuite/gcc.dg/pr104522.c
new file mode 100644
index 0000000..4d1d630
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr104522.c
@@ -0,0 +1,14 @@
+/* PR middle-end/104522 */
+/* { dg-do compile } */
+/* { dg-options "-O -fcompare-debug -dP" } */
+
+typedef short __attribute__((__vector_size__(16))) V;
+long double x;
+
+void
+foo (void)
+{
+  V t = { 512, 0, 0, 0, 16384 };
+  long double u = *(long double *) &t;
+  x /= u;
+}
diff --git a/gcc/testsuite/gcc.dg/pr104526.c b/gcc/testsuite/gcc.dg/pr104526.c
new file mode 100644
index 0000000..a295308
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr104526.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+void foo(void);
+
+static int a, b = 1, *c = &b;
+int main() {
+  for (; a; a--) {
+    int d = 2 >> (1 / *c);
+    if (!d)
+      foo();
+  }
+}
+
+/* { dg-final { scan-tree-dump-not "foo" "evrp" } } */
diff --git a/gcc/testsuite/gcc.dg/pr104544.c b/gcc/testsuite/gcc.dg/pr104544.c
new file mode 100644
index 0000000..275b666
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr104544.c
@@ -0,0 +1,19 @@
+/* PR rtl-optimization/104544 */
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2 -fcompare-debug" } */
+
+int m, n;
+__int128 q;
+
+void
+bar (unsigned __int128 x, int y)
+{
+  if (x)
+    q += y;
+}
+
+void
+foo (void)
+{
+  bar (!!q - 1, (m += m ? m : 1) < n);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr104519.c b/gcc/testsuite/gcc.dg/torture/pr104519.c
new file mode 100644
index 0000000..389c7bb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr104519.c
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+
+signed char a, b;
+int main()
+{
+  for (b = -7; b; b += 3)
+    if (a)
+      __builtin_abort();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr104543.c b/gcc/testsuite/gcc.dg/torture/pr104543.c
new file mode 100644
index 0000000..4896351
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr104543.c
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+/* { dg-additional-options "-floop-unroll-and-jam" } */
+
+int a[3], b, c;
+static int e()
+{
+  if (!c) {
+    for (b = 0; b < 3; b++)
+      for (c = 0; c < 3; c++)
+        a[c] ^= 1;
+    return -1;
+  }
+  return 0;
+}
+int main()
+{
+  e();
+  if (a[1] != 1)
+    __builtin_abort();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-inst-cas.c b/gcc/testsuite/gcc.target/aarch64/atomic-inst-cas.c
index f6f2892..0b4533a 100644
--- a/gcc/testsuite/gcc.target/aarch64/atomic-inst-cas.c
+++ b/gcc/testsuite/gcc.target/aarch64/atomic-inst-cas.c
@@ -1,5 +1,7 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -march=armv8-a+lse" } */
+/* -Winvalid-memory-model warnings are issued before the dead invalid calls
+   are removed.  */
+/* { dg-options "-O2 -march=armv8-a+lse -Wno-invalid-memory-model" } */
 
 /* Test ARMv8.1-A CAS instruction.  */
 
diff --git a/gcc/testsuite/gcc.target/aarch64/bic-bitmask-1.c b/gcc/testsuite/gcc.target/aarch64/bic-bitmask-1.c
index 568c1ff..bcb9cdd 100644
--- a/gcc/testsuite/gcc.target/aarch64/bic-bitmask-1.c
+++ b/gcc/testsuite/gcc.target/aarch64/bic-bitmask-1.c
@@ -10,4 +10,4 @@
   return vceqq_s32 (vbicq_s32 (a, cst), zero);
 }
 
-/* { dg-final { scan-assembler-not {\tbic\t} { xfail { aarch64*-*-* } } } } */
+/* { dg-final { scan-assembler-not {\tbic\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/ldp_stp_14.c b/gcc/testsuite/gcc.target/aarch64/ldp_stp_14.c
new file mode 100644
index 0000000..c7b5f7d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/ldp_stp_14.c
@@ -0,0 +1,89 @@
+/* { dg-options "-O2 -fno-tree-loop-distribute-patterns" } */
+/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */
+
+#include "ldp_stp_14.h"
+
+/*
+** const_2_int16_t_0:
+**	str	wzr, \[x0\]
+**	ret
+*/
+CONST_FN (2, int16_t, 0);
+
+/*
+** const_4_int16_t_0:
+**	str	xzr, \[x0\]
+**	ret
+*/
+CONST_FN (4, int16_t, 0);
+
+/*
+** const_8_int16_t_0:
+**	stp	xzr, xzr, \[x0\]
+**	ret
+*/
+CONST_FN (8, int16_t, 0);
+
+/* No preference between vectorizing or not vectorizing here.  */
+CONST_FN (16, int16_t, 0);
+
+/*
+** const_32_int16_t_0:
+**	movi	v([0-9]+)\.4s, .*
+**	stp	q\1, q\1, \[x0\]
+**	stp	q\1, q\1, \[x0, #?32\]
+**	ret
+*/
+CONST_FN (32, int16_t, 0);
+
+/* No preference between vectorizing or not vectorizing here.  */
+CONST_FN (2, int16_t, 1);
+
+/*
+** const_4_int16_t_1:
+**	movi	v([0-9]+)\.4h, .*
+**	str	d\1, \[x0\]
+**	ret
+*/
+CONST_FN (4, int16_t, 1);
+
+/*
+** const_8_int16_t_1:
+**	movi	v([0-9]+)\.8h, .*
+**	str	q\1, \[x0\]
+**	ret
+*/
+CONST_FN (8, int16_t, 1);
+
+/* Fuzzy match due to PR104387.  */
+/*
+** dup_2_int16_t:
+**	...
+**	strh	w1, \[x0, #?2\]
+**	ret
+*/
+DUP_FN (2, int16_t);
+
+/*
+** dup_4_int16_t:
+**	dup	v([0-9]+)\.4h, w1
+**	str	d\1, \[x0\]
+**	ret
+*/
+DUP_FN (4, int16_t);
+
+/*
+** dup_8_int16_t:
+**	dup	v([0-9]+)\.8h, w1
+**	str	q\1, \[x0\]
+**	ret
+*/
+DUP_FN (8, int16_t);
+
+/*
+** cons2_1_int16_t:
+**	strh	w1, \[x0\]
+**	strh	w2, \[x0, #?2\]
+**	ret
+*/
+CONS2_FN (1, int16_t);
diff --git a/gcc/testsuite/gcc.target/aarch64/ldp_stp_14.h b/gcc/testsuite/gcc.target/aarch64/ldp_stp_14.h
new file mode 100644
index 0000000..39c463f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/ldp_stp_14.h
@@ -0,0 +1,50 @@
+#include <stdint.h>
+
+#define PRAGMA(X) _Pragma (#X)
+#define UNROLL(COUNT) PRAGMA (GCC unroll (COUNT))
+
+#define CONST_FN(COUNT, TYPE, VAL)		\
+  void						\
+  const_##COUNT##_##TYPE##_##VAL (TYPE *x)	\
+  {						\
+    UNROLL (COUNT)				\
+    for (int i = 0; i < COUNT; ++i)		\
+      x[i] = VAL;				\
+  }
+
+#define DUP_FN(COUNT, TYPE)			\
+  void						\
+  dup_##COUNT##_##TYPE (TYPE *x, TYPE val)	\
+  {						\
+    UNROLL (COUNT)				\
+    for (int i = 0; i < COUNT; ++i)		\
+      x[i] = val;				\
+  }
+
+#define CONS2_FN(COUNT, TYPE)					\
+  void								\
+  cons2_##COUNT##_##TYPE (TYPE *x, TYPE val0, TYPE val1)	\
+  {								\
+    UNROLL (COUNT)						\
+    for (int i = 0; i < COUNT * 2; i += 2)			\
+      {								\
+	x[i + 0] = val0;					\
+	x[i + 1] = val1;					\
+      }								\
+  }
+
+#define CONS4_FN(COUNT, TYPE)					\
+  void								\
+  cons4_##COUNT##_##TYPE (TYPE *x, TYPE val0, TYPE val1,	\
+			  TYPE val2, TYPE val3)			\
+  {								\
+    UNROLL (COUNT)						\
+    for (int i = 0; i < COUNT * 4; i += 4)			\
+      {								\
+	x[i + 0] = val0;					\
+	x[i + 1] = val1;					\
+	x[i + 2] = val2;					\
+	x[i + 3] = val3;					\
+      }								\
+  }
+
diff --git a/gcc/testsuite/gcc.target/aarch64/ldp_stp_15.c b/gcc/testsuite/gcc.target/aarch64/ldp_stp_15.c
new file mode 100644
index 0000000..131cd0a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/ldp_stp_15.c
@@ -0,0 +1,137 @@
+/* { dg-options "-O2 -fno-tree-loop-distribute-patterns" } */
+/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */
+
+#include "ldp_stp_14.h"
+
+/*
+** const_2_int32_t_0:
+**	str	xzr, \[x0\]
+**	ret
+*/
+CONST_FN (2, int32_t, 0);
+
+/*
+** const_4_int32_t_0:
+**	stp	xzr, xzr, \[x0\]
+**	ret
+*/
+CONST_FN (4, int32_t, 0);
+
+/* No preference between vectorizing or not vectorizing here.  */
+CONST_FN (8, int32_t, 0);
+
+/*
+** const_16_int32_t_0:
+**	movi	v([0-9]+)\.4s, .*
+**	stp	q\1, q\1, \[x0\]
+**	stp	q\1, q\1, \[x0, #?32\]
+**	ret
+*/
+CONST_FN (16, int32_t, 0);
+
+/* No preference between vectorizing or not vectorizing here.  */
+CONST_FN (2, int32_t, 1);
+
+/*
+** const_4_int32_t_1:
+**	movi	v([0-9]+)\.4s, .*
+**	str	q\1, \[x0\]
+**	ret
+*/
+CONST_FN (4, int32_t, 1);
+
+/*
+** const_8_int32_t_1:
+**	movi	v([0-9]+)\.4s, .*
+**	stp	q\1, q\1, \[x0\]
+**	ret
+*/
+CONST_FN (8, int32_t, 1);
+
+/*
+** dup_2_int32_t:
+**	stp	w1, w1, \[x0\]
+**	ret
+*/
+DUP_FN (2, int32_t);
+
+/*
+** dup_4_int32_t:
+**	stp	w1, w1, \[x0\]
+**	stp	w1, w1, \[x0, #?8\]
+**	ret
+*/
+DUP_FN (4, int32_t);
+
+/*
+** dup_8_int32_t:
+**	dup	v([0-9]+)\.4s, w1
+**	stp	q\1, q\1, \[x0\]
+**	ret
+*/
+DUP_FN (8, int32_t);
+
+/*
+** cons2_1_int32_t:
+**	stp	w1, w2, \[x0\]
+**	ret
+*/
+CONS2_FN (1, int32_t);
+
+/*
+** cons2_2_int32_t:
+**	stp	w1, w2, \[x0\]
+**	stp	w1, w2, \[x0, #?8\]
+**	ret
+*/
+CONS2_FN (2, int32_t);
+
+/*
+** cons2_4_int32_t:
+**	stp	w1, w2, \[x0\]
+**	stp	w1, w2, \[x0, #?8\]
+**	stp	w1, w2, \[x0, #?16\]
+**	stp	w1, w2, \[x0, #?24\]
+**	ret
+*/
+CONS2_FN (4, int32_t);
+
+/* No preference between vectorizing or not vectorizing here.  */
+CONS2_FN (8, int32_t);
+
+/*
+** cons2_16_int32_t:
+**	...
+**	stp	q[0-9]+, .*
+**	ret
+*/
+CONS2_FN (16, int32_t);
+
+/*
+** cons4_1_int32_t:
+**	stp	w1, w2, \[x0\]
+**	stp	w3, w4, \[x0, #?8\]
+**	ret
+*/
+CONS4_FN (1, int32_t);
+
+/*
+** cons4_2_int32_t:
+**	stp	w1, w2, \[x0\]
+**	stp	w3, w4, \[x0, #?8\]
+**	stp	w1, w2, \[x0, #?16\]
+**	stp	w3, w4, \[x0, #?24\]
+**	ret
+*/
+CONS4_FN (2, int32_t);
+
+/* No preference between vectorizing or not vectorizing here.  */
+CONS4_FN (4, int32_t);
+
+/*
+** cons4_8_int32_t:
+**	...
+**	stp	q[0-9]+, .*
+**	ret
+*/
+CONS4_FN (8, int32_t);
diff --git a/gcc/testsuite/gcc.target/aarch64/ldp_stp_16.c b/gcc/testsuite/gcc.target/aarch64/ldp_stp_16.c
new file mode 100644
index 0000000..8ab117c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/ldp_stp_16.c
@@ -0,0 +1,133 @@
+/* { dg-options "-O2 -fno-tree-loop-distribute-patterns" } */
+/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */
+
+#include "ldp_stp_14.h"
+
+/*
+** const_2_float_0:
+**	str	xzr, \[x0\]
+**	ret
+*/
+CONST_FN (2, float, 0);
+
+/*
+** const_4_float_0:
+**	stp	xzr, xzr, \[x0\]
+**	ret
+*/
+CONST_FN (4, float, 0);
+
+/* No preference between vectorizing or not vectorizing here.  */
+CONST_FN (8, float, 0);
+
+/*
+** const_16_float_0:
+**	movi	v([0-9]+)\.4s, .*
+**	stp	q\1, q\1, \[x0\]
+**	stp	q\1, q\1, \[x0, #?32\]
+**	ret
+*/
+CONST_FN (16, float, 0);
+
+/*
+** const_2_float_1:
+**	fmov	v([0-9]+)\.2s, .*
+**	str	d\1, \[x0\]
+**	ret
+*/
+CONST_FN (2, float, 1);
+
+/*
+** const_4_float_1:
+**	fmov	v([0-9]+)\.4s, .*
+**	str	q\1, \[x0\]
+**	ret
+*/
+CONST_FN (4, float, 1);
+
+/*
+** dup_2_float:
+**	stp	s0, s0, \[x0\]
+**	ret
+*/
+DUP_FN (2, float);
+
+/* No preference between vectorizing or not vectorizing here.  */
+DUP_FN (4, float);
+
+/*
+** dup_8_float:
+**	dup	v([0-9]+)\.4s, v0.s\[0\]
+**	stp	q\1, q\1, \[x0\]
+**	ret
+*/
+DUP_FN (8, float);
+
+/*
+** cons2_1_float:
+**	stp	s0, s1, \[x0\]
+**	ret
+*/
+CONS2_FN (1, float);
+
+/*
+** cons2_2_float:
+**	stp	s0, s1, \[x0\]
+**	stp	s0, s1, \[x0, #?8\]
+**	ret
+*/
+CONS2_FN (2, float);
+
+/*
+** cons2_4_float:	{ target aarch64_little_endian }
+**	ins	v0.s\[1\], v1.s\[0\]
+**	stp	d0, d0, \[x0\]
+**	stp	d0, d0, \[x0, #?16\]
+**	ret
+*/
+/*
+** cons2_4_float:	{ target aarch64_big_endian }
+**	ins	v1.s\[1\], v0.s\[0\]
+**	stp	d1, d1, \[x0\]
+**	stp	d1, d1, \[x0, #?16\]
+**	ret
+*/
+CONS2_FN (4, float);
+
+/*
+** cons2_8_float:
+**	dup	v([0-9]+)\.4s, .*
+**	...
+**	stp	q\1, q\1, \[x0\]
+**	stp	q\1, q\1, \[x0, #?32\]
+**	ret
+*/
+CONS2_FN (8, float);
+
+/*
+** cons4_1_float:
+**	stp	s0, s1, \[x0\]
+**	stp	s2, s3, \[x0, #?8\]
+**	ret
+*/
+CONS4_FN (1, float);
+
+/*
+** cons4_2_float:
+**	stp	s0, s1, \[x0\]
+**	stp	s2, s3, \[x0, #?8\]
+**	stp	s0, s1, \[x0, #?16\]
+**	stp	s2, s3, \[x0, #?24\]
+**	ret
+*/
+CONS4_FN (2, float);
+
+/*
+** cons4_4_float:
+**	ins	v([0-9]+)\.s.*
+**	...
+**	stp	q\1, q\1, \[x0\]
+**	stp	q\1, q\1, \[x0, #?32\]
+**	ret
+*/
+CONS4_FN (4, float);
diff --git a/gcc/testsuite/gcc.target/aarch64/ldp_stp_17.c b/gcc/testsuite/gcc.target/aarch64/ldp_stp_17.c
new file mode 100644
index 0000000..c1122fc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/ldp_stp_17.c
@@ -0,0 +1,120 @@
+/* { dg-options "-O2 -fno-tree-loop-distribute-patterns" } */
+/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */
+
+#include "ldp_stp_14.h"
+
+/*
+** const_2_int64_t_0:
+**	stp	xzr, xzr, \[x0\]
+**	ret
+*/
+CONST_FN (2, int64_t, 0);
+
+/* No preference between vectorizing or not vectorizing here.  */
+CONST_FN (4, int64_t, 0);
+
+/*
+** const_8_int64_t_0:
+**	movi	v([0-9]+)\.4s, .*
+**	stp	q\1, q\1, \[x0\]
+**	stp	q\1, q\1, \[x0, #?32\]
+**	ret
+*/
+CONST_FN (8, int64_t, 0);
+
+/*
+** dup_2_int64_t:
+**	stp	x1, x1, \[x0\]
+**	ret
+*/
+DUP_FN (2, int64_t);
+
+/*
+** dup_4_int64_t:
+**	stp	x1, x1, \[x0\]
+**	stp	x1, x1, \[x0, #?16\]
+**	ret
+*/
+DUP_FN (4, int64_t);
+
+/* No preference between vectorizing or not vectorizing here.  */
+DUP_FN (8, int64_t);
+
+/*
+** dup_16_int64_t:
+**	dup	v([0-9])\.2d, x1
+**	stp	q\1, q\1, \[x0\]
+**	stp	q\1, q\1, \[x0, #?32\]
+**	stp	q\1, q\1, \[x0, #?64\]
+**	stp	q\1, q\1, \[x0, #?96\]
+**	ret
+*/
+DUP_FN (16, int64_t);
+
+/*
+** cons2_1_int64_t:
+**	stp	x1, x2, \[x0\]
+**	ret
+*/
+CONS2_FN (1, int64_t);
+
+/*
+** cons2_2_int64_t:
+**	stp	x1, x2, \[x0\]
+**	stp	x1, x2, \[x0, #?16\]
+**	ret
+*/
+CONS2_FN (2, int64_t);
+
+/*
+** cons2_4_int64_t:
+**	stp	x1, x2, \[x0\]
+**	stp	x1, x2, \[x0, #?16\]
+**	stp	x1, x2, \[x0, #?32\]
+**	stp	x1, x2, \[x0, #?48\]
+**	ret
+*/
+CONS2_FN (4, int64_t);
+
+/* No preference between vectorizing or not vectorizing here.  */
+CONS2_FN (8, int64_t);
+
+/*
+** cons2_16_int64_t:
+**	...
+**	stp	q[0-9]+, .*
+**	ret
+*/
+CONS2_FN (16, int64_t);
+
+/*
+** cons4_1_int64_t:
+**	stp	x1, x2, \[x0\]
+**	stp	x3, x4, \[x0, #?16\]
+**	ret
+*/
+CONS4_FN (1, int64_t);
+
+/*
+** cons4_2_int64_t:
+**	stp	x1, x2, \[x0\]
+**	stp	x3, x4, \[x0, #?16\]
+**	stp	x1, x2, \[x0, #?32\]
+**	stp	x3, x4, \[x0, #?48\]
+**	ret
+*/
+CONS4_FN (2, int64_t);
+
+/* No preference between vectorizing or not vectorizing here.  */
+CONS4_FN (4, int64_t);
+
+/* We should probably vectorize this, but currently don't.  */
+CONS4_FN (8, int64_t);
+
+/*
+** cons4_16_int64_t:
+**	...
+**	stp	q[0-9]+, .*
+**	ret
+*/
+CONS4_FN (16, int64_t);
diff --git a/gcc/testsuite/gcc.target/aarch64/ldp_stp_18.c b/gcc/testsuite/gcc.target/aarch64/ldp_stp_18.c
new file mode 100644
index 0000000..eaa855c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/ldp_stp_18.c
@@ -0,0 +1,123 @@
+/* { dg-options "-O2 -fno-tree-loop-distribute-patterns" } */
+/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */
+
+#include "ldp_stp_14.h"
+
+/*
+** const_2_double_0:
+**	stp	xzr, xzr, \[x0\]
+**	ret
+*/
+CONST_FN (2, double, 0);
+
+/* No preference between vectorizing or not vectorizing here.  */
+CONST_FN (4, double, 0);
+
+/*
+** const_8_double_0:
+**	movi	v([0-9]+)\.2d, .*
+**	stp	q\1, q\1, \[x0\]
+**	stp	q\1, q\1, \[x0, #?32\]
+**	ret
+*/
+CONST_FN (8, double, 0);
+
+/*
+** dup_2_double:
+**	stp	d0, d0, \[x0\]
+**	ret
+*/
+DUP_FN (2, double);
+
+/*
+** dup_4_double:
+**	stp	d0, d0, \[x0\]
+**	stp	d0, d0, \[x0, #?16\]
+**	ret
+*/
+DUP_FN (4, double);
+
+/*
+** dup_8_double:
+**	dup	v([0-9])\.2d, v0\.d\[0\]
+**	stp	q\1, q\1, \[x0\]
+**	stp	q\1, q\1, \[x0, #?32\]
+**	ret
+*/
+DUP_FN (8, double);
+
+/*
+** dup_16_double:
+**	dup	v([0-9])\.2d, v0\.d\[0\]
+**	stp	q\1, q\1, \[x0\]
+**	stp	q\1, q\1, \[x0, #?32\]
+**	stp	q\1, q\1, \[x0, #?64\]
+**	stp	q\1, q\1, \[x0, #?96\]
+**	ret
+*/
+DUP_FN (16, double);
+
+/*
+** cons2_1_double:
+**	stp	d0, d1, \[x0\]
+**	ret
+*/
+CONS2_FN (1, double);
+
+/*
+** cons2_2_double:
+**	stp	d0, d1, \[x0\]
+**	stp	d0, d1, \[x0, #?16\]
+**	ret
+*/
+CONS2_FN (2, double);
+
+/*
+** cons2_4_double:
+**	...
+**	stp	q[0-9]+, .*
+**	ret
+*/
+CONS2_FN (4, double);
+
+/*
+** cons2_8_double:
+**	...
+**	stp	q[0-9]+, .*
+**	ret
+*/
+CONS2_FN (8, double);
+
+/*
+** cons4_1_double:
+**	stp	d0, d1, \[x0\]
+**	stp	d2, d3, \[x0, #?16\]
+**	ret
+*/
+CONS4_FN (1, double);
+
+/*
+** cons4_2_double:
+**	stp	d0, d1, \[x0\]
+**	stp	d2, d3, \[x0, #?16\]
+**	stp	d0, d1, \[x0, #?32\]
+**	stp	d2, d3, \[x0, #?48\]
+**	ret
+*/
+CONS4_FN (2, double);
+
+/*
+** cons2_8_double:
+**	...
+**	stp	q[0-9]+, .*
+**	ret
+*/
+CONS4_FN (4, double);
+
+/*
+** cons2_8_double:
+**	...
+**	stp	q[0-9]+, .*
+**	ret
+*/
+CONS4_FN (8, double);
diff --git a/gcc/testsuite/gcc.target/aarch64/ldp_stp_19.c b/gcc/testsuite/gcc.target/aarch64/ldp_stp_19.c
new file mode 100644
index 0000000..9eb4163
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/ldp_stp_19.c
@@ -0,0 +1,6 @@
+/* { dg-options "-O2 -mstrict-align" } */
+
+#include "ldp_stp_5.c"
+
+/* { dg-final { scan-assembler-times {stp\tq[0-9]+, q[0-9]} 3 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {str\tq[0-9]+} 1 { xfail *-*-* } } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/ldp_stp_5.c b/gcc/testsuite/gcc.target/aarch64/ldp_stp_5.c
index 9426618..56d1d3c 100644
--- a/gcc/testsuite/gcc.target/aarch64/ldp_stp_5.c
+++ b/gcc/testsuite/gcc.target/aarch64/ldp_stp_5.c
@@ -1,4 +1,4 @@
-/* { dg-options "-O2" } */
+/* { dg-options "-O2 -mstrict-align" } */
 
 double arr[4][4];
 
diff --git a/gcc/testsuite/gcc.target/aarch64/max_plus_1.c b/gcc/testsuite/gcc.target/aarch64/max_plus_1.c
new file mode 100644
index 0000000..ef336ae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/max_plus_1.c
@@ -0,0 +1,149 @@
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
+/*
+** f1:
+**	adds	(w[0-9]+), w0, #4
+**	csel	w0, \1, wzr, g[te]
+**	ret
+*/
+/*
+** f2:
+**	adds	(w[0-9]+), w0, #4
+**	csel	w0, \1, wzr, g[te]
+**	ret
+*/
+/*
+** f3:
+**	adds	(w[0-9]+), w0, #5
+**	csinc	w0, \1, wzr, gt
+**	ret
+*/
+/*
+** f4:
+**	adds	(w[0-9]+), w0, #3
+**	csinv	w0, \1, wzr, ge
+**	ret
+*/
+
+#ifndef TYPE
+#define TYPE int32_t
+#define TYPE_MIN INT32_MIN
+#define TYPE_MAX INT32_MAX
+#define VALUE -4
+#endif
+
+#include <stdint.h>
+
+TYPE __attribute__((noipa))
+f1 (TYPE x)
+{
+  return (x > VALUE ? x - VALUE : 0);
+}
+
+TYPE __attribute__((noipa))
+f2 (TYPE x)
+{
+  return (x > VALUE ? x : VALUE) - VALUE;
+}
+
+TYPE __attribute__((noipa))
+f3 (TYPE x)
+{
+  return (x > VALUE ? x : VALUE) - (VALUE - 1);
+}
+
+TYPE __attribute__((noipa))
+f4 (TYPE x)
+{
+  return (x > VALUE ? x : VALUE) - (VALUE + 1);
+}
+
+TYPE __attribute__((noipa))
+f5 (TYPE x)
+{
+  return (x > VALUE ? x : VALUE) - (VALUE + 2);
+}
+
+TYPE __attribute__((noipa))
+f6 (TYPE x)
+{
+  return (x > VALUE ? x : VALUE) - (VALUE - 2);
+}
+
+int
+main (void)
+{
+  TYPE max_test = TYPE_MAX;
+  if (TYPE_MIN < 0 && VALUE < 0)
+    max_test += VALUE;
+
+  if (f1 (TYPE_MIN) != 0)
+    __builtin_abort ();
+  if (f1 (VALUE - 1) != 0)
+    __builtin_abort ();
+  if (f1 (VALUE) != 0)
+    __builtin_abort ();
+  if (f1 (VALUE + 1) != 1)
+    __builtin_abort ();
+  if (f1 (max_test) != max_test - VALUE)
+    __builtin_abort ();
+
+  if (f2 (TYPE_MIN) != 0)
+    __builtin_abort ();
+  if (f2 (VALUE - 1) != 0)
+    __builtin_abort ();
+  if (f2 (VALUE) != 0)
+    __builtin_abort ();
+  if (f2 (VALUE + 1) != 1)
+    __builtin_abort ();
+  if (f2 (max_test) != max_test - VALUE)
+    __builtin_abort ();
+
+  if (f3 (TYPE_MIN) != 1)
+    __builtin_abort ();
+  if (f3 (VALUE - 1) != 1)
+    __builtin_abort ();
+  if (f3 (VALUE) != 1)
+    __builtin_abort ();
+  if (f3 (VALUE + 1) != 2)
+    __builtin_abort ();
+  if (f3 (max_test - 1) != max_test - VALUE)
+    __builtin_abort ();
+
+  if (f4 (TYPE_MIN) != -1)
+    __builtin_abort ();
+  if (f4 (VALUE - 1) != -1)
+    __builtin_abort ();
+  if (f4 (VALUE) != -1)
+    __builtin_abort ();
+  if (f4 (VALUE + 1) != 0)
+    __builtin_abort ();
+  if (f4 (max_test) != max_test - VALUE - 1)
+    __builtin_abort ();
+
+  if (f5 (TYPE_MIN) != -2)
+    __builtin_abort ();
+  if (f5 (VALUE - 1) != -2)
+    __builtin_abort ();
+  if (f5 (VALUE) != -2)
+    __builtin_abort ();
+  if (f5 (VALUE + 1) != -1)
+    __builtin_abort ();
+  if (f5 (max_test) != max_test - VALUE - 2)
+    __builtin_abort ();
+
+  if (f6 (TYPE_MIN) != 2)
+    __builtin_abort ();
+  if (f6 (VALUE - 1) != 2)
+    __builtin_abort ();
+  if (f6 (VALUE) != 2)
+    __builtin_abort ();
+  if (f6 (VALUE + 1) != 3)
+    __builtin_abort ();
+  if (VALUE <= max_test - 2 && f6 (max_test - 2) != max_test - VALUE)
+    __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/max_plus_2.c b/gcc/testsuite/gcc.target/aarch64/max_plus_2.c
new file mode 100644
index 0000000..a2a1295
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/max_plus_2.c
@@ -0,0 +1,35 @@
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
+/*
+** f1:
+**	adds	(x[0-9]+), x0, #4094
+**	csel	x0, \1, xzr, g[te]
+**	ret
+*/
+/*
+** f2:
+**	adds	(x[0-9]+), x0, #4094
+**	csel	x0, \1, xzr, g[te]
+**	ret
+*/
+/*
+** f3:
+**	adds	(x[0-9]+), x0, #4095
+**	csinc	x0, \1, xzr, gt
+**	ret
+*/
+/*
+** f4:
+**	adds	(x[0-9]+), x0, #4093
+**	csinv	x0, \1, xzr, ge
+**	ret
+*/
+
+#define TYPE int64_t
+#define TYPE_MIN INT64_MIN
+#define TYPE_MAX INT64_MAX
+#define VALUE -4094
+
+#include "max_plus_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/max_plus_3.c b/gcc/testsuite/gcc.target/aarch64/max_plus_3.c
new file mode 100644
index 0000000..a9792ec
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/max_plus_3.c
@@ -0,0 +1,35 @@
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
+/*
+** f1:
+**	adds	(w[0-9]+), w0, #4095
+**	csel	w0, \1, wzr, g[te]
+**	ret
+*/
+/*
+** f2:
+**	adds	(w[0-9]+), w0, #4095
+**	csel	w0, \1, wzr, g[te]
+**	ret
+*/
+/*
+** f3:
+**	adds	(w[0-9]+), w0, #4096
+**	csinc	w0, \1, wzr, gt
+**	ret
+*/
+/*
+** f4:
+**	adds	(w[0-9]+), w0, #4094
+**	csinv	w0, \1, wzr, ge
+**	ret
+*/
+
+#define TYPE int32_t
+#define TYPE_MIN INT32_MIN
+#define TYPE_MAX INT32_MAX
+#define VALUE -4095
+
+#include "max_plus_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/max_plus_4.c b/gcc/testsuite/gcc.target/aarch64/max_plus_4.c
new file mode 100644
index 0000000..5090fa1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/max_plus_4.c
@@ -0,0 +1,30 @@
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
+/*
+** f1:
+**	adds	(x[0-9]+), x0, #4096
+**	csel	x0, \1, xzr, g[te]
+**	ret
+*/
+/*
+** f2:
+**	adds	(x[0-9]+), x0, #4096
+**	csel	x0, \1, xzr, g[te]
+**	ret
+*/
+/* f3 out of range */
+/*
+** f4:
+**	adds	(x[0-9]+), x0, #4095
+**	csinv	x0, \1, xzr, ge
+**	ret
+*/
+
+#define TYPE int64_t
+#define TYPE_MIN INT64_MIN
+#define TYPE_MAX INT64_MAX
+#define VALUE -4096
+
+#include "max_plus_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/max_plus_5.c b/gcc/testsuite/gcc.target/aarch64/max_plus_5.c
new file mode 100644
index 0000000..63f3b34
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/max_plus_5.c
@@ -0,0 +1,35 @@
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
+/*
+** f1:
+**	adds	(w[0-9]+), w0, #4095
+**	csel	w0, \1, wzr, (cs|hi)
+**	ret
+*/
+/*
+** f2:
+**	adds	(w[0-9]+), w0, #4095
+**	csel	w0, \1, wzr, (cs|hi)
+**	ret
+*/
+/*
+** f3:
+**	adds	(w[0-9]+), w0, #4096
+**	csinc	w0, \1, wzr, hi
+**	ret
+*/
+/*
+** f4:
+**	adds	(w[0-9]+), w0, #4094
+**	csinv	w0, \1, wzr, cs
+**	ret
+*/
+
+#define TYPE uint32_t
+#define TYPE_MIN 0
+#define TYPE_MAX UINT32_MAX
+#define VALUE (uint32_t)-4095
+
+#include "max_plus_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/max_plus_6.c b/gcc/testsuite/gcc.target/aarch64/max_plus_6.c
new file mode 100644
index 0000000..ad592c6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/max_plus_6.c
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+
+#define TYPE uint64_t
+#define TYPE_MIN 0
+#define TYPE_MAX UINT64_MAX
+#define VALUE (uint64_t)-2
+
+#include "max_plus_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/max_plus_7.c b/gcc/testsuite/gcc.target/aarch64/max_plus_7.c
new file mode 100644
index 0000000..ac9f27d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/max_plus_7.c
@@ -0,0 +1,35 @@
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
+/*
+** f1:
+**	adds	(x[0-9]+), x0, #3
+**	csel	x0, \1, xzr, (cs|hi)
+**	ret
+*/
+/*
+** f2:
+**	adds	(x[0-9]+), x0, #3
+**	csel	x0, \1, xzr, (cs|hi)
+**	ret
+*/
+/*
+** f3:
+**	adds	(x[0-9]+), x0, #4
+**	csinc	x0, \1, xzr, hi
+**	ret
+*/
+/*
+** f4:
+**	adds	(x[0-9]+), x0, #2
+**	csinv	x0, \1, xzr, cs
+**	ret
+*/
+
+#define TYPE uint64_t
+#define TYPE_MIN 0
+#define TYPE_MAX UINT64_MAX
+#define VALUE (uint64_t)-3
+
+#include "max_plus_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/min_plus_1.c b/gcc/testsuite/gcc.target/aarch64/min_plus_1.c
new file mode 100644
index 0000000..f4c9106
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/min_plus_1.c
@@ -0,0 +1,149 @@
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
+/*
+** f1:
+**	subs	(w[0-9]+), w0, #?4
+**	csel	w0, \1, wzr, l[te]
+**	ret
+*/
+/*
+** f2:
+**	subs	(w[0-9]+), w0, #?4
+**	csel	w0, \1, wzr, l[te]
+**	ret
+*/
+/*
+** f3:
+**	subs	(w[0-9]+), w0, #?3
+**	csinc	w0, \1, wzr, le
+**	ret
+*/
+/*
+** f4:
+**	subs	(w[0-9]+), w0, #?5
+**	csinv	w0, \1, wzr, lt
+**	ret
+*/
+
+#ifndef TYPE
+#define TYPE int32_t
+#define TYPE_MIN INT32_MIN
+#define TYPE_MAX INT32_MAX
+#define VALUE 4
+#endif
+
+#include <stdint.h>
+
+TYPE __attribute__((noipa))
+f1 (TYPE x)
+{
+  return (x < VALUE ? x - VALUE : 0);
+}
+
+TYPE __attribute__((noipa))
+f2 (TYPE x)
+{
+  return (x < VALUE ? x : VALUE) - VALUE;
+}
+
+TYPE __attribute__((noipa))
+f3 (TYPE x)
+{
+  return (x < VALUE ? x : VALUE) - (VALUE - 1);
+}
+
+TYPE __attribute__((noipa))
+f4 (TYPE x)
+{
+  return (x < VALUE ? x : VALUE) - (VALUE + 1);
+}
+
+TYPE __attribute__((noipa))
+f5 (TYPE x)
+{
+  return (x < VALUE ? x : VALUE) - (VALUE + 2);
+}
+
+TYPE __attribute__((noipa))
+f6 (TYPE x)
+{
+  return (x < VALUE ? x : VALUE) - (VALUE - 2);
+}
+
+int
+main (void)
+{
+  TYPE min_test = TYPE_MIN;
+  if (TYPE_MIN < 0 && VALUE > 0)
+    min_test += VALUE;
+
+  if (f1 (min_test) != min_test - VALUE)
+    __builtin_abort ();
+  if (f1 (VALUE - 1) != -1)
+    __builtin_abort ();
+  if (f1 (VALUE) != 0)
+    __builtin_abort ();
+  if (f1 (VALUE + 1) != 0)
+    __builtin_abort ();
+  if (f1 (TYPE_MAX) != 0)
+    __builtin_abort ();
+
+  if (f2 (min_test) != min_test - VALUE)
+    __builtin_abort ();
+  if (f2 (VALUE - 1) != -1)
+    __builtin_abort ();
+  if (f2 (VALUE) != 0)
+    __builtin_abort ();
+  if (f2 (VALUE + 1) != 0)
+    __builtin_abort ();
+  if (f2 (TYPE_MAX) != 0)
+    __builtin_abort ();
+
+  if (f3 (min_test) != min_test - VALUE + 1)
+    __builtin_abort ();
+  if (f3 (VALUE - 1) != 0)
+    __builtin_abort ();
+  if (f3 (VALUE) != 1)
+    __builtin_abort ();
+  if (f3 (VALUE + 1) != 1)
+    __builtin_abort ();
+  if (f3 (TYPE_MAX) != 1)
+    __builtin_abort ();
+
+  if (f4 (min_test + 1) != min_test - VALUE)
+    __builtin_abort ();
+  if (f4 (VALUE - 1) != -2)
+    __builtin_abort ();
+  if (f4 (VALUE) != -1)
+    __builtin_abort ();
+  if (f4 (VALUE + 1) != -1)
+    __builtin_abort ();
+  if (f4 (TYPE_MAX) != -1)
+    __builtin_abort ();
+
+  if (VALUE >= min_test + 2 && f5 (min_test + 2) != min_test - VALUE)
+    __builtin_abort ();
+  if (f5 (VALUE - 1) != -3)
+    __builtin_abort ();
+  if (f5 (VALUE) != -2)
+    __builtin_abort ();
+  if (f5 (VALUE + 1) != -2)
+    __builtin_abort ();
+  if (f5 (TYPE_MAX) != -2)
+    __builtin_abort ();
+
+  if (f6 (min_test) != min_test - VALUE + 2)
+    __builtin_abort ();
+  if (f6 (VALUE - 1) != 1)
+    __builtin_abort ();
+  if (f6 (VALUE) != 2)
+    __builtin_abort ();
+  if (f6 (VALUE + 1) != 2)
+    __builtin_abort ();
+  if (f6 (TYPE_MAX) != 2)
+    __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/min_plus_2.c b/gcc/testsuite/gcc.target/aarch64/min_plus_2.c
new file mode 100644
index 0000000..bc0141b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/min_plus_2.c
@@ -0,0 +1,35 @@
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
+/*
+** f1:
+**	subs	(x[0-9]+), x0, #?4094
+**	csel	x0, \1, xzr, l[te]
+**	ret
+*/
+/*
+** f2:
+**	subs	(x[0-9]+), x0, #?4094
+**	csel	x0, \1, xzr, l[te]
+**	ret
+*/
+/*
+** f3:
+**	subs	(x[0-9]+), x0, #?4093
+**	csinc	x0, \1, xzr, le
+**	ret
+*/
+/*
+** f4:
+**	subs	(x[0-9]+), x0, #?4095
+**	csinv	x0, \1, xzr, lt
+**	ret
+*/
+
+#define TYPE int64_t
+#define TYPE_MIN INT64_MIN
+#define TYPE_MAX INT64_MAX
+#define VALUE 4094
+
+#include "min_plus_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/min_plus_3.c b/gcc/testsuite/gcc.target/aarch64/min_plus_3.c
new file mode 100644
index 0000000..1808e4b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/min_plus_3.c
@@ -0,0 +1,35 @@
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
+/*
+** f1:
+**	subs	(w[0-9]+), w0, #?4095
+**	csel	w0, \1, wzr, l[te]
+**	ret
+*/
+/*
+** f2:
+**	subs	(w[0-9]+), w0, #?4095
+**	csel	w0, \1, wzr, l[te]
+**	ret
+*/
+/*
+** f3:
+**	subs	(w[0-9]+), w0, #?4094
+**	csinc	w0, \1, wzr, le
+**	ret
+*/
+/*
+** f4:
+**	subs	(w[0-9]+), w0, #?4096
+**	csinv	w0, \1, wzr, lt
+**	ret
+*/
+
+#define TYPE int32_t
+#define TYPE_MIN INT32_MIN
+#define TYPE_MAX INT32_MAX
+#define VALUE 4095
+
+#include "min_plus_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/min_plus_4.c b/gcc/testsuite/gcc.target/aarch64/min_plus_4.c
new file mode 100644
index 0000000..6c581fed
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/min_plus_4.c
@@ -0,0 +1,30 @@
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
+/*
+** f1:
+**	subs	(x[0-9]+), x0, #?4096
+**	csel	x0, \1, xzr, l[te]
+**	ret
+*/
+/*
+** f2:
+**	subs	(x[0-9]+), x0, #?4096
+**	csel	x0, \1, xzr, l[te]
+**	ret
+*/
+/*
+** f3:
+**	subs	(x[0-9]+), x0, #?4095
+**	csinc	x0, \1, xzr, le
+**	ret
+*/
+/* f4 out of range */
+
+#define TYPE int64_t
+#define TYPE_MIN INT64_MIN
+#define TYPE_MAX INT64_MAX
+#define VALUE 4096
+
+#include "min_plus_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/min_plus_5.c b/gcc/testsuite/gcc.target/aarch64/min_plus_5.c
new file mode 100644
index 0000000..97542d5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/min_plus_5.c
@@ -0,0 +1,35 @@
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
+/*
+** f1:
+**	subs	(w[0-9]+), w0, #?4095
+**	csel	w0, \1, wzr, (cc|ls)
+**	ret
+*/
+/*
+** f2:
+**	subs	(w[0-9]+), w0, #?4095
+**	csel	w0, \1, wzr, (cc|ls)
+**	ret
+*/
+/*
+** f3:
+**	subs	(w[0-9]+), w0, #?4094
+**	csinc	w0, \1, wzr, ls
+**	ret
+*/
+/*
+** f4:
+**	subs	(w[0-9]+), w0, #?4096
+**	csinv	w0, \1, wzr, cc
+**	ret
+*/
+
+#define TYPE uint32_t
+#define TYPE_MIN 0
+#define TYPE_MAX UINT32_MAX
+#define VALUE 4095
+
+#include "min_plus_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/min_plus_6.c b/gcc/testsuite/gcc.target/aarch64/min_plus_6.c
new file mode 100644
index 0000000..176533c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/min_plus_6.c
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+
+#define TYPE uint64_t
+#define TYPE_MIN 0
+#define TYPE_MAX UINT64_MAX
+#define VALUE 1
+
+#include "min_plus_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/min_plus_7.c b/gcc/testsuite/gcc.target/aarch64/min_plus_7.c
new file mode 100644
index 0000000..d6a217a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/min_plus_7.c
@@ -0,0 +1,35 @@
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
+/*
+** f1:
+**	subs	(x[0-9]+), x0, #?2
+**	csel	x0, \1, xzr, (cc|ls)
+**	ret
+*/
+/*
+** f2:
+**	subs	(x[0-9]+), x0, #?2
+**	csel	x0, \1, xzr, (cc|ls)
+**	ret
+*/
+/*
+** f3:
+**	subs	(x[0-9]+), x0, #?1
+**	csinc	x0, \1, xzr, ls
+**	ret
+*/
+/*
+** f4:
+**	subs	(x[0-9]+), x0, #?3
+**	csinv	x0, \1, xzr, cc
+**	ret
+*/
+
+#define TYPE uint64_t
+#define TYPE_MIN 0
+#define TYPE_MAX UINT64_MAX
+#define VALUE 2
+
+#include "min_plus_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/pr100056.c b/gcc/testsuite/gcc.target/aarch64/pr100056.c
index 0b77824..70499772 100644
--- a/gcc/testsuite/gcc.target/aarch64/pr100056.c
+++ b/gcc/testsuite/gcc.target/aarch64/pr100056.c
@@ -1,7 +1,9 @@
 /* PR target/100056 */
 /* { dg-do compile } */
 /* { dg-options "-O2" } */
-/* { dg-final { scan-assembler-not {\t[us]bfiz\tw[0-9]+, w[0-9]+, 11} } } */
+/* { dg-final { scan-assembler-not {\t[us]bfiz\tw[0-9]+, w[0-9]+, 11} { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\t[us]bfiz\tw[0-9]+, w[0-9]+, 11} 2 } } */
+/* { dg-final { scan-assembler-times {\tadd\tw[0-9]+, w[0-9]+, w[0-9]+, uxtb\n} 2 } } */
 
 int
 or_shift_u8 (unsigned char i)
diff --git a/gcc/testsuite/gcc.target/aarch64/shl-combine-2.c b/gcc/testsuite/gcc.target/aarch64/shl-combine-2.c
index 6a0331f..491fd44 100644
--- a/gcc/testsuite/gcc.target/aarch64/shl-combine-2.c
+++ b/gcc/testsuite/gcc.target/aarch64/shl-combine-2.c
@@ -1,6 +1,8 @@
 /* { dg-do assemble } */
 /* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */
 
+#pragma GCC target "+nosve"
+
 #define TYPE char
 
 void e (signed TYPE * restrict a, signed TYPE *b, int n)
diff --git a/gcc/testsuite/gcc.target/aarch64/shl-combine-3.c b/gcc/testsuite/gcc.target/aarch64/shl-combine-3.c
index 2086b24a..39bef21 100644
--- a/gcc/testsuite/gcc.target/aarch64/shl-combine-3.c
+++ b/gcc/testsuite/gcc.target/aarch64/shl-combine-3.c
@@ -1,6 +1,8 @@
 /* { dg-do assemble } */
 /* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */
 
+#pragma GCC target "+nosve"
+
 #define TYPE short
 
 void e (signed TYPE * restrict a, signed TYPE *b, int n)
diff --git a/gcc/testsuite/gcc.target/aarch64/shl-combine-4.c b/gcc/testsuite/gcc.target/aarch64/shl-combine-4.c
index 0831810..15dcbff 100644
--- a/gcc/testsuite/gcc.target/aarch64/shl-combine-4.c
+++ b/gcc/testsuite/gcc.target/aarch64/shl-combine-4.c
@@ -1,6 +1,8 @@
 /* { dg-do assemble } */
 /* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */
 
+#pragma GCC target "+nosve"
+
 #define TYPE int
 
 void e (signed TYPE * restrict a, signed TYPE *b, int n)
diff --git a/gcc/testsuite/gcc.target/aarch64/shl-combine-5.c b/gcc/testsuite/gcc.target/aarch64/shl-combine-5.c
index 6b2a6bd..703f630 100644
--- a/gcc/testsuite/gcc.target/aarch64/shl-combine-5.c
+++ b/gcc/testsuite/gcc.target/aarch64/shl-combine-5.c
@@ -1,6 +1,8 @@
 /* { dg-do assemble } */
 /* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */
 
+#pragma GCC target "+nosve"
+
 #define TYPE long
 
 void e (signed TYPE * restrict a, signed TYPE *b, int n)
diff --git a/gcc/testsuite/gcc.target/aarch64/store_v2vec_lanes.c b/gcc/testsuite/gcc.target/aarch64/store_v2vec_lanes.c
index 3296d04..7ea8a67 100644
--- a/gcc/testsuite/gcc.target/aarch64/store_v2vec_lanes.c
+++ b/gcc/testsuite/gcc.target/aarch64/store_v2vec_lanes.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2" } */
+/* { dg-options "-O2 -fno-tree-vectorize" } */
 
 typedef long long v2di __attribute__ ((vector_size (16)));
 typedef double v2df __attribute__ ((vector_size (16)));
diff --git a/gcc/testsuite/gcc.target/aarch64/xtn-combine-1.c b/gcc/testsuite/gcc.target/aarch64/xtn-combine-1.c
index 14e0414..27b7858 100644
--- a/gcc/testsuite/gcc.target/aarch64/xtn-combine-1.c
+++ b/gcc/testsuite/gcc.target/aarch64/xtn-combine-1.c
@@ -1,6 +1,8 @@
 /* { dg-do assemble } */
 /* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */
 
+#pragma GCC target "+nosve"
+
 #define SIGN signed
 #define TYPE1 char
 #define TYPE2 short
diff --git a/gcc/testsuite/gcc.target/aarch64/xtn-combine-2.c b/gcc/testsuite/gcc.target/aarch64/xtn-combine-2.c
index c259010..02f03fa 100644
--- a/gcc/testsuite/gcc.target/aarch64/xtn-combine-2.c
+++ b/gcc/testsuite/gcc.target/aarch64/xtn-combine-2.c
@@ -1,6 +1,8 @@
 /* { dg-do assemble } */
 /* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */
 
+#pragma GCC target "+nosve"
+
 #define SIGN signed
 #define TYPE1 short
 #define TYPE2 int
diff --git a/gcc/testsuite/gcc.target/aarch64/xtn-combine-3.c b/gcc/testsuite/gcc.target/aarch64/xtn-combine-3.c
index 9a2065f..4bcbd85 100644
--- a/gcc/testsuite/gcc.target/aarch64/xtn-combine-3.c
+++ b/gcc/testsuite/gcc.target/aarch64/xtn-combine-3.c
@@ -1,6 +1,8 @@
 /* { dg-do assemble } */
 /* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */
 
+#pragma GCC target "+nosve"
+
 #define SIGN signed
 #define TYPE1 int
 #define TYPE2 long long
diff --git a/gcc/testsuite/gcc.target/aarch64/xtn-combine-4.c b/gcc/testsuite/gcc.target/aarch64/xtn-combine-4.c
index 77c3dce..29703d1 100644
--- a/gcc/testsuite/gcc.target/aarch64/xtn-combine-4.c
+++ b/gcc/testsuite/gcc.target/aarch64/xtn-combine-4.c
@@ -1,6 +1,8 @@
 /* { dg-do assemble } */
 /* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */
 
+#pragma GCC target "+nosve"
+
 #define SIGN unsigned
 #define TYPE1 char
 #define TYPE2 short
diff --git a/gcc/testsuite/gcc.target/aarch64/xtn-combine-5.c b/gcc/testsuite/gcc.target/aarch64/xtn-combine-5.c
index ae30e86..f5ee30d 100644
--- a/gcc/testsuite/gcc.target/aarch64/xtn-combine-5.c
+++ b/gcc/testsuite/gcc.target/aarch64/xtn-combine-5.c
@@ -1,6 +1,8 @@
 /* { dg-do assemble } */
 /* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */
 
+#pragma GCC target "+nosve"
+
 #define SIGN unsigned
 #define TYPE1 short
 #define TYPE2 int
diff --git a/gcc/testsuite/gcc.target/aarch64/xtn-combine-6.c b/gcc/testsuite/gcc.target/aarch64/xtn-combine-6.c
index 882f3d3..3ddb87e 100644
--- a/gcc/testsuite/gcc.target/aarch64/xtn-combine-6.c
+++ b/gcc/testsuite/gcc.target/aarch64/xtn-combine-6.c
@@ -1,6 +1,8 @@
 /* { dg-do assemble } */
 /* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */
 
+#pragma GCC target "+nosve"
+
 #define SIGN unsigned
 #define TYPE1 int
 #define TYPE2 long long
diff --git a/gcc/testsuite/gcc.target/i386/pr104448.c b/gcc/testsuite/gcc.target/i386/pr104448.c
new file mode 100644
index 0000000..b10345a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr104448.c
@@ -0,0 +1,9 @@
+/* PR target/104448 */
+/* { dg-do compile { target { *-*-linux* && lp64 } } } */
+/* { dg-options "-mavx5124vnniw -mno-xsave -mabi=ms" } */
+
+int
+main ()
+{
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/htm-1.c b/gcc/testsuite/gcc.target/powerpc/htm-1.c
index f27e32c..399a7ec 100644
--- a/gcc/testsuite/gcc.target/powerpc/htm-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/htm-1.c
@@ -12,14 +12,21 @@
 {
   long i;
   unsigned long mask = 0;
+  unsigned long retry_count = 0;
 
 repeat:
   if (__builtin_tbegin (0))
     {
       mask++;
+      retry_count = 0;
     }
   else
-    abort();
+    {
+      /* Retry a limited number of times before aborting.  */
+      if (retry_count++ < 10)
+	goto repeat;
+      abort ();
+    }
 
   if (mask == 1)
     {
diff --git a/gcc/testsuite/gcc.target/powerpc/pr104253.c b/gcc/testsuite/gcc.target/powerpc/pr104253.c
new file mode 100644
index 0000000..02049cc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr104253.c
@@ -0,0 +1,156 @@
+/*
+ * Require float128 support because __ibm128 currently is not enabled unless we
+ * also have __float128 support.  We require software IEEE 128-bit support,
+ * which will work on power8.  If we have hardware IEEE 128-bit support (power9
+ * or power10), ppc_float128_sw will still enable running the test.
+ */
+
+/* { dg-do run } */
+/* { require-effective-target ppc_float128_sw } */
+/* { dg-options "-O2 -mvsx -mfloat128" } */
+
+/*
+ * PR target/104253
+ *
+ * Verify that the various conversions to and from __ibm128 work.  When the
+ *  default for long double is changed to IEEE 128-bit, originally GCC would
+ *  call the functions using an 'if' name instead of 'tf' name.
+ */
+
+#include <stdlib.h>
+
+extern float              ibm128_to_sf  (__ibm128) __attribute__((noinline));
+extern double             ibm128_to_df  (__ibm128) __attribute__((noinline));
+extern int                ibm128_to_si  (__ibm128) __attribute__((noinline));
+extern long long          ibm128_to_di  (__ibm128) __attribute__((noinline));
+extern unsigned int       ibm128_to_usi (__ibm128) __attribute__((noinline));
+extern unsigned long long ibm128_to_udi (__ibm128) __attribute__((noinline));
+
+extern __ibm128 sf_to_ibm128  (float)              __attribute__((noinline));
+extern __ibm128 df_to_ibm128  (double)             __attribute__((noinline));
+extern __ibm128 si_to_ibm128  (int)                __attribute__((noinline));
+extern __ibm128 di_to_ibm128  (long long)          __attribute__((noinline));
+extern __ibm128 usi_to_ibm128 (unsigned int)       __attribute__((noinline));
+extern __ibm128 udi_to_ibm128 (unsigned long long) __attribute__((noinline));
+
+float
+ibm128_to_sf  (__ibm128 x)
+{
+  return x;
+}
+
+double
+ibm128_to_df  (__ibm128 x)
+{
+  return x;
+}
+
+int
+ibm128_to_si  (__ibm128 x)
+{
+  return x;
+}
+
+long long
+ibm128_to_di  (__ibm128 x)
+{
+  return x;
+}
+
+unsigned int
+ibm128_to_usi (__ibm128 x)
+{
+  return x;
+}
+
+unsigned long long
+ibm128_to_udi (__ibm128 x)
+{
+  return x;
+}
+
+__ibm128
+sf_to_ibm128  (float x)
+{
+  return x;
+}
+
+__ibm128
+df_to_ibm128  (double x)
+{
+  return x;
+}
+
+__ibm128
+si_to_ibm128  (int x)
+{
+  return x;
+}
+
+__ibm128
+di_to_ibm128  (long long x)
+{
+  return x;
+}
+
+__ibm128
+usi_to_ibm128 (unsigned int x)
+{
+  return x;
+}
+
+__ibm128
+udi_to_ibm128 (unsigned long long x)
+{
+  return x;
+}
+
+volatile float			seven_sf	= 7.0f;
+volatile double			seven_df	= 7.0;
+volatile int			seven_si	= 7;
+volatile long long		seven_di	= 7LL;
+volatile unsigned int		seven_usi	= 7U;
+volatile unsigned long long	seven_udi	= 7ULL;
+volatile __ibm128		seven_ibm128	= 7.0;
+
+int
+main (void)
+{
+  if (seven_ibm128 != sf_to_ibm128 (seven_sf))
+    abort ();
+
+  if (seven_ibm128 != df_to_ibm128 (seven_df))
+    abort ();
+
+  if (seven_ibm128 != si_to_ibm128 (seven_si))
+    abort ();
+
+  if (seven_ibm128 != di_to_ibm128 (seven_di))
+    abort ();
+
+  if (seven_ibm128 != usi_to_ibm128 (seven_usi))
+    abort ();
+
+  if (seven_ibm128 != udi_to_ibm128 (seven_udi))
+    abort ();
+
+  if (seven_sf != ibm128_to_sf (seven_ibm128))
+    abort ();
+
+  if (seven_df != ibm128_to_df (seven_ibm128))
+    abort ();
+
+  if (seven_si != ibm128_to_si (seven_ibm128))
+    abort ();
+
+  if (seven_di != ibm128_to_di (seven_ibm128))
+    abort ();
+
+  if (seven_usi != ibm128_to_usi (seven_ibm128))
+    abort ();
+
+  if (seven_udi != ibm128_to_udi (seven_ibm128))
+    abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/casttuple.d b/gcc/testsuite/gdc.test/compilable/casttuple.d
new file mode 100644
index 0000000..c4c2bc8
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/casttuple.d
@@ -0,0 +1,31 @@
+alias tuple(T...) = T;
+
+void exactMatch()
+{
+    tuple!int tup_1;
+
+    auto i = cast() tup_1;
+    static assert(is(typeof(i) == int));
+    const i_const = cast(const) tup_1;
+    static assert(is(typeof(i_const) == const int));
+
+    auto totup_1 = cast(tuple!int) tup_1;
+    static assert(is(typeof(totup_1) == tuple!int));
+
+    tuple!(int, int) tup_2;
+    auto totup_2 = cast(tuple!(int, int)) tup_2;
+    static assert(is(typeof(totup_2) == tuple!(int, int)));
+}
+
+void implicitConv()
+{
+    tuple!short tup_1;
+    auto totup_1 = cast(tuple!int) tup_1;
+    static assert(is(typeof(tup_1) == tuple!short));
+    static assert(is(typeof(totup_1) == tuple!int));
+
+    tuple!(short, short) tup_2;
+    auto totup_2 = cast(tuple!(int, int)) tup_2;
+    static assert(is(typeof(tup_2) == tuple!(short, short)));
+    static assert(is(typeof(totup_2) == tuple!(int, int)));
+}
diff --git a/gcc/testsuite/gdc.test/compilable/deprecated_override.d b/gcc/testsuite/gdc.test/compilable/deprecated_override.d
new file mode 100644
index 0000000..c9da34d
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/deprecated_override.d
@@ -0,0 +1,97 @@
+// https://issues.dlang.org/show_bug.cgi?id=22668
+
+// Overrides with same deprecated'ness are allowed
+
+class SameParent
+{
+    deprecated void foo() {}
+    void foo(int) {}
+
+    void bar(int) {}
+    deprecated void bar() {}
+}
+
+class SameChild : SameParent
+{
+    deprecated override void foo() {}
+    override void foo(int) {}
+
+    override void bar(int) {}
+    deprecated override void bar() {}
+}
+
+/**
+Only the parent declaration is deprecated
+
+TEST_OUTPUT:
+----
+compilable/deprecated_override.d(44): Deprecation: `deprecated_override.IntroducingChild.foo` is overriding the deprecated method `deprecated_override.IntroducingParent.foo`
+compilable/deprecated_override.d(48): Deprecation: `deprecated_override.IntroducingChild.bar` is overriding the deprecated method `deprecated_override.IntroducingParent.bar`
+----
+**/
+
+class IntroducingParent
+{
+    deprecated void foo() {}
+    void foo(int) {}
+
+    void bar(int) {}
+    deprecated void bar() {}
+}
+
+class IntroducingChild : IntroducingParent
+{
+    override void foo() {}
+    override void foo(int) {}
+
+    override void bar(int) {}
+    override void bar() {}
+}
+
+// Unrelated to this path but should this error as well?
+
+class IntroducingGrandchild : IntroducingChild
+{
+    override void foo() {}
+    override void foo(int) {}
+
+    override void bar(int) {}
+    override void bar() {}
+}
+
+/**
+Only the overriding declaration is deprecated
+
+TEST_OUTPUT:
+----
+compilable/deprecated_override.d(83): Deprecation: `deprecated_override.OverrideChild.foo` cannot be marked as `deprecated` because it is overriding a function in the base class
+compilable/deprecated_override.d(87): Deprecation: `deprecated_override.OverrideChild.bar` cannot be marked as `deprecated` because it is overriding a function in the base class
+----
+**/
+
+class OverrideParent
+{
+    void foo() {}
+    void foo(int) {}
+
+    void bar(int) {}
+    void bar() {}
+}
+
+class OverrideChild : OverrideParent
+{
+    deprecated override void foo() {}
+    override void foo(int) {}
+
+    override void bar(int) {}
+    deprecated override void bar() {}
+}
+
+class OverrideGrandChild : OverrideChild
+{
+    deprecated override void foo() {}
+    override void foo(int) {}
+
+    override void bar(int) {}
+    deprecated override void bar() {}
+}
diff --git a/gcc/testsuite/gdc.test/compilable/extra-files/header1.d b/gcc/testsuite/gdc.test/compilable/extra-files/header1.d
index 209d4a0..01cf889 100644
--- a/gcc/testsuite/gdc.test/compilable/extra-files/header1.d
+++ b/gcc/testsuite/gdc.test/compilable/extra-files/header1.d
@@ -600,3 +600,9 @@
 void test14x(@Test14UDA1 int, @Test14UDA2("1") int, @test14uda3("2") int, @Test14UDA4!"3" int) {}
 
 void test15x(@(20) void delegate(int) @safe dg){}
+
+T throwStuff(T)(T t)
+{
+    if (false) test13x(1, throw new Exception(""), 2);
+    return t ? t : throw new Exception("Bad stuff happens!");
+}
diff --git a/gcc/testsuite/gdc.test/compilable/fix17635.d b/gcc/testsuite/gdc.test/compilable/fix17635.d
new file mode 100644
index 0000000..dd14de1
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/fix17635.d
@@ -0,0 +1,16 @@
+// https://issues.dlang.org/show_bug.cgi?id=17635
+
+alias T = immutable int;
+
+T** f(const T** input) pure
+{
+    T** output;
+    return output;
+}
+
+void main()
+{
+    T i;
+    T* p = &i;
+    immutable T** r = f(&p);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/fix22291.d b/gcc/testsuite/gdc.test/compilable/fix22291.d
new file mode 100644
index 0000000..4090c5e
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/fix22291.d
@@ -0,0 +1,134 @@
+//https://issues.dlang.org/show_bug.cgi?id=22291
+
+alias AliasSeq(T...) = T;
+void noParameters()
+{
+    static assert(typeof(__traits(parameters)).length == 0);
+}
+void noArgs()
+{
+    //Arguments are not valid, this should not compile
+    static assert(!__traits(compiles, __traits(parameters, 456)));
+}
+shared static this()
+{
+    static assert(typeof(__traits(parameters)).length == 0);
+}
+int echoPlusOne(int x)
+{
+    __traits(parameters)[0] += 1;
+    return x;
+}
+static assert(echoPlusOne(1) == 2);
+class Tree {
+    int opApply(int delegate(size_t, Tree) dg) {
+        if (dg(0, this)) return 1;
+        return 0;
+    }
+}
+void useOpApply(Tree top, int x)
+{
+    foreach(idx; 0..5)
+    {
+        static assert(is(typeof(__traits(parameters)) == AliasSeq!(Tree, int)));
+    }
+    foreach(idx, elem; top)
+    {
+        static assert(is(typeof(__traits(parameters)) == AliasSeq!(size_t, Tree)));
+    }
+}
+class Test
+{
+    static assert(!__traits(compiles, __traits(parameters)));
+    void handle(int x)
+    {
+        static assert(typeof(__traits(parameters)).length == 1);
+    }
+}
+
+int add(int x, int y)
+{
+	return x + y;
+}
+
+auto forwardToAdd(int x, int y)
+{
+	return add(__traits(parameters));
+}
+static assert(forwardToAdd(2, 3) == 5);
+struct TestConstructor
+{
+    int x;
+    string y;
+    //This parameter will not have a name but it's (tuple) members
+    //will
+    this(typeof(this.tupleof))
+    {
+        this.tupleof = __traits(parameters);
+    }
+}
+bool test(int x, string y)
+{
+    auto s = TestConstructor(2, "pi");
+    return s.x == x && s.y == y;
+}
+static assert(test(2, "pi"));
+int testNested(int x)
+{
+    static assert(typeof(__traits(parameters)).length == 1);
+    int add(int x, int y)
+    {
+        static assert(typeof(__traits(parameters)).length == 2);
+        return x + y;
+    }
+    return add(x + 2, x + 3);
+}
+void testPack(Pack...)(Pack x)
+{
+    static assert(is(typeof(__traits(parameters)) == typeof(AliasSeq!(x))));
+}
+
+ref int forwardTest(return ref int x)
+{
+    static assert(__traits(isRef, x) == __traits(isRef, __traits(parameters)[0]));
+    return x;
+}
+
+int testRefness(int x, ref int monkey)
+{
+    {
+        //monkey = x;
+        __traits(parameters)[1] = __traits(parameters)[0];
+    }
+    return x;
+}
+int refTest()
+{
+    int x;
+    testRefness(45, x);
+    return x;
+}
+auto packLength(Pack...)(Pack x)
+{
+    return typeof(__traits(parameters)).length;
+}
+static assert(packLength(2, 3) == 2);
+alias lambda = (x) => typeof(__traits(parameters)).stringof;
+static assert(lambda(1) == "(int)");
+static assert(refTest() == 45);
+
+T testTemplate(T)(scope T input)
+{
+    void chimpInASuit(float set)
+    {
+        static assert(is(typeof(__traits(parameters)) == AliasSeq!(float)));
+    }
+    {
+        __traits(parameters) = AliasSeq!(T.max);
+    }
+    __traits(parameters) = AliasSeq!(T.init);
+    return input;
+}
+
+static assert(testTemplate!long(420) == 0);
+
diff --git a/gcc/testsuite/gdc.test/compilable/imports/cstuff3.c b/gcc/testsuite/gdc.test/compilable/imports/cstuff3.c
new file mode 100644
index 0000000..f6aaf3b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/cstuff3.c
@@ -0,0 +1,6 @@
+// check bugs in importing C files
+
+int squared(int a)
+{
+    return a * a;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/imports/imp22625.c b/gcc/testsuite/gdc.test/compilable/imports/imp22625.c
new file mode 100644
index 0000000..0d18459
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/imp22625.c
@@ -0,0 +1 @@
+typedef struct S { int x; } T;
diff --git a/gcc/testsuite/gdc.test/compilable/imports/imp22665.c b/gcc/testsuite/gdc.test/compilable/imports/imp22665.c
new file mode 100644
index 0000000..f575cff
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/imp22665.c
@@ -0,0 +1 @@
+enum E { A };
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test22685b.d b/gcc/testsuite/gdc.test/compilable/imports/test22685b.d
new file mode 100644
index 0000000..e1854d1
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/test22685b.d
@@ -0,0 +1,5 @@
+module imports.test22685b;
+
+import imports.test22685c : overloaded;
+
+void overloaded()() { }
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test22685c.d b/gcc/testsuite/gdc.test/compilable/imports/test22685c.d
new file mode 100644
index 0000000..e2c8ad1
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/test22685c.d
@@ -0,0 +1,3 @@
+module imports.test22685c;
+
+void overloaded()() { }
diff --git a/gcc/testsuite/gdc.test/compilable/issue22130.d b/gcc/testsuite/gdc.test/compilable/issue22130.d
new file mode 100644
index 0000000..34a631d
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/issue22130.d
@@ -0,0 +1,12 @@
+// https://issues.dlang.org/show_bug.cgi?id=22130
+
+int* f(const int* input) pure nothrow @safe
+{
+    int* output;
+    return output;
+}
+void main() pure nothrow @safe
+{
+    int* c = new int;
+    immutable int* i = f(c);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/noreturn1.d b/gcc/testsuite/gdc.test/compilable/noreturn1.d
index 22734cf..5bba9ba 100644
--- a/gcc/testsuite/gdc.test/compilable/noreturn1.d
+++ b/gcc/testsuite/gdc.test/compilable/noreturn1.d
@@ -20,8 +20,7 @@
 
 static assert(is( typeof(assert(0)) == noreturn ));
 
-// Does not parse yet
-// static assert(is( typeof(throw new Exception()) == noreturn ));
+static assert(is( typeof(throw new Exception("")) == noreturn ));
 
 static assert(is(noreturn == noreturn));
 static assert(!is(noreturn == const noreturn));
diff --git a/gcc/testsuite/gdc.test/compilable/test13008.d b/gcc/testsuite/gdc.test/compilable/test13008.d
index fd1f41d..f19fdb7 100644
--- a/gcc/testsuite/gdc.test/compilable/test13008.d
+++ b/gcc/testsuite/gdc.test/compilable/test13008.d
@@ -1,10 +1,6 @@
 // REQUIRED_ARGS: -o-
 // PERMUTE_ARGS: -d -de -dw
-/*
-TEST_OUTPUT*
----
----
-*/
+
 deprecated class Dep { }
 deprecated Dep depFunc1(); // error
 deprecated void depFunc2(Dep); // error
diff --git a/gcc/testsuite/gdc.test/compilable/test18771.d b/gcc/testsuite/gdc.test/compilable/test18771.d
index a71361f..e6a511c 100644
--- a/gcc/testsuite/gdc.test/compilable/test18771.d
+++ b/gcc/testsuite/gdc.test/compilable/test18771.d
@@ -1,4 +1,4 @@
-// REQUIRED_ARGS : -c
+// REQUIRED_ARGS: -c
 // EXTRA_FILES: imports/test18771a.d imports/test18771b.d imports/test18771c.d imports/test18771d.d
 // https://issues.dlang.org/show_bug.cgi?id=18771
 
diff --git a/gcc/testsuite/gdc.test/compilable/test19609.d b/gcc/testsuite/gdc.test/compilable/test19609.d
index 2646bd4..4367df1 100644
--- a/gcc/testsuite/gdc.test/compilable/test19609.d
+++ b/gcc/testsuite/gdc.test/compilable/test19609.d
@@ -1,7 +1,7 @@
 // https://issues.dlang.org/show_bug.cgi?id=19609
 // EXTRA_FILES: imports/test19609a.d imports/test19609b.d imports/test19609c.d
 /*
-TEST_OUTPUT
+TEST_OUTPUT:
 ---
 compilable/test19609.d(11): Deprecation: module `imports.test19609a` is deprecated - 
 compilable/test19609.d(12): Deprecation: module `imports.test19609b` is deprecated - hello
diff --git a/gcc/testsuite/gdc.test/compilable/test19873.d b/gcc/testsuite/gdc.test/compilable/test19873.d
index 7252edd..e69b4df 100644
--- a/gcc/testsuite/gdc.test/compilable/test19873.d
+++ b/gcc/testsuite/gdc.test/compilable/test19873.d
@@ -1,4 +1,4 @@
-// PERMUTE_ARGS -preview=dip1000
+// PERMUTE_ARGS: -preview=dip1000
 // https://issues.dlang.org/show_bug.cgi?id=19873
 int* ed(scope int* x)
 {
diff --git a/gcc/testsuite/gdc.test/compilable/test21299a.d b/gcc/testsuite/gdc.test/compilable/test21299a.d
index 3c6d8ec..12cc579 100644
--- a/gcc/testsuite/gdc.test/compilable/test21299a.d
+++ b/gcc/testsuite/gdc.test/compilable/test21299a.d
@@ -1,4 +1,4 @@
 // EXTRA_SOURCES: imports/test21299/mtype.d imports/test21299/func.d imports/test21299/rootstringtable.d
 // REQUIRED_ARGS: -main
-// LINK
+// LINK:
 module test21299a;
diff --git a/gcc/testsuite/gdc.test/compilable/test22619.d b/gcc/testsuite/gdc.test/compilable/test22619.d
new file mode 100644
index 0000000..fd5e894
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test22619.d
@@ -0,0 +1,11 @@
+// https://issues.dlang.org/show_bug.cgi?id=22619
+
+struct W1 {
+	int x;
+	this(ref inout W1 rhs) inout { this.x = rhs.x; }
+}
+
+inout(W1) f(inout W1 x) { return x; }
+void g(W1 x) {
+	auto r = f(x);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test22625.d b/gcc/testsuite/gdc.test/compilable/test22625.d
new file mode 100644
index 0000000..adf6676
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test22625.d
@@ -0,0 +1,4 @@
+// https://issues.dlang.org/show_bug.cgi?id=22625
+// EXTRA_FILES: imports/imp22625.c
+
+import imports.imp22625 : S, T;
diff --git a/gcc/testsuite/gdc.test/compilable/test22646.d b/gcc/testsuite/gdc.test/compilable/test22646.d
new file mode 100644
index 0000000..ae44d81
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test22646.d
@@ -0,0 +1,21 @@
+// https://issues.dlang.org/show_bug.cgi?id=22646
+
+/*
+TEST_OUTPUT:
+---
+true
+true
+false
+false
+---
+*/
+
+static template Bug(string name)
+{
+    enum bool ok = name.length < 3 || name[0..3] != "pad";
+}
+
+pragma(msg, Bug!"x".ok);
+pragma(msg, Bug!"foo".ok);
+pragma(msg, Bug!"pad".ok);
+pragma(msg, Bug!"pad123".ok);
diff --git a/gcc/testsuite/gdc.test/compilable/test22665.d b/gcc/testsuite/gdc.test/compilable/test22665.d
new file mode 100644
index 0000000..9d55dbb
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test22665.d
@@ -0,0 +1,22 @@
+// EXTRA_FILES: imports/imp22665.c
+
+// https://issues.dlang.org/show_bug.cgi?id=22665
+
+import imports.imp22665;
+
+E foo1(E e)
+{
+    return e.A; // with qualification, it is an enum
+}
+
+int foo2()
+{
+    return A; // without qualification, it is an int
+}
+
+E foo3(E e)
+{
+    return E.A; // with qualification, it is an enum
+}
+
+
diff --git a/gcc/testsuite/gdc.test/compilable/test22676.d b/gcc/testsuite/gdc.test/compilable/test22676.d
new file mode 100644
index 0000000..8adc132
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test22676.d
@@ -0,0 +1,25 @@
+// https://issues.dlang.org/show_bug.cgi?id=22676
+template fullyQualifiedName(T)
+{
+    static if (is(T : real))
+        enum fullyQualifiedName;
+
+    enum fullyQualifiedName = null;
+}
+
+static auto _inst()
+{
+    return fullyQualifiedName!(frop);
+}
+
+alias attr = __traits(getAttributes, _inst);
+
+class frop
+{
+    alias type_id = registry!frop;
+}
+
+template registry(T)
+{
+    enum string FOO = fullyQualifiedName!T;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test22685.d b/gcc/testsuite/gdc.test/compilable/test22685.d
new file mode 100644
index 0000000..504cc9d
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test22685.d
@@ -0,0 +1,11 @@
+// EXTRA_FILES: imports/test22685b.d imports/test22685c.d
+
+module test22685;
+
+import imports.test22685b;
+
+void twoArgs(alias a, alias b)() { }
+
+void main() {
+    twoArgs!(a => 1, overloaded);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test55.d b/gcc/testsuite/gdc.test/compilable/test55.d
index 6dfc665..4b413e1 100644
--- a/gcc/testsuite/gdc.test/compilable/test55.d
+++ b/gcc/testsuite/gdc.test/compilable/test55.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // COMPILED_IMPORTS: imports/test55a.d
 // PERMUTE_ARGS: -dw
 // REQUIRED_ARGS: -d
@@ -17,4 +17,3 @@
   alias int ListHead;
   Arm2 a;
 }
-
diff --git a/gcc/testsuite/gdc.test/compilable/testcstuff3.d b/gcc/testsuite/gdc.test/compilable/testcstuff3.d
new file mode 100644
index 0000000..89228a9
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/testcstuff3.d
@@ -0,0 +1,4 @@
+// EXTRA_FILES: imports/cstuff3.c
+import imports.cstuff3;
+
+static assert(squared(4) == 16);
diff --git a/gcc/testsuite/gdc.test/compilable/testos.d b/gcc/testsuite/gdc.test/compilable/testos.d
new file mode 100644
index 0000000..e0eb3a5
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/testos.d
@@ -0,0 +1,7 @@
+/* PERMUTE_ARGS: -os=host -os=linux -os=osx -os=freebsd -os=solaris
+ * DISABLED: win32 win64
+ */
+
+void test()
+{
+}
diff --git a/gcc/testsuite/gdc.test/compilable/b16967.d b/gcc/testsuite/gdc.test/fail_compilation/b16967.d
similarity index 70%
rename from gcc/testsuite/gdc.test/compilable/b16967.d
rename to gcc/testsuite/gdc.test/fail_compilation/b16967.d
index 57bc1c1..7a2c3e4 100644
--- a/gcc/testsuite/gdc.test/compilable/b16967.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/b16967.d
@@ -1,9 +1,8 @@
 /*
- * REQUIRED_ARGS: -c
  * TEST_OUTPUT:
 ---
-compilable/b16967.d(16): Deprecation: switch case fallthrough - use 'goto default;' if intended
-compilable/b16967.d(26): Deprecation: switch case fallthrough - use 'goto default;' if intended
+fail_compilation/b16967.d(15): Error: switch case fallthrough - use 'goto default;' if intended
+fail_compilation/b16967.d(25): Error: switch case fallthrough - use 'goto default;' if intended
 ---
 */
 int foo(int x)
diff --git a/gcc/testsuite/gdc.test/fail_compilation/bug5096.d b/gcc/testsuite/gdc.test/fail_compilation/bug5096.d
new file mode 100644
index 0000000..2063e41
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/bug5096.d
@@ -0,0 +1,14 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/bug5096.d(13): Error: unmatched closing brace
+---
+*/
+void foo(int x)
+    in {
+        assert(x > 0);
+    } do {
+        x++;
+    }
+}
+void main() {}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/bug9631.d b/gcc/testsuite/gdc.test/fail_compilation/bug9631.d
index 33ea0cd7..0edd5e9 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/bug9631.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/bug9631.d
@@ -91,9 +91,9 @@
 ---
 fail_compilation/bug9631.d(106): Error: function `bug9631.targ.ft!().ft(S _param_0)` is not callable using argument types `(S)`
 fail_compilation/bug9631.d(106):        cannot pass argument `x` of type `bug9631.S` to parameter `bug9631.tem!().S _param_0`
-fail_compilation/bug9631.d(107): Error: template `bug9631.targ.ft` cannot deduce function from argument types `!()(S)`
+fail_compilation/bug9631.d(107): Error: none of the overloads of template `bug9631.targ.ft` are callable using argument types `!()(S)`
 fail_compilation/bug9631.d(105):        Candidate is: `ft()(tem!().S)`
-fail_compilation/bug9631.d(109): Error: template `bug9631.targ.ft2` cannot deduce function from argument types `!()(S, int)`
+fail_compilation/bug9631.d(109): Error: none of the overloads of template `bug9631.targ.ft2` are callable using argument types `!()(S, int)`
 fail_compilation/bug9631.d(108):        Candidate is: `ft2(T)(S, T)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/casttuple.d b/gcc/testsuite/gdc.test/fail_compilation/casttuple.d
new file mode 100644
index 0000000..d08de08b5
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/casttuple.d
@@ -0,0 +1,25 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/casttuple.d(104): Error: cannot cast `__tup1_field_0` of type `int` to tuple type `(string)`
+fail_compilation/casttuple.d(107): Error: cannot cast `tuple(__tup2_field_0, __tup2_field_1)` of type `(int, int)` to tuple type `(string, string)`
+fail_compilation/casttuple.d(111): Error: cannot cast `tuple(foo, 123)` of type `(int, int)` to tuple type `(string, string)`
+---
+ */
+
+alias tuple(T...) = T;
+
+#line 100
+
+void nomatch()
+{
+    tuple!int tup1;
+    auto x = cast(tuple!string) tup1;
+
+    tuple!(int, int) tup2;
+    auto y = cast(tuple!(string, string)) tup2;
+
+    int foo;
+    alias tup3 = tuple!(foo, 123);
+    auto z = cast(tuple!(string, string)) tup3;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/constraints_aggr.d b/gcc/testsuite/gdc.test/fail_compilation/constraints_aggr.d
index a60ea8c..9f12ae6 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/constraints_aggr.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/constraints_aggr.d
@@ -2,12 +2,12 @@
 EXTRA_FILES: imports/constraints.d
 TEST_OUTPUT:
 ---
-fail_compilation/constraints_aggr.d(32): Error: template `imports.constraints.C.f` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_aggr.d(32): Error: none of the overloads of template `imports.constraints.C.f` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(60):        Candidate is: `f(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       !P!T`
-fail_compilation/constraints_aggr.d(33): Error: template `imports.constraints.C.g` cannot deduce function from argument types `!()()`
+fail_compilation/constraints_aggr.d(33): Error: none of the overloads of template `imports.constraints.C.g` are callable using argument types `!()()`
 fail_compilation/imports/constraints.d(63):        Candidate is: `g(this T)()`
   with `T = imports.constraints.C`
   must satisfy the following constraint:
diff --git a/gcc/testsuite/gdc.test/fail_compilation/constraints_func1.d b/gcc/testsuite/gdc.test/fail_compilation/constraints_func1.d
index 91dd405..aac8760 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/constraints_func1.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/constraints_func1.d
@@ -2,72 +2,72 @@
 EXTRA_FILES: imports/constraints.d
 TEST_OUTPUT:
 ---
-fail_compilation/constraints_func1.d(79): Error: template `imports.constraints.test1` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func1.d(79): Error: none of the overloads of template `imports.constraints.test1` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(9):        Candidate is: `test1(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       N!T`
-fail_compilation/constraints_func1.d(80): Error: template `imports.constraints.test2` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func1.d(80): Error: none of the overloads of template `imports.constraints.test2` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(10):        Candidate is: `test2(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       !P!T`
-fail_compilation/constraints_func1.d(81): Error: template `imports.constraints.test3` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func1.d(81): Error: none of the overloads of template `imports.constraints.test3` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(11):        Candidate is: `test3(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       N!T`
-fail_compilation/constraints_func1.d(82): Error: template `imports.constraints.test4` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func1.d(82): Error: none of the overloads of template `imports.constraints.test4` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(12):        Candidate is: `test4(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       N!T`
-fail_compilation/constraints_func1.d(83): Error: template `imports.constraints.test5` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func1.d(83): Error: none of the overloads of template `imports.constraints.test5` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(13):        Candidate is: `test5(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       N!T
        N!T`
-fail_compilation/constraints_func1.d(84): Error: template `imports.constraints.test6` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func1.d(84): Error: none of the overloads of template `imports.constraints.test6` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(14):        Candidate is: `test6(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       N!T
        N!T
        !P!T`
-fail_compilation/constraints_func1.d(85): Error: template `imports.constraints.test7` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func1.d(85): Error: none of the overloads of template `imports.constraints.test7` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(15):        Candidate is: `test7(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       N!T
        N!T`
-fail_compilation/constraints_func1.d(86): Error: template `imports.constraints.test8` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func1.d(86): Error: none of the overloads of template `imports.constraints.test8` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(16):        Candidate is: `test8(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       N!T`
-fail_compilation/constraints_func1.d(87): Error: template `imports.constraints.test9` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func1.d(87): Error: none of the overloads of template `imports.constraints.test9` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(17):        Candidate is: `test9(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       !P!T`
-fail_compilation/constraints_func1.d(88): Error: template `imports.constraints.test10` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func1.d(88): Error: none of the overloads of template `imports.constraints.test10` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(18):        Candidate is: `test10(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       !P!T`
-fail_compilation/constraints_func1.d(89): Error: template `imports.constraints.test11` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func1.d(89): Error: none of the overloads of template `imports.constraints.test11` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(19):        Candidate is: `test11(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       N!T
        !P!T`
-fail_compilation/constraints_func1.d(90): Error: template `imports.constraints.test12` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func1.d(90): Error: none of the overloads of template `imports.constraints.test12` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(20):        Candidate is: `test12(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       !P!T`
-fail_compilation/constraints_func1.d(92): Error: template `imports.constraints.test1` cannot deduce function from argument types `!()(int, int)`
+fail_compilation/constraints_func1.d(92): Error: none of the overloads of template `imports.constraints.test1` are callable using argument types `!()(int, int)`
 fail_compilation/imports/constraints.d(9):        Candidate is: `test1(T)(T v)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/constraints_func2.d b/gcc/testsuite/gdc.test/fail_compilation/constraints_func2.d
index 67aa78c..a20426d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/constraints_func2.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/constraints_func2.d
@@ -2,83 +2,83 @@
 EXTRA_FILES: imports/constraints.d
 TEST_OUTPUT:
 ---
-fail_compilation/constraints_func2.d(94): Error: template `imports.constraints.test13` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func2.d(94): Error: none of the overloads of template `imports.constraints.test13` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(23):        Candidate is: `test13(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       N!T
        !P!T`
-fail_compilation/constraints_func2.d(95): Error: template `imports.constraints.test14` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func2.d(95): Error: none of the overloads of template `imports.constraints.test14` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(24):        Candidate is: `test14(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       !P!T
        N!T`
-fail_compilation/constraints_func2.d(96): Error: template `imports.constraints.test15` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func2.d(96): Error: none of the overloads of template `imports.constraints.test15` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(25):        Candidate is: `test15(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       !P!T
        !P!T`
-fail_compilation/constraints_func2.d(97): Error: template `imports.constraints.test16` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func2.d(97): Error: none of the overloads of template `imports.constraints.test16` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(26):        Candidate is: `test16(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       N!T
        N!T`
-fail_compilation/constraints_func2.d(98): Error: template `imports.constraints.test17` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func2.d(98): Error: none of the overloads of template `imports.constraints.test17` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(27):        Candidate is: `test17(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       N!T`
-fail_compilation/constraints_func2.d(99): Error: template `imports.constraints.test18` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func2.d(99): Error: none of the overloads of template `imports.constraints.test18` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(28):        Candidate is: `test18(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       N!T
        N!T`
-fail_compilation/constraints_func2.d(100): Error: template `imports.constraints.test19` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func2.d(100): Error: none of the overloads of template `imports.constraints.test19` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(29):        Candidate is: `test19(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       N!T
        !P!T
        N!T`
-fail_compilation/constraints_func2.d(101): Error: template `imports.constraints.test20` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func2.d(101): Error: none of the overloads of template `imports.constraints.test20` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(30):        Candidate is: `test20(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       N!T`
-fail_compilation/constraints_func2.d(102): Error: template `imports.constraints.test21` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func2.d(102): Error: none of the overloads of template `imports.constraints.test21` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(31):        Candidate is: `test21(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       N!T
        N!T`
-fail_compilation/constraints_func2.d(103): Error: template `imports.constraints.test22` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func2.d(103): Error: none of the overloads of template `imports.constraints.test22` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(32):        Candidate is: `test22(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       !P!T
        !P!T`
-fail_compilation/constraints_func2.d(104): Error: template `imports.constraints.test23` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func2.d(104): Error: none of the overloads of template `imports.constraints.test23` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(33):        Candidate is: `test23(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       !P!T
        N!T
        !P!T`
-fail_compilation/constraints_func2.d(105): Error: template `imports.constraints.test24` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func2.d(105): Error: none of the overloads of template `imports.constraints.test24` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(34):        Candidate is: `test24(R)(R r)`
   with `R = int`
   must satisfy the following constraint:
 `       __traits(hasMember, R, "stuff")`
-fail_compilation/constraints_func2.d(106): Error: template `imports.constraints.test25` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func2.d(106): Error: none of the overloads of template `imports.constraints.test25` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(35):        Candidate is: `test25(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       N!T`
-fail_compilation/constraints_func2.d(107): Error: template `imports.constraints.test26` cannot deduce function from argument types `!(float)(int)`
+fail_compilation/constraints_func2.d(107): Error: none of the overloads of template `imports.constraints.test26` are callable using argument types `!(float)(int)`
 fail_compilation/imports/constraints.d(36):        Candidate is: `test26(T, U)(U u)`
   with `T = float,
        U = int`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/constraints_func3.d b/gcc/testsuite/gdc.test/fail_compilation/constraints_func3.d
index f0a5099..6f214b9 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/constraints_func3.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/constraints_func3.d
@@ -2,7 +2,7 @@
 EXTRA_FILES: imports/constraints.d
 TEST_OUTPUT:
 ---
-fail_compilation/constraints_func3.d(53): Error: template `imports.constraints.overload` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func3.d(53): Error: none of the overloads of template `imports.constraints.overload` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(39):        Candidates are: `overload(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
@@ -13,7 +13,7 @@
 `       !P!T`
 fail_compilation/imports/constraints.d(41):                        `overload(T)(T v1, T v2)`
 fail_compilation/imports/constraints.d(42):                        `overload(T, V)(T v1, V v2)`
-fail_compilation/constraints_func3.d(54): Error: template `imports.constraints.overload` cannot deduce function from argument types `!()(int, string)`
+fail_compilation/constraints_func3.d(54): Error: none of the overloads of template `imports.constraints.overload` are callable using argument types `!()(int, string)`
 fail_compilation/imports/constraints.d(39):        Candidates are: `overload(T)(T v)`
 fail_compilation/imports/constraints.d(40):                        `overload(T)(T v)`
 fail_compilation/imports/constraints.d(41):                        `overload(T)(T v1, T v2)`
@@ -23,21 +23,21 @@
   must satisfy one of the following constraints:
 `       N!T
        N!V`
-fail_compilation/constraints_func3.d(56): Error: template `imports.constraints.variadic` cannot deduce function from argument types `!()()`
+fail_compilation/constraints_func3.d(56): Error: none of the overloads of template `imports.constraints.variadic` are callable using argument types `!()()`
 fail_compilation/imports/constraints.d(43):        Candidate is: `variadic(A, T...)(A a, T v)`
-fail_compilation/constraints_func3.d(57): Error: template `imports.constraints.variadic` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func3.d(57): Error: none of the overloads of template `imports.constraints.variadic` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(43):        Candidate is: `variadic(A, T...)(A a, T v)`
   with `A = int,
        T = ()`
   must satisfy the following constraint:
 `       N!int`
-fail_compilation/constraints_func3.d(58): Error: template `imports.constraints.variadic` cannot deduce function from argument types `!()(int, int)`
+fail_compilation/constraints_func3.d(58): Error: none of the overloads of template `imports.constraints.variadic` are callable using argument types `!()(int, int)`
 fail_compilation/imports/constraints.d(43):        Candidate is: `variadic(A, T...)(A a, T v)`
   with `A = int,
        T = (int)`
   must satisfy the following constraint:
 `       N!int`
-fail_compilation/constraints_func3.d(59): Error: template `imports.constraints.variadic` cannot deduce function from argument types `!()(int, int, int)`
+fail_compilation/constraints_func3.d(59): Error: none of the overloads of template `imports.constraints.variadic` are callable using argument types `!()(int, int, int)`
 fail_compilation/imports/constraints.d(43):        Candidate is: `variadic(A, T...)(A a, T v)`
   with `A = int,
        T = (int, int)`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/constraints_func4.d b/gcc/testsuite/gdc.test/fail_compilation/constraints_func4.d
index 751e618..4048bae 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/constraints_func4.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/constraints_func4.d
@@ -3,7 +3,7 @@
 REQUIRED_ARGS: -verrors=context
 TEST_OUTPUT:
 ---
-fail_compilation/constraints_func4.d(90): Error: template `imports.constraints.overload` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func4.d(90): Error: none of the overloads of template `imports.constraints.overload` are callable using argument types `!()(int)`
     overload(0);
             ^
 fail_compilation/imports/constraints.d(39):        Candidates are: `overload(T)(T v)`
@@ -24,7 +24,7 @@
 fail_compilation/imports/constraints.d(42):                        `overload(T, V)(T v1, V v2)`
 void overload(T, V)(T v1, V v2) if (N!T || N!V);
      ^
-fail_compilation/constraints_func4.d(91): Error: template `imports.constraints.overload` cannot deduce function from argument types `!()(int, string)`
+fail_compilation/constraints_func4.d(91): Error: none of the overloads of template `imports.constraints.overload` are callable using argument types `!()(int, string)`
     overload(0, "");
             ^
 fail_compilation/imports/constraints.d(39):        Candidates are: `overload(T)(T v)`
@@ -44,13 +44,13 @@
        N!V`
 void overload(T, V)(T v1, V v2) if (N!T || N!V);
      ^
-fail_compilation/constraints_func4.d(93): Error: template `imports.constraints.variadic` cannot deduce function from argument types `!()()`
+fail_compilation/constraints_func4.d(93): Error: none of the overloads of template `imports.constraints.variadic` are callable using argument types `!()()`
     variadic();
             ^
 fail_compilation/imports/constraints.d(43):        Candidate is: `variadic(A, T...)(A a, T v)`
 void variadic(A, T...)(A a, T v) if (N!int);
      ^
-fail_compilation/constraints_func4.d(94): Error: template `imports.constraints.variadic` cannot deduce function from argument types `!()(int)`
+fail_compilation/constraints_func4.d(94): Error: none of the overloads of template `imports.constraints.variadic` are callable using argument types `!()(int)`
     variadic(0);
             ^
 fail_compilation/imports/constraints.d(43):        Candidate is: `variadic(A, T...)(A a, T v)`
@@ -60,7 +60,7 @@
 `       N!int`
 void variadic(A, T...)(A a, T v) if (N!int);
      ^
-fail_compilation/constraints_func4.d(95): Error: template `imports.constraints.variadic` cannot deduce function from argument types `!()(int, int)`
+fail_compilation/constraints_func4.d(95): Error: none of the overloads of template `imports.constraints.variadic` are callable using argument types `!()(int, int)`
     variadic(0, 1);
             ^
 fail_compilation/imports/constraints.d(43):        Candidate is: `variadic(A, T...)(A a, T v)`
@@ -70,7 +70,7 @@
 `       N!int`
 void variadic(A, T...)(A a, T v) if (N!int);
      ^
-fail_compilation/constraints_func4.d(96): Error: template `imports.constraints.variadic` cannot deduce function from argument types `!()(int, int, int)`
+fail_compilation/constraints_func4.d(96): Error: none of the overloads of template `imports.constraints.variadic` are callable using argument types `!()(int, int, int)`
     variadic(0, 1, 2);
             ^
 fail_compilation/imports/constraints.d(43):        Candidate is: `variadic(A, T...)(A a, T v)`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag11819b.d b/gcc/testsuite/gdc.test/fail_compilation/diag11819b.d
index a5d6a14..aa43727 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag11819b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag11819b.d
@@ -1,25 +1,24 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag11819b.d(28): Error: unrecognized trait `HasMember`, did you mean `hasMember`?
-fail_compilation/diag11819b.d(29): Error: unrecognized trait `Identifier`, did you mean `identifier`?
-fail_compilation/diag11819b.d(30): Error: unrecognized trait `GetProtection`, did you mean `getProtection`?
-fail_compilation/diag11819b.d(31): Error: unrecognized trait `Parent`, did you mean `parent`?
-fail_compilation/diag11819b.d(32): Error: unrecognized trait `GetMember`, did you mean `getMember`?
-fail_compilation/diag11819b.d(33): Error: unrecognized trait `GetOverloads`, did you mean `getOverloads`?
-fail_compilation/diag11819b.d(34): Error: unrecognized trait `GetVirtualFunctions`, did you mean `getVirtualFunctions`?
-fail_compilation/diag11819b.d(35): Error: unrecognized trait `GetVirtualMethods`, did you mean `getVirtualMethods`?
-fail_compilation/diag11819b.d(36): Error: unrecognized trait `ClassInstanceSize`, did you mean `classInstanceSize`?
-fail_compilation/diag11819b.d(37): Error: unrecognized trait `AllMembers`, did you mean `allMembers`?
-fail_compilation/diag11819b.d(38): Error: unrecognized trait `DerivedMembers`, did you mean `derivedMembers`?
-fail_compilation/diag11819b.d(39): Error: unrecognized trait `IsSame`, did you mean `isSame`?
-fail_compilation/diag11819b.d(40): Error: unrecognized trait `Compiles`, did you mean `compiles`?
-fail_compilation/diag11819b.d(41): Error: unrecognized trait `Parameters`
-fail_compilation/diag11819b.d(42): Error: unrecognized trait `GetAliasThis`, did you mean `getAliasThis`?
-fail_compilation/diag11819b.d(43): Error: unrecognized trait `GetAttributes`, did you mean `getAttributes`?
-fail_compilation/diag11819b.d(44): Error: unrecognized trait `GetFunctionAttributes`, did you mean `getFunctionAttributes`?
-fail_compilation/diag11819b.d(45): Error: unrecognized trait `GetUnitTests`, did you mean `getUnitTests`?
-fail_compilation/diag11819b.d(46): Error: unrecognized trait `GetVirtualIndex`, did you mean `getVirtualIndex`?
+fail_compilation/diag11819b.d(27): Error: unrecognized trait `HasMember`, did you mean `hasMember`?
+fail_compilation/diag11819b.d(28): Error: unrecognized trait `Identifier`, did you mean `identifier`?
+fail_compilation/diag11819b.d(29): Error: unrecognized trait `GetProtection`, did you mean `getProtection`?
+fail_compilation/diag11819b.d(30): Error: unrecognized trait `Parent`, did you mean `parent`?
+fail_compilation/diag11819b.d(31): Error: unrecognized trait `GetMember`, did you mean `getMember`?
+fail_compilation/diag11819b.d(32): Error: unrecognized trait `GetOverloads`, did you mean `getOverloads`?
+fail_compilation/diag11819b.d(33): Error: unrecognized trait `GetVirtualFunctions`, did you mean `getVirtualFunctions`?
+fail_compilation/diag11819b.d(34): Error: unrecognized trait `GetVirtualMethods`, did you mean `getVirtualMethods`?
+fail_compilation/diag11819b.d(35): Error: unrecognized trait `ClassInstanceSize`, did you mean `classInstanceSize`?
+fail_compilation/diag11819b.d(36): Error: unrecognized trait `AllMembers`, did you mean `allMembers`?
+fail_compilation/diag11819b.d(37): Error: unrecognized trait `DerivedMembers`, did you mean `derivedMembers`?
+fail_compilation/diag11819b.d(38): Error: unrecognized trait `IsSame`, did you mean `isSame`?
+fail_compilation/diag11819b.d(39): Error: unrecognized trait `Compiles`, did you mean `compiles`?
+fail_compilation/diag11819b.d(40): Error: unrecognized trait `GetAliasThis`, did you mean `getAliasThis`?
+fail_compilation/diag11819b.d(41): Error: unrecognized trait `GetAttributes`, did you mean `getAttributes`?
+fail_compilation/diag11819b.d(42): Error: unrecognized trait `GetFunctionAttributes`, did you mean `getFunctionAttributes`?
+fail_compilation/diag11819b.d(43): Error: unrecognized trait `GetUnitTests`, did you mean `getUnitTests`?
+fail_compilation/diag11819b.d(44): Error: unrecognized trait `GetVirtualIndex`, did you mean `getVirtualIndex`?
 ---
 */
 
@@ -38,7 +37,6 @@
     if (__traits(DerivedMembers)) { }
     if (__traits(IsSame)) { }
     if (__traits(Compiles)) { }
-    if (__traits(Parameters)) { }
     if (__traits(GetAliasThis)) { }
     if (__traits(GetAttributes)) { }
     if (__traits(GetFunctionAttributes)) { }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag13333.d b/gcc/testsuite/gdc.test/fail_compilation/diag13333.d
index 34eeaeb..88e8a9d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag13333.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag13333.d
@@ -1,5 +1,5 @@
 /*
-TEST_OUTPUT*
+TEST_OUTPUT:
 ---
 fail_compilation/diag13333.d(29): Error: template instance `VariantN!(maxSize!(S), T)` recursive template expansion
 fail_compilation/diag13333.d(29): Error: template instance `diag13333.maxSize!(S)` error instantiating
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag13942.d b/gcc/testsuite/gdc.test/fail_compilation/diag13942.d
index 992d5b8..aeee107 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag13942.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag13942.d
@@ -2,7 +2,7 @@
 TEST_OUTPUT:
 ---
 fail_compilation/diag13942.d(18): Error: template instance `isRawStaticArray!()` does not match template declaration `isRawStaticArray(T, A...)`
-fail_compilation/diag13942.d(26): Error: template `diag13942.to!double.to` cannot deduce function from argument types `!()()`
+fail_compilation/diag13942.d(26): Error: none of the overloads of template `diag13942.to!double.to` are callable using argument types `!()()`
 fail_compilation/diag13942.d(17):        Candidate is: `to(A...)(A args)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag16271.d b/gcc/testsuite/gdc.test/fail_compilation/diag16271.d
index b85dc8d..e209593 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag16271.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag16271.d
@@ -1,5 +1,5 @@
 /*
-TEST_OUTPUT
+TEST_OUTPUT:
 ---
 fail_compilation/diag16271.d(10): Error: found `x` when expecting function literal following `ref`
 ---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag16977.d b/gcc/testsuite/gdc.test/fail_compilation/diag16977.d
index 8f991a7..9d8dcfd 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag16977.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag16977.d
@@ -3,7 +3,7 @@
 ---
 fail_compilation/diag16977.d(25): Error: undefined identifier `undefined`, did you mean function `undefinedId`?
 fail_compilation/diag16977.d(26): Error: cannot implicitly convert expression `"\x01string"` of type `string` to `int`
-fail_compilation/diag16977.d(27): Error: template `diag16977.templ` cannot deduce function from argument types `!()(int)`
+fail_compilation/diag16977.d(27): Error: none of the overloads of template `diag16977.templ` are callable using argument types `!()(int)`
 fail_compilation/diag16977.d(20):        Candidate is: `templ(S)(S s)`
   with `S = int`
   must satisfy the following constraint:
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag19225.d b/gcc/testsuite/gdc.test/fail_compilation/diag19225.d
index bbb8251..a43a7e1 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag19225.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag19225.d
@@ -4,7 +4,7 @@
 fail_compilation/diag19225.d(14): Error: basic type expected, not `else`
 fail_compilation/diag19225.d(14):        There's no `static else`, use `else` instead.
 fail_compilation/diag19225.d(14): Error: found `else` without a corresponding `if`, `version` or `debug` statement
-fail_compilation/diag19225.d(15): Error: unrecognized declaration
+fail_compilation/diag19225.d(15): Error: unmatched closing brace
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag8101.d b/gcc/testsuite/gdc.test/fail_compilation/diag8101.d
index a0d245b..282665f 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag8101.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag8101.d
@@ -13,12 +13,12 @@
 fail_compilation/diag8101.d(39):                        `diag8101.f_2(int, int, int, int)`
 fail_compilation/diag8101.d(40):                        `diag8101.f_2(int, int, int, int, int)`
 fail_compilation/diag8101.d(59):        ... (1 more, -v to show) ...
-fail_compilation/diag8101.d(61): Error: template `diag8101.t_0` cannot deduce function from argument types `!()()`
+fail_compilation/diag8101.d(61): Error: none of the overloads of template `diag8101.t_0` are callable using argument types `!()()`
 fail_compilation/diag8101.d(43):        Candidate is: `t_0(T1)()`
-fail_compilation/diag8101.d(62): Error: template `diag8101.t_1` cannot deduce function from argument types `!()()`
+fail_compilation/diag8101.d(62): Error: none of the overloads of template `diag8101.t_1` are callable using argument types `!()()`
 fail_compilation/diag8101.d(45):        Candidates are: `t_1(T1)()`
 fail_compilation/diag8101.d(46):                        `t_1(T1, T2)()`
-fail_compilation/diag8101.d(63): Error: template `diag8101.t_2` cannot deduce function from argument types `!()()`
+fail_compilation/diag8101.d(63): Error: none of the overloads of template `diag8101.t_2` are callable using argument types `!()()`
 fail_compilation/diag8101.d(48):        Candidates are: `t_2(T1)()`
 fail_compilation/diag8101.d(49):                        `t_2(T1, T2)()`
 fail_compilation/diag8101.d(50):                        `t_2(T1, T2, T3)()`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag8648.d b/gcc/testsuite/gdc.test/fail_compilation/diag8648.d
index f202fb3..a04ed7c 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag8648.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag8648.d
@@ -2,13 +2,13 @@
 TEST_OUTPUT:
 ---
 fail_compilation/diag8648.d(18): Error: undefined identifier `X`
-fail_compilation/diag8648.d(29): Error: template `diag8648.foo` cannot deduce function from argument types `!()(Foo!(int, 1))`
+fail_compilation/diag8648.d(29): Error: none of the overloads of template `diag8648.foo` are callable using argument types `!()(Foo!(int, 1))`
 fail_compilation/diag8648.d(18):        Candidate is: `foo(T, n)(X!(T, n))`
 fail_compilation/diag8648.d(20): Error: undefined identifier `a`
-fail_compilation/diag8648.d(31): Error: template `diag8648.bar` cannot deduce function from argument types `!()(Foo!(int, 1))`
+fail_compilation/diag8648.d(31): Error: none of the overloads of template `diag8648.bar` are callable using argument types `!()(Foo!(int, 1))`
 fail_compilation/diag8648.d(20):        Candidate is: `bar(T)(Foo!(T, a))`
 fail_compilation/diag8648.d(20): Error: undefined identifier `a`
-fail_compilation/diag8648.d(32): Error: template `diag8648.bar` cannot deduce function from argument types `!()(Foo!(int, f))`
+fail_compilation/diag8648.d(32): Error: none of the overloads of template `diag8648.bar` are callable using argument types `!()(Foo!(int, f))`
 fail_compilation/diag8648.d(20):        Candidate is: `bar(T)(Foo!(T, a))`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag8684.d b/gcc/testsuite/gdc.test/fail_compilation/diag8684.d
index acfee71..9fbbebf 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag8684.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag8684.d
@@ -1,8 +1,9 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag8684.d(11): Error: found `;` when expecting `)`
-fail_compilation/diag8684.d(12): Error: semicolon expected, not `for`
+fail_compilation/diag8684.d(12): Error: found `;` when expecting `)`
+fail_compilation/diag8684.d(13): Error: semicolon needed to end declaration of `x`, instead of `for`
+fail_compilation/diag8684.d(12):        `x` declared here
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag9004.d b/gcc/testsuite/gdc.test/fail_compilation/diag9004.d
index 62fce32..37d5bd8 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag9004.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag9004.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag9004.d(21): Error: template `diag9004.bar` cannot deduce function from argument types `!()(Foo!int, int)`
+fail_compilation/diag9004.d(21): Error: none of the overloads of template `diag9004.bar` are callable using argument types `!()(Foo!int, int)`
 fail_compilation/diag9004.d(14):        Candidate is: `bar(FooT)(FooT foo, FooT.T x)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag9420.d b/gcc/testsuite/gdc.test/fail_compilation/diag9420.d
index 6b2577d..92cb47f 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag9420.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag9420.d
@@ -1,5 +1,5 @@
 /*
-TEST_OUTPUT
+TEST_OUTPUT:
 ---
 fail_compilation/diag9420.d(21): Error: function `diag9420.S.t3!().tx()` is not callable using argument types `(int)`
 fail_compilation/diag9420.d(21):        expected 0 argument(s), not 1
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diagin.d b/gcc/testsuite/gdc.test/fail_compilation/diagin.d
index a4dabee..eb88a23 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diagin.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diagin.d
@@ -4,7 +4,7 @@
 ---
 fail_compilation/diagin.d(14): Error: function `diagin.foo(in int)` is not callable using argument types `()`
 fail_compilation/diagin.d(14):        missing argument for parameter #1: `in int`
-fail_compilation/diagin.d(16): Error: template `diagin.foo1` cannot deduce function from argument types `!()(bool[])`
+fail_compilation/diagin.d(16): Error: none of the overloads of template `diagin.foo1` are callable using argument types `!()(bool[])`
 fail_compilation/diagin.d(20):        Candidate is: `foo1(T)(in T v, string)`
 ---
  */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/dip25.d b/gcc/testsuite/gdc.test/fail_compilation/dip25.d
index 44fec37..4e803be 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/dip25.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/dip25.d
@@ -3,7 +3,7 @@
 TEST_OUTPUT:
 ---
 fail_compilation/dip25.d(17): Deprecation: returning `this.buffer[]` escapes a reference to parameter `this`
-fail_compilation/dip25.d(17):        perhaps annotate the parameter with `return`
+fail_compilation/dip25.d(17):        perhaps annotate the function with `return`
 fail_compilation/dip25.d(22): Error: returning `identity(x)` escapes a reference to local variable `x`
 fail_compilation/dip25.d(23): Deprecation: returning `identity(x)` escapes a reference to parameter `x`
 fail_compilation/dip25.d(23):        perhaps annotate the parameter with `return`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail10964.d b/gcc/testsuite/gdc.test/fail_compilation/fail10964.d
index 4b31a92..de3673f 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail10964.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail10964.d
@@ -5,8 +5,8 @@
 fail_compilation/fail10964.d(29): Error: function `fail10964.S.__postblit` is not `nothrow`
 fail_compilation/fail10964.d(30): Error: function `fail10964.S.__postblit` is not `nothrow`
 fail_compilation/fail10964.d(33): Error: function `fail10964.S.__postblit` is not `nothrow`
-fail_compilation/fail10964.d(34): Error: function `core.internal.array.construction._d_arraysetctor!(S[], S)._d_arraysetctor` is not `nothrow`
-fail_compilation/fail10964.d(35): Error: function `core.internal.array.construction._d_arrayctor!(S[], S)._d_arrayctor` is not `nothrow`
+fail_compilation/fail10964.d(34): Error: function `fail10964.S.__postblit` is not `nothrow`
+fail_compilation/fail10964.d(35): Error: function `fail10964.S.__postblit` is not `nothrow`
 fail_compilation/fail10964.d(22): Error: `nothrow` function `fail10964.foo` may throw
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail11453a.d b/gcc/testsuite/gdc.test/fail_compilation/fail11453a.d
index 488bc6e..379e86b 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail11453a.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail11453a.d
@@ -1,7 +1,7 @@
 // REQUIRED_ARGS: -Ifail_compilation/extra-files
 // EXTRA_SOURCES: extra-files/foo11453.d extra-files/bar11453.d
 /*
-TEST_OUTPUT
+TEST_OUTPUT:
 ---
 fail_compilation/extra-files/bar11453.d(1): Error: package name 'foo11453' conflicts with usage as a module name in file fail_compilation/extra-files/foo11453.d
 ---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail11453b.d b/gcc/testsuite/gdc.test/fail_compilation/fail11453b.d
index c9d7b96..4e99395 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail11453b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail11453b.d
@@ -1,7 +1,7 @@
 // REQUIRED_ARGS: -Ifail_compilation/extra-files
 // EXTRA_SOURCES: extra-files/bar11453.d extra-files/foo11453.d
 /*
-TEST_OUTPUT
+TEST_OUTPUT:
 ---
 fail_compilation/extra-files/foo11453.d(1): Error: module `foo11453` from file fail_compilation/extra-files/foo11453.d conflicts with package name foo11453
 ---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail11653.d b/gcc/testsuite/gdc.test/fail_compilation/fail11653.d
index fa69edb..4eeb9be 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail11653.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail11653.d
@@ -1,9 +1,8 @@
-// REQUIRED_ARGS: -de
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail11653.d(19): Deprecation: switch case fallthrough - use 'goto case;' if intended
-fail_compilation/fail11653.d(24): Deprecation: switch case fallthrough - use 'goto default;' if intended
+fail_compilation/fail11653.d(18): Error: switch case fallthrough - use 'goto case;' if intended
+fail_compilation/fail11653.d(23): Error: switch case fallthrough - use 'goto default;' if intended
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail12744.d b/gcc/testsuite/gdc.test/fail_compilation/fail12744.d
index 46ed9f6..2056c0e 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail12744.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail12744.d
@@ -14,10 +14,10 @@
 fail_compilation/fail12744.d(40): Error: incompatible parameter storage classes `lazy` and `out`
 fail_compilation/fail12744.d(62): Error: template instance `fail12744.bar12744L!(foo12744O)` error instantiating
 fail_compilation/fail12744.d(41): Error: incompatible parameter storage classes `auto ref` and `out`
-fail_compilation/fail12744.d(67): Error: template `fail12744.bar12744A` cannot deduce function from argument types `!(foo12744O)(int)`
+fail_compilation/fail12744.d(67): Error: none of the overloads of template `fail12744.bar12744A` are callable using argument types `!(foo12744O)(int)`
 fail_compilation/fail12744.d(41):        Candidate is: `bar12744A(alias f)(auto ref PTT12744!f args)`
 fail_compilation/fail12744.d(41): Error: incompatible parameter storage classes `auto ref` and `lazy`
-fail_compilation/fail12744.d(68): Error: template `fail12744.bar12744A` cannot deduce function from argument types `!(foo12744L)(int)`
+fail_compilation/fail12744.d(68): Error: none of the overloads of template `fail12744.bar12744A` are callable using argument types `!(foo12744L)(int)`
 fail_compilation/fail12744.d(41):        Candidate is: `bar12744A(alias f)(auto ref PTT12744!f args)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail132.d b/gcc/testsuite/gdc.test/fail_compilation/fail132.d
index 2c271d9..58ce8a1 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail132.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail132.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail132.d(19): Error: outer class `A` `this` needed to `new` nested class `B`
+fail_compilation/fail132.d(19): Error: cannot construct nested class `B` because no implicit `this` reference to outer class `A` is available
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail14669.d b/gcc/testsuite/gdc.test/fail_compilation/fail14669.d
index c5ae8e7..be72663 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail14669.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail14669.d
@@ -4,7 +4,7 @@
 fail_compilation/fail14669.d(11): Error: `auto` can only be used as part of `auto ref` for template function parameters
 fail_compilation/fail14669.d(16): Error: template instance `fail14669.foo1!()` error instantiating
 fail_compilation/fail14669.d(12): Error: `auto` can only be used as part of `auto ref` for template function parameters
-fail_compilation/fail14669.d(17): Error: template `fail14669.foo2` cannot deduce function from argument types `!()(int)`
+fail_compilation/fail14669.d(17): Error: none of the overloads of template `fail14669.foo2` are callable using argument types `!()(int)`
 fail_compilation/fail14669.d(12):        Candidate is: `foo2()(auto int a)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail162.d b/gcc/testsuite/gdc.test/fail_compilation/fail162.d
index 663e0e1..a537f10 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail162.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail162.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail162.d(25): Error: template `fail162.testHelper` cannot deduce function from argument types `!()(string, string)`
+fail_compilation/fail162.d(25): Error: none of the overloads of template `fail162.testHelper` are callable using argument types `!()(string, string)`
 fail_compilation/fail162.d(10):        Candidate is: `testHelper(A...)()`
 fail_compilation/fail162.d(30): Error: template instance `fail162.test!("hello", "world")` error instantiating
 ---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail18417.d b/gcc/testsuite/gdc.test/fail_compilation/fail18417.d
index b32a99b..7da7bd1 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail18417.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail18417.d
@@ -1,4 +1,4 @@
-// REQUIRED_ARGS : -de
+// REQUIRED_ARGS: -de
 /*
 TEST_OUTPUT:
 ---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail196.d b/gcc/testsuite/gdc.test/fail_compilation/fail196.d
index 78fc361..c7b28cf 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail196.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail196.d
@@ -1,23 +1,24 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail196.d(26): Error: delimited string must end in )"
-fail_compilation/fail196.d(26): Error: Implicit string concatenation is error-prone and disallowed in D
-fail_compilation/fail196.d(26):        Use the explicit syntax instead (concatenating literals is `@nogc`): "foo(xxx)" ~ ";\x0a    assert(s == "
-fail_compilation/fail196.d(27): Error: semicolon expected, not `foo`
-fail_compilation/fail196.d(27): Error: found `");\x0a\x0a    s = q"` when expecting `;` following statement
-fail_compilation/fail196.d(29): Error: found `";\x0a    assert(s == "` when expecting `;` following statement
-fail_compilation/fail196.d(30): Error: found `");\x0a\x0a    s = q"` when expecting `;` following statement
-fail_compilation/fail196.d(32): Error: found `{` when expecting `;` following statement
-fail_compilation/fail196.d(32): Error: found `}` when expecting `;` following statement
-fail_compilation/fail196.d(33): Error: found `foo` when expecting `;` following statement
+fail_compilation/fail196.d(27): Error: delimited string must end in )"
+fail_compilation/fail196.d(27): Error: Implicit string concatenation is error-prone and disallowed in D
+fail_compilation/fail196.d(27):        Use the explicit syntax instead (concatenating literals is `@nogc`): "foo(xxx)" ~ ";\x0a    assert(s == "
+fail_compilation/fail196.d(28): Error: semicolon needed to end declaration of `s`, instead of `foo`
+fail_compilation/fail196.d(27):        `s` declared here
+fail_compilation/fail196.d(28): Error: found `");\x0a\x0a    s = q"` when expecting `;` following statement
+fail_compilation/fail196.d(30): Error: found `";\x0a    assert(s == "` when expecting `;` following statement
+fail_compilation/fail196.d(31): Error: found `");\x0a\x0a    s = q"` when expecting `;` following statement
+fail_compilation/fail196.d(33): Error: found `{` when expecting `;` following statement
 fail_compilation/fail196.d(33): Error: found `}` when expecting `;` following statement
-fail_compilation/fail196.d(35): Error: found `<` when expecting `;` following statement
-fail_compilation/fail196.d(36): Error: found `foo` when expecting `;` following statement
-fail_compilation/fail196.d(36): Error: found `<` instead of statement
-fail_compilation/fail196.d(42): Error: unterminated string constant starting at fail_compilation/fail196.d(42)
-fail_compilation/fail196.d(44): Error: found `End of File` when expecting `}` following compound statement
-fail_compilation/fail196.d(44): Error: found `End of File` when expecting `}` following compound statement
+fail_compilation/fail196.d(34): Error: found `foo` when expecting `;` following statement
+fail_compilation/fail196.d(34): Error: found `}` when expecting `;` following statement
+fail_compilation/fail196.d(36): Error: found `<` when expecting `;` following statement
+fail_compilation/fail196.d(37): Error: found `foo` when expecting `;` following statement
+fail_compilation/fail196.d(37): Error: found `<` instead of statement
+fail_compilation/fail196.d(43): Error: unterminated string constant starting at fail_compilation/fail196.d(43)
+fail_compilation/fail196.d(45): Error: found `End of File` when expecting `}` following compound statement
+fail_compilation/fail196.d(45): Error: found `End of File` when expecting `}` following compound statement
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19609.d b/gcc/testsuite/gdc.test/fail_compilation/fail19609.d
index c68f199..d2e146c 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail19609.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19609.d
@@ -1,7 +1,7 @@
 // https://issues.dlang.org/show_bug.cgi?id=19609
 /*
 EXTRA_FILES: imports/fail19609a.d imports/fail19609b.d imports/fail19609c.d imports/fail19609d.d
-TEST_OUTPUT
+TEST_OUTPUT:
 ---
 fail_compilation/imports/fail19609a.d(1): Error: `string` expected for deprecation message, not `([""])` of type `string[]`
 fail_compilation/fail19609.d(16): Deprecation: module `imports.fail19609a` is deprecated
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19897.d b/gcc/testsuite/gdc.test/fail_compilation/fail19897.d
index d5e6f57..4f5804b 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail19897.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19897.d
@@ -1,5 +1,5 @@
 /*
-TEST_OUTPUT
+TEST_OUTPUT:
 ---
 fail_compilation/fail19897.d(9): Error: cannot implicitly convert expression `[]` of type `const(char[0])` to `const(char)`
 ---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail207.d b/gcc/testsuite/gdc.test/fail_compilation/fail207.d
index 2a00f7f..2fec197 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail207.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail207.d
@@ -1,8 +1,9 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail207.d(10): Error: found end of file instead of initializer
-fail_compilation/fail207.d(10): Error: semicolon expected, not `End of File`
+fail_compilation/fail207.d(11): Error: found end of file instead of initializer
+fail_compilation/fail207.d(11): Error: semicolon needed to end declaration of `x`, instead of `End of File`
+fail_compilation/fail207.d(10):        `x` declared here
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail20730b.d b/gcc/testsuite/gdc.test/fail_compilation/fail20730b.d
index 9320423..00dd9fd 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail20730b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail20730b.d
@@ -3,7 +3,7 @@
 TEST_OUTPUT:
 ---
 (spec:1) fail_compilation/fail20730b.d-mixin-43(43): Error: C style cast illegal, use `cast(int)mod`
-fail_compilation/fail20730b.d(26): Error: template `fail20730b.atomicOp` cannot deduce function from argument types `!("+=")(shared(uint), int)`
+fail_compilation/fail20730b.d(26): Error: none of the overloads of template `fail20730b.atomicOp` are callable using argument types `!("+=")(shared(uint), int)`
 fail_compilation/fail20730b.d(41):        Candidate is: `atomicOp(string op, T, V1)(shared ref T val, V1 mod)`
   with `op = "+=",
        T = uint,
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21830.d b/gcc/testsuite/gdc.test/fail_compilation/fail21830.d
index 9955c65..2e0f84b 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail21830.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail21830.d
@@ -1,5 +1,5 @@
 /* REQUIRED_ARGS: -de -unittest
-TEST_OUTPUT
+TEST_OUTPUT:
 ---
 fail_compilation/fail21830.d(24): Deprecation: struct `fail21830.OldS21830` is deprecated - Deprecated type
 fail_compilation/fail21830.d(24): Deprecation: template `fail21830.test21830(T)(T t) if (is(T == OldS21830))` is deprecated - Deprecated template
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21831.d b/gcc/testsuite/gdc.test/fail_compilation/fail21831.d
index 699ef0b..3955133 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail21831.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail21831.d
@@ -1,5 +1,5 @@
 /* REQUIRED_ARGS: -de -unittest
-TEST_OUTPUT
+TEST_OUTPUT:
 ---
 fail_compilation/fail21831.d(19): Deprecation: struct `fail21831.S21831` is deprecated - Deprecated type
 fail_compilation/fail21831.d(19): Deprecation: template `fail21831.test21831(T)(T t) if (__traits(isDeprecated, T))` is deprecated - Deprecated template
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21832.d b/gcc/testsuite/gdc.test/fail_compilation/fail21832.d
index 03753a4..98f3df7 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail21832.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail21832.d
@@ -1,7 +1,7 @@
 // REQUIRED_ARGS: -de
 // EXTRA_FILES: imports/imp21832.d
 /*
-TEST_OUTPUT
+TEST_OUTPUT:
 ---
 fail_compilation/fail21832.d(4): Deprecation: function `imports.imp21832.fun` is deprecated
 fail_compilation/fail21832.d(10): Deprecation: template `imports.imp21832.tpl()(char a)` is deprecated
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail220.d b/gcc/testsuite/gdc.test/fail_compilation/fail220.d
index 294dc21..d3905d7 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail220.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail220.d
@@ -5,7 +5,7 @@
 fail_compilation/fail220.d(12): Error: found `==` when expecting `)`
 fail_compilation/fail220.d(12): Error: found `class` when expecting `)`
 fail_compilation/fail220.d(12): Error: declaration expected, not `)`
-fail_compilation/fail220.d(16): Error: unrecognized declaration
+fail_compilation/fail220.d(16): Error: unmatched closing brace
 ---
 */
 template types (T) {
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22035.d b/gcc/testsuite/gdc.test/fail_compilation/fail22035.d
index ba03be6..2e67b4d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail22035.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail22035.d
@@ -1,5 +1,5 @@
 // https://issues.dlang.org/show_bug.cgi?id=22035
-/* TEST_OUTPUT
+/* TEST_OUTPUT:
 ---
 fail_compilation/fail22035.d(10): Error: found `2` when expecting `:`
 fail_compilation/fail22035.d(10): Error: found `:` instead of statement
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22084.d b/gcc/testsuite/gdc.test/fail_compilation/fail22084.d
index bd11832..b0ae722 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail22084.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail22084.d
@@ -1,6 +1,6 @@
 // https://issues.dlang.org/show_bug.cgi?id=22084
 /*
-TEST_OUTPUT
+TEST_OUTPUT:
 ---
 fail_compilation/fail22084.d(22): Error: cannot pass types that need destruction as variadic arguments
 ---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22133.d b/gcc/testsuite/gdc.test/fail_compilation/fail22133.d
index 338d96d..a30d430 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail22133.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail22133.d
@@ -1,6 +1,6 @@
 // https://issues.dlang.org/show_bug.cgi?id=22133
 /*
-TEST_OUTPUT
+TEST_OUTPUT:
 ---
 fail_compilation/fail22133.d(16): Error: `s.popFront()()` has no effect
 fail_compilation/fail22133.d(17): Error: template `s.popFront()()` has no type
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22144.d b/gcc/testsuite/gdc.test/fail_compilation/fail22144.d
index e0fd5b1..694c1e9 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail22144.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail22144.d
@@ -1,5 +1,5 @@
 // https://issues.dlang.org/show_bug.cgi?id=22144
-/* TEST_OUTPUT
+/* TEST_OUTPUT:
 ---
 fail_compilation/fail22144.d(12): Error: cannot cast expression `zarray1` of type `int[0]` to `int[0][]` since sizes don't line up
 ---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22749.d b/gcc/testsuite/gdc.test/fail_compilation/fail22749.d
new file mode 100644
index 0000000..56ccac6
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail22749.d
@@ -0,0 +1,13 @@
+// EXTRA_FILES: imports/imp22749.c
+/* TEST_OUTPUT:
+---
+fail_compilation/fail22749.d(12): Error: cannot take address of bit-field `field`
+---
+*/
+import imports.imp22749;
+
+void test22749()
+{
+    S22749 s;
+    void* ptr = &s.field;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail236.d b/gcc/testsuite/gdc.test/fail_compilation/fail236.d
index f63eb21..626ec00 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail236.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail236.d
@@ -2,7 +2,7 @@
 TEST_OUTPUT:
 ---
 fail_compilation/fail236.d(14): Error: undefined identifier `x`
-fail_compilation/fail236.d(22): Error: template `fail236.Templ2` cannot deduce function from argument types `!()(int)`
+fail_compilation/fail236.d(22): Error: none of the overloads of template `fail236.Templ2` are callable using argument types `!()(int)`
 fail_compilation/fail236.d(12):        Candidate is: `Templ2(alias a)(x)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail276.d b/gcc/testsuite/gdc.test/fail_compilation/fail276.d
index 4f9b7c3..b5a99a9 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail276.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail276.d
@@ -2,7 +2,7 @@
 TEST_OUTPUT:
 ---
 fail_compilation/fail276.d(19): Error: `this` has no effect
-fail_compilation/fail276.d(15): Error: `this` is only defined in non-static member functions, not `__anonclass2`
+fail_compilation/fail276.d(15): Error: cannot construct anonymous nested class because no implicit `this` reference to outer class is available
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail4269e.d b/gcc/testsuite/gdc.test/fail_compilation/fail4269e.d
index c63bfac..8a95b34 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail4269e.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail4269e.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail4269e.d(10): Error: semicolon expected, not `X5`
+fail_compilation/fail4269e.d(10): Error: semicolon needed to end declaration of `Y` instead of `X5`
 fail_compilation/fail4269e.d(10): Error: no identifier for declarator `X5`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail59.d b/gcc/testsuite/gdc.test/fail_compilation/fail59.d
index 8c51311..5360495 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail59.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail59.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail59.d(50): Error: outer class `C1` `this` needed to `new` nested class `C2`
+fail_compilation/fail59.d(50): Error: cannot construct nested class `C2` because no implicit `this` reference to outer class `C1` is available
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail60.d b/gcc/testsuite/gdc.test/fail_compilation/fail60.d
index ec8de0b..137dfa9 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail60.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail60.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail60.d(14): Error: `this` is only defined in non-static member functions, not `A`
+fail_compilation/fail60.d(14): Error: cannot construct nested class `B` because no implicit `this` reference to outer class `A` is available
 ---
 */
 class A
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail8009.d b/gcc/testsuite/gdc.test/fail_compilation/fail8009.d
index a06dec5..235e480 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail8009.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail8009.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail8009.d(9): Error: template `fail8009.filter` cannot deduce function from argument types `!()(void)`
+fail_compilation/fail8009.d(9): Error: none of the overloads of template `fail8009.filter` are callable using argument types `!()(void)`
 fail_compilation/fail8009.d(8):        Candidate is: `filter(R)(scope bool delegate(ref BAD!R) func)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail95.d b/gcc/testsuite/gdc.test/fail_compilation/fail95.d
index b1f046a..7057a01 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail95.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail95.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail95.d(19): Error: template `fail95.A` cannot deduce function from argument types `!()(int)`
+fail_compilation/fail95.d(19): Error: none of the overloads of template `fail95.A` are callable using argument types `!()(int)`
 fail_compilation/fail95.d(11):        Candidate is: `A(alias T)(T)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fix17635.d b/gcc/testsuite/gdc.test/fail_compilation/fix17635.d
deleted file mode 100644
index 27f55e0..0000000
--- a/gcc/testsuite/gdc.test/fail_compilation/fix17635.d
+++ /dev/null
@@ -1,23 +0,0 @@
-/* REQUIRED_ARGS: -preview=dip1000
-TEST_OUTPUT:
----
-fail_compilation/fix17635.d(22): Error: cannot implicitly convert expression `f(& p)` of type `immutable(int)**` to `immutable(int**)`
----
-*/
-// https://issues.dlang.org/show_bug.cgi?id=17635
-// https://issues.dlang.org/show_bug.cgi?id=15660
-
-alias T = immutable int;
-
-T** f(const T** input) pure
-{
-    T** output;
-    return output;
-}
-
-void main()
-{
-    T i;
-    T* p = &i;
-    immutable T** r = f(&p);
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice11856_0.d b/gcc/testsuite/gdc.test/fail_compilation/ice11856_0.d
index 36bc2bd..1e51a06 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice11856_0.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice11856_0.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice11856_0.d(19): Error: template `ice11856_0.f` cannot deduce function from argument types `!()(int)`
+fail_compilation/ice11856_0.d(19): Error: none of the overloads of template `ice11856_0.f` are callable using argument types `!()(int)`
 fail_compilation/ice11856_0.d(13):        Candidates are: `f(T)(T t)`
 fail_compilation/ice11856_0.d(16):                        `f(T)(T t)`
   with `T = int`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice11856_1.d b/gcc/testsuite/gdc.test/fail_compilation/ice11856_1.d
index 70991ae..d2a1d1d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice11856_1.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice11856_1.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice11856_1.d(13): Error: template `ice11856_1.g` cannot deduce function from argument types `!()(A)`
+fail_compilation/ice11856_1.d(13): Error: none of the overloads of template `ice11856_1.g` are callable using argument types `!()(A)`
 fail_compilation/ice11856_1.d(11):        Candidate is: `g(T)(T x)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice14130.d b/gcc/testsuite/gdc.test/fail_compilation/ice14130.d
index 53e35a6..c64fb84 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice14130.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice14130.d
@@ -2,7 +2,7 @@
 TEST_OUTPUT:
 ---
 fail_compilation/ice14130.d(10): Error: undefined identifier `Undef`
-fail_compilation/ice14130.d(14): Error: template `ice14130.foo` cannot deduce function from argument types `!()(int)`
+fail_compilation/ice14130.d(14): Error: none of the overloads of template `ice14130.foo` are callable using argument types `!()(int)`
 fail_compilation/ice14130.d(10):        Candidate is: `foo(R, F = Undef)(R r, F s = 0)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice14907.d b/gcc/testsuite/gdc.test/fail_compilation/ice14907.d
index ac4ba68..e1d7aac 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice14907.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice14907.d
@@ -6,7 +6,7 @@
 fail_compilation/ice14907.d(15): Error: template `ice14907.f(int v = f)()` recursive template expansion
 fail_compilation/ice14907.d(20):        while looking for match for `f!()`
 fail_compilation/ice14907.d(15): Error: template `ice14907.f(int v = f)()` recursive template expansion
-fail_compilation/ice14907.d(21): Error: template `ice14907.f` cannot deduce function from argument types `!()()`
+fail_compilation/ice14907.d(21): Error: none of the overloads of template `ice14907.f` are callable using argument types `!()()`
 fail_compilation/ice14907.d(15):        Candidate is: `f(int v = f)()`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice6538.d b/gcc/testsuite/gdc.test/fail_compilation/ice6538.d
index 0715db5..f7c639d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice6538.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice6538.d
@@ -7,7 +7,7 @@
 TEST_OUTPUT:
 ---
 fail_compilation/ice6538.d(23): Error: expression `super` is not a valid template value argument
-fail_compilation/ice6538.d(28): Error: template `ice6538.D.foo` cannot deduce function from argument types `!()()`
+fail_compilation/ice6538.d(28): Error: none of the overloads of template `ice6538.D.foo` are callable using argument types `!()()`
 fail_compilation/ice6538.d(23):        Candidate is: `foo()()`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice9284.d b/gcc/testsuite/gdc.test/fail_compilation/ice9284.d
index a6d84ae..00602d2 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice9284.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice9284.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice9284.d(14): Error: template `ice9284.C.__ctor` cannot deduce function from argument types `!()(int)`
+fail_compilation/ice9284.d(14): Error: none of the overloads of template `ice9284.C.__ctor` are callable using argument types `!()(int)`
 fail_compilation/ice9284.d(12):        Candidate is: `__ctor()(string)`
 fail_compilation/ice9284.d(20): Error: template instance `ice9284.C.__ctor!()` error instantiating
 ---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/imp18554.d b/gcc/testsuite/gdc.test/fail_compilation/imports/imp18554.d
deleted file mode 100644
index 9f2a855..0000000
--- a/gcc/testsuite/gdc.test/fail_compilation/imports/imp18554.d
+++ /dev/null
@@ -1,4 +0,0 @@
-struct S
-{
-    private int i;
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/imp22749.c b/gcc/testsuite/gdc.test/fail_compilation/imports/imp22749.c
new file mode 100644
index 0000000..7c1850e
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/imports/imp22749.c
@@ -0,0 +1,4 @@
+struct S22749
+{
+    int field : 1;
+};
diff --git a/gcc/testsuite/gdc.test/fail_compilation/issue21936.d b/gcc/testsuite/gdc.test/fail_compilation/issue21936.d
deleted file mode 100644
index a37aa04..0000000
--- a/gcc/testsuite/gdc.test/fail_compilation/issue21936.d
+++ /dev/null
@@ -1,32 +0,0 @@
-/* REQUIRED_ARGS: -preview=dip1000 -Ifail_compilation/imports
-TEST_OUTPUT:
----
-fail_compilation/issue21936.d(15): Error: struct `issue21936s.S` variable `field` is not accessible from `@safe` code
-fail_compilation/issue21936.d(15): Error: struct `issue21936s.S` variable `field` is not accessible from `@safe` code
-fail_compilation/issue21936.d(11): Error: template instance `issue21936.constructImplicit!(S)` error instantiating
-fail_compilation/issue21936.d(7):        instantiated from here: `registerConstructors!(S)`
-fail_compilation/issue21936.d(21):        instantiated from here: `registerType!(S)`
----
-*/
-#line 2
-module issue21936;
-import issue21936s;
-struct Handlers {
-    void registerType(T)()
-    {
-        registerConstructors!T;
-    }
-    void registerConstructors(T)()
-    {
-        constructImplicit!T;
-    }
-}
-
-auto constructImplicit(T)(typeof(T.init.tupleof) x = T.init.tupleof)
-{
-}
-
-void registerHandlersDateTime(Handlers handlers)
-{
-	handlers.registerType!(S);
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/noreturn.d b/gcc/testsuite/gdc.test/fail_compilation/noreturn.d
index 4a588b4..696081a 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/noreturn.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/noreturn.d
@@ -16,8 +16,8 @@
 fail_compilation\noreturn.d(79):        called from here: `casting(1)`
 fail_compilation\noreturn.d(72): Error: `"Accessed expression of type `noreturn`"`
 fail_compilation\noreturn.d(80):        called from here: `casting(2)`
+fail_compilation/noreturn.d(120): Error: uncaught CTFE exception `object.Exception("")`
 ---
-
 https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1034.md
 */
 
@@ -116,3 +116,5 @@
 
 enum forceInClassRef = inClassRef();
 */
+
+enum throwEnum = throw new Exception("");
diff --git a/gcc/testsuite/gdc.test/fail_compilation/noreturn2.d b/gcc/testsuite/gdc.test/fail_compilation/noreturn2.d
index e7d28dc..2d27d6d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/noreturn2.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/noreturn2.d
@@ -88,3 +88,54 @@
     else
         return doStuff();
 }
+
+/+
+TEST_OUTPUT:
+---
+fail_compilation/noreturn2.d(104): Error: `object.Exception` is thrown but not caught
+fail_compilation/noreturn2.d(100): Error: `nothrow` function `noreturn2.doesNestedThrow` may throw
+---
++/
+
+int doesNestedThrow(int i) nothrow
+{
+    // Weird formatting is intended to check the loc
+    return i ? i++ :
+            throw
+            new
+            Exception("")
+    ;
+}
+
+int doesNestedThrowThrowable(int i) nothrow
+{
+    return i ? i++ : throw new Error("");
+}
+
+/+
+TEST_OUTPUT:
+---
+fail_compilation/noreturn2.d(130): Error: cannot create instance of interface `I`
+fail_compilation/noreturn2.d(133): Error: can only throw class objects derived from `Throwable`, not type `int[]`
+fail_compilation/noreturn2.d(138): Error: undefined identifier `UnkownException`
+---
++/
+
+int throwInvalid(int i) nothrow
+{
+    static interface I {}
+    // Weird formatting is intended to check the loc
+    return
+            throw
+            new
+            I()
+        ?
+            throw
+            new
+            int[4]
+        :
+            throw
+            new
+            UnkownException("")
+    ;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/objc_class2.d b/gcc/testsuite/gdc.test/fail_compilation/objc_class2.d
index 9d6658c..b4d3cd7 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/objc_class2.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/objc_class2.d
@@ -1,4 +1,4 @@
-// EXTRA_OBJC_SOURCES
+// EXTRA_OBJC_SOURCES:
 /*
 TEST_OUTPUT:
 ---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/objc_class3.d b/gcc/testsuite/gdc.test/fail_compilation/objc_class3.d
index f76443d..cf2480e 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/objc_class3.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/objc_class3.d
@@ -1,4 +1,4 @@
-// EXTRA_OBJC_SOURCES
+// EXTRA_OBJC_SOURCES:
 /*
 TEST_OUTPUT:
 ---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/objc_non_objc_base.d b/gcc/testsuite/gdc.test/fail_compilation/objc_non_objc_base.d
index 6e2b078..9956212 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/objc_non_objc_base.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/objc_non_objc_base.d
@@ -1,4 +1,4 @@
-// EXTRA_OBJC_SOURCES
+// EXTRA_OBJC_SOURCES:
 /*
 TEST_OUTPUT:
 ---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/reg6769.d b/gcc/testsuite/gdc.test/fail_compilation/reg6769.d
index b11fac9..86e37e7 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/reg6769.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/reg6769.d
@@ -1,5 +1,5 @@
 /*
-TEST_OUTPUT
+TEST_OUTPUT:
 ---
 fail_compilation/reg6769.d(14): Error: reinterpreting cast from `int[]` to `int[7]*` is not supported in CTFE
 fail_compilation/reg6769.d(27):        called from here: `reg6769a([0, 1, 2, 3, 4, 5, 6])`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/reserved_version.d b/gcc/testsuite/gdc.test/fail_compilation/reserved_version.d
index 43998b9..eeea28c 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/reserved_version.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/reserved_version.d
@@ -115,6 +115,7 @@
 fail_compilation/reserved_version.d(217): Error: version identifier `AVR` is reserved and cannot be set
 fail_compilation/reserved_version.d(218): Error: version identifier `D_PreConditions` is reserved and cannot be set
 fail_compilation/reserved_version.d(219): Error: version identifier `D_PostConditions` is reserved and cannot be set
+fail_compilation/reserved_version.d(220): Error: version identifier `D_ProfileGC` is reserved and cannot be set
 ---
 */
 
@@ -236,6 +237,7 @@
 version = AVR;
 version = D_PreConditions;
 version = D_PostConditions;
+version = D_ProfileGC;
 
 // This should work though
 debug = DigitalMars;
@@ -346,3 +348,4 @@
 debug = AVR;
 debug = D_PreConditions;
 debug = D_PostConditions;
+debug = D_ProfileGC;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/reserved_version_switch.d b/gcc/testsuite/gdc.test/fail_compilation/reserved_version_switch.d
index 6333309..792ea0a 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/reserved_version_switch.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/reserved_version_switch.d
@@ -105,6 +105,7 @@
 // REQUIRED_ARGS: -version=none
 // REQUIRED_ARGS: -version=D_PreConditions
 // REQUIRED_ARGS: -version=D_PostConditions
+// REQUIRED_ARGS: -version=D_ProfileGC
 // REQUIRED_ARGS: -debug=DigitalMars
 // REQUIRED_ARGS: -debug=GNU
 // REQUIRED_ARGS: -debug=LDC
@@ -207,6 +208,7 @@
 // REQUIRED_ARGS: -debug=none
 // REQUIRED_ARGS: -debug=D_PreConditions
 // REQUIRED_ARGS: -debug=D_PostConditions
+// REQUIRED_ARGS: -debug=D_ProfileGC
 /*
 TEST_OUTPUT:
 ---
@@ -315,5 +317,6 @@
 Error: version identifier `none` is reserved and cannot be set
 Error: version identifier `D_PreConditions` is reserved and cannot be set
 Error: version identifier `D_PostConditions` is reserved and cannot be set
+Error: version identifier `D_ProfileGC` is reserved and cannot be set
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/retscope5.d b/gcc/testsuite/gdc.test/fail_compilation/retscope5.d
index 1f9906e..0625d8e 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/retscope5.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/retscope5.d
@@ -5,7 +5,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/retscope5.d(5010): Error: reference `t` assigned to `p` with longer lifetime
+fail_compilation/retscope5.d(5010): Error: address of variable `t` assigned to `p` with longer lifetime
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test15191.d b/gcc/testsuite/gdc.test/fail_compilation/test15191.d
index 1b3078f..fea9fb7 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test15191.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test15191.d
@@ -1,5 +1,5 @@
 /* TEST_OUTPUT:
-PERMUTE_ARGS -dip1000
+PERMUTE_ARGS: -dip1000
 ---
 fail_compilation/test15191.d(31): Error: returning `&identity(x)` escapes a reference to local variable `x`
 fail_compilation/test15191.d(37): Error: returning `&identityPtr(x)` escapes a reference to local variable `x`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test16188.d b/gcc/testsuite/gdc.test/fail_compilation/test16188.d
index 38219e9..87c55ea 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test16188.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test16188.d
@@ -2,7 +2,7 @@
 ---
 fail_compilation/test16188.d(1): Error: no identifier for declarator `TEST_OUTPUT`
 fail_compilation/test16188.d(1): Error: declaration expected, not `:`
-fail_compilation/test16188.d(18): Error: unrecognized declaration
+fail_compilation/test16188.d(18): Error: unmatched closing brace
 ---
  */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test16589.d b/gcc/testsuite/gdc.test/fail_compilation/test16589.d
index 7b1f14f..0e86081 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test16589.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test16589.d
@@ -3,9 +3,9 @@
 TEST_OUTPUT:
 ---
 fail_compilation/test16589.d(26): Error: returning `&this.data` escapes a reference to parameter `this`
-fail_compilation/test16589.d(26):        perhaps annotate the parameter with `return`
+fail_compilation/test16589.d(26):        perhaps annotate the function with `return`
 fail_compilation/test16589.d(31): Error: returning `&this` escapes a reference to parameter `this`
-fail_compilation/test16589.d(31):        perhaps annotate the parameter with `return`
+fail_compilation/test16589.d(31):        perhaps annotate the function with `return`
 fail_compilation/test16589.d(37): Error: returning `&s.data` escapes a reference to parameter `s`
 fail_compilation/test16589.d(37):        perhaps annotate the parameter with `return`
 fail_compilation/test16589.d(42): Error: returning `&s` escapes a reference to parameter `s`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test17284.d b/gcc/testsuite/gdc.test/fail_compilation/test17284.d
index a0ea05b..ef19a56 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test17284.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test17284.d
@@ -2,7 +2,7 @@
 ---
 fail_compilation/test17284.d(1): Error: no identifier for declarator `TEST_OUTPUT`
 fail_compilation/test17284.d(1): Error: declaration expected, not `:`
-fail_compilation/test17284.d(12): Error: unrecognized declaration
+fail_compilation/test17284.d(12): Error: unmatched closing brace
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test17450.d b/gcc/testsuite/gdc.test/fail_compilation/test17450.d
index 6d0e25a..f350cbd 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test17450.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test17450.d
@@ -5,7 +5,7 @@
 fail_compilation/test17450.d(17): Error: returning `&s.bar` escapes a reference to parameter `s`
 fail_compilation/test17450.d(17):        perhaps annotate the parameter with `return`
 fail_compilation/test17450.d(20): Error: returning `&this.bar` escapes a reference to parameter `this`
-fail_compilation/test17450.d(20):        perhaps annotate the parameter with `return`
+fail_compilation/test17450.d(20):        perhaps annotate the function with `return`
 ---
 */
 // https://issues.dlang.org/show_bug.cgi?id=17450
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test18554.d b/gcc/testsuite/gdc.test/fail_compilation/test18554.d
deleted file mode 100644
index acbda50..0000000
--- a/gcc/testsuite/gdc.test/fail_compilation/test18554.d
+++ /dev/null
@@ -1,24 +0,0 @@
-/* REQUIRED_ARGS: -preview=dip1000
-EXTRA_FILES: imports/imp18554.d
-TEST_OUTPUT:
----
-fail_compilation/test18554.d(16): Error: struct `imp18554.S` variable `i` is not accessible from `@safe` code
----
-*/
-
-// https://issues.dlang.org/show_bug.cgi?id=18554
-
-import imports.imp18554;
-
-void test1() @safe
-{
-    S s;
-    s.tupleof[0] = 1;
-}
-
-void test2()
-{
-    S s;
-    s.tupleof[0] = 1;
-}
-
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test19107.d b/gcc/testsuite/gdc.test/fail_compilation/test19107.d
index 98858b4..93d86bf 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test19107.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test19107.d
@@ -2,7 +2,7 @@
 EXTRA_FILES: imports/imp19661.d imports/test19107a.d imports/test19107b.d
 TEST_OUTPUT:
 ---
-fail_compilation/test19107.d(24): Error: template `test19107.all` cannot deduce function from argument types `!((c) => c)(string[])`
+fail_compilation/test19107.d(24): Error: none of the overloads of template `test19107.all` are callable using argument types `!((c) => c)(string[])`
 fail_compilation/test19107.d(18):        Candidate is: `all(alias pred, T)(T t)`
   with `pred = __lambda2,
        T = string[]`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test19193.d b/gcc/testsuite/gdc.test/fail_compilation/test19193.d
index 9022776..e75d90e 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test19193.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test19193.d
@@ -1,6 +1,6 @@
 /*
 REQUIRED_ARGS: -de
-TEST_OUTPUT
+TEST_OUTPUT:
 ---
 fail_compilation/test19193.d(13): Deprecation: enum member `test19193.T19193!int.A.b` is deprecated
 ---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21912.d b/gcc/testsuite/gdc.test/fail_compilation/test21912.d
index 8dde98a..5bb92a3 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test21912.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21912.d
@@ -1,6 +1,6 @@
 /*
 PERMUTE_ARGS: -preview=dip1000
-TEST_OUTPUT
+TEST_OUTPUT:
 ---
 fail_compilation/test21912.d(24): Error: function `test21912.escapeParam` is `@nogc` yet allocates closures with the GC
 fail_compilation/test21912.d(26):        test21912.escapeParam.__lambda2 closes over variable i at fail_compilation/test21912.d(24)
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test22298.d b/gcc/testsuite/gdc.test/fail_compilation/test22298.d
new file mode 100644
index 0000000..cdb1a3e
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test22298.d
@@ -0,0 +1,30 @@
+/*
+REQUIRED_ARGS: -preview=dip1000
+TEST_OUTPUT:
+---
+fail_compilation/test22298.d(18): Error: scope variable `i` assigned to `p` with longer lifetime
+fail_compilation/test22298.d(29): Error: scope variable `y` assigned to `x` with longer lifetime
+---
+*/
+
+void g(scope void delegate(scope int*) @safe cb) @safe {
+	int x = 42;
+	cb(&x);
+}
+
+void main() @safe {
+	int* p;
+	void f(scope int* i) @safe {
+		p = i;
+	}
+
+	g(&f);
+	// address of x has escaped g
+	assert(*p == 42);
+}
+
+void f() @safe {
+    mixin("scope int* x;");
+    scope int* y;
+    x = y;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test22541.d b/gcc/testsuite/gdc.test/fail_compilation/test22541.d
new file mode 100644
index 0000000..910db0a
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test22541.d
@@ -0,0 +1,18 @@
+/* REQUIRED_ARGS: -preview=dip1000
+TEST_OUTPUT:
+---
+fail_compilation/test22541.d(104): Error: returning `i` escapes a reference to parameter `i`
+fail_compilation/test22541.d(104):        perhaps annotate the parameter with `return`
+---
+ */
+
+/* https://issues.dlang.org/show_bug.cgi?id=22541
+ */
+
+#line 100
+
+@safe
+ref int newe(ref return scope int i) // ref, error
+{
+    return i;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test22709.d b/gcc/testsuite/gdc.test/fail_compilation/test22709.d
new file mode 100644
index 0000000..dd5258e
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test22709.d
@@ -0,0 +1,29 @@
+/*
+REQUIRED_ARGS: -preview=dip1000
+TEST_OUTPUT:
+---
+fail_compilation/test22709.d(15): Error: address of variable `local` assigned to `arr` with longer lifetime
+fail_compilation/test22709.d(20): Error: address of variable `local` assigned to `arr` with longer lifetime
+---
+*/
+
+// https://issues.dlang.org/show_bug.cgi?id=22709
+@safe:
+
+void escape(ref ubyte[] arr, ref ubyte[64] local)
+{
+    arr = local[];
+}
+
+void escape1(ref ubyte[64] local, ref ubyte[] arr)
+{
+    arr = local[];
+}
+
+ubyte[] getArr()
+{
+    ubyte[64] blob;
+    ubyte[] arr;
+    escape(arr, blob[]);
+    return arr;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test3818.d b/gcc/testsuite/gdc.test/fail_compilation/test3818.d
new file mode 100644
index 0000000..c66db85
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test3818.d
@@ -0,0 +1,27 @@
+/* TEST_OUTPUT:
+---
+fail_compilation/test3818.d(104): Error: missing `; expression` before `)` of `foreach`
+fail_compilation/test3818.d(104):        perhaps the `;` goes before `a`
+fail_compilation/test3818.d(109): Error: missing `; expression` before `)` of `foreach`
+fail_compilation/test3818.d(109):        perhaps the `;` goes before `c`
+fail_compilation/test3818.d(110): Error: declaration expected, not `{`
+---
+*/
+
+// https://issues.dlang.org/show_bug.cgi?id=3818
+
+#line 100
+
+void test1()
+{
+    int[10] a;
+    foreach (i, x, a)
+    {
+    }
+}
+
+static foreach (a, b, c)
+{
+}
+
+
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test9701.d b/gcc/testsuite/gdc.test/fail_compilation/test9701.d
index 384c514..a0310c4 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test9701.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test9701.d
@@ -1,5 +1,5 @@
 /*
-TEST_OUTPUT
+TEST_OUTPUT:
 ---
 fail_compilation/test9701.d(38): Error: `@safe` is not a valid attribute for enum members
 fail_compilation/test9701.d(39): Error: `@system` is not a valid attribute for enum members
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test9701b.d b/gcc/testsuite/gdc.test/fail_compilation/test9701b.d
index 16c2541..725a4cd 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test9701b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test9701b.d
@@ -1,6 +1,6 @@
 /*
 REQUIRED_ARGS: -de
-TEST_OUTPUT
+TEST_OUTPUT:
 ---
 fail_compilation/test9701b.d(20): Deprecation: enum member `test9701b.Enum.e0` is deprecated
 fail_compilation/test9701b.d(21): Deprecation: enum member `test9701b.Enum.e1` is deprecated - message
diff --git a/gcc/testsuite/gdc.test/fail_compilation/traits_parameters.d b/gcc/testsuite/gdc.test/fail_compilation/traits_parameters.d
new file mode 100644
index 0000000..5021c54
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/traits_parameters.d
@@ -0,0 +1,10 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/traits_parameters.d(9): Error: `__traits(parameters)` cannot have arguments, but `234` was supplied
+fail_compilation/traits_parameters.d(10): Error: `__traits(parameters)` may only be used inside a function
+---
+*/
+
+typeof(__traits(parameters, 234)) xyz;
+typeof(__traits(parameters)) x;
diff --git a/gcc/testsuite/gdc.test/runnable/a18.d b/gcc/testsuite/gdc.test/runnable/a18.d
index f568982..c8ed60d 100644
--- a/gcc/testsuite/gdc.test/runnable/a18.d
+++ b/gcc/testsuite/gdc.test/runnable/a18.d
@@ -1,5 +1,5 @@
 /*
-COMPILE_SEPARATELY
+COMPILE_SEPARATELY:
 EXTRA_SOURCES: imports/a18a.d
 PERMUTE_ARGS:
 RUN_OUTPUT:
diff --git a/gcc/testsuite/gdc.test/runnable/a19.d b/gcc/testsuite/gdc.test/runnable/a19.d
index 574f95ca..3681d97 100644
--- a/gcc/testsuite/gdc.test/runnable/a19.d
+++ b/gcc/testsuite/gdc.test/runnable/a19.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/a19a.d
 // PERMUTE_ARGS:
 
diff --git a/gcc/testsuite/gdc.test/runnable/b26.d b/gcc/testsuite/gdc.test/runnable/b26.d
index 54e28da..b80d072 100644
--- a/gcc/testsuite/gdc.test/runnable/b26.d
+++ b/gcc/testsuite/gdc.test/runnable/b26.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/b26a.d
 // PERMUTE_ARGS:
 
diff --git a/gcc/testsuite/gdc.test/runnable/class_opCmp.d b/gcc/testsuite/gdc.test/runnable/class_opCmp.d
new file mode 100644
index 0000000..43f31ac
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/class_opCmp.d
@@ -0,0 +1,25 @@
+class A
+{
+    int x;
+    this(int a) { x = a; }
+
+    alias opCmp = Object.opCmp;
+    alias opCmp = my_cmp;
+
+    final int my_cmp(A a)
+    {
+        return x - a.x;
+    }
+}
+
+void main()
+{
+    auto a1 = new A(1);
+    auto a2 = new A(2);
+    A a_null = null;
+    assert(a1 > a_null);
+    assert(a_null < a1);
+    assert(!(a1 < a1));
+    assert(a1 < a2);
+    assert(a2 > a1);
+}
diff --git a/gcc/testsuite/gdc.test/runnable/fix22624.d b/gcc/testsuite/gdc.test/runnable/fix22624.d
new file mode 100644
index 0000000..542899f
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/fix22624.d
@@ -0,0 +1,19 @@
+// https://issues.dlang.org/show_bug.cgi?id=22624
+// EXTRA_FILES: imports/imp22624.c
+
+import core.stdc.stdio;
+import imports.imp22624;
+
+struct S
+{
+    B b;
+    ulong y = 0x1234_0000_5678;
+}
+
+int main()
+{
+    S s;
+    //printf("%llx\n", s.y);
+    assert(s.y == 0x1234_0000_5678);
+    return 0;
+}
diff --git a/gcc/testsuite/gdc.test/runnable/ice15138.d b/gcc/testsuite/gdc.test/runnable/ice15138.d
index 14d6bfb..95b8c27 100644
--- a/gcc/testsuite/gdc.test/runnable/ice15138.d
+++ b/gcc/testsuite/gdc.test/runnable/ice15138.d
@@ -1,6 +1,6 @@
 // EXTRA_SOURCES: imports/ice15138a.d
 // PERMUTE_ARGS: -unittest -inline
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 
 import imports.ice15138a;
 
diff --git a/gcc/testsuite/gdc.test/runnable/ice15176.d b/gcc/testsuite/gdc.test/runnable/ice15176.d
index 357207d..b47b4ec 100644
--- a/gcc/testsuite/gdc.test/runnable/ice15176.d
+++ b/gcc/testsuite/gdc.test/runnable/ice15176.d
@@ -1,5 +1,5 @@
 // EXTRA_SOURCES: imports/ice15176a.d imports/ice15176b.d
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 
 import imports.ice15176a;
 
diff --git a/gcc/testsuite/gdc.test/runnable/ice15200.d b/gcc/testsuite/gdc.test/runnable/ice15200.d
index b4e2cc3..2e1abbe 100644
--- a/gcc/testsuite/gdc.test/runnable/ice15200.d
+++ b/gcc/testsuite/gdc.test/runnable/ice15200.d
@@ -1,5 +1,5 @@
 // EXTRA_SOURCES: imports/ice15200a.d imports/ice15200b.d
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 
 module ice15200;
 
diff --git a/gcc/testsuite/gdc.test/runnable/imports/imp22624.c b/gcc/testsuite/gdc.test/runnable/imports/imp22624.c
new file mode 100644
index 0000000..ea726d3
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/imports/imp22624.c
@@ -0,0 +1,6 @@
+
+struct B
+{
+    unsigned int x : 1;
+//    unsigned int x;
+};
diff --git a/gcc/testsuite/gdc.test/runnable/issue16995.d b/gcc/testsuite/gdc.test/runnable/issue16995.d
index 3b028d4..0d59882 100644
--- a/gcc/testsuite/gdc.test/runnable/issue16995.d
+++ b/gcc/testsuite/gdc.test/runnable/issue16995.d
@@ -1,5 +1,5 @@
 // REQUIRED_ARGS: -unittest
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/module_with_tests.d imports/another_module_with_tests.d
 
 import imports.module_with_tests;
diff --git a/gcc/testsuite/gdc.test/runnable/link10425.d b/gcc/testsuite/gdc.test/runnable/link10425.d
index 95faf6f..d082516 100644
--- a/gcc/testsuite/gdc.test/runnable/link10425.d
+++ b/gcc/testsuite/gdc.test/runnable/link10425.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/bug10425.d
 
 import imports.bug10425;
diff --git a/gcc/testsuite/gdc.test/runnable/link11069b.d b/gcc/testsuite/gdc.test/runnable/link11069b.d
index 658f46e..33992d1 100644
--- a/gcc/testsuite/gdc.test/runnable/link11069b.d
+++ b/gcc/testsuite/gdc.test/runnable/link11069b.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/link11069x.d
 // EXTRA_SOURCES: imports/link11069y.d
 // EXTRA_SOURCES: imports/link11069z.d
diff --git a/gcc/testsuite/gdc.test/runnable/link11395.d b/gcc/testsuite/gdc.test/runnable/link11395.d
index fe25be1..160225e 100644
--- a/gcc/testsuite/gdc.test/runnable/link11395.d
+++ b/gcc/testsuite/gdc.test/runnable/link11395.d
@@ -1,6 +1,6 @@
 // EXTRA_SOURCES: imports/link11395a.d
 // PERMUTE_ARGS:
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 module link11395;
 import imports.link11395a;
 
diff --git a/gcc/testsuite/gdc.test/runnable/link12010.d b/gcc/testsuite/gdc.test/runnable/link12010.d
index 49c4eb1..fc838d8 100644
--- a/gcc/testsuite/gdc.test/runnable/link12010.d
+++ b/gcc/testsuite/gdc.test/runnable/link12010.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/a12010.d
 // EXTRA_FILES: imports/std12010container.d
 // REQUIRED_ARGS: -release
diff --git a/gcc/testsuite/gdc.test/runnable/link13394.d b/gcc/testsuite/gdc.test/runnable/link13394.d
index aea8686..8af0d36 100644
--- a/gcc/testsuite/gdc.test/runnable/link13394.d
+++ b/gcc/testsuite/gdc.test/runnable/link13394.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/link13394a.d
 
 module link13394;
diff --git a/gcc/testsuite/gdc.test/runnable/link13400.d b/gcc/testsuite/gdc.test/runnable/link13400.d
index fbb9ec7..3fc4dfb 100644
--- a/gcc/testsuite/gdc.test/runnable/link13400.d
+++ b/gcc/testsuite/gdc.test/runnable/link13400.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/link13400a.d
 
 import imports.link13400a;
diff --git a/gcc/testsuite/gdc.test/runnable/link13415.d b/gcc/testsuite/gdc.test/runnable/link13415.d
index 782bb6b..000ece3 100644
--- a/gcc/testsuite/gdc.test/runnable/link13415.d
+++ b/gcc/testsuite/gdc.test/runnable/link13415.d
@@ -2,7 +2,7 @@
 EXTRA_SOURCES: imports/link13415a.d
 REQUIRED_ARGS: -inline
 PERMUTE_ARGS: -allinst -unittest -debug
-COMPILE_SEPARATELY
+COMPILE_SEPARATELY:
 RUN_OUTPUT:
 ---
 i = 77;
diff --git a/gcc/testsuite/gdc.test/runnable/link14588.d b/gcc/testsuite/gdc.test/runnable/link14588.d
index 2ca4b52..cfc8157 100644
--- a/gcc/testsuite/gdc.test/runnable/link14588.d
+++ b/gcc/testsuite/gdc.test/runnable/link14588.d
@@ -1,6 +1,6 @@
 // EXTRA_SOURCES: imports/link14588a.d
 // PERMUTE_ARGS: -allinst -unittest -debug -inline
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 
 import imports.link14588a;
 
diff --git a/gcc/testsuite/gdc.test/runnable/link14814.d b/gcc/testsuite/gdc.test/runnable/link14814.d
index ed06500..10b6b6d 100644
--- a/gcc/testsuite/gdc.test/runnable/link14814.d
+++ b/gcc/testsuite/gdc.test/runnable/link14814.d
@@ -1,6 +1,6 @@
 // EXTRA_SOURCES: imports/link14814a.d
 // PERMUTE_ARGS: -inline -release -g -O -fPIC
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 
 import imports.link14814a;
 
diff --git a/gcc/testsuite/gdc.test/runnable/link15017.d b/gcc/testsuite/gdc.test/runnable/link15017.d
index 16187a8..5d39547 100644
--- a/gcc/testsuite/gdc.test/runnable/link15017.d
+++ b/gcc/testsuite/gdc.test/runnable/link15017.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/std15017variant.d
 /*
 TEST_OUTPUT:
diff --git a/gcc/testsuite/gdc.test/runnable/link7745.d b/gcc/testsuite/gdc.test/runnable/link7745.d
index 9a0eccf..a0fdad5 100644
--- a/gcc/testsuite/gdc.test/runnable/link7745.d
+++ b/gcc/testsuite/gdc.test/runnable/link7745.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/link7745b.d
 // PERMUTE_ARGS:
 
diff --git a/gcc/testsuite/gdc.test/runnable/link8023.d b/gcc/testsuite/gdc.test/runnable/link8023.d
index d4c32cb..e92b150 100644
--- a/gcc/testsuite/gdc.test/runnable/link8023.d
+++ b/gcc/testsuite/gdc.test/runnable/link8023.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/link8023b.d
 // PERMUTE_ARGS: -inline -release
 
diff --git a/gcc/testsuite/gdc.test/runnable/link9571.d b/gcc/testsuite/gdc.test/runnable/link9571.d
index 1efdbdd..caa9c78 100644
--- a/gcc/testsuite/gdc.test/runnable/link9571.d
+++ b/gcc/testsuite/gdc.test/runnable/link9571.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/link9571a.d
 
 import imports.link9571a;
diff --git a/gcc/testsuite/gdc.test/runnable/linktypeinfo.d b/gcc/testsuite/gdc.test/runnable/linktypeinfo.d
index 04579a2..508e094 100644
--- a/gcc/testsuite/gdc.test/runnable/linktypeinfo.d
+++ b/gcc/testsuite/gdc.test/runnable/linktypeinfo.d
@@ -1,6 +1,6 @@
 // EXTRA_SOURCES: imports/linktypeinfo_file.d
 // PERMUTE_ARGS: -g -inline -unittest -debug
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 
 import imports.linktypeinfo_file;
 
diff --git a/gcc/testsuite/gdc.test/runnable/noreturn1.d b/gcc/testsuite/gdc.test/runnable/noreturn1.d
index 1da0479..7d15b54 100644
--- a/gcc/testsuite/gdc.test/runnable/noreturn1.d
+++ b/gcc/testsuite/gdc.test/runnable/noreturn1.d
@@ -112,10 +112,162 @@
     }
 }
 
+/*****************************************/
+
+Exception collectException(void function() f)
+{
+    try
+    {
+        f();
+        return null;
+    }
+    catch (Exception e)
+        return e;
+}
+
+
+int return_()
+{
+    return throw new Exception("Return");
+}
+
+void ternary(int i)
+{
+    i > 0 ? i++ : throw new Exception("Ternary");
+}
+
+void call()
+{
+    ternary(throw new Exception("Call"));
+}
+
+void arrayLiteral()
+{
+    int[] arr = [
+        1,
+        throw new Exception("ArrayLiteral"),
+        2
+    ];
+}
+
+void assocArrayLiteral()
+{
+    int[string] arr = [
+        "A": 1,
+        "B": throw new Exception("AssocArrayLiteral"),
+        "C": 2
+    ];
+}
+
+void testThrowExpression()
+{
+    Exception ae = collectException({ return_(); });
+    assert(ae);
+
+    ae = collectException({ ternary(1); });
+    assert(!ae);
+
+    ae = collectException({ ternary(-1); });
+    assert(ae);
+
+    ae = collectException(&call);
+    assert(ae);
+    assert(ae.msg == "Call");
+
+    ae = collectException(&arrayLiteral);
+    assert(ae);
+
+    ae = collectException(&assocArrayLiteral);
+    assert(ae);
+}
+
+
+/*****************************************/
+
+/// Verify that throws does not screw with side effects
+void testThrowSideEffect()
+{
+    static void foo(bool, void*, int) {}
+
+    bool b;
+    int i;
+
+    try
+    {
+        foo(b = true, throw new Exception(""), i++);
+        assert(false);
+    }
+    catch (Exception) {}
+
+    assert(b == true);
+    assert(i == 0);
+}
+
+/// Verify that throws does not screw with dtors
+void testThrowDtor()
+{
+    static struct S
+    {
+        __gshared int destructed;
+        int id;
+
+        ~this()
+        {
+            assert(!(destructed & id));
+            destructed |= id;
+        }
+
+        string getMessage()
+        {
+            // Force runtime dependency
+            return destructed ? "Already destructed" : "Valid";
+        }
+    }
+
+    static void fooD(S, int, S) {}
+    bool caught;
+
+    try
+    {
+        fooD(S(1), throw new Exception(S(2).getMessage()), S(4));
+        assert(false);
+    }
+    catch (Exception e)
+    {
+        caught = true;
+        assert(e.msg == "Valid");
+    }
+    assert(caught);
+    assert(S.destructed == (1 | 2));
+
+
+    static void fooC(S, int, S) {}
+    caught = false;
+    S.destructed = 0;
+
+    try
+    {
+        fooC(S(1), throw new Exception(S(2).getMessage()), S(4));
+        assert(false);
+    }
+    catch (Exception e)
+    {
+        caught = true;
+        assert(e.msg == "Valid");
+    }
+    assert(caught);
+    assert(S.destructed == (1 | 2));
+}
+
+/*****************************************/
+
 int main()
 {
     test1();
     test2();
     test3();
+    testThrowExpression();
+    testThrowSideEffect();
+    testThrowDtor();
     return 0;
 }
diff --git a/gcc/testsuite/gdc.test/runnable/test11039.d b/gcc/testsuite/gdc.test/runnable/test11039.d
index 8c2e624..cc5cdba 100644
--- a/gcc/testsuite/gdc.test/runnable/test11039.d
+++ b/gcc/testsuite/gdc.test/runnable/test11039.d
@@ -1,5 +1,5 @@
 
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/test11039b.d
 
 import imports.test11039b;
diff --git a/gcc/testsuite/gdc.test/runnable/test11239.d b/gcc/testsuite/gdc.test/runnable/test11239.d
index 9ace1cf..3420235 100644
--- a/gcc/testsuite/gdc.test/runnable/test11239.d
+++ b/gcc/testsuite/gdc.test/runnable/test11239.d
@@ -1,6 +1,6 @@
 // EXTRA_SOURCES: imports/inc11239.d
 // REQUIRED_ARGS: -debug
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // PERMUTE_ARGS:
 
 import imports.inc11239;
diff --git a/gcc/testsuite/gdc.test/runnable/test11447a.d b/gcc/testsuite/gdc.test/runnable/test11447a.d
index cced477..b4e7b1f 100644
--- a/gcc/testsuite/gdc.test/runnable/test11447a.d
+++ b/gcc/testsuite/gdc.test/runnable/test11447a.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/a11447.d
 // PERMUTE_ARGS: -allinst
 
diff --git a/gcc/testsuite/gdc.test/runnable/test11447b.d b/gcc/testsuite/gdc.test/runnable/test11447b.d
index 1e76da7..5e37a5a 100644
--- a/gcc/testsuite/gdc.test/runnable/test11447b.d
+++ b/gcc/testsuite/gdc.test/runnable/test11447b.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/b11447.d
 // PERMUTE_ARGS: -allinst
 
diff --git a/gcc/testsuite/gdc.test/runnable/test11447c.d b/gcc/testsuite/gdc.test/runnable/test11447c.d
index ecec3e5..d3958fe 100644
--- a/gcc/testsuite/gdc.test/runnable/test11447c.d
+++ b/gcc/testsuite/gdc.test/runnable/test11447c.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/c11447.d
 // REQUIRED_ARGS: -w
 // PERMUTE_ARGS: -allinst -debug -g
diff --git a/gcc/testsuite/gdc.test/runnable/test11863.d b/gcc/testsuite/gdc.test/runnable/test11863.d
index f6446aa..9039fdb 100644
--- a/gcc/testsuite/gdc.test/runnable/test11863.d
+++ b/gcc/testsuite/gdc.test/runnable/test11863.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/std11863conv.d
 // EXTRA_FILES: imports/std11863bitmanip.d imports/std11863format.d
 
diff --git a/gcc/testsuite/gdc.test/runnable/test14901.d b/gcc/testsuite/gdc.test/runnable/test14901.d
index 73a357a..599344a 100644
--- a/gcc/testsuite/gdc.test/runnable/test14901.d
+++ b/gcc/testsuite/gdc.test/runnable/test14901.d
@@ -1,7 +1,7 @@
 // REQUIRED_ARGS:
 // PERMUTE_ARGS: -unittest
 // EXTRA_SOURCES: imports/test14901a.d imports/test14901b.d imports/test14901c.d imports/test14901d.d
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 
 module test14901;
 
diff --git a/gcc/testsuite/gdc.test/runnable/test18868.d b/gcc/testsuite/gdc.test/runnable/test18868.d
index b0085c0..26d5c66 100644
--- a/gcc/testsuite/gdc.test/runnable/test18868.d
+++ b/gcc/testsuite/gdc.test/runnable/test18868.d
@@ -1,5 +1,5 @@
 /*
-COMPILE_SEPARATELY
+COMPILE_SEPARATELY:
 EXTRA_SOURCES: imports/test18868_a.d imports/test18868_fls.d
 PERMUTE_ARGS:
 */
diff --git a/gcc/testsuite/gdc.test/runnable/test27.d b/gcc/testsuite/gdc.test/runnable/test27.d
index b45c132..9c0a8d0 100644
--- a/gcc/testsuite/gdc.test/runnable/test27.d
+++ b/gcc/testsuite/gdc.test/runnable/test27.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/test27a.d
 // PERMUTE_ARGS:
 
diff --git a/gcc/testsuite/gdc.test/runnable/test29.d b/gcc/testsuite/gdc.test/runnable/test29.d
index 03c81c6..5ca1eef 100644
--- a/gcc/testsuite/gdc.test/runnable/test29.d
+++ b/gcc/testsuite/gdc.test/runnable/test29.d
@@ -1,5 +1,5 @@
 /*
-COMPILE_SEPARATELY
+COMPILE_SEPARATELY:
 EXTRA_SOURCES: imports/test29a.d imports/test29b.d
 PERMUTE_ARGS:
 RUN_OUTPUT:
diff --git a/gcc/testsuite/gdc.test/runnable/test31.d b/gcc/testsuite/gdc.test/runnable/test31.d
index b19366d..ea18104 100644
--- a/gcc/testsuite/gdc.test/runnable/test31.d
+++ b/gcc/testsuite/gdc.test/runnable/test31.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/test31a.d
 // PERMUTE_ARGS:
 
diff --git a/gcc/testsuite/gdc.test/runnable/test32.d b/gcc/testsuite/gdc.test/runnable/test32.d
index 8340ad2..d98d468 100644
--- a/gcc/testsuite/gdc.test/runnable/test32.d
+++ b/gcc/testsuite/gdc.test/runnable/test32.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/test32a.d
 // PERMUTE_ARGS:
 
diff --git a/gcc/testsuite/gdc.test/runnable/test38.d b/gcc/testsuite/gdc.test/runnable/test38.d
index 4c76e9f..b38b9b9 100644
--- a/gcc/testsuite/gdc.test/runnable/test38.d
+++ b/gcc/testsuite/gdc.test/runnable/test38.d
@@ -1,5 +1,5 @@
 /*
-COMPILE_SEPARATELY
+COMPILE_SEPARATELY:
 EXTRA_SOURCES: imports/test38a.d
 PERMUTE_ARGS:
 RUN_OUTPUT:
diff --git a/gcc/testsuite/gdc.test/runnable/test46.d b/gcc/testsuite/gdc.test/runnable/test46.d
index 908cafb..f5089a7 100644
--- a/gcc/testsuite/gdc.test/runnable/test46.d
+++ b/gcc/testsuite/gdc.test/runnable/test46.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/test46b.d imports/test46a.d imports/test46c.d
 // PERMUTE_ARGS:
 
diff --git a/gcc/testsuite/gdc.test/runnable/test49.d b/gcc/testsuite/gdc.test/runnable/test49.d
index 641d196..9ef1da4 100644
--- a/gcc/testsuite/gdc.test/runnable/test49.d
+++ b/gcc/testsuite/gdc.test/runnable/test49.d
@@ -1,5 +1,5 @@
 /*
-COMPILE_SEPARATELY
+COMPILE_SEPARATELY:
 EXTRA_SOURCES: imports/test49a.d
 PERMUTE_ARGS:
 RUN_OUTPUT:
diff --git a/gcc/testsuite/gdc.test/runnable/test57.d b/gcc/testsuite/gdc.test/runnable/test57.d
index 8c2b662..54cf672 100644
--- a/gcc/testsuite/gdc.test/runnable/test57.d
+++ b/gcc/testsuite/gdc.test/runnable/test57.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/test57a.d imports/test57b.d
 // PERMUTE_ARGS:
 // REQUIRED_ARGS: -inline -release
diff --git a/gcc/testsuite/gdc.test/runnable/test7494.d b/gcc/testsuite/gdc.test/runnable/test7494.d
index 655d00a..ad9532a 100644
--- a/gcc/testsuite/gdc.test/runnable/test7494.d
+++ b/gcc/testsuite/gdc.test/runnable/test7494.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/test7494a.d
 // PERMUTE_ARGS:
 // REQUIRED_ARGS:
diff --git a/gcc/testsuite/gdc.test/runnable/test8997.d b/gcc/testsuite/gdc.test/runnable/test8997.d
index 9604e12..cc02132 100644
--- a/gcc/testsuite/gdc.test/runnable/test8997.d
+++ b/gcc/testsuite/gdc.test/runnable/test8997.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/test8997a.d
 
 module test8997;
diff --git a/gcc/testsuite/gdc.test/runnable/testmod1.d b/gcc/testsuite/gdc.test/runnable/testmod1.d
index 6d9aa9e..43d13d0 100644
--- a/gcc/testsuite/gdc.test/runnable/testmod1.d
+++ b/gcc/testsuite/gdc.test/runnable/testmod1.d
@@ -1,4 +1,4 @@
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/testmod1a.d imports/testmod1b.d
 // PERMUTE_ARGS:
 
diff --git a/gcc/testsuite/gdc.test/runnable/tls_dup.d b/gcc/testsuite/gdc.test/runnable/tls_dup.d
index e55f7e5..6acffb4 100644
--- a/gcc/testsuite/gdc.test/runnable/tls_dup.d
+++ b/gcc/testsuite/gdc.test/runnable/tls_dup.d
@@ -1,7 +1,7 @@
 // NOTE: this is a dup of runnable/tls.d strictly to test the same code compiled
 // separately rather than together like the original is.
 
-// COMPILE_SEPARATELY
+// COMPILE_SEPARATELY:
 // EXTRA_SOURCES: imports/tlsa.d
 // PERMUTE_ARGS:
 
diff --git a/gcc/testsuite/gdc.test/runnable_cxx/cppa.d b/gcc/testsuite/gdc.test/runnable_cxx/cppa.d
index c60d6c6..cd36bf2 100644
--- a/gcc/testsuite/gdc.test/runnable_cxx/cppa.d
+++ b/gcc/testsuite/gdc.test/runnable_cxx/cppa.d
@@ -9,6 +9,9 @@
 
 // N.B MSVC doesn't have a C++11 switch, but it defaults to the latest fully-supported standard
 
+// Broken for unknown reasons since the OMF => MsCOFF switch
+// DISABLED: win32omf
+
 import core.stdc.stdio;
 import core.stdc.stdarg;
 import core.stdc.config;
diff --git a/gcc/testsuite/gfortran.dg/gomp/depend-4.f90 b/gcc/testsuite/gfortran.dg/gomp/depend-4.f90
new file mode 100644
index 0000000..f6cf2fd
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/depend-4.f90
@@ -0,0 +1,261 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-gimple -fdump-tree-original" }
+
+! Check that 'omp depobj's depend and 'omp task/... depend' depend on
+! the same variable
+
+! For pointers, it depends on the address of the pointer target
+! For allocatable, on the allocated memory address
+
+subroutine foo(dss, dsp, dsa, daa, daaa, daap, doss, dosp, dosa, doaa, doaaa, doaap, &
+               dssv, dossv)
+  !use omp_lib
+  use iso_c_binding, only: c_intptr_t
+  implicit none (type, external)
+  integer, parameter :: omp_depend_kind = 2*c_intptr_t
+  integer :: ss, sp, sa, aa(4), aaa(:), aap(:)
+  integer :: dss, dsp, dsa, daa(4), daaa(:), daap(:)
+  integer :: doss, dosp, dosa, doaa(4), doaaa(:), doaap(:)
+  optional :: doss, dosp, dosa, doaa, doaaa, doaap
+  allocatable :: sa, aaa, dsa, daaa, dosa, doaaa
+  pointer :: sp, aap, dsp, daap, dosp, doaap
+  integer, value :: dssv, dossv
+  optional :: dossv
+
+  integer(omp_depend_kind) :: object(20)
+  integer(omp_depend_kind) :: elem(9)
+
+  !$omp depobj(object(1)) depend(in: ss)
+  !$omp depobj(object(2)) depend(in: sp)
+  !$omp depobj(object(3)) depend(in: sa)
+  !$omp depobj(object(4)) depend(in: aa)
+  !$omp depobj(object(5)) depend(in: aaa)
+  !$omp depobj(object(6)) depend(in: aap)
+  !$omp depobj(object(7)) depend(in: dss)
+  !$omp depobj(object(8)) depend(in: dsp)
+  !$omp depobj(object(9)) depend(in: dsa)
+  !$omp depobj(object(10)) depend(in: daa)
+  !$omp depobj(object(11)) depend(in: daaa)
+  !$omp depobj(object(12)) depend(in: daap)
+  !$omp depobj(object(13)) depend(in: doss)
+  !$omp depobj(object(14)) depend(in: dosp)
+  !$omp depobj(object(15)) depend(in: dosa)
+  !$omp depobj(object(16)) depend(in: doaa)
+  !$omp depobj(object(17)) depend(in: doaaa)
+  !$omp depobj(object(18)) depend(in: doaap)
+  !$omp depobj(object(19)) depend(in: dssv)
+  !$omp depobj(object(20)) depend(in: dossv)
+
+  !$omp depobj(elem(1)) depend(in: aa(2))
+  !$omp depobj(elem(2)) depend(in: aaa(2))
+  !$omp depobj(elem(3)) depend(in: aap(2))
+  !$omp depobj(elem(4)) depend(in: daa(2))
+  !$omp depobj(elem(5)) depend(in: daaa(2))
+  !$omp depobj(elem(6)) depend(in: daap(2))
+  !$omp depobj(elem(6)) depend(in: doaa(2))
+  !$omp depobj(elem(8)) depend(in: doaaa(2))
+  !$omp depobj(elem(9)) depend(in: doaap(2))
+
+  !$omp parallel
+  !$omp single
+    !$omp task depend(out: ss)
+      ss = 4
+    !$omp end task
+    !$omp task depend(out: sp)
+      sp = 4
+    !$omp end task
+    !$omp task depend(out: sa)
+      sa = 4
+    !$omp end task
+    !$omp task depend(out: aa)
+      aa = 4
+    !$omp end task
+    !$omp task depend(out: aaa)
+      aaa = 4
+    !$omp end task
+    !$omp task depend(out: aap)
+      aap = 4
+    !$omp end task
+    !$omp task depend(out: dss)
+      dss = 4
+    !$omp end task
+    !$omp task depend(out: dsp)
+      dsp = 4
+    !$omp end task
+    !$omp task depend(out: dsa)
+      dsa = 4
+    !$omp end task
+    !$omp task depend(out: daa)
+      daa = 4
+    !$omp end task
+    !$omp task depend(out: daaa)
+      daaa = 4
+    !$omp end task
+    !$omp task depend(out: daap)
+      daap = 4
+    !$omp end task
+    !$omp task depend(out: doss)
+      doss = 4
+    !$omp end task
+    !$omp task depend(out: dosp)
+      dosp = 4
+    !$omp end task
+    !$omp task depend(out: dosa)
+      dosa = 4
+    !$omp end task
+    !$omp task depend(out: doaa)
+      doaa = 4
+    !$omp end task
+    !$omp task depend(out: doaaa)
+      doaaa = 4
+    !$omp end task
+    !$omp task depend(out: doaap)
+      doaap = 4
+    !$omp end task
+    !$omp task depend(out: dossv)
+      dossv = 4
+    !$omp end task
+    !$omp task depend(out: dssv)
+      dssv = 4
+    !$omp end task
+
+    !$omp task depend(out: aa(2))
+      aa(2) = 4
+    !$omp end task
+    !$omp task depend(out: aaa(2))
+      aaa(2) = 4
+    !$omp end task
+    !$omp task depend(out: aap(2))
+      aap(2) = 4
+    !$omp end task
+    !$omp task depend(out: daa(2))
+      daa(2) = 4
+    !$omp end task
+    !$omp task depend(out: daaa(2))
+      daaa(2) = 4
+    !$omp end task
+    !$omp task depend(out: daap(2))
+      daap(2) = 4
+    !$omp end task
+    !$omp task depend(out: doaa(2))
+      doaa(2) = 4
+    !$omp end task
+    !$omp task depend(out: doaaa(2))
+      doaaa(2) = 4
+    !$omp end task
+    !$omp task depend(out: doaap(2))
+      doaap(2) = 4
+    !$omp end task
+  !$omp end single
+  !$omp end parallel
+end
+
+subroutine bar
+  implicit none (type, external)
+  integer :: depvar, x
+
+  x = 7
+  !$omp parallel
+  !$omp single
+    !$omp task depend(out: depvar)
+      x =5
+    !$omp end task
+    !$omp task depend(in: depvar)
+      if (x /= 5) stop
+    !$omp end task
+  !$omp end single
+  !$omp end parallel
+end
+
+! depvar - only used for dependency, but should still be used in depend:
+
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:depvar\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(in:depvar\\)" 1 "original" } }
+
+! { dg-final { scan-tree-dump-times "&object\\\[0\\\] = &ss;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[1\\\] = sp;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[2\\\] = sa;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[3\\\] = &aa;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[4\\\] = .integer.kind=4.\\\[0:\\\] \\* restrict\\) aaa.data;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[5\\\] = .integer.kind=4.\\\[0:\\\] \\*\\) aap.data;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[6\\\] = dss;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[7\\\] = \\*dsp;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[8\\\] = \\*dsa;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[9\\\] = daa;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[10\\\] = .integer.kind=4.\\\[0:\\\] \\* restrict\\) daaa->data;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[11\\\] = .integer.kind=4.\\\[0:\\\] \\*\\) daap->data;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[12\\\] = doss;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[13\\\] = \\*dosp;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[14\\\] = \\*dosa;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[15\\\] = doaa;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[16\\\] = .integer.kind=4.\\\[0:\\\] \\* restrict\\) doaaa->data;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[17\\\] = .integer.kind=4.\\\[0:\\\] \\*\\) doaap->data;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[18\\\] = &dssv;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[19\\\] = &dossv;" 1 "original" } }
+
+! { dg-final { scan-tree-dump-times "&elem\\\[0\\\] = &aa\\\[1\\\];" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&elem\\\[1\\\] = &\\(\\*\\(integer.kind=4.\\\[0:\\\] \\* restrict\\) aaa.data\\)\\\[aaa.offset \\+ 2\\\];" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&elem\\\[2\\\] = \\(integer.kind=4. \\*\\) \\(aap.data \\+ .sizetype. \\(\\(aap.offset \\+ aap.dim\\\[0\\\].stride \\* 2\\) \\* aap.span\\)\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&elem\\\[3\\\] = &\\(\\*daa\\)\\\[1\\\];" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&elem\\\[4\\\] = &\\(\\*\\(integer.kind=4.\\\[0:\\\] \\* restrict\\) daaa->data\\)\\\[daaa->offset \\+ 2\\\];" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&elem\\\[5\\\] = \\(integer.kind=4. \\*\\) \\(daap->data \\+ .sizetype. \\(\\(daap->offset \\+ daap->dim\\\[0\\\].stride \\* 2\\) \\* daap->span\\)\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&elem\\\[5\\\] = &\\(\\*doaa\\)\\\[1\\\];" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&elem\\\[7\\\] = &\\(\\*\\(integer.kind=4.\\\[0:\\\] \\* restrict\\) doaaa->data\\)\\\[doaaa->offset \\+ 2\\\];" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&elem\\\[8\\\] = \\(integer.kind=4. \\*\\) \\(doaap->data \\+ .sizetype. \\(\\(doaap->offset \\+ doaap->dim\\\[0\\\].stride \\* 2\\) \\* doaap->span\\)\\);" 1 "original" } }
+
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:ss\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*sp\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*sa\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:aa\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) aaa.data\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\*\\) aap.data\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*dss\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\*dsp\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\*dsa\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*daa\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) daaa->data\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\*\\) daap->data\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*doss\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\*dosp\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\*dosa\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*doaa\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) doaaa->data\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\*\\) doaap->data\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:aa\\\[1\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\(\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) aaa.data\\)\\\[aaa.offset \\+ 2\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(integer\\(kind=4\\) \\*\\) \\(aap.data \\+ \\(sizetype\\) \\(\\(aap.offset \\+ aap.dim\\\[0\\\].stride \\* 2\\) \\* aap.span\\)\\)\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\(\\*daa\\)\\\[1\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\(\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) daaa->data\\)\\\[daaa->offset \\+ 2\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(integer\\(kind=4\\) \\*\\) \\(daap->data \\+ \\(sizetype\\) \\(\\(daap->offset \\+ daap->dim\\\[0\\\].stride \\* 2\\) \\* daap->span\\)\\)\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\(\\*doaa\\)\\\[1\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\(\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) doaaa->data\\)\\\[doaaa->offset \\+ 2\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(integer\\(kind=4\\) \\*\\) \\(doaap->data \\+ \\(sizetype\\) \\(\\(doaap->offset \\+ doaap->dim\\\[0\\\].stride \\* 2\\) \\* doaap->span\\)\\)\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:dossv\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:dssv\\)" 1 "original" } }
+
+
+! gimple dump - check only those which are simple one-line checkable:
+
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:&ss\\) shared\\(ss\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:sp\\) shared\\(sp\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:sa\\) shared\\(sa\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:&aa\\) shared\\(aa\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:dss\\) shared\\(dss\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:daa\\) shared\\(daa\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:doss\\) shared\\(doss\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:doaa\\) shared\\(doaa\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:&aa\\\[1\\\]\\) shared\\(aa\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:&dossv\\) shared\\(dossv\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:&dssv\\) shared\\(dssv\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = \\*dsp;" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = \\*dsa;" 3 "gimple" } }
+! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = \\*dosp;" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = \\*dosa;" 3 "gimple" } }
+! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = doaaa->data;" 4 "gimple" } }
+! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = doaap->data;" 4 "gimple" } }
+! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = &\\(\\*daa\\)\\\[1\\\];" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = &\\(\\*doaa\\)\\\[1\\\];" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "= &dssv;" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "= &dossv;" 1 "gimple" } }
+
+
diff --git a/gcc/testsuite/gfortran.dg/gomp/depend-5.f90 b/gcc/testsuite/gfortran.dg/gomp/depend-5.f90
new file mode 100644
index 0000000..4cbe3d4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/depend-5.f90
@@ -0,0 +1,82 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-original" }
+
+! Check that depobj is correctly dereferenced in the depend clause.
+
+subroutine foo(dss, dsp, dsa, daa, daaa, daap, doss, dosp, dosa, doaa, doaaa, doaap)
+  !use omp_lib
+  use iso_c_binding, only: c_intptr_t
+  implicit none (type, external)
+  integer, parameter :: omp_depend_kind = 2*c_intptr_t
+  integer(omp_depend_kind) :: ss, sp, sa, aa(4), aaa(:), aap(:)
+  integer(omp_depend_kind) :: dss, dsp, dsa, daa(4), daaa(:), daap(:)
+  integer(omp_depend_kind) :: doss, dosp, dosa, doaa(4), doaaa(:), doaap(:)
+  optional :: doss, dosp, dosa, doaa, doaaa, doaap
+  allocatable :: sa, aaa, dsa, daaa, dosa, doaaa
+  pointer :: sp, aap, dsp, daap, dosp, doaap
+
+  ! Assume the depend types are initialized ...
+
+  !$omp parallel
+  !$omp single
+    !$omp task depend(depobj: ss)
+    !$omp end task
+    !$omp task depend(depobj: sp)
+    !$omp end task
+    !$omp task depend(depobj: sa)
+    !$omp end task
+    !$omp task depend(depobj: dss)
+    !$omp end task
+    !$omp task depend(depobj: dsp)
+    !$omp end task
+    !$omp task depend(depobj: dsa)
+    !$omp end task
+    !$omp task depend(depobj: doss)
+    !$omp end task
+    !$omp task depend(depobj: dosp)
+    !$omp end task
+    !$omp task depend(depobj: dosa)
+    !$omp end task
+
+    !$omp task depend(depobj: aa(2))
+    !$omp end task
+    !$omp task depend(depobj: aaa(2))
+    !$omp end task
+    !$omp task depend(depobj: aap(2))
+    !$omp end task
+    !$omp task depend(depobj: daa(2))
+    !$omp end task
+    !$omp task depend(depobj: daaa(2))
+    !$omp end task
+    !$omp task depend(depobj: daap(2))
+    !$omp end task
+    !$omp task depend(depobj: doaa(2))
+    !$omp end task
+    !$omp task depend(depobj: doaaa(2))
+    !$omp end task
+    !$omp task depend(depobj: doaap(2))
+    !$omp end task
+  !$omp end single
+  !$omp end parallel
+end
+
+
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(depobj:ss\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(depobj:\\*sp\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(depobj:\\*sa\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(depobj:\\*dss\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(depobj:\\*\\*dsp\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(depobj:\\*\\*dsa\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(depobj:\\*doss\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(depobj:\\*\\*dosp\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(depobj:\\*\\*dosa\\)" 1 "original" } }
+
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(depobj:aa\\\[1\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(depobj:\\(\\*\\(integer\\(kind=\[0-9\]+\\)\\\[0:\\\] \\* restrict\\) aaa.data\\)\\\[aaa.offset \\+ 2\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(depobj:\\*\\(integer\\(kind=\[0-9\]+\\) \\*\\) \\(aap.data \\+ \\(sizetype\\) \\(\\(aap.offset \\+ aap.dim\\\[0\\\].stride \\* 2\\) \\* aap.span\\)\\)\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(depobj:\\(\\*daa\\)\\\[1\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(depobj:\\(\\*\\(integer\\(kind=\[0-9\]+\\)\\\[0:\\\] \\* restrict\\) daaa->data\\)\\\[daaa->offset \\+ 2\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(depobj:\\*\\(integer\\(kind=\[0-9\]+\\) \\*\\) \\(daap->data \\+ \\(sizetype\\) \\(\\(daap->offset \\+ daap->dim\\\[0\\\].stride \\* 2\\) \\* daap->span\\)\\)\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(depobj:\\(\\*doaa\\)\\\[1\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(depobj:\\(\\*\\(integer\\(kind=\[0-9\]+\\)\\\[0:\\\] \\* restrict\\) doaaa->data\\)\\\[doaaa->offset \\+ 2\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(depobj:\\*\\(integer\\(kind=\[0-9\]+\\) \\*\\) \\(doaap->data \\+ \\(sizetype\\) \\(\\(doaap->offset \\+ doaap->dim\\\[0\\\].stride \\* 2\\) \\* doaap->span\\)\\)\\)" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/depend-6.f90 b/gcc/testsuite/gfortran.dg/gomp/depend-6.f90
new file mode 100644
index 0000000..b6c1afe
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/depend-6.f90
@@ -0,0 +1,259 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-gimple -fdump-tree-original" }
+
+! Check that 'omp depobj's depend and 'omp task/... depend' depend on
+! the same variable
+
+! For pointers, it depends on the address of the pointer target
+! For allocatable, on the allocated memory address
+
+subroutine foo(dss, dsp, dsa, daa, daaa, daap, doss, dosp, dosa, doaa, doaaa, doaap, &
+               dssv, dossv)
+  !use omp_lib
+  use iso_c_binding, only: c_intptr_t, c_ptr, c_null_ptr
+  implicit none (type, external)
+  integer, parameter :: omp_depend_kind = 2*c_intptr_t
+  type(c_ptr) :: ss, sp, sa, aa(4), aaa(:), aap(:)
+  type(c_ptr) :: dss, dsp, dsa, daa(4), daaa(:), daap(:)
+  type(c_ptr) :: doss, dosp, dosa, doaa(4), doaaa(:), doaap(:)
+  optional :: doss, dosp, dosa, doaa, doaaa, doaap
+  allocatable :: sa, aaa, dsa, daaa, dosa, doaaa
+  pointer :: sp, aap, dsp, daap, dosp, doaap
+  type(c_ptr), value :: dssv, dossv
+  optional :: dossv
+
+  integer(omp_depend_kind) :: object(20)
+  integer(omp_depend_kind) :: elem(9)
+
+  !$omp depobj(object(1)) depend(in: ss)
+  !$omp depobj(object(2)) depend(in: sp)
+  !$omp depobj(object(3)) depend(in: sa)
+  !$omp depobj(object(4)) depend(in: aa)
+  !$omp depobj(object(5)) depend(in: aaa)
+  !$omp depobj(object(6)) depend(in: aap)
+  !$omp depobj(object(7)) depend(in: dss)
+  !$omp depobj(object(8)) depend(in: dsp)
+  !$omp depobj(object(9)) depend(in: dsa)
+  !$omp depobj(object(10)) depend(in: daa)
+  !$omp depobj(object(11)) depend(in: daaa)
+  !$omp depobj(object(12)) depend(in: daap)
+  !$omp depobj(object(13)) depend(in: doss)
+  !$omp depobj(object(14)) depend(in: dosp)
+  !$omp depobj(object(15)) depend(in: dosa)
+  !$omp depobj(object(16)) depend(in: doaa)
+  !$omp depobj(object(17)) depend(in: doaaa)
+  !$omp depobj(object(18)) depend(in: doaap)
+  !$omp depobj(object(19)) depend(in: dssv)
+  !$omp depobj(object(20)) depend(in: dossv)
+
+  !$omp depobj(elem(1)) depend(in: aa(2))
+  !$omp depobj(elem(2)) depend(in: aaa(2))
+  !$omp depobj(elem(3)) depend(in: aap(2))
+  !$omp depobj(elem(4)) depend(in: daa(2))
+  !$omp depobj(elem(5)) depend(in: daaa(2))
+  !$omp depobj(elem(6)) depend(in: daap(2))
+  !$omp depobj(elem(6)) depend(in: doaa(2))
+  !$omp depobj(elem(8)) depend(in: doaaa(2))
+  !$omp depobj(elem(9)) depend(in: doaap(2))
+
+  !$omp parallel
+  !$omp single
+    !$omp task depend(out: ss)
+      ss = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: sp)
+      sp = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: sa)
+      sa = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: aa)
+      aa = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: aaa)
+      aaa = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: aap)
+      aap = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: dss)
+      dss = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: dsp)
+      dsp = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: dsa)
+      dsa = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: daa)
+      daa = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: daaa)
+      daaa = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: daap)
+      daap = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: doss)
+      doss = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: dosp)
+      dosp = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: dosa)
+      dosa = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: doaa)
+      doaa = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: doaaa)
+      doaaa = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: doaap)
+      doaap = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: dossv)
+      dossv = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: dssv)
+      dssv = c_null_ptr
+    !$omp end task
+
+    !$omp task depend(out: aa(2))
+      aa(2) = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: aaa(2))
+      aaa(2) = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: aap(2))
+      aap(2) = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: daa(2))
+      daa(2) = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: daaa(2))
+      daaa(2) = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: daap(2))
+      daap(2) = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: doaa(2))
+      doaa(2) = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: doaaa(2))
+      doaaa(2) = c_null_ptr
+    !$omp end task
+    !$omp task depend(out: doaap(2))
+      doaap(2) = c_null_ptr
+    !$omp end task
+  !$omp end single
+  !$omp end parallel
+end
+
+subroutine bar
+  implicit none (type, external)
+  integer :: depvar, x
+
+  x = 7
+  !$omp parallel
+  !$omp single
+    !$omp task depend(out: depvar)
+      x =5
+    !$omp end task
+    !$omp task depend(in: depvar)
+      if (x /= 5) stop
+    !$omp end task
+  !$omp end single
+  !$omp end parallel
+end
+
+! depvar - only used for dependency, but should still be used in depend:
+
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:depvar\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(in:depvar\\)" 1 "original" } }
+
+! { dg-final { scan-tree-dump-times "&object\\\[0\\\] = &ss;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[1\\\] = sp;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[2\\\] = sa;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[3\\\] = &aa;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[4\\\] = .void \\*\\\[0:\\\] \\* restrict\\) aaa.data;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[5\\\] = .void \\*\\\[0:\\\] \\*\\) aap.data;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[6\\\] = dss;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[7\\\] = \\*dsp;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[8\\\] = \\*dsa;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[9\\\] = daa;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[10\\\] = .void \\*\\\[0:\\\] \\* restrict\\) daaa->data;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[11\\\] = .void \\*\\\[0:\\\] \\*\\) daap->data;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[12\\\] = doss;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[13\\\] = \\*dosp;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[14\\\] = \\*dosa;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[15\\\] = doaa;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[16\\\] = .void \\*\\\[0:\\\] \\* restrict\\) doaaa->data;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[17\\\] = .void \\*\\\[0:\\\] \\*\\) doaap->data;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[18\\\] = &dssv;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&object\\\[19\\\] = &dossv;" 1 "original" } }
+
+! { dg-final { scan-tree-dump-times "&elem\\\[0\\\] = &aa\\\[1\\\];" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&elem\\\[1\\\] = &\\(\\*\\(void \\*\\\[0:\\\] \\* restrict\\) aaa.data\\)\\\[aaa.offset \\+ 2\\\];" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&elem\\\[2\\\] = \\(void \\* \\*\\) \\(aap.data \\+ .sizetype. \\(\\(aap.offset \\+ aap.dim\\\[0\\\].stride \\* 2\\) \\* aap.span\\)\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&elem\\\[3\\\] = &\\(\\*daa\\)\\\[1\\\];" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&elem\\\[4\\\] = &\\(\\*\\(void \\*\\\[0:\\\] \\* restrict\\) daaa->data\\)\\\[daaa->offset \\+ 2\\\];" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&elem\\\[5\\\] = \\(void \\* \\*\\) \\(daap->data \\+ .sizetype. \\(\\(daap->offset \\+ daap->dim\\\[0\\\].stride \\* 2\\) \\* daap->span\\)\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&elem\\\[5\\\] = &\\(\\*doaa\\)\\\[1\\\];" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&elem\\\[7\\\] = &\\(\\*\\(void \\*\\\[0:\\\] \\* restrict\\) doaaa->data\\)\\\[doaaa->offset \\+ 2\\\];" 1 "original" } }
+! { dg-final { scan-tree-dump-times "&elem\\\[8\\\] = \\(void \\* \\*\\) \\(doaap->data \\+ .sizetype. \\(\\(doaap->offset \\+ doaap->dim\\\[0\\\].stride \\* 2\\) \\* doaap->span\\)\\);" 1 "original" } }
+
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:ss\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*sp\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*sa\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:aa\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(void \\*\\\[0:\\\] \\* restrict\\) aaa.data\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(void \\*\\\[0:\\\] \\*\\) aap.data\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*dss\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\*dsp\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\*dsa\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*daa\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(void \\*\\\[0:\\\] \\* restrict\\) daaa->data\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(void \\*\\\[0:\\\] \\*\\) daap->data\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*doss\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\*dosp\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\*dosa\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*doaa\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(void \\*\\\[0:\\\] \\* restrict\\) doaaa->data\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(void \\*\\\[0:\\\] \\*\\) doaap->data\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:aa\\\[1\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\(\\*\\(void \\*\\\[0:\\\] \\* restrict\\) aaa.data\\)\\\[aaa.offset \\+ 2\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(void \\* \\*\\) \\(aap.data \\+ \\(sizetype\\) \\(\\(aap.offset \\+ aap.dim\\\[0\\\].stride \\* 2\\) \\* aap.span\\)\\)\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\(\\*daa\\)\\\[1\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\(\\*\\(void \\*\\\[0:\\\] \\* restrict\\) daaa->data\\)\\\[daaa->offset \\+ 2\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(void \\* \\*\\) \\(daap->data \\+ \\(sizetype\\) \\(\\(daap->offset \\+ daap->dim\\\[0\\\].stride \\* 2\\) \\* daap->span\\)\\)\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\(\\*doaa\\)\\\[1\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\(\\*\\(void \\*\\\[0:\\\] \\* restrict\\) doaaa->data\\)\\\[doaaa->offset \\+ 2\\\]\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(void \\* \\*\\) \\(doaap->data \\+ \\(sizetype\\) \\(\\(doaap->offset \\+ doaap->dim\\\[0\\\].stride \\* 2\\) \\* doaap->span\\)\\)\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:dossv\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:dssv\\)" 1 "original" } }
+
+
+! gimple dump - check only those which are simple one-line checkable:
+
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:&ss\\) shared\\(ss\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:sp\\) shared\\(sp\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:sa\\) shared\\(sa\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:&aa\\) shared\\(aa\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:dss\\) shared\\(dss\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:daa\\) shared\\(daa\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:doss\\) shared\\(doss\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:doaa\\) shared\\(doaa\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:&aa\\\[1\\\]\\) shared\\(aa\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:&dossv\\) shared\\(dossv\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:&dssv\\) shared\\(dssv\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = \\*dsp;" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = \\*dsa;" 3 "gimple" } }
+! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = \\*dosp;" 2 "gimple" } }
+! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = \\*dosa;" 3 "gimple" } }
+! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = doaaa->data;" 4 "gimple" } }
+! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = doaap->data;" 4 "gimple" } }
+! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = &\\(\\*daa\\)\\\[1\\\];" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = &\\(\\*doaa\\)\\\[1\\\];" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "= &dssv;" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "= &dossv;" 1 "gimple" } }
diff --git a/gcc/testsuite/gfortran.dg/pr104211.f90 b/gcc/testsuite/gfortran.dg/pr104211.f90
new file mode 100644
index 0000000..21b0a26
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr104211.f90
@@ -0,0 +1,11 @@
+! { dg-do compile }
+! PR fortran/104211 - ICE in find_array_section
+! Contributed by G.Steinmetz
+
+program p
+  type t
+     real :: n
+  end type
+  type(t), parameter :: a(3) = [t(2)] ! { dg-error "Different shape" }
+  type(t), parameter :: b(2) = a(2:3) ! { dg-error "Error in array constructor" }
+end
diff --git a/gcc/testsuite/gfortran.dg/pr104528.f b/gcc/testsuite/gfortran.dg/pr104528.f
new file mode 100644
index 0000000..5b43feb
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr104528.f
@@ -0,0 +1,44 @@
+! { dg-do compile }
+! { dg-options "-O2 -fpeel-loops -ftree-loop-vectorize -fno-tree-scev-cprop --param iv-max-considered-uses=2" }
+      REAL               FUNCTION FOO(M, N, A, W)
+
+      INTEGER            M, N
+
+      REAL               W(*)
+      COMPLEX            A(*)
+
+      INTEGER            II, JI, JJ, KK, LL, MP
+
+      EXTERNAL           BAR
+
+      INTEGER            QUX
+      EXTERNAL           QUX
+
+      CALL BAR(II)
+
+      IF (M .EQ. 0) THEN
+         IF (N .EQ. 0) THEN
+            DO 140 KK = II, II + MP
+               W(KK) = 0
+ 140        CONTINUE
+         ELSE
+            KK = II + MP
+         END IF
+
+         DO 130 JI = KK, KK + MP
+            DO 120 LL = JJ, JJ + MP
+               DO 110 KK = II, II + MP
+                  W(KK) = (A(KK))
+ 110           CONTINUE
+ 120        CONTINUE
+ 130     CONTINUE
+
+         IF (W(KK) .EQ. 0) THEN
+            FOO = W(QUX(MP, W, 1))
+         END IF
+
+      END IF
+
+      RETURN
+
+      END
diff --git a/gcc/tree-ssa-dse.cc b/gcc/tree-ssa-dse.cc
index 47997df..2b22a61 100644
--- a/gcc/tree-ssa-dse.cc
+++ b/gcc/tree-ssa-dse.cc
@@ -44,6 +44,7 @@
 #include "ipa-modref-tree.h"
 #include "ipa-modref.h"
 #include "target.h"
+#include "tree-ssa-loop-niter.h"
 
 /* This file implements dead store elimination.
 
@@ -1418,6 +1419,8 @@
 pass_dse::execute (function *fun)
 {
   unsigned todo = 0;
+  bool released_def = false;
+
   need_eh_cleanup = BITMAP_ALLOC (NULL);
   need_ab_cleanup = BITMAP_ALLOC (NULL);
   auto_sbitmap live_bytes (param_dse_max_object_size);
@@ -1460,6 +1463,7 @@
 		  if (gsi_remove (&gsi, true) && need_eh_cleanup)
 		    bitmap_set_bit (need_eh_cleanup, bb->index);
 		  release_defs (stmt);
+		  released_def = true;
 		}
 	    }
 	  if (gsi_end_p (gsi))
@@ -1481,6 +1485,7 @@
 		}
 	      remove_phi_node (&si, true);
 	      removed_phi = true;
+	      released_def = true;
 	    }
 	  else
 	    gsi_next (&si);
@@ -1506,6 +1511,9 @@
   BITMAP_FREE (need_eh_cleanup);
   BITMAP_FREE (need_ab_cleanup);
 
+  if (released_def)
+    free_numbers_of_iterations_estimates (fun);
+
   return todo;
 }
 
diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc
index 709bde6..484491f 100644
--- a/gcc/tree-ssa-forwprop.cc
+++ b/gcc/tree-ssa-forwprop.cc
@@ -2824,6 +2824,15 @@
 			 ? VEC_UNPACK_FLOAT_HI_EXPR
 			 : VEC_UNPACK_HI_EXPR);
 
+	  /* Conversions between DFP and FP have no special tree code
+	     but we cannot handle those since all relevant vector conversion
+	     optabs only have a single mode.  */
+	  if (CONVERT_EXPR_CODE_P (conv_code)
+	      && FLOAT_TYPE_P (TREE_TYPE (type))
+	      && (DECIMAL_FLOAT_TYPE_P (TREE_TYPE (type))
+		  != DECIMAL_FLOAT_TYPE_P (TREE_TYPE (conv_src_type))))
+	    return false;
+
 	  if (CONVERT_EXPR_CODE_P (conv_code)
 	      && (2 * TYPE_PRECISION (TREE_TYPE (TREE_TYPE (orig[0])))
 		  == TYPE_PRECISION (TREE_TYPE (type)))
diff --git a/gcc/tree-ssa-loop-niter.cc b/gcc/tree-ssa-loop-niter.cc
index 318d10c..9bb5097 100644
--- a/gcc/tree-ssa-loop-niter.cc
+++ b/gcc/tree-ssa-loop-niter.cc
@@ -1048,13 +1048,19 @@
      which the loop exits immediately, and the iv does not overflow.
 
      Also note, we prove condition 2) by checking base and final seperately
-     along with condition 1) or 1').  */
+     along with condition 1) or 1').  Since we ensure the difference
+     computation of c does not wrap with cond below and the adjusted s
+     will fit a signed type as well as an unsigned we can safely do
+     this using the type of the IV if it is not pointer typed.  */
+  tree mtype = type;
+  if (POINTER_TYPE_P (type))
+    mtype = niter_type;
   if (!niter->control.no_overflow
       && (integer_onep (s)
-	  || (multiple_of_p (type, fold_convert (niter_type, iv->base), s,
-			     false)
-	      && multiple_of_p (type, fold_convert (niter_type, final), s,
-				false))))
+	  || (multiple_of_p (mtype, fold_convert (mtype, iv->base),
+			     fold_convert (mtype, s), false)
+	      && multiple_of_p (mtype, fold_convert (mtype, final),
+				fold_convert (mtype, s), false))))
     {
       tree t, cond, relaxed_cond = boolean_false_node;
 
diff --git a/gcc/tree-ssa.cc b/gcc/tree-ssa.cc
index 8fe0682..430875a 100644
--- a/gcc/tree-ssa.cc
+++ b/gcc/tree-ssa.cc
@@ -272,7 +272,7 @@
 /* Called via walk_tree, look for SSA_NAMEs that have already been
    released.  */
 
-static tree
+tree
 find_released_ssa_name (tree *tp, int *walk_subtrees, void *data_)
 {
   struct walk_stmt_info *wi = (struct walk_stmt_info *) data_;
diff --git a/gcc/tree-ssa.h b/gcc/tree-ssa.h
index 36ddea2..0085354 100644
--- a/gcc/tree-ssa.h
+++ b/gcc/tree-ssa.h
@@ -49,6 +49,7 @@
 extern void delete_tree_ssa (function *);
 extern bool tree_ssa_useless_type_conversion (tree);
 extern tree tree_ssa_strip_useless_type_conversions (tree);
+extern tree find_released_ssa_name (tree *, int *, void *);
 
 
 extern bool ssa_defined_default_def_p (tree t);
diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
index e2cc721..c6b5a06 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -4533,6 +4533,37 @@
   return true;
 }
 
+/* Return true if all elements of the slice are the same.  */
+bool
+vect_scalar_ops_slice::all_same_p () const
+{
+  for (unsigned int i = 1; i < length; ++i)
+    if (!operand_equal_p (op (0), op (i)))
+      return false;
+  return true;
+}
+
+hashval_t
+vect_scalar_ops_slice_hash::hash (const value_type &s)
+{
+  hashval_t hash = 0;
+  for (unsigned i = 0; i < s.length; ++i)
+    hash = iterative_hash_expr (s.op (i), hash);
+  return hash;
+}
+
+bool
+vect_scalar_ops_slice_hash::equal (const value_type &s1,
+				   const compare_type &s2)
+{
+  if (s1.length != s2.length)
+    return false;
+  for (unsigned i = 0; i < s1.length; ++i)
+    if (!operand_equal_p (s1.op (i), s2.op (i)))
+      return false;
+  return true;
+}
+
 /* Compute the prologue cost for invariant or constant operands represented
    by NODE.  */
 
@@ -4549,45 +4580,39 @@
      When all elements are the same we can use a splat.  */
   tree vectype = SLP_TREE_VECTYPE (node);
   unsigned group_size = SLP_TREE_SCALAR_OPS (node).length ();
-  unsigned num_vects_to_check;
   unsigned HOST_WIDE_INT const_nunits;
   unsigned nelt_limit;
+  auto ops = &SLP_TREE_SCALAR_OPS (node);
+  auto_vec<unsigned int> starts (SLP_TREE_NUMBER_OF_VEC_STMTS (node));
   if (TYPE_VECTOR_SUBPARTS (vectype).is_constant (&const_nunits)
       && ! multiple_p (const_nunits, group_size))
     {
-      num_vects_to_check = SLP_TREE_NUMBER_OF_VEC_STMTS (node);
       nelt_limit = const_nunits;
+      hash_set<vect_scalar_ops_slice_hash> vector_ops;
+      for (unsigned int i = 0; i < SLP_TREE_NUMBER_OF_VEC_STMTS (node); ++i)
+	if (!vector_ops.add ({ ops, i * const_nunits, const_nunits }))
+	  starts.quick_push (i * const_nunits);
     }
   else
     {
       /* If either the vector has variable length or the vectors
 	 are composed of repeated whole groups we only need to
 	 cost construction once.  All vectors will be the same.  */
-      num_vects_to_check = 1;
       nelt_limit = group_size;
+      starts.quick_push (0);
     }
-  tree elt = NULL_TREE;
-  unsigned nelt = 0;
-  for (unsigned j = 0; j < num_vects_to_check * nelt_limit; ++j)
+  /* ???  We're just tracking whether vectors in a single node are the same.
+     Ideally we'd do something more global.  */
+  for (unsigned int start : starts)
     {
-      unsigned si = j % group_size;
-      if (nelt == 0)
-	elt = SLP_TREE_SCALAR_OPS (node)[si];
-      /* ???  We're just tracking whether all operands of a single
-	 vector initializer are the same, ideally we'd check if
-	 we emitted the same one already.  */
-      else if (elt != SLP_TREE_SCALAR_OPS (node)[si])
-	elt = NULL_TREE;
-      nelt++;
-      if (nelt == nelt_limit)
-	{
-	  record_stmt_cost (cost_vec, 1,
-			    SLP_TREE_DEF_TYPE (node) == vect_external_def
-			    ? (elt ? scalar_to_vec : vec_construct)
-			    : vector_load,
-			    NULL, vectype, 0, vect_prologue);
-	  nelt = 0;
-	}
+      vect_cost_for_stmt kind;
+      if (SLP_TREE_DEF_TYPE (node) == vect_constant_def)
+	kind = vector_load;
+      else if (vect_scalar_ops_slice { ops, start, nelt_limit }.all_same_p ())
+	kind = scalar_to_vec;
+      else
+	kind = vec_construct;
+      record_stmt_cost (cost_vec, 1, kind, NULL, vectype, 0, vect_prologue);
     }
 }
 
@@ -5380,7 +5405,6 @@
       unsigned dummy;
       finish_cost (scalar_target_cost_data, nullptr,
 		   &dummy, &scalar_cost, &dummy);
-      delete scalar_target_cost_data;
 
       /* Complete the target-specific vector cost calculation.  */
       class vector_costs *vect_target_cost_data = init_cost (bb_vinfo, false);
@@ -5393,6 +5417,7 @@
 	     && li_vector_costs[vi].first == vl);
       finish_cost (vect_target_cost_data, scalar_target_cost_data,
 		   &vec_prologue_cost, &vec_inside_cost, &vec_epilogue_cost);
+      delete scalar_target_cost_data;
       delete vect_target_cost_data;
 
       vec_outside_cost = vec_prologue_cost + vec_epilogue_cost;
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index ec479d3..ddd0637 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -113,6 +113,41 @@
 		 std::pair<stmt_vec_info, innermost_loop_behavior *> >
 	  vec_base_alignments;
 
+/* Represents elements [START, START + LENGTH) of cyclical array OPS*
+   (i.e. OPS repeated to give at least START + LENGTH elements)  */
+struct vect_scalar_ops_slice
+{
+  tree op (unsigned int i) const;
+  bool all_same_p () const;
+
+  vec<tree> *ops;
+  unsigned int start;
+  unsigned int length;
+};
+
+/* Return element I of the slice.  */
+inline tree
+vect_scalar_ops_slice::op (unsigned int i) const
+{
+  return (*ops)[(i + start) % ops->length ()];
+}
+
+/* Hash traits for vect_scalar_ops_slice.  */
+struct vect_scalar_ops_slice_hash : typed_noop_remove<vect_scalar_ops_slice>
+{
+  typedef vect_scalar_ops_slice value_type;
+  typedef vect_scalar_ops_slice compare_type;
+
+  static const bool empty_zero_p = true;
+
+  static void mark_deleted (value_type &s) { s.length = ~0U; }
+  static void mark_empty (value_type &s) { s.length = 0; }
+  static bool is_deleted (const value_type &s) { return s.length == ~0U; }
+  static bool is_empty (const value_type &s) { return s.length == 0; }
+  static hashval_t hash (const value_type &);
+  static bool equal (const value_type &, const compare_type &);
+};
+
 /************************************************************************
   SLP
  ************************************************************************/
diff --git a/gotools/ChangeLog b/gotools/ChangeLog
index 13ed04c..e1d330b 100644
--- a/gotools/ChangeLog
+++ b/gotools/ChangeLog
@@ -1,3 +1,10 @@
+2022-02-13  Ian Lance Taylor  <iant@golang.org>
+
+	* configure.ac: Revert 2022-02-09 change:
+	(RT_LIBS): Don't define.
+	* Makefile.am (check-runtime): Don't set GOLIBS to $(RT_LIBS).
+	* configure, Makefile.in: Regenerate.
+
 2022-02-11  Ian Lance Taylor  <iant@golang.org>
 
 	* Makefile.am (go_cmd_cgo_files): Add ast_go118.go
diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index c0bae0e..2158bc1 100644
--- a/libbacktrace/dwarf.c
+++ b/libbacktrace/dwarf.c
@@ -2221,6 +2221,9 @@
       u->comp_dir = NULL;
       u->abs_filename = NULL;
       u->lineoff = 0;
+      u->str_offsets_base = 0;
+      u->addr_base = 0;
+      u->rnglists_base = 0;
 
       /* The actual line number mappings will be read as needed.  */
       u->lines = NULL;
diff --git a/libgo/go/net/fcntl_libc_test.go b/libgo/go/net/fcntl_libc_test.go
index f59a1aa..c935c45 100644
--- a/libgo/go/net/fcntl_libc_test.go
+++ b/libgo/go/net/fcntl_libc_test.go
@@ -6,7 +6,10 @@
 
 package net
 
-import "syscall"
+import (
+	"syscall"
+	_ "unsafe"
+)
 
 // Use a helper function to call fcntl.  This is defined in C in
 // libgo/runtime.
diff --git a/libgo/go/os/signal/internal/pty/pty.go b/libgo/go/os/signal/internal/pty/pty.go
index e5ee3f6..01c3908 100644
--- a/libgo/go/os/signal/internal/pty/pty.go
+++ b/libgo/go/os/signal/internal/pty/pty.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build (aix || darwin || dragonfly || freebsd || hurd || (linux && !android) || netbsd || openbsd) && cgo
+//go:build (aix || darwin || dragonfly || freebsd || hurd || (linux && !android) || netbsd || openbsd || solaris) && cgo
 
 // Package pty is a simple pseudo-terminal package for Unix systems,
 // implemented by calling C functions via cgo.
diff --git a/libgo/go/runtime/os3_solaris.go b/libgo/go/runtime/os3_solaris.go
index ec23ce2..6c82574 100644
--- a/libgo/go/runtime/os3_solaris.go
+++ b/libgo/go/runtime/os3_solaris.go
@@ -36,6 +36,14 @@
 	return executablePath
 }
 
+func setProcessCPUProfiler(hz int32) {
+	setProcessCPUProfilerTimer(hz)
+}
+
+func setThreadCPUProfiler(hz int32) {
+	setThreadCPUProfilerHz(hz)
+}
+
 //go:nosplit
 func validSIGPROF(mp *m, c *sigctxt) bool {
 	return true
diff --git a/libgo/go/runtime/stubs2.go b/libgo/go/runtime/stubs2.go
index 0b9e605..5871092 100644
--- a/libgo/go/runtime/stubs2.go
+++ b/libgo/go/runtime/stubs2.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build !aix && !darwin && !js && !openbsd && !plan9 && !solaris && !windows
+//go:build !js && !plan9 && !windows
 
 package runtime
 
diff --git a/libgo/go/syscall/exec_bsd.go b/libgo/go/syscall/exec_bsd.go
index c05ae13..ff88bc4 100644
--- a/libgo/go/syscall/exec_bsd.go
+++ b/libgo/go/syscall/exec_bsd.go
@@ -143,13 +143,13 @@
 	// User and groups
 	if cred := sys.Credential; cred != nil {
 		ngroups := len(cred.Groups)
-		var groups *Gid_t
+		var groups unsafe.Pointer
 		if ngroups > 0 {
 			gids := make([]Gid_t, ngroups)
 			for i, v := range cred.Groups {
 				gids[i] = Gid_t(v)
 			}
-			groups = &gids[0]
+			groups = unsafe.Pointer(&gids[0])
 		}
 		if !cred.NoSetGroups {
 			err1 = raw_setgroups(ngroups, groups)
diff --git a/libgo/go/syscall/export_unix_test.go b/libgo/go/syscall/export_unix_test.go
index 184eb84..bd904c7 100644
--- a/libgo/go/syscall/export_unix_test.go
+++ b/libgo/go/syscall/export_unix_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build dragonfly || freebsd || hurd || linux || netbsd || openbsd
+//go:build dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 
 package syscall
 
diff --git a/libgo/go/syscall/syscall_solaris.go b/libgo/go/syscall/syscall_solaris.go
index 13c60a4..673ba82 100644
--- a/libgo/go/syscall/syscall_solaris.go
+++ b/libgo/go/syscall/syscall_solaris.go
@@ -6,8 +6,6 @@
 
 import "unsafe"
 
-const _F_DUP2FD_CLOEXEC = F_DUP2FD_CLOEXEC
-
 func (ts *Timestruc) Unix() (sec int64, nsec int64) {
 	return int64(ts.Sec), int64(ts.Nsec)
 }
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index e04e663..eaeaf57 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,7 @@
+2022-02-15  Tobias Burnus  <tobias@codesourcery.com>
+
+	* testsuite/libgomp.fortran/depend-4.f90: New test.
+
 2022-02-10  Tobias Burnus  <tobias@codesourcery.com>
 
 	PR c++/102204
diff --git a/libgomp/testsuite/libgomp.fortran/depend-4.f90 b/libgomp/testsuite/libgomp.fortran/depend-4.f90
new file mode 100644
index 0000000..80d00ca
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/depend-4.f90
@@ -0,0 +1,109 @@
+! { dg-additional-options "-fdump-tree-gimple" }
+!
+! { dg-additional-sources my-usleep.c }
+! { dg-prune-output "command-line option '-fintrinsic-modules-path=.*' is valid for Fortran but not for C" }
+!
+! Ensure that 'depend(...: var)' and 'depobj(...) depend(...: var)'
+! depend on the same variable when 'var' is a pointer
+!
+program main
+  use omp_lib
+  use iso_c_binding
+  implicit none (external, type)
+
+  interface
+    subroutine usleep(t) bind(C, name="my_usleep")
+      use iso_c_binding
+      integer(c_int), value :: t
+    end subroutine
+  end interface
+
+  integer :: bbb
+  integer, target :: c
+  integer(omp_depend_kind) :: obj(2)
+  integer, pointer :: ppp
+
+  integer :: x1, x2, x3 
+
+  c = 42
+  ppp => c
+ 
+  if (.not. associated (ppp)) &
+    stop 0;
+ 
+  x1 = 43
+  x2 = 44
+  x3 = 45
+  !$omp depobj(obj(1)) depend(inout: ppp)
+  !$omp depobj(obj(2)) depend(in: bbb)
+ 
+  !$omp parallel num_threads(5)
+  !$omp single
+ 
+    !$omp task depend (out: ppp)
+    write (*,*) "task 1 (start)"
+    call usleep(40)
+    if (x1 /= 43) stop 11
+    if (x2 /= 44) stop 12
+    x1 = 11
+    write (*,*) "task 1 (end)"
+    !$omp end task
+ 
+    !$omp task depend(inout: ppp)
+    write (*,*) "task 2 (start)"
+    call usleep(30)
+    if (x1 /= 11) stop 21
+    if (x2 /= 44) stop 22
+    x1 = 111
+    x2 = 222
+    write (*,*) "task 2 (end)"
+    !$omp end task
+ 
+    !$omp task depend(out: bbb)
+    write (*,*) "task 3 (start)"
+    call usleep(40)
+    if (x3 /= 45) stop 3
+    x3 = 33
+    write (*,*) "task 3 (end)"
+    !$omp end task
+ 
+   !$omp task depend(depobj: obj(1), obj(2))
+    write (*,*) "task 4 (start)"
+    if (x1 /= 111) stop 41
+    if (x2 /= 222) stop 42
+    if (x3 /= 33) stop 43
+    call usleep(10)
+    x1 = 411
+    x2 = 422
+    x3 = 433
+    write (*,*) "task 4 (end)"
+    !$omp end task
+ 
+    !$omp task depend(in: ppp)
+    if (x1 /= 411) stop 51
+    if (x2 /= 422) stop 52
+    if (x3 /= 433) stop 53
+    write (*,*) "task 5"
+    !$omp end task
+ 
+  !$omp end single
+  !$omp end parallel
+ 
+  ! expectation (task dependencies):
+  ! 1 - 2 \
+  !        4 - 5
+  ! 3 ----/
+ 
+end program main
+
+! Ensure that the pointer target address for ppp is taken
+! but the address of bbb itself:
+
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:ppp\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(inout:ppp\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:&bbb\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(depobj:&obj\\\[0\\\]\\) depend\\(depobj:&obj\\\[1\\\]\\)" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(in:ppp\\)" 1 "gimple" } }
+
+! { dg-final { scan-tree-dump-times "MEM\\\[\[^\r\n]+\\\] = ppp;" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "MEM\\\[\[^\r\n]+\\\] = &bbb;" 1 "gimple" } }
diff --git a/libphobos/Makefile.in b/libphobos/Makefile.in
index a8f7e16..2e9360a 100644
--- a/libphobos/Makefile.in
+++ b/libphobos/Makefile.in
@@ -15,7 +15,7 @@
 @SET_MAKE@
 
 # Makefile for the toplevel directory of the D Standard library.
-# Copyright (C) 2006-2021 Free Software Foundation, Inc.
+# Copyright (C) 2006-2022 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
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index 3aa798a..251d78d 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@
-759e60231a12482a1e1df5f891964e270dae0a1b
+dbd0c874a345438b8b4379a67525a933436d039a
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/druntime repository.
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 2d0bd37..ba64131 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -170,7 +170,7 @@
 DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	core/builtins.d core/checkedint.d core/cpuid.d core/demangle.d \
 	core/exception.d core/gc/config.d core/gc/gcinterface.d \
-	core/gc/registry.d core/internal/abort.d \
+	core/gc/registry.d core/int128.d core/internal/abort.d \
 	core/internal/array/appending.d core/internal/array/capacity.d \
 	core/internal/array/casting.d core/internal/array/comparison.d \
 	core/internal/array/concatenation.d core/internal/array/construction.d \
@@ -425,4 +425,4 @@
 	core/sys/windows/winuser.d core/sys/windows/winver.d \
 	core/sys/windows/wtsapi32.d core/sys/windows/wtypes.d
 
-DRUNTIME_DISOURCES = __main.di
+DRUNTIME_DISOURCES = __builtins.di __main.di
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index bb936dd..1c64d35 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -15,7 +15,7 @@
 @SET_MAKE@
 
 # Makefile for the D runtime library.
-# Copyright (C) 2012-2021 Free Software Foundation, Inc.
+# Copyright (C) 2012-2022 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
@@ -190,7 +190,7 @@
 am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
 	core/builtins.lo core/checkedint.lo core/cpuid.lo \
 	core/demangle.lo core/exception.lo core/gc/config.lo \
-	core/gc/gcinterface.lo core/gc/registry.lo \
+	core/gc/gcinterface.lo core/gc/registry.lo core/int128.lo \
 	core/internal/abort.lo core/internal/array/appending.lo \
 	core/internal/array/capacity.lo core/internal/array/casting.lo \
 	core/internal/array/comparison.lo \
@@ -834,7 +834,7 @@
 DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	core/builtins.d core/checkedint.d core/cpuid.d core/demangle.d \
 	core/exception.d core/gc/config.d core/gc/gcinterface.d \
-	core/gc/registry.d core/internal/abort.d \
+	core/gc/registry.d core/int128.d core/internal/abort.d \
 	core/internal/array/appending.d core/internal/array/capacity.d \
 	core/internal/array/casting.d core/internal/array/comparison.d \
 	core/internal/array/concatenation.d core/internal/array/construction.d \
@@ -1089,7 +1089,7 @@
 	core/sys/windows/winuser.d core/sys/windows/winver.d \
 	core/sys/windows/wtsapi32.d core/sys/windows/wtypes.d
 
-DRUNTIME_DISOURCES = __main.di
+DRUNTIME_DISOURCES = __builtins.di __main.di
 all: all-am
 
 .SUFFIXES:
@@ -1187,6 +1187,7 @@
 core/gc/config.lo: core/gc/$(am__dirstamp)
 core/gc/gcinterface.lo: core/gc/$(am__dirstamp)
 core/gc/registry.lo: core/gc/$(am__dirstamp)
+core/int128.lo: core/$(am__dirstamp)
 core/internal/$(am__dirstamp):
 	@$(MKDIR_P) core/internal
 	@: > core/internal/$(am__dirstamp)
diff --git a/libphobos/libdruntime/__builtins.di b/libphobos/libdruntime/__builtins.di
new file mode 100644
index 0000000..cd64881
--- /dev/null
+++ b/libphobos/libdruntime/__builtins.di
@@ -0,0 +1,40 @@
+/* This D file is implicitly imported by all ImportC source files.
+ * It provides definitions for C compiler builtin functions and declarations.
+ * The purpose is to make it unnecessary to hardwire them into the compiler.
+ * As the leading double underscore suggests, this is for internal use only.
+ *
+ * Copyright: Copyright Digital Mars 2022
+ * License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
+ * Authors:   Walter Bright
+ * Source: $(DRUNTIMESRC __builtins.d)
+ */
+
+
+module __builtins;
+
+/* gcc relies on internal __builtin_xxxx functions and templates to
+ * accomplish <stdarg.h>. D does the same thing with templates in core.stdc.stdarg.
+ * Here, we redirect the gcc builtin declarations to the equivalent
+ * ones in core.stdc.stdarg, thereby avoiding having to hardware them
+ * into the D compiler.
+ */
+
+import core.stdc.stdarg;
+
+alias va_list = core.stdc.stdarg.va_list;
+
+version (Posix)
+{
+    version (X86_64)
+        alias __va_list_tag = core.stdc.stdarg.__va_list_tag;
+}
+
+alias __builtin_va_start = core.stdc.stdarg.va_start;
+
+alias __builtin_va_end = core.stdc.stdarg.va_end;
+
+alias __builtin_va_copy = core.stdc.stdarg.va_copy;
+
+/* dmd's ImportC rewrites __builtin_va_arg into an instantiation of va_arg
+ */
+alias va_arg = core.stdc.stdarg.va_arg;
diff --git a/libphobos/libdruntime/core/demangle.d b/libphobos/libdruntime/core/demangle.d
index 1915fb0..930e0cd 100644
--- a/libphobos/libdruntime/core/demangle.d
+++ b/libphobos/libdruntime/core/demangle.d
@@ -2471,7 +2471,7 @@
 {
     enum lnk = __traits(getLinkage, FT);
     // C || Windows
-    enum hasPlainMangling = lnk == "C" || lnk == "Windows";
+    enum hasPlainMangling = lnk == "C" || lnk == "Windows" || lnk == "System";
 }
 
 @safe pure nothrow unittest
diff --git a/libphobos/libdruntime/core/int128.d b/libphobos/libdruntime/core/int128.d
new file mode 100644
index 0000000..aad2cf2
--- /dev/null
+++ b/libphobos/libdruntime/core/int128.d
@@ -0,0 +1,919 @@
+/* 128 bit integer arithmetic.
+ *
+ * Not optimized for speed.
+ *
+ * Copyright: Copyright D Language Foundation 2022.
+ * License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Authors:   Walter Bright
+ * Source:    $(DRUNTIMESRC core/_int128.d)
+ */
+
+module core.int128;
+
+nothrow:
+@safe:
+@nogc:
+
+alias I = long;
+alias U = ulong;
+enum Ubits = uint(U.sizeof * 8);
+
+align(16) struct Cent
+{
+    U lo;      // low 64 bits
+    U hi;      // high 64 bits
+}
+
+enum One = Cent(1);
+enum Zero = Cent();
+enum MinusOne = neg(One);
+
+/*****************************
+ * Test against 0
+ * Params:
+ *      c = Cent to test
+ * Returns:
+ *      true if != 0
+ */
+pure
+bool tst(Cent c)
+{
+    return c.hi || c.lo;
+}
+
+
+/*****************************
+ * Complement
+ * Params:
+ *      c = Cent to complement
+ * Returns:
+ *      complemented value
+ */
+pure
+Cent com(Cent c)
+{
+    c.lo = ~c.lo;
+    c.hi = ~c.hi;
+    return c;
+}
+
+/*****************************
+ * Negate
+ * Params:
+ *      c = Cent to negate
+ * Returns:
+ *      negated value
+ */
+pure
+Cent neg(Cent c)
+{
+    if (c.lo == 0)
+        c.hi = -c.hi;
+    else
+    {
+        c.lo = -c.lo;
+        c.hi = ~c.hi;
+    }
+    return c;
+}
+
+/*****************************
+ * Increment
+ * Params:
+ *      c = Cent to increment
+ * Returns:
+ *      incremented value
+ */
+pure
+Cent inc(Cent c)
+{
+    return add(c, One);
+}
+
+/*****************************
+ * Decrement
+ * Params:
+ *      c = Cent to decrement
+ * Returns:
+ *      incremented value
+ */
+pure
+Cent dec(Cent c)
+{
+    return sub(c, One);
+}
+
+/*****************************
+ * Shift left one bit
+ * Params:
+ *      c = Cent to shift
+ * Returns:
+ *      shifted value
+ */
+pure
+Cent shl1(Cent c)
+{
+    c.hi = (c.hi << 1) | (cast(I)c.lo < 0);
+    c.lo <<= 1;
+    return c;
+}
+
+/*****************************
+ * Unsigned shift right one bit
+ * Params:
+ *      c = Cent to shift
+ * Returns:
+ *      shifted value
+ */
+pure
+Cent shr1(Cent c)
+{
+    c.lo = (c.lo >> 1) | ((c.hi & 1) << (Ubits - 1));
+    c.hi >>= 1;
+    return c;
+}
+
+
+/*****************************
+ * Arithmetic shift right one bit
+ * Params:
+ *      c = Cent to shift
+ * Returns:
+ *      shifted value
+ */
+pure
+Cent sar1(Cent c)
+{
+    c.lo = (c.lo >> 1) | ((c.hi & 1) << (Ubits - 1));
+    c.hi = cast(I)c.hi >> 1;
+    return c;
+}
+
+/*****************************
+ * Shift left n bits
+ * Params:
+ *      c = Cent to shift
+ *      n = number of bits to shift
+ * Returns:
+ *      shifted value
+ */
+pure
+Cent shl(Cent c, uint n)
+{
+    if (n >= Ubits * 2)
+        return Zero;
+
+    if (n >= Ubits)
+    {
+        c.hi = c.lo << (n - Ubits);
+        c.lo = 0;
+    }
+    else
+    {
+        c.hi = ((c.hi << n) | (c.lo >> (Ubits - n - 1) >> 1));
+        c.lo = c.lo << n;
+    }
+    return c;
+}
+
+/*****************************
+ * Unsigned shift right n bits
+ * Params:
+ *      c = Cent to shift
+ *      n = number of bits to shift
+ * Returns:
+ *      shifted value
+ */
+pure
+Cent shr(Cent c, uint n)
+{
+    if (n >= Ubits * 2)
+        return Zero;
+
+    if (n >= Ubits)
+    {
+        c.lo = c.hi >> (n - Ubits);
+        c.hi = 0;
+    }
+    else
+    {
+        c.lo = ((c.lo >> n) | (c.hi << (Ubits - n - 1) << 1));
+        c.hi = c.hi >> n;
+    }
+    return c;
+}
+
+/*****************************
+ * Arithmetic shift right n bits
+ * Params:
+ *      c = Cent to shift
+ *      n = number of bits to shift
+ * Returns:
+ *      shifted value
+ */
+pure
+Cent sar(Cent c, uint n)
+{
+    const signmask = -(c.hi >> (Ubits - 1));
+    const signshift = (Ubits * 2) - n;
+    c = shr(c, n);
+
+    // Sign extend all bits beyond the precision of Cent.
+    if (n >= Ubits * 2)
+    {
+        c.hi = signmask;
+        c.lo = signmask;
+    }
+    else if (signshift >= Ubits * 2)
+    {
+    }
+    else if (signshift >= Ubits)
+    {
+        c.hi &= ~(U.max << (signshift - Ubits));
+        c.hi |= signmask << (signshift - Ubits);
+    }
+    else
+    {
+        c.hi = signmask;
+        c.lo &= ~(U.max << signshift);
+        c.lo |= signmask << signshift;
+    }
+    return c;
+}
+
+/*****************************
+ * Rotate left one bit
+ * Params:
+ *      c = Cent to rotate
+ * Returns:
+ *      rotated value
+ */
+pure
+Cent rol1(Cent c)
+{
+    int carry = cast(I)c.hi < 0;
+
+    c.hi = (c.hi << 1) | (cast(I)c.lo < 0);
+    c.lo = (c.lo << 1) | carry;
+    return c;
+}
+
+/*****************************
+ * Rotate right one bit
+ * Params:
+ *      c = Cent to rotate
+ * Returns:
+ *      rotated value
+ */
+pure
+Cent ror1(Cent c)
+{
+    int carry = c.lo & 1;
+    c.lo = (c.lo >> 1) | (cast(U)(c.hi & 1) << (Ubits - 1));
+    c.hi = (c.hi >> 1) | (cast(U)carry << (Ubits - 1));
+    return c;
+}
+
+
+/*****************************
+ * Rotate left n bits
+ * Params:
+ *      c = Cent to rotate
+ *      n = number of bits to rotate
+ * Returns:
+ *      rotated value
+ */
+pure
+Cent rol(Cent c, uint n)
+{
+    n &= Ubits * 2 - 1;
+    Cent l = shl(c, n);
+    Cent r = shr(c, Ubits * 2 - n);
+    return or(l, r);
+}
+
+/*****************************
+ * Rotate right n bits
+ * Params:
+ *      c = Cent to rotate
+ *      n = number of bits to rotate
+ * Returns:
+ *      rotated value
+ */
+pure
+Cent ror(Cent c, uint n)
+{
+    n &= Ubits * 2 - 1;
+    Cent r = shr(c, n);
+    Cent l = shl(c, Ubits * 2 - n);
+    return or(r, l);
+}
+
+/****************************
+ * And c1 & c2.
+ * Params:
+ *      c1 = operand 1
+ *      c2 = operand 2
+ * Returns:
+ *      c1 & c2
+ */
+pure
+Cent and(Cent c1, Cent c2)
+{
+    return Cent(c1.lo & c2.lo, c1.hi & c2.hi);
+}
+
+/****************************
+ * Or c1 | c2.
+ * Params:
+ *      c1 = operand 1
+ *      c2 = operand 2
+ * Returns:
+ *      c1 | c2
+ */
+pure
+Cent or(Cent c1, Cent c2)
+{
+    return Cent(c1.lo | c2.lo, c1.hi | c2.hi);
+}
+
+/****************************
+ * Xor c1 ^ c2.
+ * Params:
+ *      c1 = operand 1
+ *      c2 = operand 2
+ * Returns:
+ *      c1 ^ c2
+ */
+pure
+Cent xor(Cent c1, Cent c2)
+{
+    return Cent(c1.lo ^ c2.lo, c1.hi ^ c2.hi);
+}
+
+/****************************
+ * Add c1 to c2.
+ * Params:
+ *      c1 = operand 1
+ *      c2 = operand 2
+ * Returns:
+ *      c1 + c2
+ */
+pure
+Cent add(Cent c1, Cent c2)
+{
+    U r = cast(U)(c1.lo + c2.lo);
+    return Cent(r, cast(U)(c1.hi + c2.hi + (r < c1.lo)));
+}
+
+/****************************
+ * Subtract c2 from c1.
+ * Params:
+ *      c1 = operand 1
+ *      c2 = operand 2
+ * Returns:
+ *      c1 - c2
+ */
+pure
+Cent sub(Cent c1, Cent c2)
+{
+    return add(c1, neg(c2));
+}
+
+/****************************
+ * Multiply c1 * c2.
+ * Params:
+ *      c1 = operand 1
+ *      c2 = operand 2
+ * Returns:
+ *      c1 * c2
+ */
+pure
+Cent mul(Cent c1, Cent c2)
+{
+    enum mulmask = (1UL << (Ubits / 2)) - 1;
+    enum mulshift = Ubits / 2;
+
+    // This algorithm splits the operands into 4 words, then computes and sums
+    // the partial products of each part.
+    const c2l0 = c2.lo & mulmask;
+    const c2l1 = c2.lo >> mulshift;
+    const c2h0 = c2.hi & mulmask;
+    const c2h1 = c2.hi >> mulshift;
+
+    const c1l0 = c1.lo & mulmask;
+    U r0 = c1l0 * c2l0;
+    U r1 = c1l0 * c2l1 + (r0 >> mulshift);
+    U r2 = c1l0 * c2h0 + (r1 >> mulshift);
+    U r3 = c1l0 * c2h1 + (r2 >> mulshift);
+
+    const c1l1 = c1.lo >> mulshift;
+    r1 = c1l1 * c2l0 + (r1 & mulmask);
+    r2 = c1l1 * c2l1 + (r2 & mulmask) + (r1 >> mulshift);
+    r3 = c1l1 * c2h0 + (r3 & mulmask) + (r2 >> mulshift);
+
+    const c1h0 = c1.hi & mulmask;
+    r2 = c1h0 * c2l0 + (r2 & mulmask);
+    r3 = c1h0 * c2l1 + (r3 & mulmask) + (r2 >> mulshift);
+
+    const c1h1 = c1.hi >> mulshift;
+    r3 = c1h1 * c2l0 + (r3 & mulmask);
+
+    return Cent((r0 & mulmask) + (r1 & mulmask) * (mulmask + 1),
+                (r2 & mulmask) + (r3 & mulmask) * (mulmask + 1));
+
+}
+
+
+/****************************
+ * Unsigned divide c1 / c2.
+ * Params:
+ *      c1 = dividend
+ *      c2 = divisor
+ * Returns:
+ *      quotient c1 / c2
+ */
+pure
+Cent udiv(Cent c1, Cent c2)
+{
+    Cent modulus;
+    return udivmod(c1, c2, modulus);
+}
+
+/****************************
+ * Unsigned divide c1 / c2. The remainder after division is stored to modulus.
+ * Params:
+ *      c1 = dividend
+ *      c2 = divisor
+ *      modulus = set to c1 % c2
+ * Returns:
+ *      quotient c1 / c2
+ */
+pure
+Cent udivmod(Cent c1, Cent c2, out Cent modulus)
+{
+    //printf("udiv c1(%llx,%llx) c2(%llx,%llx)\n", c1.lo, c1.hi, c2.lo, c2.hi);
+    // Based on "Unsigned Doubleword Division" in Hacker's Delight
+    import core.bitop;
+
+    // Divides a 128-bit dividend by a 64-bit divisor.
+    // The result must fit in 64 bits.
+    static U udivmod128_64(Cent c1, U c2, out U modulus)
+    {
+        // We work in base 2^^32
+        enum base = 1UL << 32;
+        enum divmask = (1UL << (Ubits / 2)) - 1;
+        enum divshift = Ubits / 2;
+
+        // Check for overflow and divide by 0
+        if (c1.hi >= c2)
+        {
+            modulus = 0UL;
+            return ~0UL;
+        }
+
+        // Computes [num1 num0] / den
+        static uint udiv96_64(U num1, uint num0, U den)
+        {
+            // Extract both digits of the denominator
+            const den1 = cast(uint)(den >> divshift);
+            const den0 = cast(uint)(den & divmask);
+            // Estimate ret as num1 / den1, and then correct it
+            U ret = num1 / den1;
+            const t2 = (num1 % den1) * base + num0;
+            const t1 = ret * den0;
+            if (t1 > t2)
+                ret -= (t1 - t2 > den) ? 2 : 1;
+            return cast(uint)ret;
+        }
+
+        // Determine the normalization factor. We multiply c2 by this, so that its leading
+        // digit is at least half base. In binary this means just shifting left by the number
+        // of leading zeros, so that there's a 1 in the MSB.
+        // We also shift number by the same amount. This cannot overflow because c1.hi < c2.
+        const shift = (Ubits - 1) - bsr(c2);
+        c2 <<= shift;
+        U num2 = c1.hi;
+        num2 <<= shift;
+        num2 |= (c1.lo >> (-shift & 63)) & (-cast(I)shift >> 63);
+        c1.lo <<= shift;
+
+        // Extract the low digits of the numerator (after normalizing)
+        const num1 = cast(uint)(c1.lo >> divshift);
+        const num0 = cast(uint)(c1.lo & divmask);
+
+        // Compute q1 = [num2 num1] / c2
+        const q1 = udiv96_64(num2, num1, c2);
+        // Compute the true (partial) remainder
+        const rem = num2 * base + num1 - q1 * c2;
+        // Compute q0 = [rem num0] / c2
+        const q0 = udiv96_64(rem, num0, c2);
+
+        modulus = (rem * base + num0 - q0 * c2) >> shift;
+        return (cast(U)q1 << divshift) | q0;
+    }
+
+    // Special cases
+    if (!tst(c2))
+    {
+        // Divide by zero
+        modulus = Zero;
+        return com(modulus);
+    }
+    if (c1.hi == 0 && c2.hi == 0)
+    {
+        // Single precision divide
+        modulus = Cent(c1.lo % c2.lo);
+        return Cent(c1.lo / c2.lo);
+    }
+    if (c1.hi == 0)
+    {
+        // Numerator is smaller than the divisor
+        modulus = c1;
+        return Zero;
+    }
+    if (c2.hi == 0)
+    {
+        // Divisor is a 64-bit value, so we just need one 128/64 division.
+        // If c1 / c2 would overflow, break c1 up into two halves.
+        const q1 = (c1.hi < c2.lo) ? 0 : (c1.hi / c2.lo);
+        if (q1)
+            c1.hi = c1.hi % c2.lo;
+        U rem;
+        const q0 = udivmod128_64(c1, c2.lo, rem);
+        modulus = Cent(rem);
+        return Cent(q0, q1);
+    }
+
+    // Full cent precision division.
+    // Here c2 >= 2^^64
+    // We know that c2.hi != 0, so count leading zeros is OK
+    // We have 0 <= shift <= 63
+    const shift = (Ubits - 1) - bsr(c2.hi);
+
+    // Normalize the divisor so its MSB is 1
+    // v1 = (c2 << shift) >> 64
+    U v1 = shl(c2, shift).hi;
+
+    // To ensure no overflow.
+    Cent u1 = shr1(c1);
+
+    // Get quotient from divide unsigned operation.
+    U rem_ignored;
+    const q1 = udivmod128_64(u1, v1, rem_ignored);
+
+    // Undo normalization and division of c1 by 2.
+    Cent quotient = shr(shl(Cent(q1), shift), 63);
+
+    // Make quotient correct or too small by 1
+    if (tst(quotient))
+        quotient = dec(quotient);
+
+    // Now quotient is correct.
+    // Compute rem = c1 - (quotient * c2);
+    Cent rem = sub(c1, mul(quotient, c2));
+
+    // Check if remainder is larger than the divisor
+    if (uge(rem, c2))
+    {
+        // Increment quotient
+        quotient = inc(quotient);
+        // Subtract c2 from remainder
+        rem = sub(rem, c2);
+    }
+    modulus = rem;
+    //printf("quotient "); print(quotient);
+    //printf("modulus  "); print(modulus);
+    return quotient;
+}
+
+
+/****************************
+ * Signed divide c1 / c2.
+ * Params:
+ *      c1 = dividend
+ *      c2 = divisor
+ * Returns:
+ *      quotient c1 / c2
+ */
+pure
+Cent div(Cent c1, Cent c2)
+{
+    Cent modulus;
+    return divmod(c1, c2, modulus);
+}
+
+/****************************
+ * Signed divide c1 / c2. The remainder after division is stored to modulus.
+ * Params:
+ *      c1 = dividend
+ *      c2 = divisor
+ *      modulus = set to c1 % c2
+ * Returns:
+ *      quotient c1 / c2
+ */
+pure
+Cent divmod(Cent c1, Cent c2, out Cent modulus)
+{
+    /* Muck about with the signs so we can use the unsigned divide
+     */
+    if (cast(I)c1.hi < 0)
+    {
+        if (cast(I)c2.hi < 0)
+        {
+            Cent r = udivmod(neg(c1), neg(c2), modulus);
+            modulus = neg(modulus);
+            return r;
+        }
+        Cent r = neg(udivmod(neg(c1), c2, modulus));
+        modulus = neg(modulus);
+        return r;
+    }
+    else if (cast(I)c2.hi < 0)
+    {
+        return neg(udivmod(c1, neg(c2), modulus));
+    }
+    else
+        return udivmod(c1, c2, modulus);
+}
+
+/****************************
+ * If c1 > c2 unsigned
+ * Params:
+ *      c1 = operand 1
+ *      c2 = operand 2
+ * Returns:
+ *      true if c1 > c2
+ */
+pure
+bool ugt(Cent c1, Cent c2)
+{
+    return (c1.hi == c2.hi) ? (c1.lo > c2.lo) : (c1.hi > c2.hi);
+}
+
+/****************************
+ * If c1 >= c2 unsigned
+ * Params:
+ *      c1 = operand 1
+ *      c2 = operand 2
+ * Returns:
+ *      true if c1 >= c2
+ */
+pure
+bool uge(Cent c1, Cent c2)
+{
+    return !ugt(c2, c1);
+}
+
+/****************************
+ * If c1 < c2 unsigned
+ * Params:
+ *      c1 = operand 1
+ *      c2 = operand 2
+ * Returns:
+ *      true if c1 < c2
+ */
+pure
+bool ult(Cent c1, Cent c2)
+{
+    return ugt(c2, c1);
+}
+
+/****************************
+ * If c1 <= c2 unsigned
+ * Params:
+ *      c1 = operand 1
+ *      c2 = operand 2
+ * Returns:
+ *      true if c1 <= c2
+ */
+pure
+bool ule(Cent c1, Cent c2)
+{
+    return !ugt(c1, c2);
+}
+
+/****************************
+ * If c1 > c2 signed
+ * Params:
+ *      c1 = operand 1
+ *      c2 = operand 2
+ * Returns:
+ *      true if c1 > c2
+ */
+pure
+bool gt(Cent c1, Cent c2)
+{
+    return (c1.hi == c2.hi)
+        ? (c1.lo > c2.lo)
+        : (cast(I)c1.hi > cast(I)c2.hi);
+}
+
+/****************************
+ * If c1 >= c2 signed
+ * Params:
+ *      c1 = operand 1
+ *      c2 = operand 2
+ * Returns:
+ *      true if c1 >= c2
+ */
+pure
+bool ge(Cent c1, Cent c2)
+{
+    return !gt(c2, c1);
+}
+
+/****************************
+ * If c1 < c2 signed
+ * Params:
+ *      c1 = operand 1
+ *      c2 = operand 2
+ * Returns:
+ *      true if c1 < c2
+ */
+pure
+bool lt(Cent c1, Cent c2)
+{
+    return gt(c2, c1);
+}
+
+/****************************
+ * If c1 <= c2 signed
+ * Params:
+ *      c1 = operand 1
+ *      c2 = operand 2
+ * Returns:
+ *      true if c1 <= c2
+ */
+pure
+bool le(Cent c1, Cent c2)
+{
+    return !gt(c1, c2);
+}
+
+/*******************************************************/
+
+version (unittest)
+{
+    version (none)
+    {
+        import core.stdc.stdio;
+
+        @trusted
+        void print(Cent c)
+        {
+            printf("%lld, %lld\n", cast(ulong)c.lo, cast(ulong)c.hi);
+            printf("x%llx, x%llx\n", cast(ulong)c.lo, cast(ulong)c.hi);
+        }
+    }
+}
+
+unittest
+{
+    const C0 = Zero;
+    const C1 = One;
+    const C2 = Cent(2);
+    const C3 = Cent(3);
+    const C5 = Cent(5);
+    const C10 = Cent(10);
+    const C20 = Cent(20);
+    const C30 = Cent(30);
+    const C100 = Cent(100);
+
+    const Cm1 =  neg(One);
+    const Cm3 =  neg(C3);
+    const Cm10 = neg(C10);
+
+    const C3_1 = Cent(1,3);
+    const C3_2 = Cent(2,3);
+    const C4_8  = Cent(8, 4);
+    const C5_0  = Cent(0, 5);
+    const C7_1 = Cent(1,7);
+    const C7_9 = Cent(9,7);
+    const C9_3 = Cent(3,9);
+    const C10_0 = Cent(0,10);
+    const C10_1 = Cent(1,10);
+    const C10_3 = Cent(3,10);
+    const C11_3 = Cent(3,11);
+    const C20_0 = Cent(0,20);
+    const C90_30 = Cent(30,90);
+
+    const Cm10_0 = inc(com(C10_0)); // Cent(0, -10);
+    const Cm10_1 = inc(com(C10_1)); // Cent(-1, -11);
+    const Cm10_3 = inc(com(C10_3)); // Cent(-3, -11);
+
+    enum Cs_3 = Cent(3, I.min);
+
+    const Cbig_1 = Cent(0xa3ccac1832952398, 0xc3ac542864f652f8);
+    const Cbig_2 = Cent(0x5267b85f8a42fc20, 0);
+    const Cbig_3 = Cent(0xf0000000ffffffff, 0);
+
+    /************************/
+
+    assert( ugt(C1, C0) );
+    assert( ult(C1, C2) );
+    assert( uge(C1, C0) );
+    assert( ule(C1, C2) );
+
+    assert( !ugt(C0, C1) );
+    assert( !ult(C2, C1) );
+    assert( !uge(C0, C1) );
+    assert( !ule(C2, C1) );
+
+    assert( !ugt(C1, C1) );
+    assert( !ult(C1, C1) );
+    assert( uge(C1, C1) );
+    assert( ule(C2, C2) );
+
+    assert( ugt(C10_3, C10_1) );
+    assert( ugt(C11_3, C10_3) );
+    assert( !ugt(C9_3, C10_3) );
+    assert( !ugt(C9_3, C9_3) );
+
+    assert( gt(C2, C1) );
+    assert( !gt(C1, C2) );
+    assert( !gt(C1, C1) );
+    assert( gt(C0, Cm1) );
+    assert( gt(Cm1, neg(C10)));
+    assert( !gt(Cm1, Cm1) );
+    assert( !gt(Cm1, C0) );
+
+    assert( !lt(C2, C1) );
+    assert( !le(C2, C1) );
+    assert( ge(C2, C1) );
+
+    assert(neg(C10_0) == Cm10_0);
+    assert(neg(C10_1) == Cm10_1);
+    assert(neg(C10_3) == Cm10_3);
+
+    assert(add(C7_1,C3_2) == C10_3);
+    assert(sub(C1,C2) == Cm1);
+
+    assert(inc(C3_1) == C3_2);
+    assert(dec(C3_2) == C3_1);
+
+    assert(shl(C10,0) == C10);
+    assert(shl(C10,Ubits) == C10_0);
+    assert(shl(C10,1) == C20);
+    assert(shl(C10,Ubits * 2) == C0);
+    assert(shr(C10_0,0) == C10_0);
+    assert(shr(C10_0,Ubits) == C10);
+    assert(shr(C10_0,Ubits - 1) == C20);
+    assert(shr(C10_0,Ubits + 1) == C5);
+    assert(shr(C10_0,Ubits * 2) == C0);
+    assert(sar(C10_0,0) == C10_0);
+    assert(sar(C10_0,Ubits) == C10);
+    assert(sar(C10_0,Ubits - 1) == C20);
+    assert(sar(C10_0,Ubits + 1) == C5);
+    assert(sar(C10_0,Ubits * 2) == C0);
+    assert(sar(Cm1,Ubits * 2) == Cm1);
+
+    assert(shl1(C10) == C20);
+    assert(shr1(C10_0) == C5_0);
+    assert(sar1(C10_0) == C5_0);
+    assert(sar1(Cm1) == Cm1);
+
+    Cent modulus;
+
+    assert(udiv(C10,C2) == C5);
+    assert(udivmod(C10,C2, modulus) ==  C5);   assert(modulus == C0);
+    assert(udivmod(C10,C3, modulus) ==  C3);   assert(modulus == C1);
+    assert(udivmod(C10,C0, modulus) == Cm1);   assert(modulus == C0);
+    assert(udivmod(C2,C90_30, modulus) == C0); assert(modulus == C2);
+    assert(udiv(mul(C90_30, C2), C2) == C90_30);
+    assert(udiv(mul(C90_30, C2), C90_30) == C2);
+
+    assert(div(C10,C3) == C3);
+    assert(divmod( C10,  C3, modulus) ==  C3); assert(modulus ==  C1);
+    assert(divmod(Cm10,  C3, modulus) == Cm3); assert(modulus == Cm1);
+    assert(divmod( C10, Cm3, modulus) == Cm3); assert(modulus ==  C1);
+    assert(divmod(Cm10, Cm3, modulus) ==  C3); assert(modulus == Cm1);
+    assert(divmod(C2, C90_30, modulus) == C0); assert(modulus == C2);
+    assert(div(mul(C90_30, C2), C2) == C90_30);
+    assert(div(mul(C90_30, C2), C90_30) == C2);
+
+    assert(divmod(Cbig_1, Cbig_2, modulus) == Cent(0x4496aa309d4d4a2f, U.max));
+    assert(modulus == Cent(0xd83203d0fdc799b8, U.max));
+    assert(udivmod(Cbig_1, Cbig_2, modulus) == Cent(0x5fe0e9bace2bedad, 2));
+    assert(modulus == Cent(0x2c923125a68721f8, 0));
+    assert(div(Cbig_1, Cbig_3) == Cent(0xbfa6c02b5aff8b86, U.max));
+    assert(udiv(Cbig_1, Cbig_3) == Cent(0xd0b7d13b48cb350f, 0));
+
+    assert(mul(Cm10, C1) == Cm10);
+    assert(mul(C1, Cm10) == Cm10);
+    assert(mul(C9_3, C10) == C90_30);
+    assert(mul(Cs_3, C10) == C30);
+    assert(mul(Cm10, Cm10) == C100);
+
+    assert( or(C4_8, C3_1) == C7_9);
+    assert(and(C4_8, C7_9) == C4_8);
+    assert(xor(C4_8, C7_9) == C3_1);
+
+    assert(rol(Cm1,  1) == Cm1);
+    assert(ror(Cm1, 45) == Cm1);
+    assert(rol(ror(C7_9, 5), 5) == C7_9);
+    assert(rol(C7_9, 1) == rol1(C7_9));
+    assert(ror(C7_9, 1) == ror1(C7_9));
+}
+
+
diff --git a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
index a731d6f..87c45fb 100644
--- a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
+++ b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
@@ -4571,7 +4571,7 @@
         else
             return debugTypeName(ci.next);
     else
-        name = ti.classinfo.name;
+        name = typeid(ti).name;
     return name;
 }
 
diff --git a/libphobos/libdruntime/core/lifetime.d b/libphobos/libdruntime/core/lifetime.d
index 9a99f2d..091269a 100644
--- a/libphobos/libdruntime/core/lifetime.d
+++ b/libphobos/libdruntime/core/lifetime.d
@@ -2108,6 +2108,65 @@
     move(x, x);
 }
 
+private enum bool hasContextPointers(T) = {
+    static if (__traits(isStaticArray, T))
+    {
+        return hasContextPointers!(typeof(T.init[0]));
+    }
+    else static if (is(T == struct))
+    {
+        import core.internal.traits : anySatisfy;
+        return __traits(isNested, T) || anySatisfy!(hasContextPointers, typeof(T.tupleof));
+    }
+    else return false;
+} ();
+
+@safe @nogc nothrow pure unittest
+{
+    static assert(!hasContextPointers!int);
+    static assert(!hasContextPointers!(void*));
+
+    static struct S {}
+    static assert(!hasContextPointers!S);
+    static assert(!hasContextPointers!(S[1]));
+
+    struct Nested
+    {
+        void foo() {}
+    }
+
+    static assert(hasContextPointers!Nested);
+    static assert(hasContextPointers!(Nested[1]));
+
+    static struct OneLevel
+    {
+        int before;
+        Nested n;
+        int after;
+    }
+
+    static assert(hasContextPointers!OneLevel);
+    static assert(hasContextPointers!(OneLevel[1]));
+
+    static struct TwoLevels
+    {
+        int before;
+        OneLevel o;
+        int after;
+    }
+
+    static assert(hasContextPointers!TwoLevels);
+    static assert(hasContextPointers!(TwoLevels[1]));
+
+    union U
+    {
+        Nested n;
+    }
+
+    // unions can have false positives, so this query ignores them
+    static assert(!hasContextPointers!U);
+}
+
 // target must be first-parameter, because in void-functions DMD + dip1000 allows it to take the place of a return-scope
 private void moveEmplaceImpl(T)(scope ref T target, return scope ref T source)
 {
@@ -2119,9 +2178,10 @@
 //              "Cannot move object with internal pointer unless `opPostMove` is defined.");
 //    }
 
+    import core.internal.traits : hasElaborateAssign, isAssignable, hasElaborateMove,
+                                  hasElaborateDestructor, hasElaborateCopyConstructor;
     static if (is(T == struct))
     {
-        import core.internal.traits;
 
         //  Unsafe when compiling without -preview=dip1000
         assert((() @trusted => &source !is &target)(), "source and target must not be identical");
@@ -2141,28 +2201,35 @@
         // object in order to avoid double freeing and undue aliasing
         static if (hasElaborateDestructor!T || hasElaborateCopyConstructor!T)
         {
-            // If T is nested struct, keep original context pointer
-            static if (__traits(isNested, T))
-                enum sz = T.sizeof - (void*).sizeof;
-            else
-                enum sz = T.sizeof;
-
+            // If there are members that are nested structs, we must take care
+            // not to erase any context pointers, so we might have to recurse
             static if (__traits(isZeroInit, T))
-            {
-                import core.stdc.string : memset;
-                () @trusted { memset(&source, 0, sz); }();
-            }
+                wipe(source);
             else
-            {
-                import core.stdc.string : memcpy;
-                () @trusted { memcpy(&source, __traits(initSymbol, T).ptr, sz); }();
-            }
+                wipe(source, ref () @trusted { return *cast(immutable(T)*) __traits(initSymbol, T).ptr; } ());
         }
     }
     else static if (__traits(isStaticArray, T))
     {
-        for (size_t i = 0; i < source.length; ++i)
-            moveEmplaceImpl(target[i], source[i]);
+        static if (T.length)
+        {
+            static if (!hasElaborateMove!T &&
+                       !hasElaborateDestructor!T &&
+                       !hasElaborateCopyConstructor!T)
+            {
+                // Single blit if no special per-instance handling is required
+                () @trusted
+                {
+                    assert(source.ptr !is target.ptr, "source and target must not be identical");
+                    *cast(ubyte[T.sizeof]*) &target = *cast(ubyte[T.sizeof]*) &source;
+                } ();
+            }
+            else
+            {
+                for (size_t i = 0; i < source.length; ++i)
+                    moveEmplaceImpl(target[i], source[i]);
+            }
+        }
     }
     else
     {
@@ -2258,6 +2325,13 @@
     f(move(ncarray));
 }
 
+//debug = PRINTF;
+
+debug(PRINTF)
+{
+    import core.stdc.stdio;
+}
+
 /// Implementation of `_d_delstruct` and `_d_delstructTrace`
 template _d_delstructImpl(T)
 {
@@ -2361,3 +2435,270 @@
     assert(innerDtors == 2);
     assert(outerDtors == 1);
 }
+
+// issue 25552
+pure nothrow @system unittest
+{
+    int i;
+    struct Nested
+    {
+    pure nothrow @nogc:
+        char[1] arr; // char.init is not 0
+        ~this() { ++i; }
+    }
+
+    {
+        Nested[1] dst = void;
+        Nested[1] src = [Nested(['a'])];
+
+        moveEmplace(src, dst);
+        assert(i == 0);
+        assert(dst[0].arr == ['a']);
+        assert(src[0].arr == [char.init]);
+        assert(dst[0].tupleof[$-1] is src[0].tupleof[$-1]);
+    }
+    assert(i == 2);
+}
+
+// issue 25552
+@safe unittest
+{
+    int i;
+    struct Nested
+    {
+        ~this() { ++i; }
+    }
+
+    static struct NotNested
+    {
+        Nested n;
+    }
+
+    static struct Deep
+    {
+        NotNested nn;
+    }
+
+    static struct Deeper
+    {
+        NotNested[1] nn;
+    }
+
+    static assert(__traits(isZeroInit, Nested));
+    static assert(__traits(isZeroInit, NotNested));
+    static assert(__traits(isZeroInit, Deep));
+    static assert(__traits(isZeroInit, Deeper));
+
+    {
+        auto a = NotNested(Nested());
+        assert(a.n.tupleof[$-1]);
+        auto b = move(a);
+        assert(b.n.tupleof[$-1]);
+        assert(a.n.tupleof[$-1] is b.n.tupleof[$-1]);
+
+        auto c = Deep(NotNested(Nested()));
+        auto d = move(c);
+        assert(d.nn.n.tupleof[$-1]);
+        assert(c.nn.n.tupleof[$-1] is d.nn.n.tupleof[$-1]);
+
+        auto e = Deeper([NotNested(Nested())]);
+        auto f = move(e);
+        assert(f.nn[0].n.tupleof[$-1]);
+        assert(e.nn[0].n.tupleof[$-1] is f.nn[0].n.tupleof[$-1]);
+    }
+    assert(i == 6);
+}
+
+// issue 25552
+@safe unittest
+{
+    int i;
+    struct Nested
+    {
+        align(32) // better still find context pointer correctly!
+        int[3] stuff = [0, 1, 2];
+        ~this() { ++i; }
+    }
+
+    static struct NoAssign
+    {
+        int value;
+        @disable void opAssign(typeof(this));
+    }
+
+    static struct NotNested
+    {
+        int before = 42;
+        align(Nested.alignof * 4) // better still find context pointer correctly!
+        Nested n;
+        auto after = NoAssign(43);
+    }
+
+    static struct Deep
+    {
+        NotNested nn;
+    }
+
+    static struct Deeper
+    {
+        NotNested[1] nn;
+    }
+
+    static assert(!__traits(isZeroInit, Nested));
+    static assert(!__traits(isZeroInit, NotNested));
+    static assert(!__traits(isZeroInit, Deep));
+    static assert(!__traits(isZeroInit, Deeper));
+
+    {
+        auto a = NotNested(1, Nested([3, 4, 5]), NoAssign(2));
+        auto b = move(a);
+        assert(b.n.tupleof[$-1]);
+        assert(a.n.tupleof[$-1] is b.n.tupleof[$-1]);
+        assert(a.n.stuff == [0, 1, 2]);
+        assert(a.before == 42);
+        assert(a.after == NoAssign(43));
+
+        auto c = Deep(NotNested(1, Nested([3, 4, 5]), NoAssign(2)));
+        auto d = move(c);
+        assert(d.nn.n.tupleof[$-1]);
+        assert(c.nn.n.tupleof[$-1] is d.nn.n.tupleof[$-1]);
+        assert(c.nn.n.stuff == [0, 1, 2]);
+        assert(c.nn.before == 42);
+        assert(c.nn.after == NoAssign(43));
+
+        auto e = Deeper([NotNested(1, Nested([3, 4, 5]), NoAssign(2))]);
+        auto f = move(e);
+        assert(f.nn[0].n.tupleof[$-1]);
+        assert(e.nn[0].n.tupleof[$-1] is f.nn[0].n.tupleof[$-1]);
+        assert(e.nn[0].n.stuff == [0, 1, 2]);
+        assert(e.nn[0].before == 42);
+        assert(e.nn[0].after == NoAssign(43));
+    }
+    assert(i == 6);
+}
+
+// wipes source after moving
+pragma(inline, true)
+private void wipe(T, Init...)(return scope ref T source, ref const scope Init initializer) @trusted
+if (!Init.length ||
+    ((Init.length == 1) && (is(immutable T == immutable Init[0]))))
+{
+    static if (__traits(isStaticArray, T) && hasContextPointers!T)
+    {
+        for (auto i = 0; i < T.length; i++)
+            static if (Init.length)
+                wipe(source[i], initializer[0][i]);
+            else
+                wipe(source[i]);
+    }
+    else static if (is(T == struct) && hasContextPointers!T)
+    {
+        import core.internal.traits : anySatisfy;
+        static if (anySatisfy!(hasContextPointers, typeof(T.tupleof)))
+        {
+            static foreach (i; 0 .. T.tupleof.length - __traits(isNested, T))
+                static if (Init.length)
+                    wipe(source.tupleof[i], initializer[0].tupleof[i]);
+                else
+                    wipe(source.tupleof[i]);
+        }
+        else
+        {
+            static if (__traits(isNested, T))
+                enum sz = T.tupleof[$-1].offsetof;
+            else
+                enum sz = T.sizeof;
+
+            static if (Init.length)
+                *cast(ubyte[sz]*) &source = *cast(ubyte[sz]*) &initializer[0];
+            else
+                *cast(ubyte[sz]*) &source = 0;
+        }
+    }
+    else
+    {
+        import core.internal.traits : hasElaborateAssign, isAssignable;
+        static if (Init.length)
+        {
+            static if (hasElaborateAssign!T || !isAssignable!T)
+                *cast(ubyte[T.sizeof]*) &source = *cast(ubyte[T.sizeof]*) &initializer[0];
+            else
+                source = *cast(T*) &initializer[0];
+        }
+        else
+        {
+            *cast(ubyte[T.sizeof]*) &source = 0;
+        }
+    }
+}
+
+/**
+ * Allocate an exception of type `T` from the exception pool and call its constructor.
+ * It has the same interface as `rt.lifetime._d_newclass()`.
+ * `T` must be Throwable or derived from it, must declare an explicit ctor
+ * and cannot be a COM or C++ class.
+ * Returns:
+ *      constructed instance of the type
+ */
+T _d_newThrowable(T, Args...)(auto ref Args args) @trusted
+    if (is(T : Throwable) && is(typeof(T.__ctor(forward!args))) &&
+        __traits(getLinkage, T) == "D")
+{
+    debug(PRINTF) printf("_d_newThrowable(%s)\n", cast(char*) T.stringof);
+
+    import core.stdc.stdlib : malloc;
+    auto init = __traits(initSymbol, T);
+    void* p = malloc(init.length);
+    if (!p)
+    {
+        import core.exception : onOutOfMemoryError;
+        onOutOfMemoryError();
+    }
+
+    debug(PRINTF) printf(" p = %p\n", p);
+
+    // initialize it
+    p[0 .. init.length] = init[];
+
+    import core.internal.traits : hasIndirections;
+    if (hasIndirections!T)
+    {
+        // Inform the GC about the pointers in the object instance
+        import core.memory : GC;
+        GC.addRange(p, init.length);
+    }
+
+    debug(PRINTF) printf("initialization done\n");
+
+    (cast(Throwable) p).refcount() = 1;
+
+    auto t = cast(T) p;
+    t.__ctor(forward!args);
+
+    return t;
+}
+
+@system unittest
+{
+    class E : Exception
+    {
+        int x;
+
+        this(int x, string msg = "", Throwable nextInChain = null)
+        {
+            super(msg, nextInChain);
+            this.x = x;
+        }
+    }
+
+    auto exc = _d_newThrowable!Exception("Exception");
+    assert(exc.refcount() == 1);
+    assert(exc.msg == "Exception");
+
+    static assert(!__traits(compiles, _d_newThrowable!E()));
+
+    auto e = _d_newThrowable!E(42, "E", null);
+    assert(e.refcount() == 1);
+    assert(e.x == 42);
+    assert(e.msg == "E");
+}
diff --git a/libphobos/libdruntime/core/memory.d b/libphobos/libdruntime/core/memory.d
index c4df0f2..6ba569a 100644
--- a/libphobos/libdruntime/core/memory.d
+++ b/libphobos/libdruntime/core/memory.d
@@ -459,8 +459,11 @@
      * Throws:
      *  OutOfMemoryError on allocation failure.
      */
-    pragma(mangle, "gc_malloc") static void* malloc(size_t sz, uint ba = 0, const scope TypeInfo ti = null) pure nothrow;
-
+    version (D_ProfileGC)
+        pragma(mangle, "gc_mallocTrace") static void* malloc(size_t sz, uint ba = 0, const scope TypeInfo ti = null,
+            string file = __FILE__, int line = __LINE__, string func = __FUNCTION__) pure nothrow;
+    else
+        pragma(mangle, "gc_malloc") static void* malloc(size_t sz, uint ba = 0, const scope TypeInfo ti = null) pure nothrow;
 
     /**
      * Requests an aligned block of managed memory from the garbage collector.
@@ -482,7 +485,11 @@
      * Throws:
      *  OutOfMemoryError on allocation failure.
      */
-    pragma(mangle, "gc_qalloc") static BlkInfo qalloc(size_t sz, uint ba = 0, const scope TypeInfo ti = null) pure nothrow;
+    version (D_ProfileGC)
+        pragma(mangle, "gc_qallocTrace") static BlkInfo qalloc(size_t sz, uint ba = 0, const scope TypeInfo ti = null,
+            string file = __FILE__, int line = __LINE__, string func = __FUNCTION__) pure nothrow;
+    else
+        pragma(mangle, "gc_qalloc") static BlkInfo qalloc(size_t sz, uint ba = 0, const scope TypeInfo ti = null) pure nothrow;
 
 
     /**
@@ -506,7 +513,11 @@
      * Throws:
      *  OutOfMemoryError on allocation failure.
      */
-    pragma(mangle, "gc_calloc") static void* calloc(size_t sz, uint ba = 0, const TypeInfo ti = null) pure nothrow;
+    version (D_ProfileGC)
+        pragma(mangle, "gc_callocTrace") static void* calloc(size_t sz, uint ba = 0, const TypeInfo ti = null,
+            string file = __FILE__, int line = __LINE__, string func = __FUNCTION__) pure nothrow;
+    else
+        pragma(mangle, "gc_calloc") static void* calloc(size_t sz, uint ba = 0, const TypeInfo ti = null) pure nothrow;
 
 
     /**
@@ -551,7 +562,11 @@
      * Throws:
      *  `OutOfMemoryError` on allocation failure.
      */
-    pragma(mangle, "gc_realloc") static void* realloc(return scope void* p, size_t sz, uint ba = 0, const TypeInfo ti = null) pure nothrow;
+    version (D_ProfileGC)
+        pragma(mangle, "gc_reallocTrace") static void* realloc(return scope void* p, size_t sz, uint ba = 0, const TypeInfo ti = null,
+            string file = __FILE__, int line = __LINE__, string func = __FUNCTION__) pure nothrow;
+    else
+        pragma(mangle, "gc_realloc") static void* realloc(return scope void* p, size_t sz, uint ba = 0, const TypeInfo ti = null) pure nothrow;
 
     // https://issues.dlang.org/show_bug.cgi?id=13111
     ///
@@ -593,7 +608,12 @@
      *  as an indicator of success. $(LREF capacity) should be used to
      *  retrieve actual usable slice capacity.
      */
-    pragma(mangle, "gc_extend") static size_t extend(void* p, size_t mx, size_t sz, const TypeInfo ti = null) pure nothrow;
+    version (D_ProfileGC)
+        pragma(mangle, "gc_extendTrace") static size_t extend(void* p, size_t mx, size_t sz, const TypeInfo ti = null,
+            string file = __FILE__, int line = __LINE__, string func = __FUNCTION__) pure nothrow;
+    else
+        pragma(mangle, "gc_extend") static size_t extend(void* p, size_t mx, size_t sz, const TypeInfo ti = null) pure nothrow;
+
     /// Standard extending
     unittest
     {
diff --git a/libphobos/libdruntime/core/stdc/math.d b/libphobos/libdruntime/core/stdc/math.d
index de029c4..0c5da0b 100644
--- a/libphobos/libdruntime/core/stdc/math.d
+++ b/libphobos/libdruntime/core/stdc/math.d
@@ -850,59 +850,59 @@
         FP_FAST_FMAL = 0,
     }
 
-    int __fpclassifyf(float x);
-    int __fpclassify(double x);
-    int __fpclassifyl(real x);
+    pure int __fpclassifyf(float x);
+    pure int __fpclassify(double x);
+    pure int __fpclassifyl(real x);
 
-    int __finitef(float x);
-    int __finite(double x);
-    int __finitel(real x);
+    pure int __finitef(float x);
+    pure int __finite(double x);
+    pure int __finitel(real x);
 
-    int __isinff(float x);
-    int __isinf(double x);
-    int __isinfl(real x);
+    pure int __isinff(float x);
+    pure int __isinf(double x);
+    pure int __isinfl(real x);
 
-    int __isnanf(float x);
-    int __isnan(double x);
-    int __isnanl(real x);
+    pure int __isnanf(float x);
+    pure int __isnan(double x);
+    pure int __isnanl(real x);
 
-    int __signbitf(float x);
-    int __signbit(double x);
-    int __signbitl(real x);
+    pure int __signbitf(float x);
+    pure int __signbit(double x);
+    pure int __signbitl(real x);
 
     ///
-    pragma(mangle, "__fpclassifyf") int fpclassify(float x);
+    pragma(mangle, "__fpclassifyf") pure int fpclassify(float x);
     ///
-    pragma(mangle, "__fpclassify")  int fpclassify(double x);
+    pragma(mangle, "__fpclassify")  pure int fpclassify(double x);
     ///
     pragma(mangle, real.sizeof == double.sizeof ? "__fpclassify" : "__fpclassifyl")
-    int fpclassify(real x);
+    pure int fpclassify(real x);
 
     ///
-    pragma(mangle, "__finitef") int isfinite(float x);
+    pragma(mangle, "__finitef") pure int isfinite(float x);
     ///
-    pragma(mangle, "__finite")  int isfinite(double x);
+    pragma(mangle, "__finite")  pure int isfinite(double x);
     ///
     pragma(mangle, real.sizeof == double.sizeof ? "__finite" : "__finitel")
-    int isfinite(real x);
+    pure int isfinite(real x);
 
     ///
-    pragma(mangle, "__isinff") int isinf(float x);
+    pragma(mangle, "__isinff") pure int isinf(float x);
     ///
-    pragma(mangle, "__isinf")  int isinf(double x);
+    pragma(mangle, "__isinf")  pure int isinf(double x);
     ///
     pragma(mangle, real.sizeof == double.sizeof ? "__isinf" : "__isinfl")
-    int isinf(real x);
+    pure int isinf(real x);
 
     ///
-    pragma(mangle, "__isnanf") int isnan(float x);
+    pragma(mangle, "__isnanf") pure int isnan(float x);
     ///
-    pragma(mangle, "__isnan")  int isnan(double x);
+    pragma(mangle, "__isnan")  pure int isnan(double x);
     ///
     pragma(mangle, real.sizeof == double.sizeof ? "__isnan" : "__isnanl")
-    int isnan(real x);
+    pure int isnan(real x);
 
-  extern (D)
+  extern (D) pure
   {
     ///
     int isnormal(float x)       { return fpclassify(x) == FP_NORMAL; }
@@ -913,12 +913,12 @@
   }
 
     ///
-    pragma(mangle, "__signbitf") int signbit(float x);
+    pragma(mangle, "__signbitf") pure int signbit(float x);
     ///
-    pragma(mangle, "__signbit")  int signbit(double x);
+    pragma(mangle, "__signbit")  pure int signbit(double x);
     ///
     pragma(mangle, real.sizeof == double.sizeof ? "__signbit" : "__signbitl")
-    int signbit(real x);
+    pure int signbit(real x);
 }
 else version (Darwin)
 {
@@ -3089,7 +3089,7 @@
     ///
     pure real atanl(real x);
     ///
-    real atan2l(real x, real y);
+    real atan2l(real y, real x);
     ///
     pure real cosl(real x);
     ///
@@ -3377,7 +3377,7 @@
     pure real acosl(real x);
     pure real asinl(real x);
     pure real atanl(real x);
-    real atan2l(real x, real y);
+    real atan2l(real y, real x);
     pure real cosl(real x);
     pure real sinl(real x);
     pure real tanl(real x);
@@ -3872,7 +3872,7 @@
     ///
     float   atan2f(float y, float x);
     ///
-    extern(D) real atan2l(real y, real x) { return atan2(cast(double) x, cast(double) y); }
+    extern(D) real atan2l(real y, real x) { return atan2(cast(double) y, cast(double) x); }
 
     ///
     pure double  cos(double x);
diff --git a/libphobos/libdruntime/core/sys/darwin/dlfcn.d b/libphobos/libdruntime/core/sys/darwin/dlfcn.d
index 406d588..6084f3f 100644
--- a/libphobos/libdruntime/core/sys/darwin/dlfcn.d
+++ b/libphobos/libdruntime/core/sys/darwin/dlfcn.d
@@ -25,20 +25,6 @@
 
 public import core.sys.posix.dlfcn;
 
-struct Dl_info
-{
-    const(char)* dli_fname;
-    void*        dli_fbase;
-    const(char)* dli_sname;
-    void*        dli_saddr;
-}
-
-int dladdr(const scope void* addr, Dl_info* info);
-
-enum RTLD_NOLOAD = 0x10;
-enum RTLD_NODELETE = 0x80;
-enum RTLD_FIRST = 0x100;
-
 enum RTLD_NEXT = cast(void*) -1;
 enum RTLD_DEFAULT = cast(void*) -2;
 enum RTLD_SELF = cast(void*) -3;
diff --git a/libphobos/libdruntime/core/sys/dragonflybsd/dlfcn.d b/libphobos/libdruntime/core/sys/dragonflybsd/dlfcn.d
index 2c5d8d7..0e8b15c 100644
--- a/libphobos/libdruntime/core/sys/dragonflybsd/dlfcn.d
+++ b/libphobos/libdruntime/core/sys/dragonflybsd/dlfcn.d
@@ -15,18 +15,6 @@
 extern (C) nothrow @nogc @system:
 
 /*
- * Modes and flags for dlopen().
- */
-static assert(RTLD_LAZY   == 1);
-static assert(RTLD_NOW    == 2);
-enum RTLD_MODEMASK        =  0x3;
-static assert(RTLD_GLOBAL == 0x100);
-static assert(RTLD_LOCAL  == 0);
-enum RTLD_TRACE           =  0x200;
-enum RTLD_NODELETE        =  0x01000;
-enum RTLD_NOLOAD          =  0x02000;
-
-/*
  * Request arguments for dlinfo().
  */
 enum RTLD_DI_LINKMAP     = 2;    /* Obtain link map. */
@@ -43,17 +31,6 @@
 enum RTLD_SELF    = cast(void *)-3;    /* Search the caller itself. */
 
 /*
- * Structure filled in by dladdr().
- */
-struct Dl_info {
-    const(char)     *dli_fname;     /* Pathname of shared object. */
-    void            *dli_fbase;     /* Base address of shared object. */
-    const(char)     *dli_sname;     /* Name of nearest symbol. */
-    void            *dli_saddr;     /* Address of nearest symbol. */
-}
-
-
-/*
  * Structures, returned by the RTLD_DI_SERINFO dlinfo() request.
  */
 struct Dl_serpath {
@@ -91,7 +68,6 @@
 }
 
 void*    fdlopen(int, int);
-int      dladdr(const(void)*, Dl_info*);
 dlfunc_t dlfunc(void*, const(char)*);
 int      dlinfo(void*, int, void*);
 /*void     dllockinit(void* _context,
diff --git a/libphobos/libdruntime/core/sys/freebsd/dlfcn.d b/libphobos/libdruntime/core/sys/freebsd/dlfcn.d
index 7baacfe..aac41d8 100644
--- a/libphobos/libdruntime/core/sys/freebsd/dlfcn.d
+++ b/libphobos/libdruntime/core/sys/freebsd/dlfcn.d
@@ -17,18 +17,6 @@
 enum __BSD_VISIBLE = true;
 
 /*
- * Modes and flags for dlopen().
- */
-static assert(RTLD_LAZY   == 1);
-static assert(RTLD_NOW    == 2);
-enum RTLD_MODEMASK        =  0x3;
-static assert(RTLD_GLOBAL == 0x100);
-static assert(RTLD_LOCAL  == 0);
-enum RTLD_TRACE           =  0x200;
-enum RTLD_NODELETE        =  0x01000;
-enum RTLD_NOLOAD          =  0x02000;
-
-/*
  * Request arguments for dlinfo().
  */
 enum RTLD_DI_LINKMAP     = 2;    /* Obtain link map. */
@@ -46,16 +34,6 @@
 
 static if (__BSD_VISIBLE)
 {
-    /*
-     * Structure filled in by dladdr().
-     */
-    struct Dl_info {
-        const(char)     *dli_fname;     /* Pathname of shared object. */
-        void            *dli_fbase;     /* Base address of shared object. */
-        const(char)     *dli_sname;     /* Name of nearest symbol. */
-        void            *dli_saddr;     /* Address of nearest symbol. */
-    }
-
     /*-
      * The actual type declared by this typedef is immaterial, provided that
      * it is a function pointer.  Its purpose is to provide a return type for
@@ -97,7 +75,6 @@
 static if (__BSD_VISIBLE)
 {
     void*    fdlopen(int, int);
-    int      dladdr(const(void)*, Dl_info*);
     dlfunc_t dlfunc(void*, const(char)*);
     int      dlinfo(void*, int, void*);
     void     dllockinit(void* _context,
diff --git a/libphobos/libdruntime/core/sys/linux/dlfcn.d b/libphobos/libdruntime/core/sys/linux/dlfcn.d
index a815d09..4a12284 100644
--- a/libphobos/libdruntime/core/sys/linux/dlfcn.d
+++ b/libphobos/libdruntime/core/sys/linux/dlfcn.d
@@ -34,16 +34,6 @@
 version (X86_Any)
 {
     // http://sourceware.org/git/?p=glibc.git;a=blob;f=bits/dlfcn.h
-    // enum RTLD_LAZY = 0x00001; // POSIX
-    // enum RTLD_NOW = 0x00002; // POSIX
-    enum RTLD_BINDING_MASK = 0x3;
-    enum RTLD_NOLOAD = 0x00004;
-    enum RTLD_DEEPBIND = 0x00008;
-
-    // enum RTLD_GLOBAL = 0x00100; // POSIX
-    // enum RTLD_LOCAL = 0; // POSIX
-    enum RTLD_NODELETE = 0x01000;
-
     static if (__USE_GNU)
     {
         RT DL_CALL_FCT(RT, Args...)(RT function(Args) fctp, auto ref Args args)
@@ -58,16 +48,6 @@
 else version (HPPA_Any)
 {
     // http://sourceware.org/git/?p=glibc.git;a=blob;f=ports/sysdeps/hppa/bits/dlfcn.h
-    // enum RTLD_LAZY = 0x0001; // POSIX
-    // enum RTLD_NOW = 0x0002; // POSIX
-    enum RTLD_BINDING_MASK = 0x3;
-    enum RTLD_NOLOAD = 0x00004;
-    enum RTLD_DEEPBIND = 0x00008;
-
-    // enum RTLD_GLOBAL = 0x0004; // POSIX
-    // enum RTLD_LOCAL = 0; // POSIX
-    enum RTLD_NODELETE = 0x01000;
-
     static if (__USE_GNU)
     {
         RT DL_CALL_FCT(RT, Args...)(RT function(Args) fctp, auto ref Args args)
@@ -82,16 +62,6 @@
 else version (MIPS_Any)
 {
     // http://sourceware.org/git/?p=glibc.git;a=blob;f=ports/sysdeps/mips/bits/dlfcn.h
-    // enum RTLD_LAZY = 0x0001; // POSIX
-    // enum RTLD_NOW = 0x0002; // POSIX
-    enum RTLD_BINDING_MASK = 0x3;
-    enum RTLD_NOLOAD = 0x00008;
-    enum RTLD_DEEPBIND = 0x00010;
-
-    // enum RTLD_GLOBAL = 0x0004; // POSIX
-    // enum RTLD_LOCAL = 0; // POSIX
-    enum RTLD_NODELETE = 0x01000;
-
     static if (__USE_GNU)
     {
         RT DL_CALL_FCT(RT, Args...)(RT function(Args) fctp, auto ref Args args)
@@ -106,16 +76,6 @@
 else version (PPC_Any)
 {
     // http://sourceware.org/git/?p=glibc.git;a=blob;f=bits/dlfcn.h
-    // enum RTLD_LAZY = 0x0001; // POSIX
-    // enum RTLD_NOW = 0x0002; // POSIX
-    enum RTLD_BINDING_MASK = 0x3;
-    enum RTLD_NOLOAD = 0x00004;
-    enum RTLD_DEEPBIND = 0x00008;
-
-    // enum RTLD_GLOBAL = 0x00100; // POSIX
-    // enum RTLD_LOCAL = 0; // POSIX
-    enum RTLD_NODELETE = 0x01000;
-
     static if (__USE_GNU)
     {
         RT DL_CALL_FCT(RT, Args...)(RT function(Args) fctp, auto ref Args args)
@@ -130,16 +90,6 @@
 else version (ARM_Any)
 {
     // http://sourceware.org/git/?p=glibc.git;a=blob;f=bits/dlfcn.h
-    // enum RTLD_LAZY = 0x0001; // POSIX
-    // enum RTLD_NOW = 0x0002; // POSIX
-    enum RTLD_BINDING_MASK = 0x3;
-    enum RTLD_NOLOAD = 0x00004;
-    enum RTLD_DEEPBIND = 0x00008;
-
-    // enum RTLD_GLOBAL = 0x00100; // POSIX
-    // enum RTLD_LOCAL = 0; // POSIX
-    enum RTLD_NODELETE = 0x01000;
-
     static if (__USE_GNU)
     {
         RT DL_CALL_FCT(RT, Args...)(RT function(Args) fctp, auto ref Args args)
@@ -154,16 +104,6 @@
 else version (RISCV_Any)
 {
     // http://sourceware.org/git/?p=glibc.git;a=blob;f=bits/dlfcn.h
-    // enum RTLD_LAZY = 0x0001; // POSIX
-    // enum RTLD_NOW = 0x0002; // POSIX
-    enum RTLD_BINDING_MASK = 0x3;
-    enum RTLD_NOLOAD = 0x00004;
-    enum RTLD_DEEPBIND = 0x00008;
-
-    // enum RTLD_GLOBAL = 0x00100; // POSIX
-    // enum RTLD_LOCAL = 0; // POSIX
-    enum RTLD_NODELETE = 0x01000;
-
     static if (__USE_GNU)
     {
         RT DL_CALL_FCT(RT, Args...)(RT function(Args) fctp, auto ref Args args)
@@ -178,16 +118,6 @@
 else version (SPARC_Any)
 {
     // http://sourceware.org/git/?p=glibc.git;a=blob;f=bits/dlfcn.h
-    // enum RTLD_LAZY = 0x0001; // POSIX
-    // enum RTLD_NOW = 0x0002; // POSIX
-    enum RTLD_BINDING_MASK = 0x3;
-    enum RTLD_NOLOAD = 0x00004;
-    enum RTLD_DEEPBIND = 0x00008;
-
-    // enum RTLD_GLOBAL = 0x00100; // POSIX
-    // enum RTLD_LOCAL = 0; // POSIX
-    enum RTLD_NODELETE = 0x01000;
-
     static if (__USE_GNU)
     {
         RT DL_CALL_FCT(RT, Args...)(RT function(Args) fctp, auto ref Args args)
@@ -202,16 +132,6 @@
 else version (IBMZ_Any)
 {
     // http://sourceware.org/git/?p=glibc.git;a=blob;f=bits/dlfcn.h
-    // enum RTLD_LAZY = 0x0001; // POSIX
-    // enum RTLD_NOW = 0x0002; // POSIX
-    enum RTLD_BINDING_MASK = 0x3;
-    enum RTLD_NOLOAD = 0x00004;
-    enum RTLD_DEEPBIND = 0x00008;
-
-    // enum RTLD_GLOBAL = 0x00100; // POSIX
-    // enum RTLD_LOCAL = 0; // POSIX
-    enum RTLD_NODELETE = 0x01000;
-
     static if (__USE_GNU)
     {
         RT DL_CALL_FCT(RT, Args...)(RT function(Args) fctp, auto ref Args args)
@@ -251,15 +171,6 @@
 
 static if (__USE_GNU)
 {
-    struct Dl_info
-    {
-        const(char)* dli_fname;
-        void* dli_fbase;
-        const(char)* dli_sname;
-        void* dli_saddr;
-    }
-
-    int dladdr(const scope void* __address, Dl_info* __info);
     int dladdr1(void* __address, Dl_info* __info, void** __extra_info, int __flags);
 
     enum
diff --git a/libphobos/libdruntime/core/sys/linux/sys/inotify.d b/libphobos/libdruntime/core/sys/linux/sys/inotify.d
index e0acf33..11bdc85 100644
--- a/libphobos/libdruntime/core/sys/linux/sys/inotify.d
+++ b/libphobos/libdruntime/core/sys/linux/sys/inotify.d
@@ -6,7 +6,21 @@
  */
 module core.sys.linux.sys.inotify;
 
-version (linux):
+// The BSDs (including macOS) have a kqueue-backed API-compatible inotify
+// library in ports. However, inotify is a Linux interface so it lives here.
+// All BSD people need this library to use inotify:
+//   https://github.com/libinotify-kqueue/libinotify-kqueue
+// It is the responsibility of all BSD people to configure the library before
+// using this interface.
+
+version (linux)        version = LinuxOrCompatible;
+version (Darwin)       version = LinuxOrCompatible;
+version (FreeBSD)      version = LinuxOrCompatible;
+version (OpenBSD)      version = LinuxOrCompatible;
+version (NetBSD)       version = LinuxOrCompatible;
+version (DragonFlyBSD) version = LinuxOrCompatible;
+
+version (LinuxOrCompatible):
 extern (C):
 @system:
 nothrow:
diff --git a/libphobos/libdruntime/core/sys/netbsd/dlfcn.d b/libphobos/libdruntime/core/sys/netbsd/dlfcn.d
index 468ffbf..3785592 100644
--- a/libphobos/libdruntime/core/sys/netbsd/dlfcn.d
+++ b/libphobos/libdruntime/core/sys/netbsd/dlfcn.d
@@ -19,17 +19,6 @@
 enum __BSD_VISIBLE = true;
 
 /*
- * Modes and flags for dlopen().
- */
-static assert(RTLD_LAZY   == 1);
-static assert(RTLD_NOW    == 2);
-static assert(RTLD_GLOBAL == 0x100);
-static assert(RTLD_LOCAL  == 0x200);
-//enum RTLD_TRACE           =  0x200;
-enum RTLD_NODELETE        =  0x01000;
-enum RTLD_NOLOAD          =  0x02000;
-
-/*
  * Request arguments for dlinfo().
  */
 enum RTLD_DI_LINKMAP     = 3;    /* Obtain link map. */
@@ -47,16 +36,6 @@
 
 static if (__BSD_VISIBLE)
 {
-    /*
-     * Structure filled in by dladdr().
-     */
-    struct Dl_info {
-        const(char)     *dli_fname;     /* Pathname of shared object. */
-        void            *dli_fbase;     /* Base address of shared object. */
-        const(char)     *dli_sname;     /* Name of nearest symbol. */
-        void            *dli_saddr;     /* Address of nearest symbol. */
-    }
-
     /*-
      * The actual type declared by this typedef is immaterial, provided that
      * it is a function pointer.  Its purpose is to provide a return type for
@@ -97,16 +76,6 @@
 
 static if (__BSD_VISIBLE)
 {
-    //void*    fdlopen(int, int);
-    int      dladdr(const(void)*, Dl_info*);
-    //dlfunc_t dlfunc(void*, const(char)*);
     int      dlinfo(void*, int, void*);
-    /+void     dllockinit(void* _context,
-        void* function(void* _context) _lock_create,
-        void  function(void* _lock)    _rlock_acquire,
-        void  function(void* _lock)    _wlock_acquire,
-        void  function(void* _lock)    _lock_release,
-        void  function(void* _lock)    _lock_destroy,
-        void  function(void* _context) _context_destroy);+/
     void*    dlvsym(void*, const(char)*, const(char)*);
 }
diff --git a/libphobos/libdruntime/core/sys/openbsd/dlfcn.d b/libphobos/libdruntime/core/sys/openbsd/dlfcn.d
index b28dc63..1227669 100644
--- a/libphobos/libdruntime/core/sys/openbsd/dlfcn.d
+++ b/libphobos/libdruntime/core/sys/openbsd/dlfcn.d
@@ -11,13 +11,6 @@
 extern (C):
 nothrow:
 
-static assert(RTLD_LAZY   == 1);
-static assert(RTLD_NOW    == 2);
-static assert(RTLD_GLOBAL == 0x100);
-static assert(RTLD_LOCAL  == 0);
-enum RTLD_TRACE           =  0x200;
-enum RTLD_NODELETE        =  0x400;
-
 enum RTLD_NEXT    = cast(void *)-1;
 enum RTLD_DEFAULT = cast(void *)-2;
 enum RTLD_SELF    = cast(void *)-3;
diff --git a/libphobos/libdruntime/core/sys/posix/dirent.d b/libphobos/libdruntime/core/sys/posix/dirent.d
index 8a2440e..bffbc51 100644
--- a/libphobos/libdruntime/core/sys/posix/dirent.d
+++ b/libphobos/libdruntime/core/sys/posix/dirent.d
@@ -37,12 +37,124 @@
 // Required
 //
 /*
-DIR
-
 struct dirent
 {
     char[] d_name;
 }
+*/
+
+version (linux)
+{
+    struct dirent
+    {
+        ino_t       d_ino;
+        off_t       d_off;
+        ushort      d_reclen;
+        ubyte       d_type;
+        char[256]   d_name = 0;
+    }
+}
+else version (Darwin)
+{
+    // _DARWIN_FEATURE_64_BIT_INODE dirent is default for Mac OSX >10.5 and is
+    // only meaningful type for other OS X/Darwin variants (e.g. iOS).
+    // man dir(5) has some info, man stat(2) gives details.
+    struct dirent
+    {
+        ino_t       d_ino;
+        alias       d_fileno = d_ino;
+        ulong       d_seekoff;
+        ushort      d_reclen;
+        ushort      d_namlen;
+        ubyte       d_type;
+        char[1024]  d_name = 0;
+    }
+}
+else version (FreeBSD)
+{
+    import core.sys.freebsd.config;
+
+    static if (__FreeBSD_version >= 1200000)
+    {
+        struct dirent
+        {
+            ino_t     d_fileno;
+            off_t     d_off;
+            ushort    d_reclen;
+            ubyte     d_type;
+            ubyte     d_pad0;
+            ushort    d_namlen;
+            ushort    d_pad1;
+            char[256] d_name = 0;
+        }
+    }
+    else
+    {
+        align(4)
+        struct dirent
+        {
+            uint      d_fileno;
+            ushort    d_reclen;
+            ubyte     d_type;
+            ubyte     d_namlen;
+            char[256] d_name = 0;
+        }
+    }
+}
+else version (NetBSD)
+{
+    struct dirent
+    {
+        ulong      d_fileno;
+        ushort    d_reclen;
+        ushort    d_namlen;
+        ubyte     d_type;
+        char[512] d_name = 0;
+    }
+}
+else version (OpenBSD)
+{
+    align(4)
+    struct dirent
+    {
+        ino_t     d_fileno;
+        off_t     d_off;
+        ushort    d_reclen;
+        ubyte     d_type;
+        ubyte     d_namlen;
+        ubyte[4]  __d_padding;
+        char[256] d_name = 0;
+    }
+}
+else version (DragonFlyBSD)
+{
+    struct dirent
+    {
+        ino_t     d_fileno;       /* file number of entry */
+        ushort    d_reclen;       /* strlen(d_name) */
+        ubyte     d_type;         /* file type, see blow */
+        ubyte     d_unused1;      /* padding, reserved */
+        uint      d_unused2;      /* reserved */
+        char[256] d_name = 0;     /* name, NUL-terminated */
+    }
+}
+else version (Solaris)
+{
+    struct dirent
+    {
+        ino_t d_ino;
+        off_t d_off;
+        ushort d_reclen;
+        char[1] d_name = 0;
+    }
+}
+else
+{
+    static assert(false, "Unsupported platform");
+}
+
+/*
+DIR
 
 int     closedir(DIR*);
 DIR*    opendir(const scope char*);
@@ -67,15 +179,6 @@
         DT_WHT      = 14
     }
 
-    struct dirent
-    {
-        ino_t       d_ino;
-        off_t       d_off;
-        ushort      d_reclen;
-        ubyte       d_type;
-        char[256]   d_name = 0;
-    }
-
     struct DIR
     {
         // Managed by OS
@@ -106,20 +209,6 @@
         DT_WHT      = 14
     }
 
-    // _DARWIN_FEATURE_64_BIT_INODE dirent is default for Mac OSX >10.5 and is
-    // only meaningful type for other OS X/Darwin variants (e.g. iOS).
-    // man dir(5) has some info, man stat(2) gives details.
-    struct dirent
-    {
-        ino_t       d_ino;
-        alias       d_fileno = d_ino;
-        ulong       d_seekoff;
-        ushort      d_reclen;
-        ushort      d_namlen;
-        ubyte       d_type;
-        char[1024]  d_name = 0;
-    }
-
     struct DIR
     {
         // Managed by OS
@@ -157,33 +246,6 @@
         DT_WHT      = 14
     }
 
-    static if (__FreeBSD_version >= 1200000)
-    {
-        struct dirent
-        {
-            ino_t     d_fileno;
-            off_t     d_off;
-            ushort    d_reclen;
-            ubyte     d_type;
-            ubyte     d_pad0;
-            ushort    d_namlen;
-            ushort    d_pad1;
-            char[256] d_name = 0;
-        }
-    }
-    else
-    {
-        align(4)
-        struct dirent
-        {
-            uint      d_fileno;
-            ushort    d_reclen;
-            ubyte     d_type;
-            ubyte     d_namlen;
-            char[256] d_name = 0;
-        }
-    }
-
     alias void* DIR;
 
     version (GNU)
@@ -213,15 +275,6 @@
         DT_WHT      = 14
     }
 
-    struct dirent
-    {
-        ulong      d_fileno;
-        ushort    d_reclen;
-        ushort    d_namlen;
-        ubyte     d_type;
-        char[512] d_name = 0;
-    }
-
     alias void* DIR;
 
     dirent* __readdir30(DIR*);
@@ -241,18 +294,6 @@
         DT_SOCK     = 12,
     }
 
-    align(4)
-    struct dirent
-    {
-        ino_t     d_fileno;
-        off_t     d_off;
-        ushort    d_reclen;
-        ubyte     d_type;
-        ubyte     d_namlen;
-        ubyte[4]  __d_padding;
-        char[256] d_name = 0;
-    }
-
     alias void* DIR;
 
     dirent* readdir(DIR*);
@@ -273,30 +314,12 @@
         DT_DBF      = 15,         /* database record file */
     }
 
-    struct dirent
-    {
-        ino_t     d_fileno;       /* file number of entry */
-        ushort    d_reclen;       /* strlen(d_name) */
-        ubyte     d_type;         /* file type, see blow */
-        ubyte     d_unused1;      /* padding, reserved */
-        uint      d_unused2;      /* reserved */
-        char[256] d_name = 0;     /* name, NUL-terminated */
-    }
-
     alias void* DIR;
 
     dirent* readdir(DIR*);
 }
 else version (Solaris)
 {
-    struct dirent
-    {
-        ino_t d_ino;
-        off_t d_off;
-        ushort d_reclen;
-        char[1] d_name = 0;
-    }
-
     struct DIR
     {
         int dd_fd;
@@ -338,15 +361,6 @@
         DT_WHT      = 14
     }
 
-    struct dirent
-    {
-        ulong       d_ino;
-        long        d_off;
-        ushort      d_reclen;
-        ubyte       d_type;
-        char[256]   d_name = 0;
-    }
-
     struct DIR
     {
     }
@@ -368,15 +382,6 @@
         DT_WHT      = 14
     }
 
-    struct dirent
-    {
-        ino_t       d_ino;
-        off_t       d_off;
-        ushort      d_reclen;
-        ubyte       d_type;
-        char[256]   d_name = 0;
-    }
-
     struct DIR
     {
     }
@@ -408,23 +413,6 @@
         DT_WHT      = 14
     }
 
-    struct dirent
-    {
-        static if (__USE_FILE_OFFSET64)
-        {
-            ino64_t d_ino;
-            off64_t d_off;
-        }
-        else
-        {
-            ino_t d_ino;
-            off_t d_off;
-        }
-        ushort      d_reclen;
-        ubyte       d_type;
-        char[256]   d_name = 0;
-    }
-
     struct DIR
     {
         // Managed by OS
diff --git a/libphobos/libdruntime/core/sys/posix/dlfcn.d b/libphobos/libdruntime/core/sys/posix/dlfcn.d
index f6476ec..a9519ca 100644
--- a/libphobos/libdruntime/core/sys/posix/dlfcn.d
+++ b/libphobos/libdruntime/core/sys/posix/dlfcn.d
@@ -66,59 +66,100 @@
 {
     version (X86_Any)
     {
+        // http://sourceware.org/git/?p=glibc.git;a=blob;f=bits/dlfcn.h
         enum RTLD_LAZY      = 0x00001;
         enum RTLD_NOW       = 0x00002;
+        enum RTLD_BINDING_MASK = 0x3;
+        enum RTLD_NOLOAD    = 0x00004;
+        enum RTLD_DEEPBIND  = 0x00008;
         enum RTLD_GLOBAL    = 0x00100;
         enum RTLD_LOCAL     = 0x00000;
+        enum RTLD_NODELETE  = 0x01000;
     }
     else version (HPPA_Any)
     {
+        // http://sourceware.org/git/?p=glibc.git;a=blob;f=ports/sysdeps/hppa/bits/dlfcn.h
         enum RTLD_LAZY      = 0x0001;
         enum RTLD_NOW       = 0x0002;
+        enum RTLD_BINDING_MASK = 0x3;
+        enum RTLD_NOLOAD    = 0x00004;
+        enum RTLD_DEEPBIND  = 0x00008;
         enum RTLD_GLOBAL    = 0x0100;
         enum RTLD_LOCAL     = 0;
+        enum RTLD_NODELETE  = 0x01000;
     }
     else version (MIPS_Any)
     {
+    // http://sourceware.org/git/?p=glibc.git;a=blob;f=ports/sysdeps/mips/bits/dlfcn.h
         enum RTLD_LAZY      = 0x0001;
         enum RTLD_NOW       = 0x0002;
+        enum RTLD_BINDING_MASK = 0x3;
+        enum RTLD_NOLOAD    = 0x00008;
+        enum RTLD_DEEPBIND  = 0x00010;
         enum RTLD_GLOBAL    = 0x0004;
         enum RTLD_LOCAL     = 0;
+        enum RTLD_NODELETE  = 0x01000;
     }
     else version (PPC_Any)
     {
+        // http://sourceware.org/git/?p=glibc.git;a=blob;f=bits/dlfcn.h
         enum RTLD_LAZY      = 0x00001;
         enum RTLD_NOW       = 0x00002;
+        enum RTLD_BINDING_MASK = 0x3;
+        enum RTLD_NOLOAD    = 0x00004;
+        enum RTLD_DEEPBIND  = 0x00008;
         enum RTLD_GLOBAL    = 0x00100;
         enum RTLD_LOCAL     = 0;
+        enum RTLD_NODELETE  = 0x01000;
     }
     else version (ARM_Any)
     {
+        // http://sourceware.org/git/?p=glibc.git;a=blob;f=bits/dlfcn.h
         enum RTLD_LAZY      = 0x00001;
         enum RTLD_NOW       = 0x00002;
+        enum RTLD_BINDING_MASK = 0x3;
+        enum RTLD_NOLOAD    = 0x00004;
+        enum RTLD_DEEPBIND  = 0x00008;
         enum RTLD_GLOBAL    = 0x00100;
         enum RTLD_LOCAL     = 0;
+        enum RTLD_NODELETE  = 0x01000;
     }
     else version (RISCV_Any)
     {
+        // http://sourceware.org/git/?p=glibc.git;a=blob;f=bits/dlfcn.h
         enum RTLD_LAZY      = 0x00001;
         enum RTLD_NOW       = 0x00002;
+        enum RTLD_BINDING_MASK = 0x3;
+        enum RTLD_NOLOAD    = 0x00004;
+        enum RTLD_DEEPBIND  = 0x00008;
         enum RTLD_GLOBAL    = 0x00100;
         enum RTLD_LOCAL     = 0;
+        enum RTLD_NODELETE  = 0x01000;
     }
     else version (SPARC_Any)
     {
+        // http://sourceware.org/git/?p=glibc.git;a=blob;f=bits/dlfcn.h
         enum RTLD_LAZY      = 0x00001;
         enum RTLD_NOW       = 0x00002;
+        enum RTLD_BINDING_MASK = 0x3;
+        enum RTLD_NOLOAD    = 0x00004;
+        enum RTLD_DEEPBIND  = 0x00008;
         enum RTLD_GLOBAL    = 0x00100;
         enum RTLD_LOCAL     = 0;
+        enum RTLD_NODELETE  = 0x01000;
+
     }
     else version (IBMZ_Any)
     {
+        // http://sourceware.org/git/?p=glibc.git;a=blob;f=bits/dlfcn.h
         enum RTLD_LAZY      = 0x00001;
         enum RTLD_NOW       = 0x00002;
+        enum RTLD_BINDING_MASK = 0x3;
+        enum RTLD_NOLOAD    = 0x00004;
+        enum RTLD_DEEPBIND  = 0x00008;
         enum RTLD_GLOBAL    = 0x00100;
         enum RTLD_LOCAL     = 0;
+        enum RTLD_NODELETE  = 0x01000;
     }
     else
         static assert(0, "unimplemented");
@@ -127,13 +168,25 @@
     char* dlerror();
     void* dlopen(const scope char*, int);
     void* dlsym(void*, const scope char*);
+    int dladdr(const scope void*, Dl_info*);
+
+    struct Dl_info
+    {
+        const(char)* dli_fname;
+        void* dli_fbase;
+        const(char)* dli_sname;
+        void* dli_saddr;
+    }
 }
 else version (Darwin)
 {
     enum RTLD_LAZY      = 0x00001;
     enum RTLD_NOW       = 0x00002;
+    enum RTLD_NOLOAD    = 0x10;
+    enum RTLD_NODELETE  = 0x80;
     enum RTLD_GLOBAL    = 0x00100;
     enum RTLD_LOCAL     = 0x00000;
+    enum RTLD_FIRST     = 0x100;
 
     int   dlclose(void*);
     char* dlerror();
@@ -153,8 +206,12 @@
 {
     enum RTLD_LAZY      = 1;
     enum RTLD_NOW       = 2;
+    enum RTLD_MODEMASK  =  0x3;
     enum RTLD_GLOBAL    = 0x100;
     enum RTLD_LOCAL     = 0;
+    enum RTLD_TRACE     =  0x200;
+    enum RTLD_NODELETE  =  0x01000;
+    enum RTLD_NOLOAD    =  0x02000;
 
     int   dlclose(void*);
     char* dlerror();
@@ -199,6 +256,8 @@
     enum RTLD_NOW       = 2;
     enum RTLD_GLOBAL    = 0x100;
     enum RTLD_LOCAL     = 0;
+    enum RTLD_TRACE     = 0x200;
+    enum RTLD_NODELETE  = 0x400;
 
     int   dlclose(void*);
     char* dlerror();
@@ -218,8 +277,12 @@
 {
     enum RTLD_LAZY      = 1;
     enum RTLD_NOW       = 2;
+    enum RTLD_MODEMASK  =  0x3;
     enum RTLD_GLOBAL    = 0x100;
     enum RTLD_LOCAL     = 0;
+    enum RTLD_TRACE     =  0x200;
+    enum RTLD_NODELETE  =  0x01000;
+    enum RTLD_NOLOAD    =  0x02000;
 
     int   dlclose(void*);
     char* dlerror();
@@ -239,8 +302,16 @@
 {
     enum RTLD_LAZY      = 1;
     enum RTLD_NOW       = 2;
+    enum RTLD_NOLOAD    = 0x00004;
+    enum RTLD_DEEPBIND  = 0x00008;
     enum RTLD_GLOBAL    = 0x100;
     enum RTLD_LOCAL     = 0;
+    enum RTLD_PARENT    = 0x00200;
+    enum RTLD_GROUP     = 0x00400;
+    enum RTLD_WORLD     = 0x00800;
+    enum RTLD_NODELETE  = 0x01000;
+    enum RTLD_FIRST     = 0x02000;
+    enum RTLD_CONFGEN   = 0x10000;
 
     int   dlclose(void*);
     char* dlerror();
@@ -343,4 +414,13 @@
     char* dlerror();
     void* dlopen(const scope char*, int);
     void* dlsym(void*, const scope char*);
+    int dladdr(const scope void*, Dl_info*);
+
+    struct Dl_info
+    {
+        const(char)* dli_fname;
+        void* dli_fbase;
+        const(char)* dli_sname;
+        void* dli_saddr;
+    }
 }
diff --git a/libphobos/libdruntime/core/sys/posix/fcntl.d b/libphobos/libdruntime/core/sys/posix/fcntl.d
index 6833f3b..3c196d2 100644
--- a/libphobos/libdruntime/core/sys/posix/fcntl.d
+++ b/libphobos/libdruntime/core/sys/posix/fcntl.d
@@ -96,12 +96,8 @@
     off_t   l_len;
     pid_t   l_pid;
 }
-
-int creat(const scope char*, mode_t);
-int fcntl(int, int, ...);
-int open(const scope char*, int, ...);
 */
-version (CRuntime_Glibc)
+version (linux)
 {
     enum F_DUPFD        = 0;
     enum F_GETFD        = 1;
@@ -121,6 +117,12 @@
     enum F_SETLK        = 6;
     enum F_SETLKW       = 7;
   }
+  else version (PPC64)
+  {
+    enum F_GETLK        = 5;
+    enum F_SETLK        = 6;
+    enum F_SETLKW       = 7;
+  }
   else version (SystemZ)
   {
     static assert(off_t.sizeof == 8);
@@ -163,6 +165,19 @@
         enum O_SYNC         = 0x101000; // octal 04010000
         enum O_DSYNC        = 0x1000;   // octal   010000
         enum O_RSYNC        = O_SYNC;
+
+        enum O_DIRECTORY    = 0x010000; // octal   0200000
+        enum O_NOFOLLOW     = 0x020000; // octal   0400000
+        enum O_DIRECT       = 0x004000; // octal    040000
+        version (X86_64)
+            enum O_LARGEFILE = 0;
+        else
+            enum O_LARGEFILE = 0x08000; // octal   0100000
+        enum O_TMPFILE      = 0x410000; // octal 020200000
+        enum O_ASYNC        = 0x2000;   // octal    020000
+        enum O_NOATIME      = 0x40000;  // octal  01000000
+        enum O_PATH         = 0x200000; // octal 010000000
+        enum O_NDELAY       = O_NONBLOCK;
     }
     else version (HPPA_Any)
     {
@@ -177,6 +192,16 @@
         enum O_SYNC         = 0x48000;  // octal 01100000
         enum O_DSYNC        = 0x40000;  // octal 01000000
         enum O_RSYNC        = 0x80000;  // octal 02000000
+
+        enum O_DIRECTORY    = 0x001000; // octal 000010000
+        enum O_NOFOLLOW     = 0x000080; // octal 000000200
+        enum O_DIRECT       = 0x004000; // octal    040000
+        enum O_LARGEFILE    = 0x000800; // octal  00004000
+        enum O_TMPFILE      = 0x801000; // octal 040010000
+        enum O_ASYNC        = 0x2000;   // octal    020000
+        enum O_NOATIME      = 0x100000; // octal 004000000
+        enum O_PATH         = 0x400000; // octal 020000000
+        enum O_NDELAY       = O_NONBLOCK;
     }
     else version (MIPS_Any)
     {
@@ -191,6 +216,19 @@
         enum O_CLOEXEC      = 0x80000;
         enum O_RSYNC        = O_SYNC;
         enum O_SYNC         = 0x4010;
+
+        enum O_DIRECTORY    = 0x010000;
+        enum O_NOFOLLOW     = 0x020000;
+        enum O_DIRECT       = 0x8000;
+        version (MIPS_N64)
+            enum O_LARGEFILE = 0;
+        else
+            enum O_LARGEFILE = 0x2000;
+        enum O_TMPFILE      = 0x410000;
+        enum O_ASYNC        = 0x1000;
+        enum O_NOATIME      = 0x40000;
+        enum O_PATH         = 0x200000;
+        enum O_NDELAY       = O_NONBLOCK;
     }
     else version (PPC_Any)
     {
@@ -205,6 +243,19 @@
         enum O_SYNC         = 0x101000; // octal 04010000
         enum O_DSYNC        = 0x1000;   // octal   010000
         enum O_RSYNC        = O_SYNC;
+
+        enum O_DIRECTORY    = 0x004000; // octal    040000
+        enum O_NOFOLLOW     = 0x008000; // octal   0100000
+        enum O_DIRECT       = 0x020000; // octal   0400000
+        version (D_LP64)
+            enum O_LARGEFILE = 0;
+        else
+            enum O_LARGEFILE = 0x10000; // octal   0200000
+        enum O_TMPFILE      = 0x404000; // octal 020040000
+        enum O_ASYNC        = 0x2000;   // octal    020000
+        enum O_NOATIME      = 0x40000;  // octal  01000000
+        enum O_PATH         = 0x200000;
+        enum O_NDELAY       = O_NONBLOCK;
     }
     else version (ARM_Any)
     {
@@ -219,6 +270,19 @@
         enum O_SYNC         = 0x101000; // octal 04010000
         enum O_DSYNC        = 0x1000;   // octal   010000
         enum O_RSYNC        = O_SYNC;
+
+        enum O_DIRECTORY    = 0x004000; // octal    040000
+        enum O_NOFOLLOW     = 0x008000; // octal   0100000
+        enum O_DIRECT       = 0x010000; // octal   0200000
+        version (D_LP64)
+            enum O_LARGEFILE = 0;
+        else
+            enum O_LARGEFILE = 0x20000; // octal   0400000
+        enum O_TMPFILE      = 0x404000; // octal 020040000
+        enum O_ASYNC        = 0x2000;   // octal    020000
+        enum O_NOATIME      = 0x40000;  // octal  01000000
+        enum O_PATH         = 0x200000; // octal 010000000
+        enum O_NDELAY       = O_NONBLOCK;
     }
     else version (RISCV_Any)
     {
@@ -233,6 +297,19 @@
         enum O_SYNC         = 0x101000; // octal 04010000
         enum O_DSYNC        = 0x1000;   // octal   010000
         enum O_RSYNC        = O_SYNC;
+
+        enum O_DIRECTORY    = 0x010000;
+        enum O_NOFOLLOW     = 0x020000;
+        enum O_DIRECT       = 0x004000;
+        version (D_LP64)
+            enum O_LARGEFILE = 0;
+        else
+            enum O_LARGEFILE = 0x8000;
+        enum O_TMPFILE      = 0x410000;
+        enum O_ASYNC        = 0x2000;
+        enum O_NOATIME      = 0x40000;
+        enum O_PATH         = 0x200000;
+        enum O_NDELAY       = O_NONBLOCK;
     }
     else version (SPARC_Any)
     {
@@ -247,6 +324,19 @@
         enum O_SYNC         = 0x802000;
         enum O_DSYNC        = 0x2000;
         enum O_RSYNC        = O_SYNC;
+
+        enum O_DIRECTORY    = 0x10000;
+        enum O_NOFOLLOW     = 0x20000;
+        enum O_DIRECT       = 0x100000;
+        version (D_LP64)
+            enum O_LARGEFILE = 0;
+        else
+            enum O_LARGEFILE = 0x40000;
+        enum O_TMPFILE      = 0x2010000;
+        enum O_ASYNC        = 0x0040;
+        enum O_NOATIME      = 0x200000;
+        enum O_PATH         = 0x1000000;
+        enum O_NDELAY       = (0x0004|O_NONBLOCK);
     }
     else version (IBMZ_Any)
     {
@@ -261,11 +351,33 @@
         enum O_SYNC         = 0x101000; // octal 04010000
         enum O_DSYNC        = 0x1000;   // octal   010000
         enum O_RSYNC        = O_SYNC;
+
+        enum O_DIRECTORY    = 0x010000; // octal   0200000
+        enum O_NOFOLLOW     = 0x020000; // octal   0400000
+        enum O_DIRECT       = 0x004000; // octal    040000
+        version (D_LP64)
+            enum O_LARGEFILE = 0;
+        else
+            enum O_LARGEFILE = 0x08000; // octal   0100000
+        enum O_TMPFILE      = 0x410000; // octal 020200000
+        enum O_ASYNC        = 0x2000;   // octal    020000
+        enum O_NOATIME      = 0x40000;  // octal  01000000
+        enum O_PATH         = 0x200000; // octal 010000000
+        enum O_NDELAY       = O_NONBLOCK;
     }
     else
         static assert(0, "unimplemented");
 
-    enum O_ACCMODE      = 0x3;
+    version (CRuntime_Musl)
+    {
+        enum O_SEARCH   = O_PATH;
+        enum O_EXEC     = O_PATH;
+        enum O_ACCMODE  = (3|O_SEARCH);
+    }
+    else
+    {
+        enum O_ACCMODE  = 0x3;
+    }
     enum O_RDONLY       = 0x0;
     enum O_WRONLY       = 0x1;
     enum O_RDWR         = 0x2;
@@ -279,22 +391,11 @@
         pid_t   l_pid;
     }
 
-    static if ( __USE_FILE_OFFSET64 )
-    {
-        int   creat64(const scope char*, mode_t);
-        alias creat64 creat;
-
-        int   open64(const scope char*, int, ...);
-        alias open64 open;
-    }
-    else
-    {
-        int   creat(const scope char*, mode_t);
-        int   open(const scope char*, int, ...);
-    }
-
     enum AT_SYMLINK_NOFOLLOW = 0x100;
     enum AT_FDCWD = -100;
+    enum AT_REMOVEDIR = 0x200;
+    enum AT_SYMLINK_FOLLOW = 0x400;
+    enum AT_EACCESS = 0x200;
 }
 else version (Darwin)
 {
@@ -339,9 +440,6 @@
         short   l_type;
         short   l_whence;
     }
-
-    int creat(const scope char*, mode_t);
-    int open(const scope char*, int, ...);
 }
 else version (FreeBSD)
 {
@@ -401,9 +499,6 @@
         short   l_whence;
     }
 
-    int creat(const scope char*, mode_t);
-    int open(const scope char*, int, ...);
-
     enum AT_SYMLINK_NOFOLLOW = 0x200;
     enum AT_FDCWD = -100;
 }
@@ -466,9 +561,6 @@
         short   l_whence;
     }
 
-    int creat(const scope char*, mode_t);
-    int open(const scope char*, int, ...);
-
     enum AT_FDCWD            = -100;
 
     enum AT_EACCESS          = 0x01;
@@ -524,10 +616,6 @@
         short   l_type;
         short   l_whence;
     }
-
-
-    int creat(const scope char*, mode_t);
-    int open(const scope char*, int, ...);
 }
 else version (DragonFlyBSD)
 {
@@ -612,11 +700,6 @@
     }
 
     alias oflock = flock;
-
-    int creat(const scope char*, mode_t);
-    int open(const scope char*, int, ...);
-    //int fcntl(int, int, ...);  /*defined below*/
-    //int flock(int, int);
 }
 else version (Solaris)
 {
@@ -700,7 +783,60 @@
             c_long[4]   l_pad;
         }
     }
+}
+else
+{
+    static assert(false, "Unsupported platform");
+}
 
+/*
+int creat(const scope char*, mode_t);
+int fcntl(int, int, ...);
+int open(const scope char*, int, ...);
+*/
+version (CRuntime_Glibc)
+{
+    static if ( __USE_FILE_OFFSET64 )
+    {
+        int   creat64(const scope char*, mode_t);
+        alias creat64 creat;
+
+        int   open64(const scope char*, int, ...);
+        alias open64 open;
+    }
+    else
+    {
+        int   creat(const scope char*, mode_t);
+        int   open(const scope char*, int, ...);
+    }
+}
+else version (Darwin)
+{
+    int creat(const scope char*, mode_t);
+    int open(const scope char*, int, ...);
+}
+else version (FreeBSD)
+{
+    int creat(const scope char*, mode_t);
+    int open(const scope char*, int, ...);
+}
+else version (OpenBSD)
+{
+    int creat(const scope char*, mode_t);
+    int open(const scope char*, int, ...);
+}
+else version (NetBSD)
+{
+    int creat(const scope char*, mode_t);
+    int open(const scope char*, int, ...);
+}
+else version (DragonFlyBSD)
+{
+    int creat(const scope char*, mode_t);
+    int open(const scope char*, int, ...);
+}
+else version (Solaris)
+{
     version (D_LP64)
     {
         int creat(const scope char*, mode_t);
@@ -731,323 +867,15 @@
 }
 else version (CRuntime_Bionic)
 {
-    // All these except for the two functions open and creat really come from
-    // the linux kernel and can probably be merged.
-    enum F_DUPFD        = 0;
-    enum F_GETFD        = 1;
-    enum F_SETFD        = 2;
-    enum F_GETFL        = 3;
-    enum F_SETFL        = 4;
-    enum F_GETLK        = 5;
-    enum F_SETLK        = 6;
-    enum F_SETLKW       = 7;
-    enum F_SETOWN       = 8;
-    enum F_GETOWN       = 9;
-
-    enum FD_CLOEXEC     = 1;
-
-    enum F_RDLCK        = 0;
-    enum F_WRLCK        = 1;
-    enum F_UNLCK        = 2;
-
-    enum O_CREAT        = 0x40;     // octal     0100
-    enum O_EXCL         = 0x80;     // octal     0200
-    enum O_NOCTTY       = 0x100;    // octal     0400
-    enum O_TRUNC        = 0x200;    // octal    01000
-
-    enum O_APPEND       = 0x400;    // octal    02000
-    enum O_NONBLOCK     = 0x800;    // octal    04000
-
-    version (D_LP64)
-    {
-        enum O_SYNC     = 0x101000; // octal 04010000
-    }
-    else
-    {
-        enum O_SYNC     = 0x1000;   // octal   010000
-    }
-
-    enum O_ACCMODE      = 0x3;
-    enum O_RDONLY       = 0x0;
-    enum O_WRONLY       = 0x1;
-    enum O_RDWR         = 0x2;
-
-    struct flock
-    {
-        short   l_type;
-        short   l_whence;
-        off_t   l_start;
-        off_t   l_len;
-        pid_t   l_pid;
-    }
-
     int   creat(const scope char*, mode_t);
     int   open(const scope char*, int, ...);
-
-    enum AT_FDCWD = -100;
 }
 else version (CRuntime_Musl)
 {
-    version (X86_64)
-    {
-        enum
-        {
-            O_DIRECTORY     = 0x010000, // octal   0200000
-            O_NOFOLLOW      = 0x020000, // octal   0400000
-            O_DIRECT        = 0x004000, // octal    040000
-            O_LARGEFILE     =        0,
-            O_TMPFILE       = 0x410000, // octal 020200000
-
-            F_GETLK        = 5,
-            F_SETLK        = 6,
-            F_SETLKW       = 7,
-        }
-    }
-    // Note: Definitions for i386 are in arch/generic/bits/fcntl.h
-    else version (X86)
-    {
-        enum
-        {
-            O_DIRECTORY     = 0x010000, // octal   0200000
-            O_NOFOLLOW      = 0x020000, // octal   0400000
-            O_DIRECT        = 0x004000, // octal    040000
-            O_LARGEFILE     = 0x008000, // octal   0100000
-            O_TMPFILE       = 0x410000, // octal 020200000
-
-            F_GETLK        = 12,
-            F_SETLK        = 13,
-            F_SETLKW       = 14,
-        }
-    }
-    else version (ARM)
-    {
-        enum
-        {
-            O_DIRECTORY     = 0x004000, // octal    040000
-            O_NOFOLLOW      = 0x008000, // octal   0100000
-            O_DIRECT        = 0x010000, // octal   0200000
-            O_LARGEFILE     = 0x020000, // octal   0400000
-            O_TMPFILE       = 0x404000, // octal 020040000
-
-            F_GETLK        = 12,
-            F_SETLK        = 13,
-            F_SETLKW       = 14,
-        }
-    }
-    else version (AArch64)
-    {
-        enum
-        {
-            O_DIRECTORY     = 0x004000, // octal    040000
-            O_NOFOLLOW      = 0x008000, // octal   0100000
-            O_DIRECT        = 0x010000, // octal   0200000
-            O_LARGEFILE     = 0x020000, // octal   0400000
-            O_TMPFILE       = 0x404000, // octal 020040000
-
-            F_GETLK        = 5,
-            F_SETLK        = 6,
-            F_SETLKW       = 7,
-        }
-    }
-    else version (SystemZ)
-    {
-        enum
-        {
-            O_DIRECTORY     = 0x010000, // octal   0200000
-            O_NOFOLLOW      = 0x020000, // octal   0400000
-            O_DIRECT        = 0x004000, // octal    040000
-            O_LARGEFILE     = 0x008000, // octal   0100000
-            O_TMPFILE       = 0x410000, // octal 020200000
-
-            F_GETLK        = 5,
-            F_SETLK        = 6,
-            F_SETLKW       = 7,
-        }
-    }
-    else version (PPC64)
-    {
-        enum
-        {
-            O_DIRECTORY     = 0x004000, // octal    040000
-            O_NOFOLLOW      = 0x008000, // octal   0100000
-            O_DIRECT        = 0x020000, // octal   0400000
-            O_LARGEFILE     = 0x010000, // octal   0200000
-            O_TMPFILE       = 0x410000, // octal 020200000
-
-            F_GETLK        = 5,
-            F_SETLK        = 6,
-            F_SETLKW       = 7,
-        }
-    }
-    else
-        static assert(0, "Platform not supported");
-
-    enum
-    {
-        O_CREAT         = 0x40,     // octal     0100
-        O_EXCL          = 0x80,     // octal     0200
-        O_NOCTTY        = 0x100,    // octal     0400
-        O_TRUNC         = 0x200,    // octal    01000
-
-        O_APPEND        = 0x400,    // octal    02000
-        O_NONBLOCK      = 0x800,    // octal    04000
-        O_DSYNC         = 0x1000,   // octal   010000
-        O_SYNC          = 0x101000, // octal 04010000
-        O_RSYNC         = O_SYNC,
-        O_CLOEXEC       = 0x80000,
-
-        O_ASYNC         = 0x2000,
-        O_NOATIME       = 0x40000,
-        O_PATH          = 0x200000,
-        O_NDELAY        = O_NONBLOCK,
-        O_SEARCH        = O_PATH,
-        O_EXEC          = O_PATH,
-
-        O_ACCMODE       = (3|O_SEARCH),
-        O_RDONLY        = 0,
-        O_WRONLY        = 1,
-        O_RDWR          = 2,
-    }
-    enum
-    {
-        F_DUPFD        = 0,
-        F_GETFD        = 1,
-        F_SETFD        = 2,
-        F_GETFL        = 3,
-        F_SETFL        = 4,
-        // F_GETLK, F_SETLK, F_SETLKW are arch-specific
-        F_SETOWN       = 8,
-        F_GETOWN       = 9,
-    }
-    enum
-    {
-        F_RDLCK        = 0,
-        F_WRLCK        = 1,
-        F_UNLCK        = 2,
-    }
-    struct flock
-    {
-        short   l_type;
-        short   l_whence;
-        off_t   l_start;
-        off_t   l_len;
-        pid_t   l_pid;
-    }
-    enum FD_CLOEXEC     = 1;
     int open(const scope char*, int, ...);
-
-    enum AT_FDCWD = -100;
-    enum AT_SYMLINK_NOFOLLOW = 0x100;
-    enum AT_REMOVEDIR = 0x200;
-    enum AT_SYMLINK_FOLLOW = 0x400;
-    enum AT_EACCESS = 0x200;
 }
 else version (CRuntime_UClibc)
 {
-    enum F_DUPFD        = 0;
-    enum F_GETFD        = 1;
-    enum F_SETFD        = 2;
-    enum F_GETFL        = 3;
-    enum F_SETFL        = 4;
-
-    version (X86_64)
-    {
-        enum F_GETLK        = 5;
-        enum F_SETLK        = 6;
-        enum F_SETLKW       = 7;
-    }
-    else static if (__USE_FILE_OFFSET64)
-    {
-        enum F_GETLK        = 5;
-        enum F_SETLK        = 6;
-        enum F_SETLKW       = 7;
-    }
-    else
-    {
-        enum F_GETLK        = 12;
-        enum F_SETLK        = 13;
-        enum F_SETLKW       = 14;
-    }
-
-    enum F_GETOWN       = 9;
-    enum F_SETOWN       = 8;
-
-    enum FD_CLOEXEC     = 1;
-
-    enum F_RDLCK        = 0;
-    enum F_UNLCK        = 2;
-    enum F_WRLCK        = 1;
-
-    version (X86_Any)
-    {
-        enum O_CREAT        = 0x40;     // octal     0100
-        enum O_EXCL         = 0x80;     // octal     0200
-        enum O_NOCTTY       = 0x100;    // octal     0400
-        enum O_TRUNC        = 0x200;    // octal    01000
-
-        enum O_APPEND       = 0x400;    // octal    02000
-        enum O_NONBLOCK     = 0x800;    // octal    04000
-        enum O_CLOEXEC      = 0x80000;  // octal    02000000
-        enum O_SYNC         = 0x1000;   // octal    010000
-        enum O_NDELAY       = O_NONBLOCK;
-        enum O_FSYNC        = O_SYNC;
-        enum O_ASYNC        = 0x2000;   // octal    020000
-    }
-    else version (MIPS_Any)
-    {
-        enum O_CREAT        = 0x0100;
-        enum O_EXCL         = 0x0400;
-        enum O_NOCTTY       = 0x0800;
-        enum O_TRUNC        = 0x0200;
-
-        enum O_APPEND       = 0x0008;
-        enum O_SYNC         = 0x0010;
-        enum O_NONBLOCK     = 0x0080;
-        enum O_CLOEXEC      = 0x80000;  // octal    02000000
-        enum O_NDELAY       = O_NONBLOCK;
-        enum O_FSYNC        = O_SYNC;
-        enum O_ASYNC        = 0x1000;
-    }
-    else version (ARM_Any)
-    {
-        enum O_CREAT        = 0x40;     // octal     0100
-        enum O_EXCL         = 0x80;     // octal     0200
-        enum O_NOCTTY       = 0x100;    // octal     0400
-        enum O_TRUNC        = 0x200;    // octal    01000
-
-        enum O_APPEND       = 0x400;    // octal    02000
-        enum O_NONBLOCK     = 0x800;    // octal    04000
-        enum O_CLOEXEC      = 0x80000;  // octal    02000000
-        enum O_SYNC         = 0x1000;   // octal    010000
-        enum O_NDELAY       = O_NONBLOCK;
-        enum O_FSYNC        = O_SYNC;
-        enum O_ASYNC        = 0x2000;     // octal 020000
-    }
-    else
-        static assert(0, "unimplemented");
-
-    enum O_ACCMODE      = 0x3;
-    enum O_RDONLY       = 0x0;
-    enum O_WRONLY       = 0x1;
-    enum O_RDWR         = 0x2;
-
-    struct flock
-    {
-        short   l_type;
-        short   l_whence;
-        static if (__USE_FILE_OFFSET64)
-        {
-            off64_t   l_start;
-            off64_t   l_len;
-        }
-        else
-        {
-            off_t   l_start;
-            off_t   l_len;
-        }
-        pid_t   l_pid;
-    }
-
     static if ( __USE_FILE_OFFSET64 )
     {
         int   creat64(const scope char*, mode_t);
@@ -1061,9 +889,6 @@
         int   creat(const scope char*, mode_t);
         int   open(const scope char*, int, ...);
     }
-
-    enum AT_SYMLINK_NOFOLLOW    = 0x100;
-    enum AT_FDCWD               = -100;
 }
 else
 {
diff --git a/libphobos/libdruntime/core/sys/posix/poll.d b/libphobos/libdruntime/core/sys/posix/poll.d
index fdc4176..7c2d570 100644
--- a/libphobos/libdruntime/core/sys/posix/poll.d
+++ b/libphobos/libdruntime/core/sys/posix/poll.d
@@ -44,17 +44,6 @@
 
 nfds_t
 
-POLLIN
-POLLRDNORM
-POLLRDBAND
-POLLPRI
-POLLOUT
-POLLWRNORM
-POLLWRBAND
-POLLERR
-POLLHUP
-POLLNVAL
-
 int poll(pollfd[], nfds_t, int);
 */
 
@@ -69,20 +58,6 @@
 
     alias c_ulong nfds_t;
 
-    enum
-    {
-        POLLIN      = 0x001,
-        POLLRDNORM  = 0x040,
-        POLLRDBAND  = 0x080,
-        POLLPRI     = 0x002,
-        POLLOUT     = 0x004,
-        POLLWRNORM  = 0x100,
-        POLLWRBAND  = 0x200,
-        POLLERR     = 0x008,
-        POLLHUP     = 0x010,
-        POLLNVAL    = 0x020,
-    }
-
     int poll(pollfd*, nfds_t, int);
 }
 else version (Darwin)
@@ -96,6 +71,148 @@
 
     alias uint nfds_t;
 
+    int poll(pollfd*, nfds_t, int);
+}
+else version (FreeBSD)
+{
+    alias uint nfds_t;
+
+    struct pollfd
+    {
+        int     fd;
+        short   events;
+        short   revents;
+    }
+
+    int poll(pollfd*, nfds_t, int);
+}
+else version (NetBSD)
+{
+    alias uint nfds_t;
+
+    struct pollfd
+    {
+        int     fd;
+        short   events;
+        short   revents;
+    }
+
+    int poll(pollfd*, nfds_t, int);
+}
+else version (OpenBSD)
+{
+    alias uint nfds_t;
+
+    struct pollfd
+    {
+        int     fd;
+        short   events;
+        short   revents;
+    }
+
+    int poll(pollfd*, nfds_t, int);
+}
+else version (DragonFlyBSD)
+{
+    alias uint nfds_t;
+
+    struct pollfd
+    {
+        int     fd;
+        short   events;
+        short   revents;
+    }
+
+    int poll(pollfd*, nfds_t, int);
+}
+else version (Solaris)
+{
+    alias c_ulong nfds_t;
+
+    struct pollfd
+    {
+        int     fd;
+        short   events;
+        short   revents;
+    }
+
+    int poll(pollfd*, nfds_t, int);
+}
+else version (CRuntime_Bionic)
+{
+    struct pollfd
+    {
+        int     fd;
+        short   events;
+        short   revents;
+    }
+
+    alias uint nfds_t;
+
+    int poll(pollfd*, nfds_t, c_long);
+}
+else version (CRuntime_Musl)
+{
+    struct pollfd
+    {
+        int     fd;
+        short   events;
+        short   revents;
+    }
+
+    alias uint nfds_t;
+
+    int poll(pollfd*, nfds_t, c_long);
+}
+else version (CRuntime_UClibc)
+{
+    struct pollfd
+    {
+        int     fd;
+        short   events;
+        short   revents;
+    }
+
+    alias c_ulong nfds_t;
+
+    int poll(pollfd*, nfds_t, int);
+}
+else
+{
+    static assert(false, "Unsupported platform");
+}
+
+/*
+POLLIN
+POLLRDNORM
+POLLRDBAND
+POLLPRI
+POLLOUT
+POLLWRNORM
+POLLWRBAND
+POLLERR
+POLLHUP
+POLLNVAL
+*/
+
+version (linux)
+{
+    enum
+    {
+        POLLIN      = 0x001,
+        POLLRDNORM  = 0x040,
+        POLLRDBAND  = 0x080,
+        POLLPRI     = 0x002,
+        POLLOUT     = 0x004,
+        POLLWRNORM  = 0x100,
+        POLLWRBAND  = 0x200,
+        POLLERR     = 0x008,
+        POLLHUP     = 0x010,
+        POLLNVAL    = 0x020,
+    }
+}
+else version (Darwin)
+{
     enum
     {
         POLLIN      = 0x0001,
@@ -116,20 +233,9 @@
         POLLSTANDARD = (POLLIN|POLLPRI|POLLOUT|POLLRDNORM|POLLRDBAND|
                         POLLWRBAND|POLLERR|POLLHUP|POLLNVAL)
     }
-
-    int poll(pollfd*, nfds_t, int);
 }
 else version (FreeBSD)
 {
-    alias uint nfds_t;
-
-    struct pollfd
-    {
-        int     fd;
-        short   events;
-        short   revents;
-    }
-
     enum
     {
         POLLIN      = 0x0001,
@@ -150,20 +256,9 @@
         POLLSTANDARD = (POLLIN|POLLPRI|POLLOUT|POLLRDNORM|POLLRDBAND|
         POLLWRBAND|POLLERR|POLLHUP|POLLNVAL)
     }
-
-    int poll(pollfd*, nfds_t, int);
 }
 else version (NetBSD)
 {
-    alias uint nfds_t;
-
-    struct pollfd
-    {
-        int     fd;
-        short   events;
-        short   revents;
-    }
-
     enum
     {
         POLLIN      = 0x0001,
@@ -184,20 +279,9 @@
         POLLSTANDARD = (POLLIN|POLLPRI|POLLOUT|POLLRDNORM|POLLRDBAND|
         POLLWRBAND|POLLERR|POLLHUP|POLLNVAL)
     }
-
-    int poll(pollfd*, nfds_t, int);
 }
 else version (OpenBSD)
 {
-    alias uint nfds_t;
-
-    struct pollfd
-    {
-        int     fd;
-        short   events;
-        short   revents;
-    }
-
     enum
     {
         POLLIN      = 0x0001,
@@ -215,20 +299,9 @@
         POLLSTANDARD = (POLLIN|POLLPRI|POLLOUT|POLLRDNORM|POLLRDBAND|
         POLLWRBAND|POLLERR|POLLHUP|POLLNVAL)
     }
-
-    int poll(pollfd*, nfds_t, int);
 }
 else version (DragonFlyBSD)
 {
-    alias uint nfds_t;
-
-    struct pollfd
-    {
-        int     fd;
-        short   events;
-        short   revents;
-    }
-
     enum
     {
         POLLIN      = 0x0001,
@@ -249,20 +322,9 @@
         POLLSTANDARD = (POLLIN|POLLPRI|POLLOUT|POLLRDNORM|POLLRDBAND|
         POLLWRBAND|POLLERR|POLLHUP|POLLNVAL)
     }
-
-    int poll(pollfd*, nfds_t, int);
 }
 else version (Solaris)
 {
-    alias c_ulong nfds_t;
-
-    struct pollfd
-    {
-        int     fd;
-        short   events;
-        short   revents;
-    }
-
     enum
     {
         POLLIN      = 0x0001,
@@ -276,90 +338,8 @@
         POLLHUP     = 0x0010,
         POLLNVAL    = 0x0020,
     }
-
-    int poll(pollfd*, nfds_t, int);
 }
-else version (CRuntime_Bionic)
+else
 {
-    struct pollfd
-    {
-        int     fd;
-        short   events;
-        short   revents;
-    }
-
-    alias uint nfds_t;
-
-    enum
-    {
-        POLLIN      = 0x001,
-        POLLRDNORM  = 0x040,
-        POLLRDBAND  = 0x080,
-        POLLPRI     = 0x002,
-        POLLOUT     = 0x004,
-        POLLWRNORM  = 0x100,
-        POLLWRBAND  = 0x200,
-        POLLERR     = 0x008,
-        POLLHUP     = 0x010,
-        POLLNVAL    = 0x020,
-    }
-
-    int poll(pollfd*, nfds_t, c_long);
-}
-else version (CRuntime_Musl)
-{
-    struct pollfd
-    {
-        int     fd;
-        short   events;
-        short   revents;
-    }
-
-    alias uint nfds_t;
-
-    enum
-    {
-        POLLIN      = 0x001,
-        POLLPRI     = 0x002,
-        POLLOUT     = 0x004,
-        POLLERR     = 0x008,
-        POLLHUP     = 0x010,
-        POLLNVAL    = 0x020,
-        POLLRDNORM  = 0x040,
-        POLLRDBAND  = 0x080,
-        POLLWRNORM  = 0x100,
-        POLLWRBAND  = 0x200,
-    }
-
-    int poll(pollfd*, nfds_t, c_long);
-}
-else version (CRuntime_UClibc)
-{
-    struct pollfd
-    {
-        int     fd;
-        short   events;
-        short   revents;
-    }
-
-    alias c_ulong nfds_t;
-
-    enum
-    {
-        POLLIN      = 0x001,
-        POLLRDNORM  = 0x040,
-        POLLRDBAND  = 0x080,
-        POLLPRI     = 0x002,
-        POLLOUT     = 0x004,
-        POLLWRNORM  = 0x100,
-        POLLWRBAND  = 0x200,
-        POLLMSG     = 0x400,
-        POLLREMOVE  = 0x1000,
-        POLLRDHUP   = 0x2000,
-        POLLERR     = 0x008,
-        POLLHUP     = 0x010,
-        POLLNVAL    = 0x020,
-    }
-
-    int poll(pollfd*, nfds_t, int);
+    static assert(false, "Unsupported platform");
 }
diff --git a/libphobos/libdruntime/core/sys/posix/sched.d b/libphobos/libdruntime/core/sys/posix/sched.d
index f9d2862..35463d4 100644
--- a/libphobos/libdruntime/core/sys/posix/sched.d
+++ b/libphobos/libdruntime/core/sys/posix/sched.d
@@ -58,27 +58,33 @@
 int sched_setscheduler(pid_t, int, const scope sched_param*);
 */
 
-version (CRuntime_Glibc)
+version (linux)
 {
-    struct sched_param
+    version (CRuntime_Musl)
     {
-        int sched_priority;
+        struct sched_param
+        {
+            int sched_priority;
+            int __reserved1;
+            timespec[2] __reserved2;
+            int __reserved3;
+        }
+    }
+    else
+    {
+        struct sched_param
+        {
+            int sched_priority;
+        }
     }
 
     enum SCHED_OTHER    = 0;
     enum SCHED_FIFO     = 1;
     enum SCHED_RR       = 2;
     //SCHED_SPORADIC (SS|TSP)
-}
-else version (CRuntime_Musl)
-{
-    struct sched_param {
-        int sched_priority;
-        int sched_ss_low_priority;
-        timespec sched_ss_repl_period;
-        timespec sched_ss_init_budget;
-        int sched_ss_max_repl;
-    }
+    enum SCHED_BATCH    = 3;
+    enum SCHED_IDLE     = 5;
+    enum SCHED_RESET_ON_FORK = 0x40000000;
 }
 else version (Darwin)
 {
@@ -87,8 +93,6 @@
     enum SCHED_RR       = 2;
     //SCHED_SPORADIC (SS|TSP)
 
-    private enum __SCHED_PARAM_SIZE__ = 4;
-
     struct sched_param
     {
         int                             sched_priority;
@@ -156,33 +160,6 @@
     enum SCHED_FX = 6;
     enum _SCHED_NEXT = 7;
 }
-else version (CRuntime_Bionic)
-{
-    struct sched_param
-    {
-        int sched_priority;
-    }
-
-    enum SCHED_NORMAL   = 0;
-    enum SCHED_OTHER    = 0;
-    enum SCHED_FIFO     = 1;
-    enum SCHED_RR       = 2;
-}
-else version (CRuntime_UClibc)
-{
-    struct sched_param
-    {
-        int sched_priority;
-    }
-
-    enum SCHED_OTHER    = 0;
-    enum SCHED_FIFO     = 1;
-    enum SCHED_RR       = 2;
-    enum SCHED_BATCH    = 3;
-    enum SCHED_IDLE     = 5;
-
-    enum SCHED_RESET_ON_FORK    = 0x40000000;
-}
 else
 {
     static assert(false, "Unsupported platform");
diff --git a/libphobos/libdruntime/core/sys/posix/signal.d b/libphobos/libdruntime/core/sys/posix/signal.d
index 32e5156..68aee98 100644
--- a/libphobos/libdruntime/core/sys/posix/signal.d
+++ b/libphobos/libdruntime/core/sys/posix/signal.d
@@ -151,13 +151,15 @@
         return sig;
     }
 }
-else version (FreeBSD) {
+else version (FreeBSD)
+{
     // Note: it appears that FreeBSD (prior to 7) and OSX do not support realtime signals
     // https://github.com/freebsd/freebsd/blob/e79c62ff68fc74d88cb6f479859f6fae9baa5101/sys/sys/signal.h#L117
     enum SIGRTMIN = 65;
     enum SIGRTMAX = 126;
 }
-else version (DragonFlyBSD) {
+else version (DragonFlyBSD)
+{
     enum SIGRTMIN = 35;
     enum SIGRTMAX = 126;
 }
@@ -540,9 +542,54 @@
     static assert(false, "Unsupported platform");
 }
 
-version (CRuntime_Glibc)
+version (linux)
 {
-    version (SystemZ)
+    version (CRuntime_Musl)
+    {
+        struct sigaction_t
+        {
+            union
+            {
+                sigfn_t     sa_handler;
+                sigactfn_t  sa_sigaction;
+            }
+            sigset_t        sa_mask;
+            int             sa_flags;
+            void function() sa_restorer;
+        }
+    }
+    else version (CRuntime_Bionic)
+    {
+        version (D_LP64)
+        {
+            struct sigaction_t
+            {
+                int            sa_flags;
+                union
+                {
+                    sigfn_t    sa_handler;
+                    sigactfn_t sa_sigaction;
+                }
+                sigset_t        sa_mask;
+                void function() sa_restorer;
+        }
+        }
+        else
+        {
+            struct sigaction_t
+            {
+                union
+                {
+                    sigfn_t    sa_handler;
+                    sigactfn_t sa_sigaction;
+                }
+                sigset_t        sa_mask;
+                int             sa_flags;
+                void function() sa_restorer;
+            }
+        }
+    }
+    else version (SystemZ)
     {
         struct sigaction_t
         {
@@ -558,14 +605,110 @@
             {
                 sigfn_t     sa_handler;
             }
-            int             __glibc_reserved0;
-            int             sa_flags;
+            version (CRuntime_Glibc)
+            {
+                int         __glibc_reserved0;
+                int         sa_flags;
+            }
+            else
+            {
+                c_ulong     sa_flags;
+            }
 
             void function() sa_restorer;
 
             sigset_t        sa_mask;
         }
     }
+    else version (HPPA_Any)
+    {
+        struct sigaction_t
+        {
+            static if ( true /* __USE_POSIX199309 */ )
+            {
+                union
+                {
+                    sigfn_t     sa_handler;
+                    sigactfn_t  sa_sigaction;
+                }
+            }
+            else
+            {
+                sigfn_t     sa_handler;
+            }
+            version (CRuntime_Glibc)
+            {
+                version (D_LP64)
+                    int     __glibc_reserved0;
+                int         sa_flags;
+            }
+            else
+            {
+                c_ulong     sa_flags;
+            }
+            sigset_t        sa_mask;
+        }
+    }
+    else version (MIPS_Any)
+    {
+        struct sigaction_t
+        {
+            int sa_flags;
+
+            static if ( true /* __USE_POSIX199309 */ )
+            {
+                union
+                {
+                    sigfn_t     sa_handler;
+                    sigactfn_t  sa_sigaction;
+                }
+            }
+            else
+            {
+                sigfn_t     sa_handler;
+            }
+            sigset_t        sa_mask;
+            void function() sa_restorer;
+
+            version (CRuntime_Glibc)
+            {
+                static if ((void*).sizeof < 8)
+                    int[1]  sa_resv;
+            }
+        }
+    }
+    else version (SPARC_Any)
+    {
+        struct sigaction_t
+        {
+            static if ( true /* __USE_POSIX199309 */ )
+            {
+                union
+                {
+                    sigfn_t     sa_handler;
+                    sigactfn_t  sa_sigaction;
+                }
+            }
+            else
+            {
+                sigfn_t     sa_handler;
+            }
+            version (CRuntime_Glibc)
+            {
+                sigset_t    sa_mask;
+                version (D_LP64)
+                    int     __glibc_reserved0;
+                int         sa_flags;
+                void function() sa_restorer;
+            }
+            else
+            {
+                c_ulong     sa_flags;
+                void function() sa_restorer;
+                sigset_t    sa_mask;
+            }
+        }
+    }
     else
     {
         struct sigaction_t
@@ -589,28 +732,6 @@
         }
     }
 }
-else version (CRuntime_Musl)
-{
-    struct sigaction_t
-    {
-        static if ( true /* __USE_POSIX199309 */ )
-        {
-            union
-            {
-                sigfn_t     sa_handler;
-                sigactfn_t  sa_sigaction;
-            }
-        }
-        else
-        {
-            sigfn_t     sa_handler;
-        }
-        sigset_t        sa_mask;
-        int             sa_flags;
-
-        void function() sa_restorer;
-    }
-}
 else version (FreeBSD)
 {
     struct sigaction_t
@@ -683,91 +804,6 @@
             int[2] sa_resv;
     }
 }
-else version (CRuntime_UClibc)
-{
-    version (ARM)           version = sigaction_common;
-    else version (X86_64)   version = sigaction_common;
-
-    version (sigaction_common)
-    {
-        struct sigaction_t
-        {
-            static if ( true /* __USE_POSIX199309 */ )
-            {
-                union
-                {
-                    sigfn_t     sa_handler;
-                    sigactfn_t  sa_sigaction;
-                }
-            }
-            else
-            {
-                sigfn_t     sa_handler;
-            }
-            c_ulong     sa_flags;
-            void function() sa_restorer;
-            sigset_t    sa_mask;
-        }
-    }
-    else version (MIPS32)
-    {
-        struct sigaction_t
-        {
-            uint     sa_flags;
-            static if ( true /* __USE_POSIX199309 */ )
-            {
-                union
-                {
-                    sigfn_t     sa_handler;
-                    sigactfn_t  sa_sigaction;
-                }
-            }
-            else
-            {
-                sigfn_t     sa_handler;
-            }
-            sigset_t    sa_mask;
-            void function() sa_restorer;
-        }
-    }
-    else
-    {
-        static assert(false, "Architecture not supported.");
-    }
-}
-else version (CRuntime_Bionic)
-{
-    version (D_LP64)
-    {
-        struct sigaction_t
-        {
-            int            sa_flags;
-            union
-            {
-                sigfn_t    sa_handler;
-                sigactfn_t sa_sigaction;
-            }
-
-            sigset_t        sa_mask;
-            void function() sa_restorer;
-        }
-    }
-    else
-    {
-        struct sigaction_t
-        {
-            union
-            {
-                sigfn_t    sa_handler;
-                sigactfn_t sa_sigaction;
-            }
-
-            sigset_t        sa_mask;
-            int             sa_flags;
-            void function() sa_restorer;
-        }
-    }
-}
 else version (Darwin)
 {
     struct sigaction_t
@@ -839,26 +875,14 @@
 SI_TIMER
 SI_ASYNCIO
 SI_MESGQ
-
-int kill(pid_t, int);
-int sigaction(int, const scope sigaction_t*, sigaction_t*);
-int sigaddset(sigset_t*, int);
-int sigdelset(sigset_t*, int);
-int sigemptyset(sigset_t*);
-int sigfillset(sigset_t*);
-int sigismember(const scope sigset_t*, int);
-int sigpending(sigset_t*);
-int sigprocmask(int, const scope sigset_t*, sigset_t*);
-int sigsuspend(const scope sigset_t*);
-int sigwait(const scope sigset_t*, int*);
 */
 
 nothrow @nogc
 {
 
-version (CRuntime_Glibc)
+version (linux)
 {
-    enum SIG_HOLD = cast(sigfn_t2) 1;
+    enum SIG_HOLD = cast(sigfn_t2) 2;
 
     private enum _SIGSET_NWORDS = 1024 / (8 * c_ulong.sizeof);
 
@@ -867,20 +891,26 @@
         c_ulong[_SIGSET_NWORDS] __val;
     }
 
-    // pid_t  (defined in core.sys.types)
-
-    //SIGABRT (defined in core.stdc.signal)
-    //SIGFPE  (defined in core.stdc.signal)
-    //SIGILL  (defined in core.stdc.signal)
-    //SIGINT  (defined in core.stdc.signal)
-    //SIGSEGV (defined in core.stdc.signal)
-    //SIGTERM (defined in core.stdc.signal)
-
     enum SA_NOCLDSTOP   = 1; // (CX|XSI)
 
-    enum SIG_BLOCK      = 0;
-    enum SIG_UNBLOCK    = 1;
-    enum SIG_SETMASK    = 2;
+    version (MIPS_Any)
+    {
+        enum SIG_BLOCK      = 1;
+        enum SIG_UNBLOCK    = 2;
+        enum SIG_SETMASK    = 3;
+    }
+    else version (SPARC_Any)
+    {
+        enum SIG_BLOCK      = 1;
+        enum SIG_UNBLOCK    = 2;
+        enum SIG_SETMASK    = 4;
+    }
+    else
+    {
+        enum SIG_BLOCK      = 0;
+        enum SIG_UNBLOCK    = 1;
+        enum SIG_SETMASK    = 2;
+    }
 
     private enum __SI_MAX_SIZE = 128;
 
@@ -895,10 +925,17 @@
 
     struct siginfo_t
     {
-        int si_signo;       // Signal number
-        int si_errno;       // If non-zero, an errno value associated with
-                            // this signal, as defined in <errno.h>
-        int si_code;        // Signal code
+        int si_signo;
+        version (MIPS_Any)  // __SI_SWAP_ERRNO_CODE
+        {
+            int si_code;
+            int si_errno;
+        }
+        else
+        {
+            int si_errno;
+            int si_code;
+        }
 
         union _sifields_t
         {
@@ -907,32 +944,31 @@
             // kill()
             struct _kill_t
             {
-                pid_t si_pid; // Sending process ID
-                uid_t si_uid; // Real user ID of sending process
+                pid_t si_pid;
+                uid_t si_uid;
             } _kill_t _kill;
-
             // POSIX.1b timers.
             struct _timer_t
             {
-                int    si_tid;     // Timer ID
-                int    si_overrun; // Overrun count
-                sigval si_sigval;  // Signal value
+                int    si_tid;
+                int    si_overrun;
+                sigval si_sigval;
             } _timer_t _timer;
 
             // POSIX.1b signals
             struct _rt_t
             {
-                pid_t  si_pid;    // Sending process ID
-                uid_t  si_uid;    // Real user ID of sending process
-                sigval si_sigval; // Signal value
+                pid_t  si_pid;
+                uid_t  si_uid;
+                sigval si_sigval;
             } _rt_t _rt;
 
             // SIGCHLD
             struct _sigchild_t
             {
-                pid_t   si_pid;    // Which child
-                uid_t   si_uid;    // Real user ID of sending process
-                int     si_status; // Exit value or signal
+                pid_t   si_pid;
+                uid_t   si_uid;
+                int     si_status;
                 clock_t si_utime;
                 clock_t si_stime;
             } _sigchild_t _sigchld;
@@ -940,13 +976,13 @@
             // SIGILL, SIGFPE, SIGSEGV, SIGBUS
             struct _sigfault_t
             {
-                void*     si_addr;  // Faulting insn/memory ref
+                void*     si_addr;
             } _sigfault_t _sigfault;
 
             // SIGPOLL
             struct _sigpoll_t
             {
-                c_long   si_band;   // Band event for SIGPOLL
+                c_long   si_band;
                 int      si_fd;
             } _sigpoll_t _sigpoll;
         } _sifields_t _sifields;
@@ -972,32 +1008,12 @@
         SI_USER,
         SI_KERNEL  = 0x80
     }
-
-    int kill(pid_t, int);
-    int sigaction(int, const scope sigaction_t*, sigaction_t*);
-    int sigaddset(sigset_t*, int);
-    int sigdelset(sigset_t*, int);
-    int sigemptyset(sigset_t*);
-    int sigfillset(sigset_t*);
-    int sigismember(const scope sigset_t*, int);
-    int sigpending(sigset_t*);
-    int sigprocmask(int, const scope sigset_t*, sigset_t*);
-    int sigsuspend(const scope sigset_t*);
-    int sigwait(const scope sigset_t*, int*);
 }
 else version (Darwin)
 {
     enum SIG_HOLD = cast(sigfn_t2) 5;
 
     alias uint sigset_t;
-    // pid_t  (defined in core.sys.types)
-
-    //SIGABRT (defined in core.stdc.signal)
-    //SIGFPE  (defined in core.stdc.signal)
-    //SIGILL  (defined in core.stdc.signal)
-    //SIGINT  (defined in core.stdc.signal)
-    //SIGSEGV (defined in core.stdc.signal)
-    //SIGTERM (defined in core.stdc.signal)
 
     enum SA_NOCLDSTOP = 8; // (CX|XSI)
 
@@ -1024,18 +1040,6 @@
     enum SI_TIMER   = 0x10003;
     enum SI_ASYNCIO = 0x10004;
     enum SI_MESGQ   = 0x10005;
-
-    int kill(pid_t, int);
-    int sigaction(int, const scope sigaction_t*, sigaction_t*);
-    int sigaddset(sigset_t*, int);
-    int sigdelset(sigset_t*, int);
-    int sigemptyset(sigset_t*);
-    int sigfillset(sigset_t*);
-    int sigismember(const scope sigset_t*, int);
-    int sigpending(sigset_t*);
-    int sigprocmask(int, const scope sigset_t*, sigset_t*);
-    int sigsuspend(const scope sigset_t*);
-    int sigwait(const scope sigset_t*, int*);
 }
 else version (FreeBSD)
 {
@@ -1102,18 +1106,6 @@
     enum SI_TIMER   = 0x10003;
     enum SI_ASYNCIO = 0x10004;
     enum SI_MESGQ   = 0x10005;
-
-    int kill(pid_t, int);
-    int sigaction(int, const scope sigaction_t*, sigaction_t*);
-    int sigaddset(sigset_t*, int);
-    int sigdelset(sigset_t*, int);
-    int sigemptyset(sigset_t *);
-    int sigfillset(sigset_t *);
-    int sigismember(const scope sigset_t*, int);
-    int sigpending(sigset_t *);
-    int sigprocmask(int, const scope sigset_t*, sigset_t*);
-    int sigsuspend(const scope sigset_t*);
-    int sigwait(const scope sigset_t*, int*);
 }
 else version (NetBSD)
 {
@@ -1188,28 +1180,6 @@
     enum SI_TIMER   = -2;
     enum SI_ASYNCIO = -3;
     enum SI_MESGQ   = -4;
-
-    int kill(pid_t, int);
-    int __sigaction14(int, const scope sigaction_t*, sigaction_t*);
-    int __sigaddset14(sigset_t*, int);
-    int __sigdelset14(sigset_t*, int);
-    int __sigemptyset14(sigset_t *);
-    int __sigfillset14(sigset_t *);
-    int __sigismember14(const scope sigset_t*, int);
-    int __sigpending14(sigset_t *);
-    int __sigprocmask14(int, const scope sigset_t*, sigset_t*);
-    int __sigsuspend14(const scope sigset_t*);
-    int sigwait(const scope sigset_t*, int*);
-
-    alias __sigaction14 sigaction;
-    alias __sigaddset14 sigaddset;
-    alias __sigdelset14 sigdelset;
-    alias __sigemptyset14 sigemptyset;
-    alias __sigfillset14 sigfillset;
-    alias __sigismember14 sigismember;
-    alias __sigpending14 sigpending;
-    alias __sigprocmask14 sigprocmask;
-    alias __sigsuspend14 sigsuspend;
 }
 else version (OpenBSD)
 {
@@ -1274,18 +1244,6 @@
     enum SI_LWP    = -1;
     enum SI_QUEUE  = -2;
     enum SI_TIMER  = -3;
-
-    int kill(pid_t, int);
-    int sigaction(int, const scope sigaction_t*, sigaction_t*);
-    int sigaddset(sigset_t*, int);
-    int sigdelset(sigset_t*, int);
-    int sigemptyset(sigset_t *);
-    int sigfillset(sigset_t *);
-    int sigismember(const scope sigset_t*, int);
-    int sigpending(sigset_t *);
-    int sigprocmask(int, const scope sigset_t*, sigset_t*);
-    int sigsuspend(const scope sigset_t*);
-    int sigwait(const scope sigset_t*, int*);
 }
 else version (DragonFlyBSD)
 {
@@ -1323,18 +1281,6 @@
     enum SI_TIMER     = -2;
     enum SI_ASYNCIO   = -3;
     enum SI_MESGQ     = -4;
-
-    int kill(pid_t, int);
-    int sigaction(int, const scope sigaction_t*, sigaction_t*);
-    int sigaddset(sigset_t*, int);
-    int sigdelset(sigset_t*, int);
-    int sigemptyset(sigset_t *);
-    int sigfillset(sigset_t *);
-    int sigismember(const scope sigset_t*, int);
-    int sigpending(sigset_t *);
-    int sigprocmask(int, const scope sigset_t*, sigset_t*);
-    int sigsuspend(const scope sigset_t*);
-    int sigwait(const scope sigset_t*, int*);
 }
 else version (Solaris)
 {
@@ -1446,9 +1392,122 @@
     enum SI_TIMER   = -3;
     enum SI_ASYNCIO = -4;
     enum SI_MESGQ   = -5;
+}
+else
+{
+    static assert(false, "Unsupported platform");
+}
 
-    enum SIGIO = SIGPOLL;
+/*
+int kill(pid_t, int);
+int sigaction(int, const scope sigaction_t*, sigaction_t*);
+int sigaddset(sigset_t*, int);
+int sigdelset(sigset_t*, int);
+int sigemptyset(sigset_t*);
+int sigfillset(sigset_t*);
+int sigismember(const scope sigset_t*, int);
+int sigpending(sigset_t*);
+int sigprocmask(int, const scope sigset_t*, sigset_t*);
+int sigsuspend(const scope sigset_t*);
+int sigwait(const scope sigset_t*, int*);
+*/
 
+version (CRuntime_Glibc)
+{
+    int kill(pid_t, int);
+    int sigaction(int, const scope sigaction_t*, sigaction_t*);
+    int sigaddset(sigset_t*, int);
+    int sigdelset(sigset_t*, int);
+    int sigemptyset(sigset_t*);
+    int sigfillset(sigset_t*);
+    int sigismember(const scope sigset_t*, int);
+    int sigpending(sigset_t*);
+    int sigprocmask(int, const scope sigset_t*, sigset_t*);
+    int sigsuspend(const scope sigset_t*);
+    int sigwait(const scope sigset_t*, int*);
+}
+else version (Darwin)
+{
+    int kill(pid_t, int);
+    int sigaction(int, const scope sigaction_t*, sigaction_t*);
+    int sigaddset(sigset_t*, int);
+    int sigdelset(sigset_t*, int);
+    int sigemptyset(sigset_t*);
+    int sigfillset(sigset_t*);
+    int sigismember(const scope sigset_t*, int);
+    int sigpending(sigset_t*);
+    int sigprocmask(int, const scope sigset_t*, sigset_t*);
+    int sigsuspend(const scope sigset_t*);
+    int sigwait(const scope sigset_t*, int*);
+}
+else version (FreeBSD)
+{
+    int kill(pid_t, int);
+    int sigaction(int, const scope sigaction_t*, sigaction_t*);
+    int sigaddset(sigset_t*, int);
+    int sigdelset(sigset_t*, int);
+    int sigemptyset(sigset_t *);
+    int sigfillset(sigset_t *);
+    int sigismember(const scope sigset_t*, int);
+    int sigpending(sigset_t *);
+    int sigprocmask(int, const scope sigset_t*, sigset_t*);
+    int sigsuspend(const scope sigset_t*);
+    int sigwait(const scope sigset_t*, int*);
+}
+else version (NetBSD)
+{
+    int kill(pid_t, int);
+    int __sigaction14(int, const scope sigaction_t*, sigaction_t*);
+    int __sigaddset14(sigset_t*, int);
+    int __sigdelset14(sigset_t*, int);
+    int __sigemptyset14(sigset_t *);
+    int __sigfillset14(sigset_t *);
+    int __sigismember14(const scope sigset_t*, int);
+    int __sigpending14(sigset_t *);
+    int __sigprocmask14(int, const scope sigset_t*, sigset_t*);
+    int __sigsuspend14(const scope sigset_t*);
+    int sigwait(const scope sigset_t*, int*);
+
+    alias __sigaction14 sigaction;
+    alias __sigaddset14 sigaddset;
+    alias __sigdelset14 sigdelset;
+    alias __sigemptyset14 sigemptyset;
+    alias __sigfillset14 sigfillset;
+    alias __sigismember14 sigismember;
+    alias __sigpending14 sigpending;
+    alias __sigprocmask14 sigprocmask;
+    alias __sigsuspend14 sigsuspend;
+}
+else version (OpenBSD)
+{
+    int kill(pid_t, int);
+    int sigaction(int, const scope sigaction_t*, sigaction_t*);
+    int sigaddset(sigset_t*, int);
+    int sigdelset(sigset_t*, int);
+    int sigemptyset(sigset_t *);
+    int sigfillset(sigset_t *);
+    int sigismember(const scope sigset_t*, int);
+    int sigpending(sigset_t *);
+    int sigprocmask(int, const scope sigset_t*, sigset_t*);
+    int sigsuspend(const scope sigset_t*);
+    int sigwait(const scope sigset_t*, int*);
+}
+else version (DragonFlyBSD)
+{
+    int kill(pid_t, int);
+    int sigaction(int, const scope sigaction_t*, sigaction_t*);
+    int sigaddset(sigset_t*, int);
+    int sigdelset(sigset_t*, int);
+    int sigemptyset(sigset_t *);
+    int sigfillset(sigset_t *);
+    int sigismember(const scope sigset_t*, int);
+    int sigpending(sigset_t *);
+    int sigprocmask(int, const scope sigset_t*, sigset_t*);
+    int sigsuspend(const scope sigset_t*);
+    int sigwait(const scope sigset_t*, int*);
+}
+else version (Solaris)
+{
     int kill(pid_t, int);
     int sigaction(int, const scope sigaction_t*, sigaction_t*);
     int sigaddset(sigset_t*, int);
@@ -1467,101 +1526,15 @@
     import core.stdc.string : memset;
 
     version (X86)
-    {
-        alias uint sigset_t;
         enum int LONG_BIT = 32;
-    }
     else version (ARM)
-    {
-        alias uint sigset_t;
         enum int LONG_BIT = 32;
-    }
     else version (AArch64)
-    {
-        struct sigset_t { ulong[1] sig; }
         enum int LONG_BIT = 64;
-    }
     else version (X86_64)
-    {
-        alias ulong sigset_t;
         enum int LONG_BIT = 64;
-    }
     else
-    {
         static assert(false, "Architecture not supported.");
-    }
-
-    enum SIG_BLOCK   = 0;
-    enum SIG_UNBLOCK = 1;
-    enum SIG_SETMASK = 2;
-
-    private enum SI_MAX_SIZE = 128;
-    private enum SI_PAD_SIZE = ((SI_MAX_SIZE / int.sizeof) - 3);
-
-    struct siginfo_t
-    {
-        int si_signo;
-        int si_errno;
-        int si_code;
-
-        union _sifields_t
-        {
-            int[SI_PAD_SIZE] _pad;
-
-            struct _kill_t
-            {
-                pid_t _pid;
-                uid_t _uid;
-            } _kill_t _kill;
-
-            struct _timer_t
-            {
-                timer_t _tid;
-                int     _overrun;
-                sigval  _sigval;
-                int     _sys_private;
-            } _timer_t _timer;
-
-            struct _rt_t
-            {
-                pid_t  _pid;
-                uid_t  _uid;
-                sigval _sigval;
-            } _rt_t _rt;
-
-            struct _sigchild_t
-            {
-                pid_t   _pid;
-                uid_t   _uid;
-                int     _status;
-                clock_t _utime;
-                clock_t _stime;
-            } _sigchild_t _sigchld;
-
-            struct _sigfault_t
-            {
-                void*   _addr;
-            } _sigfault_t _sigfault;
-
-            struct _sigpoll_t
-            {
-                c_long _band;
-                int    _fd;
-            } _sigpoll_t _sigpoll;
-        } _sifields_t _sifields;
-    }
-
-    enum
-    {
-        SI_TKILL   = -6,
-        SI_SIGIO,
-        SI_ASYNCIO,
-        SI_MESGQ,
-        SI_TIMER,
-        SI_QUEUE,
-        SI_USER,
-        SI_KERNEL  = 0x80
-    }
 
     int kill(pid_t, int);
     int sigaction(int, const scope sigaction_t*, sigaction_t*);
@@ -1601,111 +1574,6 @@
 }
 else version (CRuntime_Musl)
 {
-    struct sigset_t
-    {
-        c_ulong[128/c_long.sizeof] __bits;
-    }
-
-    version (MIPS_Any)
-    {
-        enum SIG_BLOCK      = 1;
-        enum SIG_UNBLOCK    = 2;
-        enum SIG_SETMASK    = 3;
-    }
-    else
-    {
-        enum SIG_BLOCK      = 0;
-        enum SIG_UNBLOCK    = 1;
-        enum SIG_SETMASK    = 2;
-    }
-
-    struct siginfo_t
-    {
-        int si_signo;
-        version (MIPS_Any)  // __SI_SWAP_ERRNO_CODE
-        {
-            int si_code;
-            int si_errno;
-        }
-        else
-        {
-            int si_errno;
-            int si_code;
-        }
-        union __si_fields_t
-        {
-            char[128 - 2*int.sizeof - c_long.sizeof] __pad = 0;
-            struct __si_common_t
-            {
-                union __first_t
-                {
-                    struct __piduid_t
-                    {
-                        pid_t si_pid;
-                        uid_t si_uid;
-                    }
-                    __piduid_t __piduid;
-
-                    struct __timer_t
-                    {
-                        int si_timerid;
-                        int si_overrun;
-                    }
-                    __timer_t __timer;
-                }
-                __first_t __first;
-
-                union __second_t
-                {
-                    sigval si_value;
-                    struct __sigchld_t
-                    {
-                        int si_status;
-                        clock_t si_utime;
-                        clock_t si_stime;
-                    }
-                    __sigchld_t __sigchld;
-                }
-                __second_t __second;
-            }
-            __si_common_t __si_common;
-
-            struct __sigfault_t
-            {
-                void *si_addr;
-                short si_addr_lsb;
-                union __first_t
-                {
-                    struct __addr_bnd_t
-                    {
-                        void *si_lower;
-                        void *si_upper;
-                    }
-                    __addr_bnd_t __addr_bnd;
-                    uint si_pkey;
-                }
-                __first_t __first;
-            }
-            __sigfault_t __sigfault;
-
-            struct __sigpoll_t
-            {
-                c_long si_band;
-                int si_fd;
-            }
-            __sigpoll_t __sigpoll;
-
-            struct __sigsys_t
-            {
-                void *si_call_addr;
-                int si_syscall;
-                uint si_arch;
-            }
-            __sigsys_t __sigsys;
-        }
-        __si_fields_t __si_fields;
-    }
-
     int kill(pid_t, int);
     int sigaction(int, const scope sigaction_t*, sigaction_t*);
     int sigaddset(sigset_t*, int);
@@ -1720,235 +1588,6 @@
 }
 else version (CRuntime_UClibc)
 {
-    enum SIG_HOLD = cast(sigfn_t2) 2;
-
-    version (MIPS32)
-        private enum _SIGSET_NWORDS = 128 / (8 * c_ulong.sizeof);
-    else
-        private enum _SIGSET_NWORDS = 64 / (8 * c_ulong.sizeof);
-
-    struct sigset_t
-    {
-        c_ulong[_SIGSET_NWORDS] __val;
-    }
-
-    enum SA_NOCLDSTOP   = 1;
-
-    enum SIG_BLOCK      = 0;
-    enum SIG_UNBLOCK    = 1;
-    enum SIG_SETMASK    = 2;
-
-    private enum __SI_MAX_SIZE = 128;
-
-    static if ( __WORDSIZE == 64 )
-    {
-        private enum __SI_PAD_SIZE = ((__SI_MAX_SIZE / int.sizeof) - 4);
-    }
-    else
-    {
-        private enum __SI_PAD_SIZE = ((__SI_MAX_SIZE / int.sizeof) - 3);
-    }
-
-    version (ARM)           version = siginfo_common;
-    else version (X86_64)   version = siginfo_common;
-
-    version (siginfo_common)
-    {
-        struct siginfo_t
-        {
-            int si_signo;       // Signal number
-            int si_errno;       // If non-zero, an errno value associated with
-                                // this signal, as defined in <errno.h>
-            int si_code;        // Signal code
-
-            union _sifields_t
-            {
-                int[__SI_PAD_SIZE] _pad;
-
-                // kill()
-                struct _kill_t
-                {
-                    pid_t si_pid; // Sending process ID
-                    uid_t si_uid; // Real user ID of sending process
-                } _kill_t _kill;
-
-                // POSIX.1b timers.
-                struct _timer_t
-                {
-                    int    si_tid;     // Timer ID
-                    int    si_overrun; // Overrun count
-                    sigval si_sigval;  // Signal value
-                } _timer_t _timer;
-
-                // POSIX.1b signals
-                struct _rt_t
-                {
-                    pid_t  si_pid;    // Sending process ID
-                    uid_t  si_uid;    // Real user ID of sending process
-                    sigval si_sigval; // Signal value
-                } _rt_t _rt;
-
-                // SIGCHLD
-                struct _sigchild_t
-                {
-                    pid_t   si_pid;    // Which child
-                    uid_t   si_uid;    // Real user ID of sending process
-                    int     si_status; // Exit value or signal
-                    clock_t si_utime;
-                    clock_t si_stime;
-                } _sigchild_t _sigchld;
-
-                // SIGILL, SIGFPE, SIGSEGV, SIGBUS
-                struct _sigfault_t
-                {
-                    void*     si_addr;  // Faulting insn/memory ref
-                } _sigfault_t _sigfault;
-
-                // SIGPOLL
-                struct _sigpoll_t
-                {
-                    c_long si_band; // Band event for SIGPOLL;
-                    int      si_fd;
-                } _sigpoll_t _sigpoll;
-
-                // SIGSYS
-                struct _sigsys_t
-                {
-                    void*   _call_addr;   // Calling user insn.
-                    int     _syscall;     // Triggering system call number.
-                    uint    _arch;        // AUDIT_ARCH_* of syscall.
-                } _sigsys_t _sigsys;
-
-            } _sifields_t _sifields;
-
-        nothrow @nogc:
-            @property ref pid_t si_pid()() { return _sifields._kill.si_pid; }
-            @property ref uid_t si_uid()() { return _sifields._kill.si_uid; }
-            @property ref int si_timerid()() { return _sifields._timer.si_tid;}
-            @property ref int si_overrun()() { return _sifields._timer.si_overrun; }
-            @property ref int si_status()() { return _sifields._sigchld.si_status; }
-            @property ref clock_t si_utime()() { return _sifields._sigchld.si_utime; }
-            @property ref clock_t si_stime()() { return _sifields._sigchld.si_stime; }
-            @property ref sigval si_value()() { return _sifields._rt.si_sigval; }
-            @property ref int si_int()() { return _sifields._rt.si_sigval.sival_int; }
-            @property ref void* si_ptr()() { return _sifields._rt.si_sigval.sival_ptr; }
-            @property ref void* si_addr()() { return _sifields._sigfault.si_addr; }
-            @property ref c_long si_band()() { return _sifields._sigpoll.si_band; }
-            @property ref int  si_fd()() { return _sifields._sigpoll.si_fd; }
-            @property ref void*  si_call_addr()() { return _sifields._sigsys._call_addr; }
-            @property ref int  si_syscall()() { return _sifields._sigsys._syscall; }
-            @property ref uint  si_arch()() { return _sifields._sigsys._arch; }
-        }
-    }
-    else version (MIPS32)
-    {
-        struct siginfo_t
-        {
-            int si_signo;       // Signal number
-            int si_errno;       // If non-zero, an errno value associated with
-                                // this signal, as defined in <errno.h>
-            int si_code;        // Signal code
-
-            int[__SI_MAX_SIZE / int.sizeof - __SI_PAD_SIZE - 3] __pad0;
-
-            union _sifields_t
-            {
-                int[__SI_PAD_SIZE] _pad;
-
-                // kill()
-                struct _kill_t
-                {
-                    pid_t si_pid; // Sending process ID
-                    uid_t si_uid; // Real user ID of sending process
-                } _kill_t _kill;
-
-                // POSIX.1b timers.
-                struct _timer_t
-                {
-                    int    si_tid;     // Timer ID
-                    int    si_overrun; // Overrun count
-                    sigval si_sigval;  // Signal value
-                } _timer_t _timer;
-
-                // POSIX.1b signals
-                struct _rt_t
-                {
-                    pid_t  si_pid;    // Sending process ID
-                    uid_t  si_uid;    // Real user ID of sending process
-                    sigval si_sigval; // Signal value
-                } _rt_t _rt;
-
-                // SIGCHLD
-                struct _sigchild_t
-                {
-                    pid_t   si_pid;    // Which child
-                    uid_t   si_uid;    // Real user ID of sending process
-                    int     si_status; // Exit value or signal
-                    clock_t si_utime;
-                    clock_t si_stime;
-                } _sigchild_t _sigchld;
-
-                // SIGILL, SIGFPE, SIGSEGV, SIGBUS
-                struct _sigfault_t
-                {
-                    void*   si_addr;  // Faulting insn/memory ref
-                    short   si_addr_lsb;
-                } _sigfault_t _sigfault;
-
-                // SIGPOLL
-                struct _sigpoll_t
-                {
-                    c_long si_band; // Band event for SIGPOLL;
-                    int      si_fd;
-                } _sigpoll_t _sigpoll;
-
-                // SIGSYS
-                struct _sigsys_t
-                {
-                    void*   _call_addr;   // Calling user insn.
-                    int     _syscall;     // Triggering system call number.
-                    uint    _arch;        // AUDIT_ARCH_* of syscall.
-                } _sigsys_t _sigsys;
-
-            } _sifields_t _sifields;
-
-        nothrow @nogc:
-            @property ref pid_t si_pid()() { return _sifields._kill.si_pid; }
-            @property ref uid_t si_uid()() { return _sifields._kill.si_uid; }
-            @property ref int si_timerid()() { return _sifields._timer.si_tid;}
-            @property ref int si_overrun()() { return _sifields._timer.si_overrun; }
-            @property ref int si_status()() { return _sifields._sigchld.si_status; }
-            @property ref clock_t si_utime()() { return _sifields._sigchld.si_utime; }
-            @property ref clock_t si_stime()() { return _sifields._sigchld.si_stime; }
-            @property ref sigval si_value()() { return _sifields._rt.si_sigval; }
-            @property ref int si_int()() { return _sifields._rt.si_sigval.sival_int; }
-            @property ref void* si_ptr()() { return _sifields._rt.si_sigval.sival_ptr; }
-            @property ref void* si_addr()() { return _sifields._sigfault.si_addr; }
-            @property ref c_long si_band()() { return _sifields._sigpoll.si_band; }
-            @property ref int  si_fd()() { return _sifields._sigpoll.si_fd; }
-            @property ref void*  si_call_addr()() { return _sifields._sigsys._call_addr; }
-            @property ref int  si_syscall()() { return _sifields._sigsys._syscall; }
-            @property ref uint  si_arch()() { return _sifields._sigsys._arch; }
-        }
-    }
-    else
-    {
-        static assert(false, "Architecture not supported.");
-    }
-
-    enum
-    {
-        SI_ASYNCNL = -60,
-        SI_TKILL   = -6,
-        SI_SIGIO,
-        SI_ASYNCIO,
-        SI_MESGQ,
-        SI_TIMER,
-        SI_QUEUE,
-        SI_USER,
-        SI_KERNEL  = 0x80
-    }
-
     int kill(pid_t, int);
     int sigaction(int, const scope sigaction_t*, sigaction_t*);
     int sigaddset(sigset_t*, int);
@@ -1985,26 +1624,6 @@
 SA_SIGINFO
 SA_NOCLDWAIT
 SA_NODEFER
-SS_ONSTACK
-SS_DISABLE
-MINSIGSTKSZ
-SIGSTKSZ
-
-ucontext_t // from ucontext
-mcontext_t // from ucontext
-
-struct stack_t
-{
-    void*   ss_sp;
-    size_t  ss_size;
-    int     ss_flags;
-}
-
-struct sigstack
-{
-    int   ss_onstack;
-    void* ss_sp;
-}
 
 ILL_ILLOPC
 ILL_ILLOPN
@@ -2047,20 +1666,9 @@
 POLL_ERR
 POLL_PRI
 POLL_HUP
-
-sigfn_t bsd_signal(int sig, sigfn_t func);
-sigfn_t sigset(int sig, sigfn_t func);
-
-int killpg(pid_t, int);
-int sigaltstack(const scope stack_t*, stack_t*);
-int sighold(int);
-int sigignore(int);
-int siginterrupt(int, int);
-int sigpause(int);
-int sigrelse(int);
 */
 
-version (CRuntime_Glibc)
+version (linux)
 {
     version (X86_Any)
     {
@@ -2145,32 +1753,28 @@
     else
         static assert(0, "unimplemented");
 
-    enum SA_ONSTACK     = 0x08000000;
-    enum SA_RESETHAND   = 0x80000000;
-    enum SA_RESTART     = 0x10000000;
-    enum SA_SIGINFO     = 4;
-    enum SA_NOCLDWAIT   = 2;
-    enum SA_NODEFER     = 0x40000000;
-    enum SS_ONSTACK     = 1;
-    enum SS_DISABLE     = 2;
-    enum MINSIGSTKSZ    = 2048;
-    enum SIGSTKSZ       = 8192;
-
-    //ucontext_t (defined in core.sys.posix.ucontext)
-    //mcontext_t (defined in core.sys.posix.ucontext)
-
-    struct stack_t
+    version (MIPS_Any)
     {
-        void*   ss_sp;
-        int     ss_flags;
-        size_t  ss_size;
+        enum SA_ONSTACK   = 0x08000000;
+        enum SA_RESETHAND = 0x80000000;
+        enum SA_RESTART   = 0x10000000;
+        enum SA_SIGINFO   = 8;
+        enum SA_NOCLDWAIT = 0x10000;
+        enum SA_NODEFER   = 0x40000000;
+    }
+    else
+    {
+        enum SA_ONSTACK   = 0x08000000;
+        enum SA_RESETHAND = 0x80000000;
+        enum SA_RESTART   = 0x10000000;
+        enum SA_SIGINFO   = 4;
+        enum SA_NOCLDWAIT = 2;
+        enum SA_NODEFER   = 0x40000000;
     }
 
-    struct sigstack
-    {
-        void*   ss_sp;
-        int     ss_onstack;
-    }
+    enum SA_NOMASK      = SA_NODEFER;
+    enum SA_ONESHOT     = SA_RESETHAND;
+    enum SA_STACK       = SA_ONSTACK;
 
     enum
     {
@@ -2234,22 +1838,6 @@
         POLL_PRI,
         POLL_HUP
     }
-
-    sigfn_t bsd_signal(int sig, sigfn_t func);
-    sigfn_t sigset(int sig, sigfn_t func);
-
-  nothrow:
-  @nogc:
-    sigfn_t2 bsd_signal(int sig, sigfn_t2 func);
-    sigfn_t2 sigset(int sig, sigfn_t2 func);
-
-    int killpg(pid_t, int);
-    int sigaltstack(const scope stack_t*, stack_t*);
-    int sighold(int);
-    int sigignore(int);
-    int siginterrupt(int, int);
-    int sigpause(int);
-    int sigrelse(int);
 }
 else version (Darwin)
 {
@@ -2267,26 +1855,6 @@
     enum SA_SIGINFO     = 0x0040;
     enum SA_NOCLDWAIT   = 0x0020;
     enum SA_NODEFER     = 0x0010;
-    enum SS_ONSTACK     = 0x0001;
-    enum SS_DISABLE     = 0x0004;
-    enum MINSIGSTKSZ    = 32768;
-    enum SIGSTKSZ       = 131072;
-
-    //ucontext_t (defined in core.sys.posix.ucontext)
-    //mcontext_t (defined in core.sys.posix.ucontext)
-
-    struct stack_t
-    {
-        void*   ss_sp;
-        size_t  ss_size;
-        int     ss_flags;
-    }
-
-    struct sigstack
-    {
-        void*   ss_sp;
-        int     ss_onstack;
-    }
 
     enum ILL_ILLOPC = 1;
     enum ILL_ILLOPN = 4;
@@ -2344,22 +1912,6 @@
         POLL_PRI,
         POLL_HUP
     }
-
-    sigfn_t bsd_signal(int sig, sigfn_t func);
-    sigfn_t sigset(int sig, sigfn_t func);
-
-  nothrow:
-  @nogc:
-    sigfn_t2 bsd_signal(int sig, sigfn_t2 func);
-    sigfn_t2 sigset(int sig, sigfn_t2 func);
-
-    int killpg(pid_t, int);
-    int sigaltstack(const scope stack_t*, stack_t*);
-    int sighold(int);
-    int sigignore(int);
-    int siginterrupt(int, int);
-    int sigpause(int);
-    int sigrelse(int);
 }
 else version (FreeBSD)
 {
@@ -2383,31 +1935,6 @@
 
     enum
     {
-        SS_ONSTACK = 0x0001,
-        SS_DISABLE = 0x0004,
-    }
-
-    enum MINSIGSTKSZ = 512 * 4;
-    enum SIGSTKSZ    = (MINSIGSTKSZ + 32768);
-
-    //ucontext_t (defined in core.sys.posix.ucontext)
-    //mcontext_t (defined in core.sys.posix.ucontext)
-
-    struct stack_t
-    {
-        void*   ss_sp;
-        size_t  ss_size;
-        int     ss_flags;
-    }
-
-    struct sigstack
-    {
-        void*   ss_sp;
-        int     ss_onstack;
-    }
-
-    enum
-    {
         ILL_ILLOPC = 1,
         ILL_ILLOPN,
         ILL_ILLADR,
@@ -2468,22 +1995,6 @@
         POLL_PRI,
         POLL_HUP,
     }
-
-    //sigfn_t bsd_signal(int sig, sigfn_t func);
-    sigfn_t sigset(int sig, sigfn_t func);
-
-  nothrow:
-  @nogc:
-    //sigfn_t2 bsd_signal(int sig, sigfn_t2 func);
-    sigfn_t2 sigset(int sig, sigfn_t2 func);
-
-    int killpg(pid_t, int);
-    int sigaltstack(const scope stack_t*, stack_t*);
-    int sighold(int);
-    int sigignore(int);
-    int siginterrupt(int, int);
-    int sigpause(int);
-    int sigrelse(int);
 }
 else version (NetBSD)
 {
@@ -2507,31 +2018,6 @@
 
     enum
     {
-        SS_ONSTACK = 0x0001,
-        SS_DISABLE = 0x0004,
-    }
-
-    enum MINSIGSTKSZ = 8192;
-    enum SIGSTKSZ    = (MINSIGSTKSZ + 32768);
-
-    //ucontext_t (defined in core.sys.posix.ucontext)
-    //mcontext_t (defined in core.sys.posix.ucontext)
-
-    struct stack_t
-    {
-        void*   ss_sp;
-        size_t  ss_size;
-        int     ss_flags;
-    }
-
-    struct sigstack
-    {
-        void*   ss_sp;
-        int     ss_onstack;
-    }
-
-    enum
-    {
         ILL_ILLOPC = 1,
         ILL_ILLOPN,
         ILL_ILLADR,
@@ -2592,22 +2078,6 @@
         POLL_PRI,
         POLL_HUP,
     }
-
-    //sigfn_t bsd_signal(int sig, sigfn_t func);
-    sigfn_t sigset(int sig, sigfn_t func);
-
-  nothrow:
-  @nogc:
-    //sigfn_t2 bsd_signal(int sig, sigfn_t2 func);
-    sigfn_t2 sigset(int sig, sigfn_t2 func);
-
-    int killpg(pid_t, int);
-    int sigaltstack(const scope stack_t*, stack_t*);
-    int sighold(int);
-    int sigignore(int);
-    int siginterrupt(int, int);
-    int sigpause(int);
-    int sigrelse(int);
 }
 else version (OpenBSD)
 {
@@ -2631,25 +2101,6 @@
 
     enum
     {
-        SS_ONSTACK = 0x0001,
-        SS_DISABLE = 0x0004,
-    }
-
-    enum MINSIGSTKSZ = 8192;
-    enum SIGSTKSZ    = (MINSIGSTKSZ + 32768);
-
-    //ucontext_t (defined in core.sys.posix.ucontext)
-    //mcontext_t (defined in core.sys.posix.ucontext)
-
-    struct stack_t
-    {
-        void*   ss_sp;
-        size_t  ss_size;
-        int     ss_flags;
-    }
-
-    enum
-    {
         ILL_ILLOPC = 1,
         ILL_ILLOPN,
         ILL_ILLADR,
@@ -2717,13 +2168,6 @@
         POLL_HUP,
         NSIGPOLL = POLL_HUP,
     }
-
-  nothrow:
-  @nogc:
-    int killpg(pid_t, int);
-    int sigaltstack(const scope stack_t*, stack_t*);
-    int siginterrupt(int, int);
-    int sigpause(int);
 }
 else version (DragonFlyBSD)
 {
@@ -2747,31 +2191,6 @@
 
     enum
     {
-        SS_ONSTACK = 0x0001,
-        SS_DISABLE = 0x0004,
-    }
-
-    enum MINSIGSTKSZ = 8192;
-    enum SIGSTKSZ    = (MINSIGSTKSZ + 32768);
-
-    //ucontext_t (defined in core.sys.posix.ucontext)
-    //mcontext_t (defined in core.sys.posix.ucontext)
-
-    struct stack_t
-    {
-        void*   ss_sp;
-        size_t  ss_size;
-        int     ss_flags;
-    }
-
-    struct sigstack
-    {
-        void*   ss_sp;
-        int     ss_onstack;
-    }
-
-    enum
-    {
         ILL_ILLOPC = 1,
         ILL_ILLOPN,
         ILL_ILLADR,
@@ -2832,26 +2251,11 @@
         POLL_PRI,
         POLL_HUP,
     }
-
-    //sigfn_t bsd_signal(int sig, sigfn_t func);
-    sigfn_t sigset(int sig, sigfn_t func);
-
-  nothrow:
-  @nogc:
-    //sigfn_t2 bsd_signal(int sig, sigfn_t2 func);
-    sigfn_t2 sigset(int sig, sigfn_t2 func);
-
-    int killpg(pid_t, int);
-    int sigaltstack(const scope stack_t*, stack_t*);
-    int sighold(int);
-    int sigignore(int);
-    int siginterrupt(int, int);
-    int sigpause(int);
-    int sigrelse(int);
 }
 else version (Solaris)
 {
     enum SIGPOLL = 22;
+    enum SIGIO = SIGPOLL;
     enum SIGPROF = 29;
     enum SIGSYS = 12;
     enum SIGTRAP = 5;
@@ -2871,28 +2275,6 @@
 
     enum
     {
-        SS_ONSTACK = 0x0001,
-        SS_DISABLE = 0x0002,
-    }
-
-    enum MINSIGSTKSZ = 2048;
-    enum SIGSTKSZ = 8192;
-
-    struct stack_t
-    {
-        void* ss_sp;
-        size_t ss_size;
-        int ss_flags;
-    }
-
-    struct sigstack
-    {
-        void* ss_sp;
-        int ss_onstack;
-    }
-
-    enum
-    {
         ILL_ILLOPC = 1,
         ILL_ILLOPN,
         ILL_ILLADR,
@@ -2958,6 +2340,304 @@
         POLL_PRI,
         POLL_HUP,
     }
+}
+else
+{
+    static assert(false, "Unsupported platform");
+}
+
+/*
+SS_ONSTACK
+SS_DISABLE
+MINSIGSTKSZ
+SIGSTKSZ
+
+ucontext_t // from ucontext
+mcontext_t // from ucontext
+
+struct stack_t
+{
+    void*   ss_sp;
+    size_t  ss_size;
+    int     ss_flags;
+}
+
+struct sigstack
+{
+    int   ss_onstack;
+    void* ss_sp;
+}
+
+sigfn_t bsd_signal(int sig, sigfn_t func);
+sigfn_t sigset(int sig, sigfn_t func);
+
+int killpg(pid_t, int);
+int sigaltstack(const scope stack_t*, stack_t*);
+int sighold(int);
+int sigignore(int);
+int siginterrupt(int, int);
+int sigpause(int);
+int sigrelse(int);
+*/
+
+version (CRuntime_Glibc)
+{
+    enum SS_ONSTACK     = 1;
+    enum SS_DISABLE     = 2;
+    enum MINSIGSTKSZ    = 2048;
+    enum SIGSTKSZ       = 8192;
+
+    //ucontext_t (defined in core.sys.posix.ucontext)
+    //mcontext_t (defined in core.sys.posix.ucontext)
+
+    struct stack_t
+    {
+        void*   ss_sp;
+        int     ss_flags;
+        size_t  ss_size;
+    }
+
+    struct sigstack
+    {
+        void*   ss_sp;
+        int     ss_onstack;
+    }
+
+    sigfn_t bsd_signal(int sig, sigfn_t func);
+    sigfn_t sigset(int sig, sigfn_t func);
+
+  nothrow:
+  @nogc:
+    sigfn_t2 bsd_signal(int sig, sigfn_t2 func);
+    sigfn_t2 sigset(int sig, sigfn_t2 func);
+
+    int killpg(pid_t, int);
+    int sigaltstack(const scope stack_t*, stack_t*);
+    int sighold(int);
+    int sigignore(int);
+    int siginterrupt(int, int);
+    int sigpause(int);
+    int sigrelse(int);
+}
+else version (Darwin)
+{
+    enum SS_ONSTACK     = 0x0001;
+    enum SS_DISABLE     = 0x0004;
+    enum MINSIGSTKSZ    = 32768;
+    enum SIGSTKSZ       = 131072;
+
+    //ucontext_t (defined in core.sys.posix.ucontext)
+    //mcontext_t (defined in core.sys.posix.ucontext)
+
+    struct stack_t
+    {
+        void*   ss_sp;
+        size_t  ss_size;
+        int     ss_flags;
+    }
+
+    struct sigstack
+    {
+        void*   ss_sp;
+        int     ss_onstack;
+    }
+
+    sigfn_t bsd_signal(int sig, sigfn_t func);
+    sigfn_t sigset(int sig, sigfn_t func);
+
+  nothrow:
+  @nogc:
+    sigfn_t2 bsd_signal(int sig, sigfn_t2 func);
+    sigfn_t2 sigset(int sig, sigfn_t2 func);
+
+    int killpg(pid_t, int);
+    int sigaltstack(const scope stack_t*, stack_t*);
+    int sighold(int);
+    int sigignore(int);
+    int siginterrupt(int, int);
+    int sigpause(int);
+    int sigrelse(int);
+}
+else version (FreeBSD)
+{
+    enum
+    {
+        SS_ONSTACK = 0x0001,
+        SS_DISABLE = 0x0004,
+    }
+
+    enum MINSIGSTKSZ = 512 * 4;
+    enum SIGSTKSZ    = (MINSIGSTKSZ + 32768);
+
+    //ucontext_t (defined in core.sys.posix.ucontext)
+    //mcontext_t (defined in core.sys.posix.ucontext)
+
+    struct stack_t
+    {
+        void*   ss_sp;
+        size_t  ss_size;
+        int     ss_flags;
+    }
+
+    struct sigstack
+    {
+        void*   ss_sp;
+        int     ss_onstack;
+    }
+
+    //sigfn_t bsd_signal(int sig, sigfn_t func);
+    sigfn_t sigset(int sig, sigfn_t func);
+
+  nothrow:
+  @nogc:
+    //sigfn_t2 bsd_signal(int sig, sigfn_t2 func);
+    sigfn_t2 sigset(int sig, sigfn_t2 func);
+
+    int killpg(pid_t, int);
+    int sigaltstack(const scope stack_t*, stack_t*);
+    int sighold(int);
+    int sigignore(int);
+    int siginterrupt(int, int);
+    int sigpause(int);
+    int sigrelse(int);
+}
+else version (NetBSD)
+{
+    enum
+    {
+        SS_ONSTACK = 0x0001,
+        SS_DISABLE = 0x0004,
+    }
+
+    enum MINSIGSTKSZ = 8192;
+    enum SIGSTKSZ    = (MINSIGSTKSZ + 32768);
+
+    //ucontext_t (defined in core.sys.posix.ucontext)
+    //mcontext_t (defined in core.sys.posix.ucontext)
+
+    struct stack_t
+    {
+        void*   ss_sp;
+        size_t  ss_size;
+        int     ss_flags;
+    }
+
+    struct sigstack
+    {
+        void*   ss_sp;
+        int     ss_onstack;
+    }
+
+    //sigfn_t bsd_signal(int sig, sigfn_t func);
+    sigfn_t sigset(int sig, sigfn_t func);
+
+  nothrow:
+  @nogc:
+    //sigfn_t2 bsd_signal(int sig, sigfn_t2 func);
+    sigfn_t2 sigset(int sig, sigfn_t2 func);
+
+    int killpg(pid_t, int);
+    int sigaltstack(const scope stack_t*, stack_t*);
+    int sighold(int);
+    int sigignore(int);
+    int siginterrupt(int, int);
+    int sigpause(int);
+    int sigrelse(int);
+}
+else version (OpenBSD)
+{
+    enum
+    {
+        SS_ONSTACK = 0x0001,
+        SS_DISABLE = 0x0004,
+    }
+
+    enum MINSIGSTKSZ = 8192;
+    enum SIGSTKSZ    = (MINSIGSTKSZ + 32768);
+
+    //ucontext_t (defined in core.sys.posix.ucontext)
+    //mcontext_t (defined in core.sys.posix.ucontext)
+
+    struct stack_t
+    {
+        void*   ss_sp;
+        size_t  ss_size;
+        int     ss_flags;
+    }
+
+  nothrow:
+  @nogc:
+    int killpg(pid_t, int);
+    int sigaltstack(const scope stack_t*, stack_t*);
+    int siginterrupt(int, int);
+    int sigpause(int);
+}
+else version (DragonFlyBSD)
+{
+    enum
+    {
+        SS_ONSTACK = 0x0001,
+        SS_DISABLE = 0x0004,
+    }
+
+    enum MINSIGSTKSZ = 8192;
+    enum SIGSTKSZ    = (MINSIGSTKSZ + 32768);
+
+    //ucontext_t (defined in core.sys.posix.ucontext)
+    //mcontext_t (defined in core.sys.posix.ucontext)
+
+    struct stack_t
+    {
+        void*   ss_sp;
+        size_t  ss_size;
+        int     ss_flags;
+    }
+
+    struct sigstack
+    {
+        void*   ss_sp;
+        int     ss_onstack;
+    }
+
+    //sigfn_t bsd_signal(int sig, sigfn_t func);
+    sigfn_t sigset(int sig, sigfn_t func);
+
+  nothrow:
+  @nogc:
+    //sigfn_t2 bsd_signal(int sig, sigfn_t2 func);
+    sigfn_t2 sigset(int sig, sigfn_t2 func);
+
+    int killpg(pid_t, int);
+    int sigaltstack(const scope stack_t*, stack_t*);
+    int sighold(int);
+    int sigignore(int);
+    int siginterrupt(int, int);
+    int sigpause(int);
+    int sigrelse(int);
+}
+else version (Solaris)
+{
+    enum
+    {
+        SS_ONSTACK = 0x0001,
+        SS_DISABLE = 0x0002,
+    }
+
+    enum MINSIGSTKSZ = 2048;
+    enum SIGSTKSZ = 8192;
+
+    struct stack_t
+    {
+        void* ss_sp;
+        size_t ss_size;
+        int ss_flags;
+    }
+
+    struct sigstack
+    {
+        void* ss_sp;
+        int ss_onstack;
+    }
 
     sigfn_t sigset(int sig, sigfn_t func);
 
@@ -2975,20 +2655,6 @@
 }
 else version (CRuntime_Bionic)
 {
-    enum SIGPOLL   = 29;
-    enum SIGPROF   = 27;
-    enum SIGSYS    = 31;
-    enum SIGTRAP   = 5;
-    enum SIGVTALRM = 26;
-    enum SIGXCPU   = 24;
-    enum SIGXFSZ   = 25;
-
-    enum SA_ONSTACK     = 0x08000000;
-    enum SA_RESETHAND   = 0x80000000;
-    enum SA_RESTART     = 0x10000000;
-    enum SA_SIGINFO     = 4;
-    enum SA_NOCLDWAIT   = 2;
-    enum SA_NODEFER     = 0x40000000;
     enum SS_ONSTACK     = 1;
     enum SS_DISABLE     = 2;
     enum MINSIGSTKSZ    = 2048;
@@ -3001,69 +2667,6 @@
         size_t  ss_size;
     }
 
-    enum
-    {
-        ILL_ILLOPC = 1,
-        ILL_ILLOPN,
-        ILL_ILLADR,
-        ILL_ILLTRP,
-        ILL_PRVOPC,
-        ILL_PRVREG,
-        ILL_COPROC,
-        ILL_BADSTK
-    }
-
-    enum
-    {
-        FPE_INTDIV = 1,
-        FPE_INTOVF,
-        FPE_FLTDIV,
-        FPE_FLTOVF,
-        FPE_FLTUND,
-        FPE_FLTRES,
-        FPE_FLTINV,
-        FPE_FLTSUB
-    }
-
-    enum
-    {
-        SEGV_MAPERR = 1,
-        SEGV_ACCERR
-    }
-
-    enum
-    {
-        BUS_ADRALN = 1,
-        BUS_ADRERR,
-        BUS_OBJERR
-    }
-
-    enum
-    {
-        TRAP_BRKPT = 1,
-        TRAP_TRACE
-    }
-
-    enum
-    {
-        CLD_EXITED = 1,
-        CLD_KILLED,
-        CLD_DUMPED,
-        CLD_TRAPPED,
-        CLD_STOPPED,
-        CLD_CONTINUED
-    }
-
-    enum
-    {
-        POLL_IN = 1,
-        POLL_OUT,
-        POLL_MSG,
-        POLL_ERR,
-        POLL_PRI,
-        POLL_HUP
-    }
-
     sigfn_t bsd_signal(int, sigfn_t);
 
   nothrow:
@@ -3076,41 +2679,6 @@
 }
 else version (CRuntime_Musl)
 {
-    version (MIPS_Any)
-    {
-        enum SIGPOLL   = 22;
-        enum SIGPROF   = 29;
-        enum SIGSYS    = 12;
-        enum SIGTRAP   = 5;
-        enum SIGVTALRM = 28;
-        enum SIGXCPU   = 30;
-        enum SIGXFSZ   = 31;
-
-        enum SA_ONSTACK   = 0x08000000;
-        enum SA_RESETHAND = 0x80000000;
-        enum SA_RESTART   = 0x10000000;
-        enum SA_SIGINFO   = 8;
-        enum SA_NOCLDWAIT = 0x10000;
-        enum SA_NODEFER   = 0x40000000;
-    }
-    else
-    {
-        enum SIGPOLL   = 29;
-        enum SIGPROF   = 27;
-        enum SIGSYS    = 31;
-        enum SIGTRAP   = 5;
-        enum SIGVTALRM = 26;
-        enum SIGXCPU   = 24;
-        enum SIGXFSZ   = 25;
-
-        enum SA_ONSTACK   = 0x08000000;
-        enum SA_RESETHAND = 0x80000000;
-        enum SA_RESTART   = 0x10000000;
-        enum SA_SIGINFO   = 4;
-        enum SA_NOCLDWAIT = 2;
-        enum SA_NODEFER   = 0x40000000;
-    }
-
     enum SS_ONSTACK = 1;
     enum SS_DISABLE = 2;
 
@@ -3169,69 +2737,6 @@
         }
     }
 
-    enum
-    {
-        ILL_ILLOPC = 1,
-        ILL_ILLOPN,
-        ILL_ILLADR,
-        ILL_ILLTRP,
-        ILL_PRVOPC,
-        ILL_PRVREG,
-        ILL_COPROC,
-        ILL_BADSTK
-    }
-
-    enum
-    {
-        FPE_INTDIV = 1,
-        FPE_INTOVF,
-        FPE_FLTDIV,
-        FPE_FLTOVF,
-        FPE_FLTUND,
-        FPE_FLTRES,
-        FPE_FLTINV,
-        FPE_FLTSUB
-    }
-
-    enum
-    {
-        SEGV_MAPERR = 1,
-        SEGV_ACCERR
-    }
-
-    enum
-    {
-        BUS_ADRALN = 1,
-        BUS_ADRERR,
-        BUS_OBJERR
-    }
-
-    enum
-    {
-        TRAP_BRKPT = 1,
-        TRAP_TRACE
-    }
-
-    enum
-    {
-        CLD_EXITED = 1,
-        CLD_KILLED,
-        CLD_DUMPED,
-        CLD_TRAPPED,
-        CLD_STOPPED,
-        CLD_CONTINUED
-    }
-
-    enum
-    {
-        POLL_IN = 1,
-        POLL_OUT,
-        POLL_MSG,
-        POLL_ERR,
-        POLL_PRI,
-        POLL_HUP
-    }
-
     sigfn_t bsd_signal(int sig, sigfn_t func);
     sigfn_t sigset(int sig, sigfn_t func);
 
@@ -3250,77 +2755,11 @@
 }
 else version (CRuntime_UClibc)
 {
-    version (X86_64)
-    {
-        enum SIGTRAP         = 5;
-        enum SIGIOT          = 6;
-        enum SIGSTKFLT       = 16;
-        enum SIGCLD          = SIGCHLD;
-        enum SIGXCPU         = 24;
-        enum SIGXFSZ         = 25;
-        enum SIGVTALRM       = 26;
-        enum SIGPROF         = 27;
-        enum SIGWINCH        = 28;
-        enum SIGPOLL         = SIGIO;
-        enum SIGIO           = 29;
-        enum SIGPWR          = 30;
-        enum SIGSYS          = 31;
-        enum SIGUNUSED       = 31;
-    }
-    else version (MIPS32)
-    {
-        enum SIGTRAP = 5;
-        enum SIGIOT           = 6;
-        enum SIGEMT           = 7;
-        enum SIGFPE           = 8;
-        enum SIGSYS           = 12;
-        enum SIGCLD           = SIGCHLD;
-        enum SIGPWR           = 19;
-        enum SIGWINCH         = 20;
-        enum SIGIO            = 22;
-        enum SIGPOLL          = SIGIO;
-        enum SIGVTALRM        = 28;
-        enum SIGPROF          = 29;
-        enum SIGXCPU          = 30;
-        enum SIGXFSZ          = 31;
-    }
-    else version (ARM)
-    {
-        enum SIGTRAP = 5;
-        enum SIGIOT = 6;
-        enum SIGSTKFLT = 16;
-        enum SIGCLD = SIGCHLD;
-        enum SIGXCPU = 24;
-        enum SIGXFSZ = 25;
-        enum SIGVTALRM = 26;
-        enum SIGPROF = 27;
-        enum SIGWINCH = 28;
-        enum SIGPOLL = SIGIO;
-        enum SIGIO = 29;
-        enum SIGPWR = 30;
-        enum SIGSYS = 31;
-        enum SIGUNUSED = 31;
-    }
-    else
-        static assert(0, "unimplemented");
-
-    enum SA_ONSTACK     = 0x08000000;
-    enum SA_RESETHAND   = 0x80000000;
-    enum SA_RESTART     = 0x10000000;
-    enum SA_SIGINFO     = 4;
-    enum SA_NOCLDWAIT   = 2;
-    enum SA_NODEFER     = 0x40000000;
     enum SS_ONSTACK     = 1;
     enum SS_DISABLE     = 2;
     enum MINSIGSTKSZ    = 2048;
     enum SIGSTKSZ       = 8192;
 
-    enum SA_INTERRUPT   = 0x20000000;
-
-    enum SA_NOMASK      = SA_NODEFER;
-    enum SA_ONESHOT     = SA_RESETHAND;
-    enum SA_STACK       = SA_ONSTACK;
-
     version (MIPS32)
     {
         struct stack_t
@@ -3346,76 +2785,6 @@
         int     ss_onstack;
     }
 
-    // `si_code' values for SIGILL signal.
-    enum
-    {
-      ILL_ILLOPC = 1,       // Illegal opcode.
-      ILL_ILLOPN,           // Illegal operand.
-      ILL_ILLADR,           // Illegal addressing mode.
-      ILL_ILLTRP,           // Illegal trap.
-      ILL_PRVOPC,           // Privileged opcode.
-      ILL_PRVREG,           // Privileged register.
-      ILL_COPROC,           // Coprocessor error.
-      ILL_BADSTK            // Internal stack error.
-    }
-
-    // `si_code' values for SIGFPE signal.
-    enum
-    {
-      FPE_INTDIV = 1,       // Integer divide by zero.
-      FPE_INTOVF,           // Integer overflow.
-      FPE_FLTDIV,           // Floating point divide by zero.
-      FPE_FLTOVF,           // Floating point overflow.
-      FPE_FLTUND,           // Floating point underflow.
-      FPE_FLTRES,           // Floating point inexact result.
-      FPE_FLTINV,           // Floating point invalid operation.
-      FPE_FLTSUB            // Subscript out of range.
-    }
-
-    // `si_code' values for SIGSEGV signal.
-    enum
-    {
-      SEGV_MAPERR = 1,      // Address not mapped to object.
-      SEGV_ACCERR           // Invalid permissions for mapped object.
-    }
-
-    // `si_code' values for SIGBUS signal.
-    enum
-    {
-      BUS_ADRALN = 1,       // Invalid address alignment.
-      BUS_ADRERR,           // Non-existant physical address.
-      BUS_OBJERR            // Object specific hardware error.
-    }
-
-    // `si_code' values for SIGTRAP signal.
-    enum
-    {
-      TRAP_BRKPT = 1,       // Process breakpoint.
-      TRAP_TRACE            // Process trace trap.
-    }
-
-    // `si_code' values for SIGCHLD signal.
-    enum
-    {
-      CLD_EXITED = 1,       // Child has exited.
-      CLD_KILLED,           // Child was killed.
-      CLD_DUMPED,           // Child terminated abnormally.
-      CLD_TRAPPED,          // Traced child has trapped.
-      CLD_STOPPED,          // Child has stopped.
-      CLD_CONTINUED         // Stopped child has continued.
-    }
-
-    // `si_code' values for SIGPOLL signal.
-    enum
-    {
-      POLL_IN = 1,          // Data input available.
-      POLL_OUT,         // Output buffers available.
-      POLL_MSG,         // Input message available.
-      POLL_ERR,         // I/O error.
-      POLL_PRI,         // High priority input available.
-      POLL_HUP          // Device disconnected.
-    }
-
     sigfn_t sigset(int sig, sigfn_t func);
 
   nothrow:
@@ -3524,16 +2893,12 @@
     void(*)(sigval) sigev_notify_function;
     pthread_attr_t* sigev_notify_attributes;
 }
-
-int sigqueue(pid_t, int, const sigval);
-int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
-int sigwaitinfo(const scope sigset_t*, siginfo_t*);
 */
 
 nothrow:
 @nogc:
 
-version (CRuntime_Glibc)
+version (linux)
 {
     private enum __SIGEV_MAX_SIZE = 64;
 
@@ -3552,22 +2917,18 @@
         int         sigev_signo;
         int         sigev_notify;
 
-        union _sigev_un_t
+        union
         {
             int[__SIGEV_PAD_SIZE] _pad;
             pid_t                 _tid;
 
-            struct _sigev_thread_t
+            struct
             {
-                void function(sigval)   _function;
-                void*                   _attribute;
-            } _sigev_thread_t _sigev_thread;
-        } _sigev_un_t _sigev_un;
+                void function(sigval) sigev_notify_function;
+                void*                 sigev_notify_attributes;
+            }
+        }
     }
-
-    int sigqueue(pid_t, int, const sigval);
-    int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
-    int sigwaitinfo(const scope sigset_t*, siginfo_t*);
 }
 else version (FreeBSD)
 {
@@ -3576,21 +2937,17 @@
         int             sigev_notify;
         int             sigev_signo;
         sigval          sigev_value;
-        union  _sigev_un
+        union
         {
             lwpid_t _threadid;
-            struct _sigev_thread
+            struct
             {
-                void function(sigval) _function;
-                void* _attribute;
+                void function(sigval) sigev_notify_function;
+                void* sigev_notify_attributes;
             }
             c_long[8] __spare__;
         }
     }
-
-    int sigqueue(pid_t, int, const sigval);
-    int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
-    int sigwaitinfo(const scope sigset_t*, siginfo_t*);
 }
 else version (NetBSD)
 {
@@ -3602,10 +2959,6 @@
         void function(sigval) sigev_notify_function;
         void /* pthread_attr_t */*sigev_notify_attributes;
     }
-
-    int sigqueue(pid_t, int, const sigval);
-    int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
-    int sigwaitinfo(const scope sigset_t*, siginfo_t*);
 }
 else version (OpenBSD)
 {
@@ -3634,10 +2987,6 @@
         _sigval_t                 sigev_value;
         void function(_sigval_t)  sigev_notify_function;
     }
-
-    int sigqueue(pid_t, int, const sigval);
-    int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
-    int sigwaitinfo(const scope sigset_t*, siginfo_t*);
 }
 else version (Darwin)
 {
@@ -3661,84 +3010,68 @@
         pthread_attr_t* sigev_notify_attributes;
         int __sigev_pad2;
     }
+}
+else
+{
+    static assert(false, "Unsupported platform");
+}
 
+/*
+int sigqueue(pid_t, int, const sigval);
+int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
+int sigwaitinfo(const scope sigset_t*, siginfo_t*);
+*/
+
+nothrow:
+@nogc:
+
+version (CRuntime_Glibc)
+{
+    int sigqueue(pid_t, int, const sigval);
+    int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
+    int sigwaitinfo(const scope sigset_t*, siginfo_t*);
+}
+else version (FreeBSD)
+{
+    int sigqueue(pid_t, int, const sigval);
+    int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
+    int sigwaitinfo(const scope sigset_t*, siginfo_t*);
+}
+else version (NetBSD)
+{
+    int sigqueue(pid_t, int, const sigval);
+    int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
+    int sigwaitinfo(const scope sigset_t*, siginfo_t*);
+}
+else version (OpenBSD)
+{
+}
+else version (DragonFlyBSD)
+{
+    int sigqueue(pid_t, int, const sigval);
+    int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
+    int sigwaitinfo(const scope sigset_t*, siginfo_t*);
+}
+else version (Darwin)
+{
+}
+else version (Solaris)
+{
     int sigqueue(pid_t, int, const sigval);
     int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
     int sigwaitinfo(const scope sigset_t*, siginfo_t*);
 }
 else version (CRuntime_Bionic)
 {
-    private enum __ARCH_SIGEV_PREAMBLE_SIZE = (int.sizeof * 2) + sigval.sizeof;
-    private enum SIGEV_MAX_SIZE = 64;
-    private enum SIGEV_PAD_SIZE = (SIGEV_MAX_SIZE - __ARCH_SIGEV_PREAMBLE_SIZE)
-                                  / int.sizeof;
-
-    struct sigevent
-    {
-        sigval      sigev_value;
-        int         sigev_signo;
-        int         sigev_notify;
-
-        union _sigev_un_t
-        {
-            int[SIGEV_PAD_SIZE] _pad;
-            int                 _tid;
-
-            struct _sigev_thread_t
-            {
-                void function(sigval) _function;
-                void*                 _attribute;
-            } _sigev_thread_t _sigev_thread;
-        } _sigev_un_t _sigev_un;
-    }
 }
 else version (CRuntime_Musl)
 {
-    struct sigevent
-    {
-        sigval sigev_value;
-        int sigev_signo;
-        int sigev_notify;
-        void function(sigval) sigev_notify_function;
-        pthread_attr_t *sigev_notify_attributes;
-        char[56 - 3 * c_long.sizeof] __pad = void;
-    }
+    int sigqueue(pid_t, int, const sigval);
+    int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
+    int sigwaitinfo(const scope sigset_t*, siginfo_t*);
 }
 else version (CRuntime_UClibc)
 {
-    private enum __SIGEV_MAX_SIZE = 64;
-
-    static if ( __WORDSIZE == 64 )
-    {
-        private enum __SIGEV_PAD_SIZE = ((__SIGEV_MAX_SIZE / int.sizeof) - 4);
-    }
-    else
-    {
-        private enum __SIGEV_PAD_SIZE = ((__SIGEV_MAX_SIZE / int.sizeof) - 3);
-    }
-
-    struct sigevent
-    {
-        sigval      sigev_value;
-        int         sigev_signo;
-        int         sigev_notify;
-
-        union _sigev_un_t
-        {
-            int[__SIGEV_PAD_SIZE] _pad;
-            pid_t                 _tid;
-
-            struct _sigev_thread_t
-            {
-                void function(sigval)   _function;
-                void*                   _attribute;
-            } _sigev_thread_t _sigev_thread;
-        } _sigev_un_t _sigev_un;
-    }
-
-    @property void function(sigval) sigev_notify_function(ref sigevent _sigevent) { return _sigevent._sigev_un._sigev_thread._function; }
-    @property void* sigev_notify_attributes(ref sigevent _sigevent) { return  _sigevent._sigev_un._sigev_thread._attribute; }
-
     int sigqueue(pid_t, int, const sigval);
     int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
     int sigwaitinfo(const scope sigset_t*, siginfo_t*);
diff --git a/libphobos/libdruntime/core/sys/posix/stdc/time.d b/libphobos/libdruntime/core/sys/posix/stdc/time.d
index 89029de..d48a0ea 100644
--- a/libphobos/libdruntime/core/sys/posix/stdc/time.d
+++ b/libphobos/libdruntime/core/sys/posix/stdc/time.d
@@ -52,7 +52,27 @@
 public import core.sys.posix.sys.types : time_t, clock_t;
 
 ///
-version (OSX)
+version (CRuntime_Glibc)
+{
+    enum clock_t CLOCKS_PER_SEC = 1_000_000;
+    clock_t clock();
+}
+else version (CRuntime_Musl)
+{
+    enum clock_t CLOCKS_PER_SEC = 1_000_000;
+    clock_t clock();
+}
+else version (CRuntime_Bionic)
+{
+    enum clock_t CLOCKS_PER_SEC = 1_000_000;
+    clock_t clock();
+}
+else version (CRuntime_UClibc)
+{
+    enum clock_t CLOCKS_PER_SEC = 1_000_000;
+    clock_t clock();
+}
+else version (OSX)
 {
     enum clock_t CLOCKS_PER_SEC = 1_000_000; // was 100 until OSX 10.4/10.5
     version (X86)
@@ -90,26 +110,6 @@
     enum clock_t CLOCKS_PER_SEC = 1_000_000;
     clock_t clock();
 }
-else version (CRuntime_Glibc)
-{
-    enum clock_t CLOCKS_PER_SEC = 1_000_000;
-    clock_t clock();
-}
-else version (CRuntime_Musl)
-{
-    enum clock_t CLOCKS_PER_SEC = 1_000_000;
-    clock_t clock();
-}
-else version (CRuntime_Bionic)
-{
-    enum clock_t CLOCKS_PER_SEC = 1_000_000;
-    clock_t clock();
-}
-else version (CRuntime_UClibc)
-{
-    enum clock_t CLOCKS_PER_SEC = 1_000_000;
-    clock_t clock();
-}
 else
 {
     static assert(0, "unsupported system");
diff --git a/libphobos/libdruntime/core/sys/posix/stdio.d b/libphobos/libdruntime/core/sys/posix/stdio.d
index c8f92ec..077838d 100644
--- a/libphobos/libdruntime/core/sys/posix/stdio.d
+++ b/libphobos/libdruntime/core/sys/posix/stdio.d
@@ -623,35 +623,35 @@
 {
     enum P_tmpdir  = "/tmp";
 }
-version (CRuntime_Musl)
+else version (CRuntime_Musl)
 {
     enum P_tmpdir  = "/tmp";
 }
-version (Darwin)
+else version (Darwin)
 {
     enum P_tmpdir  = "/var/tmp";
 }
-version (FreeBSD)
+else version (FreeBSD)
 {
     enum P_tmpdir  = "/var/tmp/";
 }
-version (NetBSD)
+else version (NetBSD)
 {
     enum P_tmpdir  = "/var/tmp/";
 }
-version (OpenBSD)
+else version (OpenBSD)
 {
     enum P_tmpdir  = "/tmp/";
 }
-version (DragonFlyBSD)
+else version (DragonFlyBSD)
 {
     enum P_tmpdir  = "/var/tmp/";
 }
-version (Solaris)
+else version (Solaris)
 {
     enum P_tmpdir  = "/var/tmp/";
 }
-version (CRuntime_UClibc)
+else version (CRuntime_UClibc)
 {
     enum P_tmpdir  = "/tmp";
 }
diff --git a/libphobos/libdruntime/core/sys/posix/sys/ioctl.d b/libphobos/libdruntime/core/sys/posix/sys/ioctl.d
index c6f21d6..36d1edc 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/ioctl.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/ioctl.d
@@ -31,7 +31,7 @@
 extern (C) nothrow @nogc:
 @system:
 
-version (CRuntime_Glibc)
+version (linux)
 {
     import core.sys.posix.termios; // tcflag_t, speed_t, cc_t
 
@@ -326,8 +326,6 @@
     enum SIOCDEVPRIVATE = 0x89F0;
 
     enum SIOCPROTOPRIVATE = 0x89E0;
-
-    int ioctl(int __fd, c_ulong __request, ...);
 }
 else version (Darwin)
 {
@@ -348,8 +346,6 @@
     enum uint TIOCSSIZE = TIOCSWINSZ;
 
     public import core.sys.posix.sys.filio; // File related ioctls
-
-    int ioctl(int fildes, c_ulong request, ...);
 }
 else version (FreeBSD)
 {
@@ -358,8 +354,6 @@
         int len;
         void* buf;
     }
-
-    int ioctl(int, c_ulong, ...);
 }
 else version (NetBSD)
 {
@@ -370,8 +364,6 @@
         ushort ws_xpixel;
         ushort ws_ypixel;
     }
-
-    int ioctl(int, c_ulong, ...);
 }
 else version (OpenBSD)
 {
@@ -389,8 +381,6 @@
     }
 
     public import core.sys.posix.sys.filio; // File related ioctls
-
-    int ioctl(int, c_ulong, ...);
 }
 else version (DragonFlyBSD)
 {
@@ -407,7 +397,38 @@
         ushort ws_xpixel;
         ushort ws_ypixel;
     }
+}
+else version (Solaris)
+{
+}
+else
+{
+    static assert(false, "Unsupported platform");
+}
 
+///
+version (CRuntime_Glibc)
+{
+    int ioctl(int __fd, c_ulong __request, ...);
+}
+else version (Darwin)
+{
+    int ioctl(int fildes, c_ulong request, ...);
+}
+else version (FreeBSD)
+{
+    int ioctl(int, c_ulong, ...);
+}
+else version (NetBSD)
+{
+    int ioctl(int, c_ulong, ...);
+}
+else version (OpenBSD)
+{
+    int ioctl(int, c_ulong, ...);
+}
+else version (DragonFlyBSD)
+{
     int ioctl(int, c_ulong, ...);
 }
 else version (Solaris)
@@ -420,331 +441,10 @@
 }
 else version (CRuntime_Musl)
 {
-
+    int ioctl(int, int, ...);
 }
 else version (CRuntime_UClibc)
 {
-    import core.sys.posix.termios;
-
-    enum _IOC_NRBITS = 8;
-    enum _IOC_TYPEBITS = 8;
-    enum _IOC_SIZEBITS = 14;
-    enum _IOC_DIRBITS = 2;
-
-    enum _IOC_NRMASK = (1 << _IOC_NRBITS) - 1;
-    enum _IOC_TYPEMASK = (1 << _IOC_TYPEBITS) - 1;
-    enum _IOC_SIZEMASK = (1 << _IOC_SIZEBITS) - 1;
-    enum _IOC_DIRMASK = (1 << _IOC_DIRBITS) - 1;
-
-    enum _IOC_NRSHIFT = 0;
-    enum _IOC_TYPESHIFT = _IOC_NRSHIFT + _IOC_NRBITS;
-    enum _IOC_SIZESHIFT = _IOC_TYPESHIFT + _IOC_TYPEBITS;
-    enum _IOC_DIRSHIFT = _IOC_SIZESHIFT + _IOC_SIZEBITS;
-
-    enum _IOC_NONE = 0;
-    enum _IOC_WRITE = 1;
-    enum _IOC_READ = 2;
-
-    extern (D) int _IOC(T = typeof(null))(int dir, int type, int nr)
-    {
-        return (dir << _IOC_DIRSHIFT) |
-               (type << _IOC_TYPESHIFT) |
-               (nr << _IOC_NRSHIFT) |
-               (is(T == typeof(null)) ? 0 : T.sizeof << _IOC_SIZESHIFT);
-    }
-
-    extern (D) int _IO(int type, int nr)
-    {
-        return _IOC(_IOC_NONE, type, nr);
-    }
-
-    extern (D) int _IOR(T)(int type, int nr)
-    {
-        return _IOC!T(_IOC_READ, type, nr);
-    }
-
-    extern (D) int _IOW(T)(int type, int nr)
-    {
-        return _IOC!T(_IOC_WRITE, type, nr);
-    }
-
-    extern (D) int _IOWR(T)(int type, int nr)
-    {
-        return _IOC!T(_IOC_READ | _IOC_WRITE, type, nr);
-    }
-
-    extern (D) int _IOR_BAD(T)(int type, int nr)
-    {
-        return _IOC!T(_IOC_READ, type, nr);
-    }
-
-    extern (D) int _IOW_BAD(T)(int type, int nr)
-    {
-        return _IOC!T(_IOC_WRITE, type, nr);
-    }
-
-    extern (D) int _IORW_BAD(T)(int type, int nr)
-    {
-        return _IOC!T(_IOC_READ | _IOC_WRITE, type, nr);
-    }
-
-    extern (D) int _IOC_DIR(int nr)
-    {
-        return (nr >> _IOC_DIRSHIFT) & _IOC_DIRMASK;
-    }
-
-    extern (D) int _IOC_TYPE(int nr)
-    {
-        return (nr >> _IOC_TYPESHIFT) & _IOC_TYPEMASK;
-    }
-
-    extern (D) int _IOC_NR(int nr)
-    {
-        return (nr >> _IOC_NRSHIFT) & _IOC_NRMASK;
-    }
-
-    extern (D) int _IOC_SIZE(int nr)
-    {
-        return (nr >> _IOC_SIZESHIFT) & _IOC_SIZEMASK;
-    }
-
-    enum IOC_IN = _IOC_WRITE << _IOC_DIRSHIFT;
-    enum IOC_OUT = _IOC_READ << _IOC_DIRSHIFT;
-    enum IOC_INOUT = (_IOC_READ | _IOC_WRITE) << _IOC_DIRSHIFT;
-    enum IOCSIZE_MASK = _IOC_SIZEMASK << _IOC_DIRSHIFT;
-    enum IOCSIZE_SHIFT = _IOC_SIZESHIFT;
-
-    enum NCCS = 19;
-
-    struct termios
-    {
-        tcflag_t c_iflag;
-        tcflag_t c_oflag;
-        tcflag_t c_cflag;
-        tcflag_t c_lflag;
-        cc_t c_line;
-        cc_t[NCCS] c_cc;
-    }
-
-    struct termios2
-    {
-        tcflag_t c_iflag;
-        tcflag_t c_oflag;
-        tcflag_t c_cflag;
-        tcflag_t c_lflag;
-        cc_t c_line;
-        cc_t[NCCS] c_cc;
-        speed_t c_ispeed;
-        speed_t c_ospeed;
-    }
-
-    alias termios2 ktermios;
-
-    struct winsize
-    {
-        ushort ws_row;
-        ushort ws_col;
-        ushort ws_xpixel;
-        ushort ws_ypixel;
-    }
-
-    enum NCC = 8;
-
-    struct termio
-    {
-        ushort c_iflag;
-        ushort c_oflag;
-        ushort c_cflag;
-        ushort c_lflag;
-        ubyte c_line;
-        ubyte[NCC] c_cc;
-    }
-
-    enum TIOCM_LE = 0x001;
-    enum TIOCM_DTR = 0x002;
-    enum TIOCM_RTS = 0x004;
-    enum TIOCM_ST = 0x008;
-    enum TIOCM_SR = 0x010;
-    enum TIOCM_CTS = 0x020;
-    enum TIOCM_CAR = 0x040;
-    enum TIOCM_RNG = 0x080;
-    enum TIOCM_DSR = 0x100;
-    enum TIOCM_CD = TIOCM_CAR;
-    enum TIOCM_RI = TIOCM_RNG;
-
-    enum N_TTY = 0;
-    enum N_SLIP = 1;
-    enum N_MOUSE = 2;
-    enum N_PPP = 3;
-    enum N_STRIP = 4;
-    enum N_AX25 = 5;
-    enum N_X25 = 6;
-    enum N_6PACK = 7;
-    enum N_MASC = 8;
-    enum N_R3964 = 9;
-    enum N_PROFIBUS_FDL = 10;
-    enum N_IRDA = 11;
-    enum N_SMSBLOCK = 12;
-    enum N_HDLC = 13;
-    enum N_SYNC_PPP = 14;
-    enum N_HCI = 15;
-
-    enum TCGETS = 0x5401;
-    enum TCSETS = 0x5402;
-    enum TCSETSW = 0x5403;
-    enum TCSETSF = 0x5404;
-    enum TCGETA = 0x5405;
-    enum TCSETA = 0x5406;
-    enum TCSETAW = 0x5407;
-    enum TCSETAF = 0x5408;
-    enum TCSBRK = 0x5409;
-    enum TCXONC = 0x540A;
-    enum TCFLSH = 0x540B;
-    enum TIOCEXCL = 0x540C;
-    enum TIOCNXCL = 0x540D;
-    enum TIOCSCTTY = 0x540E;
-    enum TIOCGPGRP = 0x540F;
-    enum TIOCSPGRP = 0x5410;
-    enum TIOCOUTQ = 0x5411;
-    enum TIOCSTI = 0x5412;
-    enum TIOCGWINSZ = 0x5413;
-    enum TIOCSWINSZ = 0x5414;
-    enum TIOCMGET = 0x5415;
-    enum TIOCMBIS = 0x5416;
-    enum TIOCMBIC = 0x5417;
-    enum TIOCMSET = 0x5418;
-    enum TIOCGSOFTCAR = 0x5419;
-    enum TIOCSSOFTCAR = 0x541A;
-    enum FIONREAD = 0x541B;
-    enum TIOCINQ = FIONREAD;
-    enum TIOCLINUX = 0x541C;
-    enum TIOCCONS = 0x541D;
-    enum TIOCGSERIAL = 0x541E;
-    enum TIOCSSERIAL = 0x541F;
-    enum TIOCPKT = 0x5420;
-    enum FIONBIO = 0x5421;
-    enum TIOCNOTTY = 0x5422;
-    enum TIOCSETD = 0x5423;
-    enum TIOCGETD = 0x5424;
-    enum TCSBRKP = 0x5425;
-    enum TIOCSBRK = 0x5427;
-    enum TIOCCBRK = 0x5428;
-    enum TIOCGSID = 0x5429;
-
-    enum TCGETS2 = _IOR!termios2('T', 0x2A);
-    enum TCSETS2 = _IOW!termios2('T', 0x2B);
-    enum TCSETSW2 = _IOW!termios2('T', 0x2C);
-    enum TCSETSF2 = _IOW!termios2('T', 0x2D);
-
-    enum TIOCGRS485 = 0x542E;
-    enum TIOCSRS485 = 0x542F;
-
-    enum TIOCGPTN   = _IOR!uint('T', 0x30);
-    enum TIOCSPTLCK = _IOW!int('T', 0x31);
-    enum TIOCGDEV   = _IOR!uint('T', 0x32);
-
-    enum TCGETX = 0x5432;
-    enum TCSETX = 0x5433;
-    enum TCSETXF = 0x5434;
-    enum TCSETXW = 0x5435;
-
-    enum TIOCSIG = _IOW!int('T', 0x36);
-
-    enum TIOCVHANGUP = 0x5437;
-
-    enum FIONCLEX = 0x5450;
-    enum FIOCLEX = 0x5451;
-    enum FIOASYNC = 0x5452;
-    enum TIOCSERCONFIG = 0x5453;
-    enum TIOCSERGWILD = 0x5454;
-    enum TIOCSERSWILD = 0x5455;
-    enum TIOCGLCKTRMIOS = 0x5456;
-    enum TIOCSLCKTRMIOS = 0x5457;
-    enum TIOCSERGSTRUCT = 0x5458;
-    enum TIOCSERGETLSR = 0x5459;
-    enum TIOCSERGETMULTI = 0x545A;
-    enum TIOCSERSETMULTI = 0x545B;
-
-    enum TIOCMIWAIT = 0x545C;
-    enum TIOCGICOUNT = 0x545D;
-
-    enum FIOQSIZE = 0x5460;
-
-    enum TIOCPKT_DATA = 0;
-    enum TIOCPKT_FLUSHREAD = 1;
-    enum TIOCPKT_FLUSHWRITE = 2;
-    enum TIOCPKT_STOP = 4;
-    enum TIOCPKT_START = 8;
-    enum TIOCPKT_NOSTOP = 16;
-    enum TIOCPKT_DOSTOP = 32;
-    enum TIOCPKT_IOCTL = 64;
-
-    enum TIOCSER_TEMT = 0x01;
-
-    enum SIOCADDRT = 0x890B;
-    enum SIOCDELRT = 0x890C;
-    enum SIOCRTMSG = 0x890D;
-
-    enum SIOCGIFNAME = 0x8910;
-    enum SIOCSIFLINK = 0x8911;
-    enum SIOCGIFCONF = 0x8912;
-    enum SIOCGIFFLAGS = 0x8913;
-    enum SIOCSIFFLAGS = 0x8914;
-    enum SIOCGIFADDR = 0x8915;
-    enum SIOCSIFADDR = 0x8916;
-    enum SIOCGIFDSTADDR = 0x8917;
-    enum SIOCSIFDSTADDR = 0x8918;
-    enum SIOCGIFBRDADDR = 0x8919;
-    enum SIOCSIFBRDADDR = 0x891a;
-    enum SIOCGIFNETMASK = 0x891b;
-    enum SIOCSIFNETMASK = 0x891c;
-    enum SIOCGIFMETRIC = 0x891d;
-    enum SIOCSIFMETRIC = 0x891e;
-    enum SIOCGIFMEM = 0x891f;
-    enum SIOCSIFMEM = 0x8920;
-    enum SIOCGIFMTU = 0x8921;
-    enum SIOCSIFMTU = 0x8922;
-    enum SIOCSIFNAME = 0x8923;
-    enum SIOCSIFHWADDR = 0x8924;
-    enum SIOCGIFENCAP = 0x8925;
-    enum SIOCSIFENCAP = 0x8926;
-    enum SIOCGIFHWADDR = 0x8927;
-    enum SIOCGIFSLAVE = 0x8929;
-    enum SIOCSIFSLAVE = 0x8930;
-    enum SIOCADDMULTI = 0x8931;
-    enum SIOCDELMULTI = 0x8932;
-    enum SIOCGIFINDEX = 0x8933;
-    enum SIOGIFINDEX = SIOCGIFINDEX;
-    enum SIOCSIFPFLAGS = 0x8934;
-    enum SIOCGIFPFLAGS = 0x8935;
-    enum SIOCDIFADDR = 0x8936;
-    enum SIOCSIFHWBROADCAST = 0x8937;
-    enum SIOCGIFCOUNT = 0x8938;
-
-    enum SIOCGIFBR = 0x8940;
-    enum SIOCSIFBR = 0x8941;
-
-    enum SIOCGIFTXQLEN = 0x8942;
-    enum SIOCSIFTXQLEN = 0x8943;
-
-    enum SIOCDARP = 0x8953;
-    enum SIOCGARP = 0x8954;
-    enum SIOCSARP = 0x8955;
-
-    enum SIOCDRARP = 0x8960;
-    enum SIOCGRARP = 0x8961;
-    enum SIOCSRARP = 0x8962;
-
-    enum SIOCGIFMAP = 0x8970;
-    enum SIOCSIFMAP = 0x8971;
-
-    enum SIOCADDDLCI = 0x8980;
-    enum SIOCDELDLCI = 0x8981;
-
-    enum SIOCDEVPRIVATE = 0x89F0;
-
-    enum SIOCPROTOPRIVATE = 0x89E0;
-
     int ioctl(int __fd, c_ulong __request, ...);
 }
 else
diff --git a/libphobos/libdruntime/core/sys/posix/sys/ipc.d b/libphobos/libdruntime/core/sys/posix/sys/ipc.d
index d397a28..18a6cbd 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/ipc.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/ipc.d
@@ -52,11 +52,9 @@
 IPC_RMID
 IPC_SET
 IPC_STAT
-
-key_t ftok(const scope char*, int);
 */
 
-version (CRuntime_Glibc)
+version (linux)
 {
     struct ipc_perm
     {
@@ -82,8 +80,6 @@
     enum IPC_RMID       = 0;
     enum IPC_SET        = 1;
     enum IPC_STAT       = 2;
-
-    key_t ftok(const scope char*, int);
 }
 else version (Darwin)
 {
@@ -122,8 +118,6 @@
     enum IPC_RMID       = 0;
     enum IPC_SET        = 1;
     enum IPC_STAT       = 2;
-
-    key_t ftok(const scope char*, int);
 }
 else version (NetBSD)
 {
@@ -147,8 +141,6 @@
     enum IPC_RMID       = 0;
     enum IPC_SET        = 1;
     enum IPC_STAT       = 2;
-
-    key_t ftok(const scope char*, int);
 }
 else version (OpenBSD)
 {
@@ -172,8 +164,6 @@
     enum IPC_RMID       = 0;
     enum IPC_SET        = 1;
     enum IPC_STAT       = 2;
-
-    key_t ftok(const scope char*, int);
 }
 else version (DragonFlyBSD)
 {
@@ -197,79 +187,53 @@
     enum IPC_RMID       = 0;
     enum IPC_SET        = 1;
     enum IPC_STAT       = 2;
+}
+else
+{
+    static assert(false, "Unsupported platform");
+}
 
+/*
+key_t ftok(const scope char*, int);
+*/
+
+version (CRuntime_Glibc)
+{
+    key_t ftok(const scope char*, int);
+}
+else version (Darwin)
+{
+
+}
+else version (FreeBSD)
+{
+    key_t ftok(const scope char*, int);
+}
+else version (NetBSD)
+{
+    key_t ftok(const scope char*, int);
+}
+else version (OpenBSD)
+{
+    key_t ftok(const scope char*, int);
+}
+else version (DragonFlyBSD)
+{
     key_t ftok(const scope char*, int);
 }
 else version (CRuntime_Bionic)
 {
-    // All except ftok are from the linux kernel headers. Latest Bionic headers
-    // don't use this legacy definition anymore, consider updating.
-    version (D_LP64)
-    {
-        struct ipc_perm
-        {
-            key_t   key;
-            uint    uid;
-            uint    gid;
-            uint    cuid;
-            uint    cgid;
-            mode_t  mode;
-            ushort  seq;
-        }
-    }
-    else
-    {
-        struct ipc_perm
-        {
-            key_t   key;
-            ushort  uid;
-            ushort  gid;
-            ushort  cuid;
-            ushort  cgid;
-            mode_t  mode;
-            ushort  seq;
-        }
-    }
-
-    enum IPC_CREAT      = 0x0200; // 01000
-    enum IPC_EXCL       = 0x0400; // 02000
-    enum IPC_NOWAIT     = 0x0800; // 04000
-
-    enum key_t IPC_PRIVATE = 0;
-
-    enum IPC_RMID       = 0;
-    enum IPC_SET        = 1;
-    enum IPC_STAT       = 2;
-
+    key_t ftok(const scope char*, int);
+}
+else version (CRuntime_Musl)
+{
     key_t ftok(const scope char*, int);
 }
 else version (CRuntime_UClibc)
 {
-    struct ipc_perm
-    {
-        key_t   __key;
-        uid_t   uid;
-        gid_t   gid;
-        uid_t   cuid;
-        gid_t   cgid;
-        ushort  mode;
-        ushort  __pad1;
-        ushort  __seq;
-        ushort  __pad2;
-        c_ulong __unused1;
-        c_ulong __unused2;
-    }
-
-    enum IPC_CREAT      = 0x0200; // 01000
-    enum IPC_EXCL       = 0x0400; // 02000
-    enum IPC_NOWAIT     = 0x0800; // 04000
-
-    enum key_t IPC_PRIVATE = 0;
-
-    enum IPC_RMID       = 0;
-    enum IPC_SET        = 1;
-    enum IPC_STAT       = 2;
-    enum IPC_INFO       = 3;
-
     key_t ftok(const scope char*, int);
 }
+else
+{
+    static assert(false, "Unsupported platform");
+}
diff --git a/libphobos/libdruntime/core/sys/posix/sys/mman.d b/libphobos/libdruntime/core/sys/posix/sys/mman.d
index 18da102..33ce88f 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/mman.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/mman.d
@@ -54,6 +54,53 @@
 int posix_madvise(void*, size_t, int);
 */
 
+version (CRuntime_Glibc)
+{
+    static if (__USE_XOPEN2K)
+    {
+        int posix_madvise(void *__addr, size_t __len, int __advice);
+    }
+}
+else version (Darwin)
+{
+    int posix_madvise(void *addr, size_t len, int advice);
+}
+else version (FreeBSD)
+{
+    int posix_madvise(void *addr, size_t len, int advice);
+}
+else version (NetBSD)
+{
+    int posix_madvise(void *addr, size_t len, int advice);
+}
+else version (OpenBSD)
+{
+    int posix_madvise(void *addr, size_t len, int advice);
+}
+else version (DragonFlyBSD)
+{
+    int posix_madvise(void *addr, size_t len, int advice);
+}
+else version (Solaris)
+{
+}
+else version (CRuntime_Bionic)
+{
+}
+else version (CRuntime_Musl)
+{
+    int posix_madvise(void *, size_t, int);
+}
+else version (CRuntime_UClibc)
+{
+    int posix_madvise(void *__addr, size_t __len, int __advice);
+}
+else
+{
+    static assert(false, "Unsupported platform");
+}
+
+
 //
 // Advisory Information and either Memory Mapped Files or Shared Memory Objects (MC1)
 //
@@ -65,24 +112,20 @@
 POSIX_MADV_DONTNEED
 */
 
-version (CRuntime_Glibc)
+version (linux)
 {
     version (Alpha)
         private enum __POSIX_MADV_DONTNEED = 6;
     else
         private enum __POSIX_MADV_DONTNEED = 4;
 
-    static if (__USE_XOPEN2K)
+    enum
     {
-        enum
-        {
-            POSIX_MADV_NORMAL = 0,
-            POSIX_MADV_RANDOM = 1,
-            POSIX_MADV_SEQUENTIAL = 2,
-            POSIX_MADV_WILLNEED = 3,
-            POSIX_MADV_DONTNEED = __POSIX_MADV_DONTNEED,
-        }
-        int posix_madvise(void *__addr, size_t __len, int __advice);
+        POSIX_MADV_NORMAL = 0,
+        POSIX_MADV_RANDOM = 1,
+        POSIX_MADV_SEQUENTIAL = 2,
+        POSIX_MADV_WILLNEED = 3,
+        POSIX_MADV_DONTNEED = __POSIX_MADV_DONTNEED,
     }
 }
 else version (Darwin)
@@ -92,7 +135,6 @@
     enum POSIX_MADV_SEQUENTIAL  = 2;
     enum POSIX_MADV_WILLNEED    = 3;
     enum POSIX_MADV_DONTNEED    = 4;
-    int posix_madvise(void *addr, size_t len, int advice);
 }
 else version (FreeBSD)
 {
@@ -101,7 +143,6 @@
     enum POSIX_MADV_SEQUENTIAL  = 2;
     enum POSIX_MADV_WILLNEED    = 3;
     enum POSIX_MADV_DONTNEED    = 4;
-    int posix_madvise(void *addr, size_t len, int advice);
 }
 else version (NetBSD)
 {
@@ -110,7 +151,6 @@
     enum POSIX_MADV_SEQUENTIAL  = 2;
     enum POSIX_MADV_WILLNEED    = 3;
     enum POSIX_MADV_DONTNEED    = 4;
-    int posix_madvise(void *addr, size_t len, int advice);
 }
 else version (OpenBSD)
 {
@@ -119,7 +159,6 @@
     enum POSIX_MADV_SEQUENTIAL  = 2;
     enum POSIX_MADV_WILLNEED    = 3;
     enum POSIX_MADV_DONTNEED    = 4;
-    int posix_madvise(void *addr, size_t len, int advice);
 }
 else version (DragonFlyBSD)
 {
@@ -128,38 +167,10 @@
     enum POSIX_MADV_SEQUENTIAL  = 2;
     enum POSIX_MADV_WILLNEED    = 3;
     enum POSIX_MADV_DONTNEED    = 4;
-    int posix_madvise(void *addr, size_t len, int advice);
 }
 else version (Solaris)
 {
 }
-else version (CRuntime_Bionic)
-{
-}
-else version (CRuntime_Musl)
-{
-    enum
-    {
-        POSIX_MADV_NORMAL = 0,
-        POSIX_MADV_RANDOM = 1,
-        POSIX_MADV_SEQUENTIAL = 2,
-        POSIX_MADV_WILLNEED = 3,
-        POSIX_MADV_DONTNEED = 4,
-    }
-    int posix_madvise(void *, size_t, int);
-}
-else version (CRuntime_UClibc)
-{
-    enum
-    {
-        POSIX_MADV_NORMAL = 0,
-        POSIX_MADV_RANDOM = 1,
-        POSIX_MADV_SEQUENTIAL = 2,
-        POSIX_MADV_WILLNEED = 3,
-        POSIX_MADV_DONTNEED = 4,
-    }
-    int posix_madvise(void *__addr, size_t __len, int __advice);
-}
 else
 {
     static assert(false, "Unsupported platform");
@@ -175,7 +186,7 @@
 PROT_NONE
 */
 
-version (CRuntime_Glibc)
+version (linux)
 {
     enum PROT_NONE      = 0x0;
     enum PROT_READ      = 0x1;
@@ -224,27 +235,6 @@
     enum PROT_WRITE = 0x02;
     enum PROT_EXEC = 0x04;
 }
-else version (CRuntime_Bionic)
-{
-    enum PROT_NONE = 0x00;
-    enum PROT_READ = 0x01;
-    enum PROT_WRITE = 0x02;
-    enum PROT_EXEC = 0x04;
-}
-else version (CRuntime_Musl)
-{
-    enum PROT_NONE      = 0x0;
-    enum PROT_READ      = 0x1;
-    enum PROT_WRITE     = 0x2;
-    enum PROT_EXEC      = 0x4;
-}
-else version (CRuntime_UClibc)
-{
-    enum PROT_NONE      = 0x0;
-    enum PROT_READ      = 0x1;
-    enum PROT_WRITE     = 0x2;
-    enum PROT_EXEC      = 0x4;
-}
 else
 {
     static assert(false, "Unsupported platform");
@@ -337,11 +327,9 @@
 MS_ASYNC (MF|SIO)
 MS_SYNC (MF|SIO)
 MS_INVALIDATE (MF|SIO)
-
-int msync(void*, size_t, int); (MF|SIO)
 */
 
-version (CRuntime_Glibc)
+version (linux)
 {
     enum MAP_SHARED     = 0x01;
     enum MAP_PRIVATE    = 0x02;
@@ -405,8 +393,6 @@
         enum MS_INVALIDATE = 2;
         enum MS_SYNC = 4;
     }
-
-    int msync(void*, size_t, int);
 }
 else version (Darwin)
 {
@@ -420,8 +406,6 @@
     enum MS_ASYNC       = 0x0001;
     enum MS_INVALIDATE  = 0x0002;
     enum MS_SYNC        = 0x0010;
-
-    int msync(void*, size_t, int);
 }
 else version (FreeBSD)
 {
@@ -435,8 +419,6 @@
     enum MS_SYNC        = 0x0000;
     enum MS_ASYNC       = 0x0001;
     enum MS_INVALIDATE  = 0x0002;
-
-    int msync(void*, size_t, int);
 }
 else version (NetBSD)
 {
@@ -450,9 +432,6 @@
     enum MS_SYNC        = 0x0004;
     enum MS_ASYNC       = 0x0001;
     enum MS_INVALIDATE  = 0x0002;
-
-    int __msync13(void*, size_t, int);
-    alias msync = __msync13;
 }
 else version (OpenBSD)
 {
@@ -467,8 +446,6 @@
     enum MS_SYNC        = 0x0002;
     enum MS_ASYNC       = 0x0001;
     enum MS_INVALIDATE  = 0x0004;
-
-    int msync(void*, size_t, int);
 }
 else version (DragonFlyBSD)
 {
@@ -482,8 +459,6 @@
     enum MS_SYNC        = 0x0000;
     enum MS_ASYNC       = 0x0001;
     enum MS_INVALIDATE  = 0x0002;
-
-    int msync(void*, size_t, int);
 }
 else version (Solaris)
 {
@@ -497,72 +472,55 @@
     enum MS_SYNC = 0x0004;
     enum MS_ASYNC = 0x0001;
     enum MS_INVALIDATE  = 0x0002;
+}
+else
+{
+    static assert(false, "Unsupported platform");
+}
 
+/*
+int msync(void*, size_t, int); (MF|SIO)
+*/
+
+version (CRuntime_Glibc)
+{
+    int msync(void*, size_t, int);
+}
+else version (Darwin)
+{
+    int msync(void*, size_t, int);
+}
+else version (FreeBSD)
+{
+    int msync(void*, size_t, int);
+}
+else version (NetBSD)
+{
+    int __msync13(void*, size_t, int);
+    alias msync = __msync13;
+}
+else version (OpenBSD)
+{
+    int msync(void*, size_t, int);
+}
+else version (DragonFlyBSD)
+{
+    int msync(void*, size_t, int);
+}
+else version (Solaris)
+{
     int msync(void*, size_t, int);
 }
 else version (CRuntime_Bionic)
 {
-    enum MAP_SHARED     = 0x0001;
-    enum MAP_PRIVATE    = 0x0002;
-    enum MAP_FIXED      = 0x0010;
-    enum MAP_ANON       = 0x0020;
-
-    enum MAP_FAILED     = cast(void*)-1;
-
-    enum MS_SYNC        = 4;
-    enum MS_ASYNC       = 1;
-    enum MS_INVALIDATE  = 2;
-
     int msync(const scope void*, size_t, int);
 }
 else version (CRuntime_Musl)
 {
-    enum MAP_SHARED     = 0x01;
-    enum MAP_PRIVATE    = 0x02;
-    enum MAP_FIXED      = 0x10;
-
-    enum MAP_FAILED     = cast(void*) -1;
-    enum MAP_ANON = 0x20;
-    enum MS_ASYNC = 1;
-    enum MS_INVALIDATE = 2;
-    enum MS_SYNC = 4;
     int msync(void*, size_t, int);
 }
 else version (CRuntime_UClibc)
 {
-    enum MAP_SHARED     = 0x01;
-    enum MAP_PRIVATE    = 0x02;
-    enum MAP_FIXED      = 0x10;
-
-    enum MAP_FAILED     = cast(void*) -1;
-
-    version (X86_64)
-    {
-        enum MAP_ANON       = 0x20;
-        enum MS_ASYNC       = 1;
-        enum MS_INVALIDATE  = 2;
-        enum MS_SYNC        = 4;
-    }
-    else version (MIPS32)
-    {
-        enum MAP_ANON       = 0x0800;
-        enum MS_ASYNC       = 1;
-        enum MS_INVALIDATE  = 2;
-        enum MS_SYNC        = 4;
-    }
-    else version (ARM)
-    {
-        enum MAP_ANON       = 0x020;
-        enum MS_ASYNC       = 1;
-        enum MS_INVALIDATE  = 2;
-        enum MS_SYNC        = 4;
-    }
-    else
-    {
-        static assert(false, "Architecture not supported.");
-    }
-
-
     int msync(void*, size_t, int);
 }
 else
@@ -576,12 +534,9 @@
 /*
 MCL_CURRENT
 MCL_FUTURE
-
-int mlockall(int);
-int munlockall();
 */
 
-version (CRuntime_Glibc)
+version (linux)
 {
     version (SPARC_Any) enum
     {
@@ -603,89 +558,96 @@
         MCL_CURRENT = 1,
         MCL_FUTURE = 2,
     }
-
-    int mlockall(int);
-    int munlockall();
-
 }
 else version (Darwin)
 {
     enum MCL_CURRENT    = 0x0001;
     enum MCL_FUTURE     = 0x0002;
-
-    int mlockall(int);
-    int munlockall();
 }
 else version (FreeBSD)
 {
     enum MCL_CURRENT    = 0x0001;
     enum MCL_FUTURE     = 0x0002;
-
-    int mlockall(int);
-    int munlockall();
 }
 else version (NetBSD)
 {
     enum MCL_CURRENT    = 0x0001;
     enum MCL_FUTURE     = 0x0002;
-
-    int mlockall(int);
-    int munlockall();
 }
 else version (OpenBSD)
 {
     enum MCL_CURRENT    = 0x0001;
     enum MCL_FUTURE     = 0x0002;
-
-    int mlockall(int);
-    int munlockall();
 }
 else version (DragonFlyBSD)
 {
     enum MCL_CURRENT    = 0x0001;
     enum MCL_FUTURE     = 0x0002;
-
-    int mlockall(int);
-    int munlockall();
 }
 else version (Solaris)
 {
     enum MCL_CURRENT = 0x0001;
     enum MCL_FUTURE = 0x0002;
+}
+else
+{
+    static assert(false, "Unsupported platform");
+}
 
+/*
+int mlockall(int);
+int munlockall();
+*/
+
+version (CRuntime_Glibc)
+{
+    int mlockall(int);
+    int munlockall();
+}
+else version (Darwin)
+{
+    int mlockall(int);
+    int munlockall();
+}
+else version (FreeBSD)
+{
+    int mlockall(int);
+    int munlockall();
+}
+else version (NetBSD)
+{
+    int mlockall(int);
+    int munlockall();
+}
+else version (OpenBSD)
+{
+    int mlockall(int);
+    int munlockall();
+}
+else version (DragonFlyBSD)
+{
+    int mlockall(int);
+    int munlockall();
+}
+else version (Solaris)
+{
     int mlockall(int);
     int munlockall();
 }
 else version (CRuntime_Bionic)
 {
-    enum MCL_CURRENT = 1;
-    enum MCL_FUTURE  = 2;
-
     int mlockall(int);
     int munlockall();
 }
 else version (CRuntime_Musl)
 {
-    enum
-    {
-        MCL_CURRENT = 1,
-        MCL_FUTURE = 2,
-    }
-
     int mlockall(int);
     int munlockall();
 }
 else version (CRuntime_UClibc)
 {
-    enum
-    {
-        MCL_CURRENT = 1,
-        MCL_FUTURE = 2,
-    }
-
     int mlockall(int);
     int munlockall();
-
 }
 else
 {
diff --git a/libphobos/libdruntime/core/sys/posix/sys/resource.d b/libphobos/libdruntime/core/sys/posix/sys/resource.d
index c5d584c..5ab0174 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/resource.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/resource.d
@@ -52,12 +52,6 @@
     RUSAGE_CHILDREN,
 }
 
-struct rlimit
-{
-    rlim_t rlim_cur;
-    rlim_t rlim_max;
-}
-
 struct rusage
 {
     timeval ru_utime;
@@ -74,19 +68,10 @@
     RLIMIT_STACK,
     RLIMIT_AS,
 }
-
-int getpriority(int, id_t);
-int getrlimit(int, rlimit*);
-int getrusage(int, rusage*);
-int setpriority(int, id_t, int);
-int setrlimit(int, const rlimit*);
 */
 
-
-version (CRuntime_Glibc)
+version (linux)
 {
-    // rusage and some other constants in the Bionic section below really
-    // come from the linux kernel headers, but they're all mixed right now.
     enum
     {
         PRIO_PROCESS = 0,
@@ -111,6 +96,7 @@
     {
         RUSAGE_SELF     =  0,
         RUSAGE_CHILDREN = -1,
+        RUSAGE_THREAD = 1
     }
 
     struct rusage
@@ -131,6 +117,8 @@
         c_long ru_nsignals;
         c_long ru_nvcsw;
         c_long ru_nivcsw;
+        version (CRuntime_Musl)
+            c_long[16] __reserved;
     }
 
     enum
@@ -200,9 +188,8 @@
     enum
     {
         RLIM_INFINITY   = (cast(rlim_t)((cast(ulong) 1 << 63) - 1)),
-        // FreeBSD explicitly does not define the following:
-        //RLIM_SAVED_MAX,
-        //RLIM_SAVED_CUR,
+        RLIM_SAVED_MAX  = RLIM_INFINITY,
+        RLIM_SAVED_CUR  = RLIM_INFINITY,
     }
 
     enum
@@ -258,9 +245,8 @@
     enum
     {
         RLIM_INFINITY   = (cast(rlim_t)((cast(ulong) 1 << 63) - 1)),
-        // FreeBSD explicitly does not define the following:
-        //RLIM_SAVED_MAX,
-        //RLIM_SAVED_CUR,
+        RLIM_SAVED_MAX = RLIM_INFINITY,
+        RLIM_SAVED_CUR = RLIM_INFINITY,
     }
 
     enum
@@ -375,9 +361,8 @@
     enum
     {
         RLIM_INFINITY   = (cast(rlim_t)((cast(ulong) 1 << 63) - 1)),
-        // DragonFlyBSD explicitly does not define the following:
-        //RLIM_SAVED_MAX,
-        //RLIM_SAVED_CUR,
+        RLIM_SAVED_MAX  = RLIM_INFINITY,
+        RLIM_SAVED_CUR  = RLIM_INFINITY,
     }
 
     enum
@@ -474,162 +459,22 @@
         RLIMIT_AS     = 6,
     }
 }
-else version (CRuntime_Bionic)
+else
+    static assert (false, "Unsupported platform");
+
+/*
+struct rlimit
 {
-    enum
-    {
-        PRIO_PROCESS = 0,
-        PRIO_PGRP    = 1,
-        PRIO_USER    = 2,
-    }
-
-    alias c_ulong rlim_t;
-    enum RLIM_INFINITY = cast(c_ulong)(~0UL);
-
-    enum
-    {
-        RUSAGE_SELF     =  0,
-        RUSAGE_CHILDREN = -1,
-    }
-
-    struct rusage
-    {
-        timeval ru_utime;
-        timeval ru_stime;
-        c_long ru_maxrss;
-        c_long ru_ixrss;
-        c_long ru_idrss;
-        c_long ru_isrss;
-        c_long ru_minflt;
-        c_long ru_majflt;
-        c_long ru_nswap;
-        c_long ru_inblock;
-        c_long ru_oublock;
-        c_long ru_msgsnd;
-        c_long ru_msgrcv;
-        c_long ru_nsignals;
-        c_long ru_nvcsw;
-        c_long ru_nivcsw;
-    }
-
-    enum
-    {
-        RLIMIT_CORE   = 4,
-        RLIMIT_CPU    = 0,
-        RLIMIT_DATA   = 2,
-        RLIMIT_FSIZE  = 1,
-        RLIMIT_NOFILE = 7,
-        RLIMIT_STACK  = 3,
-        RLIMIT_AS     = 9,
-    }
+    rlim_t rlim_cur;
+    rlim_t rlim_max;
 }
-else version (CRuntime_Musl)
-{
-    alias ulong rlim_t;
-    enum RLIM_INFINITY = cast(c_ulong)(~0UL);
 
-    int getrlimit(int, rlimit*);
-    int setrlimit(int, const scope rlimit*);
-    alias getrlimit getrlimit64;
-    alias setrlimit setrlimit64;
-    enum
-    {
-        RUSAGE_SELF = 0,
-        RUSAGE_CHILDREN = -1,
-        RUSAGE_THREAD = 1
-    }
-    struct rusage
-    {
-        timeval ru_utime;
-        timeval ru_stime;
-        c_long ru_maxrss;
-        c_long ru_ixrss;
-        c_long ru_idrss;
-        c_long ru_isrss;
-        c_long ru_minflt;
-        c_long ru_majflt;
-        c_long ru_nswap;
-        c_long ru_inblock;
-        c_long ru_oublock;
-        c_long ru_msgsnd;
-        c_long ru_msgrcv;
-        c_long ru_nsignals;
-        c_long ru_nvcsw;
-        c_long ru_nivcsw;
-        c_long[16] __reserved;
-    }
-
-    enum
-    {
-        RLIMIT_CPU    = 0,
-        RLIMIT_FSIZE  = 1,
-        RLIMIT_DATA   = 2,
-        RLIMIT_STACK  = 3,
-        RLIMIT_CORE   = 4,
-        RLIMIT_NOFILE = 7,
-        RLIMIT_AS     = 9,
-    }
-}
-else version (CRuntime_UClibc)
-{
-    enum
-    {
-        PRIO_PROCESS = 0,
-        PRIO_PGRP    = 1,
-        PRIO_USER    = 2,
-    }
-
-    static if (__USE_FILE_OFFSET64)
-         alias ulong rlim_t;
-    else
-         alias c_ulong rlim_t;
-
-    static if (__USE_FILE_OFFSET64)
-        enum RLIM_INFINITY = 0xffffffffffffffffUL;
-    else
-        enum RLIM_INFINITY = cast(c_ulong)(~0UL);
-
-    enum RLIM_SAVED_MAX = RLIM_INFINITY;
-    enum RLIM_SAVED_CUR = RLIM_INFINITY;
-
-    enum
-    {
-        RUSAGE_SELF     =  0,
-        RUSAGE_CHILDREN = -1,
-    }
-
-    struct rusage
-    {
-        timeval ru_utime;
-        timeval ru_stime;
-        c_long ru_maxrss;
-        c_long ru_ixrss;
-        c_long ru_idrss;
-        c_long ru_isrss;
-        c_long ru_minflt;
-        c_long ru_majflt;
-        c_long ru_nswap;
-        c_long ru_inblock;
-        c_long ru_oublock;
-        c_long ru_msgsnd;
-        c_long ru_msgrcv;
-        c_long ru_nsignals;
-        c_long ru_nvcsw;
-        c_long ru_nivcsw;
-    }
-
-    enum
-    {
-        RLIMIT_CORE   = 4,
-        RLIMIT_CPU    = 0,
-        RLIMIT_DATA   = 2,
-        RLIMIT_FSIZE  = 1,
-        RLIMIT_NOFILE = 7,
-        RLIMIT_STACK  = 3,
-        RLIMIT_AS     = 9,
-    }
-}
-else static assert (false, "Unsupported platform");
+int getpriority(int, id_t);
+int getrlimit(int, rlimit*);
+int getrusage(int, rusage*);
+int setpriority(int, id_t, int);
+int setrlimit(int, const rlimit*);
+*/
 
 struct rlimit
 {
@@ -641,40 +486,6 @@
 {
     int getpriority(int, id_t);
     int setpriority(int, id_t, int);
-}
-else version (FreeBSD)
-{
-    int getpriority(int, int);
-    int setpriority(int, int, int);
-}
-else version (DragonFlyBSD)
-{
-    int getpriority(int, int);
-    int setpriority(int, int, int);
-}
-else version (CRuntime_Bionic)
-{
-    int getpriority(int, int);
-    int setpriority(int, int, int);
-}
-else version (Solaris)
-{
-    int getpriority(int, id_t);
-    int setpriority(int, id_t, int);
-}
-else version (Darwin)
-{
-    int getpriority(int, id_t);
-    int setpriority(int, id_t, int);
-}
-else version (CRuntime_UClibc)
-{
-    int getpriority(int, id_t);
-    int setpriority(int, id_t, int);
-}
-
-version (CRuntime_Glibc)
-{
     static if (__USE_FILE_OFFSET64)
     {
         int getrlimit64(int, rlimit*);
@@ -689,50 +500,76 @@
     }
     int getrusage(int, rusage*);
 }
-else version (CRuntime_Bionic)
-{
-    int getrlimit(int, rlimit*);
-    int getrusage(int, rusage*);
-    int setrlimit(int, const scope rlimit*);
-}
-else version (Darwin)
-{
-    int getrlimit(int, rlimit*);
-    int getrusage(int, rusage*);
-    int setrlimit(int, const scope rlimit*);
-}
 else version (FreeBSD)
 {
+    int getpriority(int, int);
     int getrlimit(int, rlimit*);
     int getrusage(int, rusage*);
+    int setpriority(int, int, int);
     int setrlimit(int, const scope rlimit*);
 }
 else version (NetBSD)
 {
+    int getpriority(int, int);
     int getrlimit(int, rlimit*);
     int getrusage(int, rusage*);
+    int setpriority(int, int, int);
     int setrlimit(int, const scope rlimit*);
 }
 else version (OpenBSD)
 {
+    int getpriority(int, int);
     int getrlimit(int, rlimit*);
     int getrusage(int, rusage*);
+    int setpriority(int, int, int);
     int setrlimit(int, const scope rlimit*);
 }
 else version (DragonFlyBSD)
 {
+    int getpriority(int, int);
     int getrlimit(int, rlimit*);
     int getrusage(int, rusage*);
+    int setpriority(int, int, int);
     int setrlimit(int, const scope rlimit*);
 }
+else version (CRuntime_Bionic)
+{
+    int getpriority(int, int);
+    int getrlimit(int, rlimit*);
+    int getrusage(int, rusage*);
+    int setpriority(int, int, int);
+    int setrlimit(int, const scope rlimit*);
+}
+else version (CRuntime_Musl)
+{
+    int getpriority(int, id_t);
+    int setpriority(int, id_t, int);
+    int getrlimit(int, rlimit*);
+    int setrlimit(int, const scope rlimit*);
+    alias getrlimit getrlimit64;
+    alias setrlimit setrlimit64;
+    int getrusage(int, rusage*);
+}
 else version (Solaris)
 {
+    int getpriority(int, int);
     int getrlimit(int, rlimit*);
     int getrusage(int, rusage*);
+    int setpriority(int, int, int);
+    int setrlimit(int, const scope rlimit*);
+}
+else version (Darwin)
+{
+    int getpriority(int, id_t);
+    int getrlimit(int, rlimit*);
+    int getrusage(int, rusage*);
+    int setpriority(int, id_t, int);
     int setrlimit(int, const scope rlimit*);
 }
 else version (CRuntime_UClibc)
 {
+    int getpriority(int, id_t);
+    int setpriority(int, id_t, int);
     static if (__USE_FILE_OFFSET64)
     {
         int getrlimit64(int, rlimit*);
@@ -747,3 +584,5 @@
     }
     int getrusage(int, rusage*);
 }
+else
+    static assert (false, "Unsupported platform");
diff --git a/libphobos/libdruntime/core/sys/posix/sys/shm.d b/libphobos/libdruntime/core/sys/posix/sys/shm.d
index 2e85096..ce34141 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/shm.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/shm.d
@@ -38,8 +38,6 @@
 SHM_RDONLY
 SHM_RND
 
-SHMLBA
-
 shmatt_t
 
 struct shmid_ds
@@ -53,20 +51,13 @@
     time_t      shm_dtime;
     time_t      shm_ctime;
 }
-
-void* shmat(int, const scope void*, int);
-int   shmctl(int, int, shmid_ds*);
-int   shmdt(const scope void*);
-int   shmget(key_t, size_t, int);
 */
 
-version (CRuntime_Glibc)
+version (linux)
 {
     enum SHM_RDONLY     = 0x01000; // 010000
     enum SHM_RND        = 0x02000; // 020000
-
-    int   __getpagesize();
-    alias __getpagesize SHMLBA;
+    enum SHM_REMAP      = 0x4000; // 040000
 
     alias c_ulong   shmatt_t;
 
@@ -87,17 +78,11 @@
         c_ulong     __unused4;
         c_ulong     __unused5;
     }
-
-    void* shmat(int, const scope void*, int);
-    int   shmctl(int, int, shmid_ds*);
-    int   shmdt(const scope void*);
-    int   shmget(key_t, size_t, int);
 }
 else version (FreeBSD)
 {
     enum SHM_RDONLY     = 0x01000; // 010000
     enum SHM_RND        = 0x02000; // 020000
-    enum SHMLBA         = 1 << 12; // PAGE_SIZE = (1<<PAGE_SHIFT)
 
     alias c_ulong   shmatt_t;
 
@@ -125,17 +110,11 @@
          time_t      shm_dtime;
          time_t      shm_ctime;
     }
-
-    void* shmat(int, const scope void*, int);
-    int   shmctl(int, int, shmid_ds*);
-    int   shmdt(const scope void*);
-    int   shmget(key_t, size_t, int);
 }
 else version (NetBSD)
 {
     enum SHM_RDONLY     = 0x01000; // 010000
     enum SHM_RND        = 0x02000; // 020000
-    enum SHMLBA         = 1 << 12; // PAGE_SIZE = (1<<PAGE_SHIFT)
 
     alias c_ulong   shmatt_t;
 
@@ -151,17 +130,11 @@
         time_t          shm_ctime;
         void*           shm_internal;
     }
-
-    void* shmat(int, const scope void*, int);
-    int   shmctl(int, int, shmid_ds*);
-    int   shmdt(const scope void*);
-    int   shmget(key_t, size_t, int);
 }
 else version (OpenBSD)
 {
     enum SHM_RDONLY     = 0x01000; // 010000
     enum SHM_RND        = 0x02000; // 020000
-    enum SHMLBA         = 1 << _MAX_PAGE_SHIFT;
 
     alias short shmatt_t;
 
@@ -180,17 +153,11 @@
         c_long   __shm_ctimensec;
         void*      shm_internal;
     }
-
-    void* shmat(int, const scope void*, int);
-    int   shmctl(int, int, shmid_ds*);
-    int   shmdt(const scope void*);
-    int   shmget(key_t, size_t, int);
 }
 else version (DragonFlyBSD)
 {
     enum SHM_RDONLY     = 0x01000; // 010000
     enum SHM_RND        = 0x02000; // 020000
-    enum SHMLBA         = 1 << 12; // PAGE_SIZE = (1<<PAGE_SHIFT)
 
     alias c_ulong   shmatt_t;
 
@@ -206,6 +173,69 @@
          time_t         shm_ctime;
          private void*  shm_internal;
     }
+}
+else version (Darwin)
+{
+
+}
+else version (Solaris)
+{
+
+}
+else
+{
+    static assert(false, "Unsupported platform");
+}
+
+/*
+SHMLBA
+
+void* shmat(int, const scope void*, int);
+int   shmctl(int, int, shmid_ds*);
+int   shmdt(const scope void*);
+int   shmget(key_t, size_t, int);
+*/
+
+version (CRuntime_Glibc)
+{
+    int   __getpagesize();
+    alias __getpagesize SHMLBA;
+
+    void* shmat(int, const scope void*, int);
+    int   shmctl(int, int, shmid_ds*);
+    int   shmdt(const scope void*);
+    int   shmget(key_t, size_t, int);
+}
+else version (FreeBSD)
+{
+    enum SHMLBA = 1 << 12; // PAGE_SIZE = (1<<PAGE_SHIFT)
+
+    void* shmat(int, const scope void*, int);
+    int   shmctl(int, int, shmid_ds*);
+    int   shmdt(const scope void*);
+    int   shmget(key_t, size_t, int);
+}
+else version (NetBSD)
+{
+    enum SHMLBA = 1 << 12; // PAGE_SIZE = (1<<PAGE_SHIFT)
+
+    void* shmat(int, const scope void*, int);
+    int   shmctl(int, int, shmid_ds*);
+    int   shmdt(const scope void*);
+    int   shmget(key_t, size_t, int);
+}
+else version (OpenBSD)
+{
+    enum SHMLBA = 1 << _MAX_PAGE_SHIFT;
+
+    void* shmat(int, const scope void*, int);
+    int   shmctl(int, int, shmid_ds*);
+    int   shmdt(const scope void*);
+    int   shmget(key_t, size_t, int);
+}
+else version (DragonFlyBSD)
+{
+    enum SHMLBA = 1 << 12; // PAGE_SIZE = (1<<PAGE_SHIFT)
 
     void* shmat(int, const scope void*, int);
     int   shmctl(int, int, shmid_ds*);
@@ -216,66 +246,30 @@
 {
 
 }
-else version (CRuntime_UClibc)
+else version (Solaris)
 {
-    enum SHM_RDONLY     = 0x1000; // 010000
-    enum SHM_RND        = 0x2000; // 020000
-    enum SHM_REMAP      = 0x4000; // 040000
 
-    int   __getpagesize();
-    alias __getpagesize SHMLBA;
-
-    alias c_ulong   shmatt_t;
-
-    version (X86_64)
-        enum includeUnused  = false;
-    else version (MIPS32)
-        enum includeUnused  = false;
-    else
-        enum includeUnused  = true;
-
-    struct shmid_ds
-    {
-        ipc_perm    shm_perm;
-        size_t      shm_segsz;
-        time_t      shm_atime;
-        static if (includeUnused) c_ulong     __unused1;
-        time_t      shm_dtime;
-        static if (includeUnused) c_ulong     __unused2;
-        time_t      shm_ctime;
-        static if (includeUnused) c_ulong     __unused3;
-        pid_t       shm_cpid;
-        pid_t       shm_lpid;
-        shmatt_t    shm_nattch;
-        c_ulong     __unused4;
-        c_ulong     __unused5;
-    }
-
-    struct shminfo
-    {
-        c_ulong shmmax;
-        c_ulong shmmin;
-        c_ulong shmmni;
-        c_ulong shmseg;
-        c_ulong shmall;
-        c_ulong __unused1;
-        c_ulong __unused2;
-        c_ulong __unused3;
-        c_ulong __unused4;
-    }
-
-    struct shm_info
-    {
-        int used_ids;
-        c_ulong shm_tot;
-        c_ulong shm_rss;
-        c_ulong shm_swp;
-        c_ulong swap_attempts;
-        c_ulong swap_successes;
-    }
+}
+else version (CRuntime_Musl)
+{
+    enum SHMLBA = 4096;
 
     void* shmat(int, const scope void*, int);
     int   shmctl(int, int, shmid_ds*);
     int   shmdt(const scope void*);
     int   shmget(key_t, size_t, int);
 }
+else version (CRuntime_UClibc)
+{
+    int   __getpagesize();
+    alias __getpagesize SHMLBA;
+
+    void* shmat(int, const scope void*, int);
+    int   shmctl(int, int, shmid_ds*);
+    int   shmdt(const scope void*);
+    int   shmget(key_t, size_t, int);
+}
+else
+{
+    static assert(false, "Unsupported platform");
+}
diff --git a/libphobos/libdruntime/core/sys/posix/sys/socket.d b/libphobos/libdruntime/core/sys/posix/sys/socket.d
index 6e0cfd3..670ead7 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/socket.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/socket.d
@@ -137,31 +137,10 @@
 SHUT_RD
 SHUT_RDWR
 SHUT_WR
-
-int     accept(int, sockaddr*, socklen_t*);
-int     bind(int, const scope sockaddr*, socklen_t);
-int     connect(int, const scope sockaddr*, socklen_t);
-int     getpeername(int, sockaddr*, socklen_t*);
-int     getsockname(int, sockaddr*, socklen_t*);
-int     getsockopt(int, int, int, void*, socklen_t*);
-int     listen(int, int);
-ssize_t recv(int, void*, size_t, int);
-ssize_t recvfrom(int, void*, size_t, int, sockaddr*, socklen_t*);
-ssize_t recvmsg(int, msghdr*, int);
-ssize_t send(int, const scope void*, size_t, int);
-ssize_t sendmsg(int, const scope msghdr*, int);
-ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
-int     setsockopt(int, int, int, const scope void*, socklen_t);
-int     shutdown(int, int);
-int     socket(int, int, int);
-int     sockatmark(int);
-int     socketpair(int, int, int, ref int[2]);
 */
 
-version (CRuntime_Glibc)
+version (linux)
 {
-    // Some of the constants below and from the Bionic section are really from
-    // the linux kernel headers.
     alias uint   socklen_t;
     alias ushort sa_family_t;
 
@@ -174,14 +153,14 @@
     private enum : size_t
     {
         _SS_SIZE    = 128,
-        _SS_PADSIZE = _SS_SIZE - (c_ulong.sizeof * 2)
+        _SS_PADSIZE = _SS_SIZE - c_ulong.sizeof - sa_family_t.sizeof
     }
 
     struct sockaddr_storage
     {
         sa_family_t ss_family;
-        c_ulong     __ss_align;
         byte[_SS_PADSIZE] __ss_padding;
+        c_ulong     __ss_align;
     }
 
     struct msghdr
@@ -200,10 +179,6 @@
         size_t cmsg_len;
         int    cmsg_level;
         int    cmsg_type;
-        static if ( false /* (!is( __STRICT_ANSI__ ) && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L */ )
-        {
-            ubyte[1] __cmsg_data;
-        }
     }
 
     enum : uint
@@ -211,14 +186,7 @@
         SCM_RIGHTS = 0x01
     }
 
-    static if ( false /* (!is( __STRICT_ANSI__ ) && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L */ )
-    {
-        extern (D) ubyte[1] CMSG_DATA( cmsghdr* cmsg ) pure nothrow @nogc { return cmsg.__cmsg_data; }
-    }
-    else
-    {
-        extern (D) inout(ubyte)*   CMSG_DATA( return scope inout(cmsghdr)* cmsg ) pure nothrow @nogc { return cast(ubyte*)( cmsg + 1 ); }
-    }
+    extern (D) inout(ubyte)*   CMSG_DATA( return scope inout(cmsghdr)* cmsg ) pure nothrow @nogc { return cast(ubyte*)( cmsg + 1 ); }
 
     private inout(cmsghdr)* __cmsg_nxthdr(inout(msghdr)*, inout(cmsghdr)*) pure nothrow @nogc;
     extern (D)  inout(cmsghdr)* CMSG_NXTHDR(inout(msghdr)* msg, inout(cmsghdr)* cmsg) pure nothrow @nogc
@@ -534,10 +502,19 @@
     else
         static assert(0, "unimplemented");
 
-    enum
+    version (CRuntime_Glibc)
     {
-        // https://sourceware.org/git/?p=glibc.git;a=commit;f=sysdeps/unix/sysv/linux/bits/socket.h;h=96958e2700f5b4f4d1183a0606b2b9848a53ea44
-        SOMAXCONN       = 4096
+        enum
+        {
+            SOMAXCONN   = 4096
+        }
+    }
+    else
+    {
+        enum
+        {
+            SOMAXCONN   = 128
+        }
     }
 
     enum : uint
@@ -571,25 +548,6 @@
         SHUT_WR,
         SHUT_RDWR
     }
-
-    int     accept(int, scope sockaddr*, scope socklen_t*);
-    int     bind(int, const scope sockaddr*, socklen_t);
-    int     connect(int, const scope sockaddr*, socklen_t);
-    int     getpeername(int, scope sockaddr*, scope socklen_t*);
-    int     getsockname(int, scope sockaddr*, scope socklen_t*);
-    int     getsockopt(int, int, int, scope void*, scope socklen_t*);
-    int     listen(int, int) @safe;
-    ssize_t recv(int, scope void*, size_t, int);
-    ssize_t recvfrom(int, scope void*, size_t, int, scope sockaddr*, scope socklen_t*);
-    ssize_t recvmsg(int, scope msghdr*, int);
-    ssize_t send(int, const scope void*, size_t, int);
-    ssize_t sendmsg(int, const scope msghdr*, int);
-    ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
-    int     setsockopt(int, int, int, const scope void*, socklen_t);
-    int     shutdown(int, int) @safe;
-    int     socket(int, int, int) @safe;
-    int     sockatmark(int) @safe;
-    int     socketpair(int, int, int, ref int[2]) @safe;
 }
 else version (Darwin)
 {
@@ -727,25 +685,6 @@
         SHUT_WR,
         SHUT_RDWR
     }
-
-    int     accept(int, scope sockaddr*, scope socklen_t*);
-    int     bind(int, const scope sockaddr*, socklen_t);
-    int     connect(int, const scope sockaddr*, socklen_t);
-    int     getpeername(int, scope sockaddr*, scope socklen_t*);
-    int     getsockname(int, scope sockaddr*, scope socklen_t*);
-    int     getsockopt(int, int, int, scope void*, scope socklen_t*);
-    int     listen(int, int) @safe;
-    ssize_t recv(int, scope void*, size_t, int);
-    ssize_t recvfrom(int, scope void*, size_t, int, scope sockaddr*, scope socklen_t*);
-    ssize_t recvmsg(int, scope msghdr*, int);
-    ssize_t send(int, const scope void*, size_t, int);
-    ssize_t sendmsg(int, const scope msghdr*, int);
-    ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
-    int     setsockopt(int, int, int, const scope void*, socklen_t);
-    int     shutdown(int, int) @safe;
-    int     socket(int, int, int) @safe;
-    int     sockatmark(int) @safe;
-    int     socketpair(int, int, int, ref int[2]) @safe;
 }
 else version (FreeBSD)
 {
@@ -904,25 +843,6 @@
         SHUT_WR = 1,
         SHUT_RDWR = 2
     }
-
-    int     accept(int, scope sockaddr*, scope socklen_t*);
-    int     bind(int, const scope sockaddr*, socklen_t);
-    int     connect(int, const scope sockaddr*, socklen_t);
-    int     getpeername(int, scope sockaddr*, scope socklen_t*);
-    int     getsockname(int, scope sockaddr*, scope socklen_t*);
-    int     getsockopt(int, int, int, scope void*, scope socklen_t*);
-    int     listen(int, int) @safe;
-    ssize_t recv(int, scope void*, size_t, int);
-    ssize_t recvfrom(int, scope void*, size_t, int, scope sockaddr*, scope socklen_t*);
-    ssize_t recvmsg(int, scope msghdr*, int);
-    ssize_t send(int, const scope void*, size_t, int);
-    ssize_t sendmsg(int, const scope msghdr*, int);
-    ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
-    int     setsockopt(int, int, int, const scope void*, socklen_t);
-    int     shutdown(int, int) @safe;
-    int     socket(int, int, int) @safe;
-    int     sockatmark(int) @safe;
-    int     socketpair(int, int, int, ref int[2]) @safe;
 }
 else version (NetBSD)
 {
@@ -1101,25 +1021,6 @@
         SHUT_WR = 1,
         SHUT_RDWR = 2
     }
-
-    int     accept(int, scope sockaddr*, scope socklen_t*);
-    int     bind(int, const scope sockaddr*, socklen_t);
-    int     connect(int, const scope sockaddr*, socklen_t);
-    int     getpeername(int, scope sockaddr*, scope socklen_t*);
-    int     getsockname(int, scope sockaddr*, scope socklen_t*);
-    int     getsockopt(int, int, int, scope void*, scope socklen_t*);
-    int     listen(int, int) @safe;
-    ssize_t recv(int, scope void*, size_t, int);
-    ssize_t recvfrom(int, scope void*, size_t, int, scope sockaddr*, scope socklen_t*);
-    ssize_t recvmsg(int, scope msghdr*, int);
-    ssize_t send(int, const scope void*, size_t, int);
-    ssize_t sendmsg(int, const scope msghdr*, int);
-    ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
-    int     setsockopt(int, int, int, const scope void*, socklen_t);
-    int     shutdown(int, int) @safe;
-    int     socket(int, int, int) @safe;
-    int     sockatmark(int) @safe;
-    int     socketpair(int, int, int, ref int[2]) @safe;
 }
 else version (OpenBSD)
 {
@@ -1274,25 +1175,6 @@
         SHUT_WR = 1,
         SHUT_RDWR = 2
     }
-
-    int     accept(int, scope sockaddr*, scope socklen_t*);
-    int     bind(int, const scope sockaddr*, socklen_t);
-    int     connect(int, const scope sockaddr*, socklen_t);
-    int     getpeername(int, scope sockaddr*, scope socklen_t*);
-    int     getsockname(int, scope sockaddr*, scope socklen_t*);
-    int     getsockopt(int, int, int, scope void*, scope socklen_t*);
-    int     listen(int, int) @safe;
-    ssize_t recv(int, scope void*, size_t, int);
-    ssize_t recvfrom(int, scope void*, size_t, int, scope sockaddr*, scope socklen_t*);
-    ssize_t recvmsg(int, scope msghdr*, int);
-    ssize_t send(int, const scope void*, size_t, int);
-    ssize_t sendmsg(int, const scope msghdr*, int);
-    ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
-    int     setsockopt(int, int, int, const scope void*, socklen_t);
-    int     shutdown(int, int) @safe;
-    int     socket(int, int, int) @safe;
-    int     sockatmark(int) @safe;
-    int     socketpair(int, int, int, ref int[2]) @safe;
 }
 else version (DragonFlyBSD)
 {
@@ -1493,39 +1375,6 @@
         SHUT_WR             = 1,
         SHUT_RDWR           = 2
     }
-
-/*
-    /+ sendfile(2) header/trailer struct +/
-    struct sf_hdtr {
-        iovec *             headers;
-        int                 hdr_cnt;
-        iovec *             trailers;
-        int                 trl_cnt;
-    }
-*/
-
-    int     accept(int, sockaddr*, socklen_t*);
-//    int     accept4(int, sockaddr*, socklen_t*, int);
-    int     bind(int, const scope sockaddr*, socklen_t);
-    int     connect(int, const scope sockaddr*, socklen_t);
-//    int     extconnect(int, int, sockaddr*, socklen_t);
-    int     getpeername(int, sockaddr*, socklen_t*);
-    int     getsockname(int, sockaddr*, socklen_t*);
-    int     getsockopt(int, int, int, void*, socklen_t*);
-    int     listen(int, int);
-    ssize_t recv(int, void*, size_t, int);
-    ssize_t recvfrom(int, void*, size_t, int, sockaddr*, socklen_t*);
-    ssize_t recvmsg(int, msghdr*, int);
-    ssize_t send(int, const scope void*, size_t, int);
-    ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
-    ssize_t sendmsg(int, const scope msghdr*, int);
-//    int     sendfile(int, int, off_t, size_t, sf_hdtr *, off_t *, int);
-    int     setsockopt(int, int, int, const scope void*, socklen_t);
-    int     shutdown(int, int);
-    int     sockatmark(int);
-    int     socket(int, int, int);
-    int     socketpair(int, int, int, ref int[2]);
-//  void    pfctlinput(int, struct sockaddr *);
 }
 else version (Solaris)
 {
@@ -1655,7 +1504,165 @@
         SHUT_WR,
         SHUT_RDWR
     }
+}
+else
+{
+    static assert(false, "Unsupported platform");
+}
 
+/*
+int     accept(int, sockaddr*, socklen_t*);
+int     bind(int, const scope sockaddr*, socklen_t);
+int     connect(int, const scope sockaddr*, socklen_t);
+int     getpeername(int, sockaddr*, socklen_t*);
+int     getsockname(int, sockaddr*, socklen_t*);
+int     getsockopt(int, int, int, void*, socklen_t*);
+int     listen(int, int);
+ssize_t recv(int, void*, size_t, int);
+ssize_t recvfrom(int, void*, size_t, int, sockaddr*, socklen_t*);
+ssize_t recvmsg(int, msghdr*, int);
+ssize_t send(int, const scope void*, size_t, int);
+ssize_t sendmsg(int, const scope msghdr*, int);
+ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
+int     setsockopt(int, int, int, const scope void*, socklen_t);
+int     shutdown(int, int);
+int     socket(int, int, int);
+int     sockatmark(int);
+int     socketpair(int, int, int, ref int[2]);
+*/
+
+version (CRuntime_Glibc)
+{
+    int     accept(int, scope sockaddr*, scope socklen_t*);
+    int     bind(int, const scope sockaddr*, socklen_t);
+    int     connect(int, const scope sockaddr*, socklen_t);
+    int     getpeername(int, scope sockaddr*, scope socklen_t*);
+    int     getsockname(int, scope sockaddr*, scope socklen_t*);
+    int     getsockopt(int, int, int, scope void*, scope socklen_t*);
+    int     listen(int, int) @safe;
+    ssize_t recv(int, scope void*, size_t, int);
+    ssize_t recvfrom(int, scope void*, size_t, int, scope sockaddr*, scope socklen_t*);
+    ssize_t recvmsg(int, scope msghdr*, int);
+    ssize_t send(int, const scope void*, size_t, int);
+    ssize_t sendmsg(int, const scope msghdr*, int);
+    ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
+    int     setsockopt(int, int, int, const scope void*, socklen_t);
+    int     shutdown(int, int) @safe;
+    int     socket(int, int, int) @safe;
+    int     sockatmark(int) @safe;
+    int     socketpair(int, int, int, ref int[2]) @safe;
+}
+else version (Darwin)
+{
+    int     accept(int, scope sockaddr*, scope socklen_t*);
+    int     bind(int, const scope sockaddr*, socklen_t);
+    int     connect(int, const scope sockaddr*, socklen_t);
+    int     getpeername(int, scope sockaddr*, scope socklen_t*);
+    int     getsockname(int, scope sockaddr*, scope socklen_t*);
+    int     getsockopt(int, int, int, scope void*, scope socklen_t*);
+    int     listen(int, int) @safe;
+    ssize_t recv(int, scope void*, size_t, int);
+    ssize_t recvfrom(int, scope void*, size_t, int, scope sockaddr*, scope socklen_t*);
+    ssize_t recvmsg(int, scope msghdr*, int);
+    ssize_t send(int, const scope void*, size_t, int);
+    ssize_t sendmsg(int, const scope msghdr*, int);
+    ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
+    int     setsockopt(int, int, int, const scope void*, socklen_t);
+    int     shutdown(int, int) @safe;
+    int     socket(int, int, int) @safe;
+    int     sockatmark(int) @safe;
+    int     socketpair(int, int, int, ref int[2]) @safe;
+}
+else version (FreeBSD)
+{
+    int     accept(int, scope sockaddr*, scope socklen_t*);
+    int     bind(int, const scope sockaddr*, socklen_t);
+    int     connect(int, const scope sockaddr*, socklen_t);
+    int     getpeername(int, scope sockaddr*, scope socklen_t*);
+    int     getsockname(int, scope sockaddr*, scope socklen_t*);
+    int     getsockopt(int, int, int, scope void*, scope socklen_t*);
+    int     listen(int, int) @safe;
+    ssize_t recv(int, scope void*, size_t, int);
+    ssize_t recvfrom(int, scope void*, size_t, int, scope sockaddr*, scope socklen_t*);
+    ssize_t recvmsg(int, scope msghdr*, int);
+    ssize_t send(int, const scope void*, size_t, int);
+    ssize_t sendmsg(int, const scope msghdr*, int);
+    ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
+    int     setsockopt(int, int, int, const scope void*, socklen_t);
+    int     shutdown(int, int) @safe;
+    int     socket(int, int, int) @safe;
+    int     sockatmark(int) @safe;
+    int     socketpair(int, int, int, ref int[2]) @safe;
+}
+else version (NetBSD)
+{
+    int     accept(int, scope sockaddr*, scope socklen_t*);
+    int     bind(int, const scope sockaddr*, socklen_t);
+    int     connect(int, const scope sockaddr*, socklen_t);
+    int     getpeername(int, scope sockaddr*, scope socklen_t*);
+    int     getsockname(int, scope sockaddr*, scope socklen_t*);
+    int     getsockopt(int, int, int, scope void*, scope socklen_t*);
+    int     listen(int, int) @safe;
+    ssize_t recv(int, scope void*, size_t, int);
+    ssize_t recvfrom(int, scope void*, size_t, int, scope sockaddr*, scope socklen_t*);
+    ssize_t recvmsg(int, scope msghdr*, int);
+    ssize_t send(int, const scope void*, size_t, int);
+    ssize_t sendmsg(int, const scope msghdr*, int);
+    ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
+    int     setsockopt(int, int, int, const scope void*, socklen_t);
+    int     shutdown(int, int) @safe;
+    int     socket(int, int, int) @safe;
+    int     sockatmark(int) @safe;
+    int     socketpair(int, int, int, ref int[2]) @safe;
+}
+else version (OpenBSD)
+{
+    int     accept(int, scope sockaddr*, scope socklen_t*);
+    int     bind(int, const scope sockaddr*, socklen_t);
+    int     connect(int, const scope sockaddr*, socklen_t);
+    int     getpeername(int, scope sockaddr*, scope socklen_t*);
+    int     getsockname(int, scope sockaddr*, scope socklen_t*);
+    int     getsockopt(int, int, int, scope void*, scope socklen_t*);
+    int     listen(int, int) @safe;
+    ssize_t recv(int, scope void*, size_t, int);
+    ssize_t recvfrom(int, scope void*, size_t, int, scope sockaddr*, scope socklen_t*);
+    ssize_t recvmsg(int, scope msghdr*, int);
+    ssize_t send(int, const scope void*, size_t, int);
+    ssize_t sendmsg(int, const scope msghdr*, int);
+    ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
+    int     setsockopt(int, int, int, const scope void*, socklen_t);
+    int     shutdown(int, int) @safe;
+    int     socket(int, int, int) @safe;
+    int     sockatmark(int) @safe;
+    int     socketpair(int, int, int, ref int[2]) @safe;
+}
+else version (DragonFlyBSD)
+{
+    int     accept(int, sockaddr*, socklen_t*);
+//    int     accept4(int, sockaddr*, socklen_t*, int);
+    int     bind(int, const scope sockaddr*, socklen_t);
+    int     connect(int, const scope sockaddr*, socklen_t);
+//    int     extconnect(int, int, sockaddr*, socklen_t);
+    int     getpeername(int, sockaddr*, socklen_t*);
+    int     getsockname(int, sockaddr*, socklen_t*);
+    int     getsockopt(int, int, int, void*, socklen_t*);
+    int     listen(int, int);
+    ssize_t recv(int, void*, size_t, int);
+    ssize_t recvfrom(int, void*, size_t, int, sockaddr*, socklen_t*);
+    ssize_t recvmsg(int, msghdr*, int);
+    ssize_t send(int, const scope void*, size_t, int);
+    ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
+    ssize_t sendmsg(int, const scope msghdr*, int);
+//    int     sendfile(int, int, off_t, size_t, sf_hdtr *, off_t *, int);
+    int     setsockopt(int, int, int, const scope void*, socklen_t);
+    int     shutdown(int, int);
+    int     sockatmark(int);
+    int     socket(int, int, int);
+    int     socketpair(int, int, int, ref int[2]);
+//  void    pfctlinput(int, struct sockaddr *);
+}
+else version (Solaris)
+{
     int     accept(int, scope sockaddr*, scope socklen_t*);
     int     bind(int, const scope sockaddr*, socklen_t);
     int     connect(int, const scope sockaddr*, socklen_t);
@@ -1677,146 +1684,6 @@
 }
 else version (CRuntime_Bionic)
 {
-    alias int    socklen_t;
-    alias ushort sa_family_t;
-
-    struct sockaddr
-    {
-        sa_family_t sa_family;
-        byte[14]    sa_data;
-    }
-
-    private enum size_t _K_SS_MAXSIZE  = 128;
-
-    struct sockaddr_storage
-    {
-        ushort ss_family;
-        byte[_K_SS_MAXSIZE - ushort.sizeof] __data;
-    }
-
-    enum : uint
-    {
-        SCM_RIGHTS = 0x01
-    }
-
-    private enum _ALIGNBYTES = c_long.sizeof - 1;
-
-    extern (D)
-    {
-        size_t CMSG_ALIGN( size_t len )
-        {
-            return (len + _ALIGNBYTES) & ~_ALIGNBYTES;
-        }
-
-        void* CMSG_DATA( cmsghdr* cmsg )
-        {
-            return cast(void*) (cast(char*) cmsg + CMSG_ALIGN( cmsghdr.sizeof ));
-        }
-
-        cmsghdr* CMSG_NXTHDR( msghdr* mhdr, cmsghdr* cmsg )
-        {
-            cmsghdr* __ptr = cast(cmsghdr*) ((cast(ubyte*) cmsg) + CMSG_ALIGN(cmsg.cmsg_len));
-            return cast(c_ulong)( cast(char*)(__ptr+1) - cast(char*) mhdr.msg_control) > mhdr.msg_controllen ? null : __ptr;
-        }
-
-        cmsghdr* CMSG_FIRSTHDR( msghdr* mhdr )
-        {
-            return mhdr.msg_controllen >= cmsghdr.sizeof ? cast(cmsghdr*) mhdr.msg_control : null;
-        }
-    }
-
-    struct linger
-    {
-        int l_onoff;
-        int l_linger;
-    }
-
-    struct msghdr
-    {
-        void*           msg_name;
-        int             msg_namelen;
-        iovec*          msg_iov;
-        __kernel_size_t msg_iovlen;
-        void*           msg_control;
-        __kernel_size_t msg_controllen;
-        uint            msg_flags;
-    }
-
-    struct cmsghdr
-    {
-        __kernel_size_t cmsg_len;
-        int             cmsg_level;
-        int             cmsg_type;
-    }
-
-    alias size_t __kernel_size_t;
-
-    enum
-    {
-        SOCK_DGRAM      = 2,
-        SOCK_SEQPACKET  = 5,
-        SOCK_STREAM     = 1
-    }
-
-    enum
-    {
-        SOL_SOCKET      = 1
-    }
-
-    enum
-    {
-        SO_ACCEPTCONN   = 30,
-        SO_BROADCAST    = 6,
-        SO_DEBUG        = 1,
-        SO_DONTROUTE    = 5,
-        SO_ERROR        = 4,
-        SO_KEEPALIVE    = 9,
-        SO_LINGER       = 13,
-        SO_OOBINLINE    = 10,
-        SO_RCVBUF       = 8,
-        SO_RCVLOWAT     = 18,
-        SO_RCVTIMEO     = 20,
-        SO_REUSEADDR    = 2,
-        SO_SNDBUF       = 7,
-        SO_SNDLOWAT     = 19,
-        SO_SNDTIMEO     = 21,
-        SO_TYPE         = 3
-    }
-
-    enum
-    {
-        SOMAXCONN       = 128
-    }
-
-    enum : uint
-    {
-        MSG_CTRUNC      = 0x08,
-        MSG_DONTROUTE   = 0x04,
-        MSG_EOR         = 0x80,
-        MSG_OOB         = 0x01,
-        MSG_PEEK        = 0x02,
-        MSG_TRUNC       = 0x20,
-        MSG_WAITALL     = 0x100
-    }
-
-    enum
-    {
-        AF_APPLETALK    = 5,
-        AF_INET         = 2,
-        AF_IPX          = 4,
-        AF_UNIX         = 1,
-        AF_UNSPEC       = 0
-    }
-
-    enum
-    {
-        SHUT_RD,
-        SHUT_WR,
-        SHUT_RDWR
-    }
-
-    enum SOCK_RDM = 4;
-
     int     accept(int, scope sockaddr*, scope socklen_t*);
     int     bind(int, const scope sockaddr*, socklen_t);
     int     connect(int, const scope sockaddr*, socklen_t);
@@ -1838,139 +1705,6 @@
 }
 else version (CRuntime_Musl)
 {
-    alias uint socklen_t;
-    alias ushort sa_family_t;
-
-    struct sockaddr
-    {
-        sa_family_t sa_family;
-        byte[14]    sa_data;
-    }
-
-    private enum : size_t
-    {
-        _SS_SIZE    = 128,
-        _SS_PADSIZE = _SS_SIZE - c_ulong.sizeof - sa_family_t.sizeof
-    }
-
-    struct sockaddr_storage
-    {
-        sa_family_t ss_family;
-        byte[_SS_PADSIZE] __ss_padding;
-        c_ulong     __ss_align;
-    }
-
-    enum
-    {
-        SOCK_STREAM = 1,
-        SOCK_DGRAM = 2,
-        SOCK_RDM = 4,
-        SOCK_SEQPACKET = 5,
-        SOCK_DCCP = 6,
-        SOCK_PACKET = 10
-    }
-    enum
-    {
-        AF_UNSPEC       = 0,
-        AF_LOCAL        = 1,
-        AF_UNIX         = AF_LOCAL,
-        AF_FILE         = AF_LOCAL,
-        AF_INET         = 2,
-        AF_AX25         = 3,
-        AF_IPX          = 4,
-        AF_APPLETALK    = 5,
-        PF_APPLETALK    = AF_APPLETALK,
-        PF_IPX          = AF_IPX
-    }
-
-    enum
-    {
-        SHUT_RD,
-        SHUT_WR,
-        SHUT_RDWR
-    }
-
-    enum
-    {
-        SOL_SOCKET      = 1
-    }
-
-    enum
-    {
-        SO_DEBUG        = 1
-    }
-
-    version (MIPS_Any)
-    {
-        enum
-        {
-            SO_REUSEADDR    = 0x0004,
-            SO_TYPE         = 0x1008,
-            SO_ERROR        = 0x1007,
-            SO_DONTROUTE    = 0x0010,
-            SO_BROADCAST    = 0x0020,
-            SO_SNDBUF       = 0x1001,
-            SO_RCVBUF       = 0x1002,
-            SO_KEEPALIVE    = 0x0008,
-            SO_OOBINLINE    = 0x0100,
-            SO_LINGER       = 0x0080,
-            SO_REUSEPORT    = 0x0200,
-            SO_RCVLOWAT     = 0x1004,
-            SO_SNDLOWAT     = 0x1003,
-            SO_RCVTIMEO     = 0x1006,
-            SO_SNDTIMEO     = 0x1005,
-            SO_ACCEPTCONN   = 0x1009
-        }
-    }
-    else
-    {
-        enum
-        {
-            SO_REUSEADDR    = 2,
-            SO_TYPE         = 3,
-            SO_ERROR        = 4,
-            SO_DONTROUTE    = 5,
-            SO_BROADCAST    = 6,
-            SO_SNDBUF       = 7,
-            SO_RCVBUF       = 8,
-            SO_KEEPALIVE    = 9,
-            SO_OOBINLINE    = 10,
-            SO_LINGER       = 13,
-            SO_REUSEPORT    = 15,
-            SO_RCVLOWAT     = 18,
-            SO_SNDLOWAT     = 19,
-            SO_RCVTIMEO     = 20,
-            SO_SNDTIMEO     = 21,
-            SO_ACCEPTCONN   = 30
-        }
-    }
-
-    enum : uint
-    {
-        MSG_OOB         = 0x01,
-        MSG_PEEK        = 0x02,
-        MSG_DONTROUTE   = 0x04,
-        MSG_CTRUNC      = 0x08,
-        MSG_TRUNC       = 0x20,
-        MSG_EOR         = 0x80,
-        MSG_WAITALL     = 0x100,
-        MSG_NOSIGNAL    = 0x4000
-    }
-
-    struct linger
-    {
-        int l_onoff;
-        int l_linger;
-    }
-    struct msghdr {
-        void *msg_name;
-        socklen_t msg_namelen;
-        iovec *msg_iov;
-        int msg_iovlen, __pad1;
-        void *msg_control;
-        socklen_t msg_controllen, __pad2;
-        int msg_flags;
-    }
     int     accept(int, sockaddr*, socklen_t*);
     int     bind(int, const scope sockaddr*, socklen_t);
     int     connect(int, const scope sockaddr*, socklen_t);
@@ -1992,182 +1726,6 @@
 }
 else version (CRuntime_UClibc)
 {
-    alias uint   socklen_t;
-    alias ushort sa_family_t;
-
-    struct sockaddr
-    {
-        sa_family_t sa_family;
-        byte[14]    sa_data;
-    }
-
-    private enum : size_t
-    {
-        _SS_SIZE    = 128,
-        _SS_PADSIZE = _SS_SIZE - (c_ulong.sizeof * 2)
-    }
-
-    struct sockaddr_storage
-    {
-        sa_family_t ss_family;
-        c_ulong     __ss_align;
-        byte[_SS_PADSIZE] __ss_padding;
-    }
-
-    struct msghdr
-    {
-        void*     msg_name;
-        socklen_t msg_namelen;
-        iovec*    msg_iov;
-        size_t    msg_iovlen;
-        void*     msg_control;
-        size_t    msg_controllen;
-        int       msg_flags;
-    }
-
-    struct cmsghdr
-    {
-        size_t cmsg_len;
-        int    cmsg_level;
-        int    cmsg_type;
-    }
-
-    enum : uint
-    {
-        SCM_RIGHTS = 0x01
-    }
-
-    extern (D) inout(ubyte)*   CMSG_DATA( inout(cmsghdr)* cmsg ) pure nothrow @nogc { return cast(ubyte*)( cmsg + 1 ); }
-
-    private inout(cmsghdr)* __cmsg_nxthdr(inout(msghdr)*, inout(cmsghdr)*) pure nothrow @nogc;
-    extern (D)  inout(cmsghdr)* CMSG_NXTHDR(inout(msghdr)* msg, inout(cmsghdr)* cmsg) pure nothrow @nogc
-    {
-        return __cmsg_nxthdr(msg, cmsg);
-    }
-
-    extern (D) inout(cmsghdr)* CMSG_FIRSTHDR( inout(msghdr)* mhdr ) pure nothrow @nogc
-    {
-        return ( cast(size_t)mhdr.msg_controllen >= cmsghdr.sizeof
-                             ? cast(inout(cmsghdr)*) mhdr.msg_control
-                             : cast(inout(cmsghdr)*) null );
-    }
-
-    extern (D)
-    {
-        size_t CMSG_ALIGN( size_t len ) pure nothrow @nogc
-        {
-            return (len + size_t.sizeof - 1) & cast(size_t) (~(size_t.sizeof - 1));
-        }
-
-        size_t CMSG_LEN( size_t len ) pure nothrow @nogc
-        {
-            return CMSG_ALIGN(cmsghdr.sizeof) + len;
-        }
-    }
-
-    extern (D) size_t CMSG_SPACE(size_t len) pure nothrow @nogc
-    {
-        return CMSG_ALIGN(len) + CMSG_ALIGN(cmsghdr.sizeof);
-    }
-
-    struct linger
-    {
-        int l_onoff;
-        int l_linger;
-    }
-
-    version (X86_Any)
-    {
-        enum
-        {
-            SOCK_DGRAM      = 2,
-            SOCK_SEQPACKET  = 5,
-            SOCK_STREAM     = 1,
-            SOCK_CLOEXEC    = 0x80000, // octal 02000000
-            SOCK_NONBLOCK   = 0x800 // octal 00004000
-        }
-    }
-    else version (MIPS_Any)
-    {
-        enum
-        {
-            SOCK_DGRAM      = 1,
-            SOCK_SEQPACKET  = 5,
-            SOCK_STREAM     = 2,
-            SOCK_CLOEXEC    = 0x80000, // octal 02000000
-            SOCK_NONBLOCK   = 0x80 // octal 00000200
-        }
-    }
-    else version (ARM_Any)
-    {
-        enum
-        {
-            SOCK_DGRAM      = 2,
-            SOCK_SEQPACKET  = 5,
-            SOCK_STREAM     = 1,
-            SOCK_CLOEXEC    = 0x80000, // octal 02000000
-            SOCK_NONBLOCK   = 0x800 // octal 00004000
-        }
-    }
-    else
-        static assert(0, "unimplemented");
-
-    enum
-    {
-        SO_ACCEPTCONN   = 30,
-        SO_BROADCAST    = 6,
-        SO_DEBUG        = 1,
-        SO_DONTROUTE    = 5,
-        SO_ERROR        = 4,
-        SO_KEEPALIVE    = 9,
-        SO_LINGER       = 13,
-        SO_OOBINLINE    = 10,
-        SO_RCVBUF       = 8,
-        SO_RCVLOWAT     = 18,
-        SO_RCVTIMEO     = 20,
-        SO_REUSEADDR    = 2,
-        SO_SNDBUF       = 7,
-        SO_SNDLOWAT     = 19,
-        SO_SNDTIMEO     = 21,
-        SO_TYPE         = 3,
-
-        SOL_SOCKET      = 1,
-        SOL_TCP         = 6,
-        SOMAXCONN       = 128
-    }
-
-    enum : uint
-    {
-        MSG_CTRUNC      = 0x08,
-        MSG_DONTROUTE   = 0x04,
-        MSG_EOR         = 0x80,
-        MSG_OOB         = 0x01,
-        MSG_PEEK        = 0x02,
-        MSG_TRUNC       = 0x20,
-        MSG_WAITALL     = 0x100,
-        MSG_NOSIGNAL    = 0x4000
-    }
-
-    enum
-    {
-        AF_APPLETALK    = 5,
-        AF_INET         = 2,
-        AF_IPX          = 4,
-        AF_UNIX         = 1,
-        AF_UNSPEC       = 0,
-        PF_APPLETALK    = AF_APPLETALK,
-        PF_IPX          = AF_IPX
-    }
-
-    enum int SOCK_RDM   = 4;
-
-    enum
-    {
-        SHUT_RD,
-        SHUT_WR,
-        SHUT_RDWR
-    }
-
     int     accept(int, sockaddr*, socklen_t*);
     int     bind(int, const scope sockaddr*, socklen_t);
     int     connect(int, const scope sockaddr*, socklen_t);
@@ -2199,7 +1757,7 @@
 AF_INET6
 */
 
-version (CRuntime_Glibc)
+version (linux)
 {
     enum
     {
@@ -2248,24 +1806,6 @@
         AF_INET6 = 26,
     }
 }
-else version (CRuntime_Bionic)
-{
-    enum
-    {
-        AF_INET6    = 10
-    }
-}
-else version (CRuntime_Musl)
-{
-    enum AF_INET6 = 10;
-}
-else version (CRuntime_UClibc)
-{
-    enum
-    {
-        AF_INET6    = 10
-    }
-}
 else
 {
     static assert(false, "Unsupported platform");
@@ -2278,7 +1818,7 @@
 SOCK_RAW
 */
 
-version (CRuntime_Glibc)
+version (linux)
 {
     enum
     {
@@ -2327,27 +1867,6 @@
         SOCK_RAW = 4,
     }
 }
-else version (CRuntime_Bionic)
-{
-    enum
-    {
-        SOCK_RAW    = 3
-    }
-}
-else version (CRuntime_Musl)
-{
-    enum
-    {
-        SOCK_RAW    = 3
-    }
-}
-else version (CRuntime_UClibc)
-{
-    enum
-    {
-        SOCK_RAW    = 3
-    }
-}
 else
 {
     static assert(false, "Unsupported platform");
diff --git a/libphobos/libdruntime/core/sys/posix/sys/stat.d b/libphobos/libdruntime/core/sys/posix/sys/stat.d
index 7d0b170..51455a9 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/stat.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/stat.d
@@ -55,45 +55,16 @@
     time_t  st_ctime;
 }
 
-S_IRWXU
-    S_IRUSR
-    S_IWUSR
-    S_IXUSR
-S_IRWXG
-    S_IRGRP
-    S_IWGRP
-    S_IXGRP
-S_IRWXO
-    S_IROTH
-    S_IWOTH
-    S_IXOTH
 S_ISUID
 S_ISGID
 S_ISVTX
 
-S_ISBLK(m)
-S_ISCHR(m)
-S_ISDIR(m)
-S_ISFIFO(m)
-S_ISREG(m)
-S_ISLNK(m)
-S_ISSOCK(m)
-
 S_TYPEISMQ(buf)
 S_TYPEISSEM(buf)
 S_TYPEISSHM(buf)
-
-int    chmod(const scope char*, mode_t);
-int    fchmod(int, mode_t);
-int    fstat(int, stat*);
-int    lstat(const scope char*, stat*);
-int    mkdir(const scope char*, mode_t);
-int    mkfifo(const scope char*, mode_t);
-int    stat(const scope char*, stat*);
-mode_t umask(mode_t);
  */
 
-version (CRuntime_Glibc)
+version (linux)
 {
     version (X86)
     {
@@ -956,41 +927,10 @@
     else
         static assert(0, "unimplemented");
 
-    enum S_IRUSR    = 0x100; // octal 0400
-    enum S_IWUSR    = 0x080; // octal 0200
-    enum S_IXUSR    = 0x040; // octal 0100
-    enum S_IRWXU    = S_IRUSR | S_IWUSR | S_IXUSR;
-
-    enum S_IRGRP    = S_IRUSR >> 3;
-    enum S_IWGRP    = S_IWUSR >> 3;
-    enum S_IXGRP    = S_IXUSR >> 3;
-    enum S_IRWXG    = S_IRWXU >> 3;
-
-    enum S_IROTH    = S_IRGRP >> 3;
-    enum S_IWOTH    = S_IWGRP >> 3;
-    enum S_IXOTH    = S_IXGRP >> 3;
-    enum S_IRWXO    = S_IRWXG >> 3;
-
     enum S_ISUID    = 0x800; // octal 04000
     enum S_ISGID    = 0x400; // octal 02000
     enum S_ISVTX    = 0x200; // octal 01000
 
-    private
-    {
-        extern (D) bool S_ISTYPE( mode_t mode, uint mask )
-        {
-            return ( mode & S_IFMT ) == mask;
-        }
-    }
-
-    extern (D) bool S_ISBLK( mode_t mode )  { return S_ISTYPE( mode, S_IFBLK );  }
-    extern (D) bool S_ISCHR( mode_t mode )  { return S_ISTYPE( mode, S_IFCHR );  }
-    extern (D) bool S_ISDIR( mode_t mode )  { return S_ISTYPE( mode, S_IFDIR );  }
-    extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO );  }
-    extern (D) bool S_ISREG( mode_t mode )  { return S_ISTYPE( mode, S_IFREG );  }
-    extern (D) bool S_ISLNK( mode_t mode )  { return S_ISTYPE( mode, S_IFLNK );  }
-    extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
-
     static if ( true /*__USE_POSIX199309*/ )
     {
         extern bool S_TYPEISMQ( stat_t* buf )  { return false; }
@@ -1000,10 +940,6 @@
 
     enum UTIME_NOW = 0x3fffffff;
     enum UTIME_OMIT = 0x3ffffffe;
-
-    int utimensat(int dirfd, const char *pathname,
-        ref const(timespec)[2] times, int flags);
-    int futimens(int fd, ref const(timespec)[2] times);
 }
 else version (Darwin)
 {
@@ -1049,40 +985,9 @@
         long[2]     st_qspare;
     }
 
-    enum S_IRUSR    = 0x100;  // octal 0400
-    enum S_IWUSR    = 0x080;  // octal 0200
-    enum S_IXUSR    = 0x040;  // octal 0100
-    enum S_IRWXU    = S_IRUSR | S_IWUSR | S_IXUSR;
-
-    enum S_IRGRP    = S_IRUSR >> 3;
-    enum S_IWGRP    = S_IWUSR >> 3;
-    enum S_IXGRP    = S_IXUSR >> 3;
-    enum S_IRWXG    = S_IRWXU >> 3;
-
-    enum S_IROTH    = S_IRGRP >> 3;
-    enum S_IWOTH    = S_IWGRP >> 3;
-    enum S_IXOTH    = S_IXGRP >> 3;
-    enum S_IRWXO    = S_IRWXG >> 3;
-
     enum S_ISUID    = 0x800; // octal 04000
     enum S_ISGID    = 0x400; // octal 02000
     enum S_ISVTX    = 0x200; // octal 01000
-
-    private
-    {
-        extern (D) bool S_ISTYPE( mode_t mode, uint mask )
-        {
-            return ( mode & S_IFMT ) == mask;
-        }
-    }
-
-    extern (D) bool S_ISBLK( mode_t mode )  { return S_ISTYPE( mode, S_IFBLK );  }
-    extern (D) bool S_ISCHR( mode_t mode )  { return S_ISTYPE( mode, S_IFCHR );  }
-    extern (D) bool S_ISDIR( mode_t mode )  { return S_ISTYPE( mode, S_IFDIR );  }
-    extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO );  }
-    extern (D) bool S_ISREG( mode_t mode )  { return S_ISTYPE( mode, S_IFREG );  }
-    extern (D) bool S_ISLNK( mode_t mode )  { return S_ISTYPE( mode, S_IFLNK );  }
-    extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
 }
 else version (FreeBSD)
 {
@@ -1164,51 +1069,12 @@
         }
     }
 
-    enum S_IRUSR    = 0x100; // octal 0000400
-    enum S_IWUSR    = 0x080; // octal 0000200
-    enum S_IXUSR    = 0x040; // octal 0000100
-    enum S_IRWXU    = 0x1C0; // octal 0000700
-
-    enum S_IRGRP    = 0x020;  // octal 0000040
-    enum S_IWGRP    = 0x010;  // octal 0000020
-    enum S_IXGRP    = 0x008;  // octal 0000010
-    enum S_IRWXG    = 0x038;  // octal 0000070
-
-    enum S_IROTH    = 0x4; // 0000004
-    enum S_IWOTH    = 0x2; // 0000002
-    enum S_IXOTH    = 0x1; // 0000001
-    enum S_IRWXO    = 0x7; // 0000007
-
     enum S_ISUID    = 0x800; // octal 0004000
     enum S_ISGID    = 0x400; // octal 0002000
     enum S_ISVTX    = 0x200; // octal 0001000
 
-    private
-    {
-        extern (D) bool S_ISTYPE( mode_t mode, uint mask )
-        {
-            return ( mode & S_IFMT ) == mask;
-        }
-    }
-
-    extern (D) bool S_ISBLK( mode_t mode )  { return S_ISTYPE( mode, S_IFBLK );  }
-    extern (D) bool S_ISCHR( mode_t mode )  { return S_ISTYPE( mode, S_IFCHR );  }
-    extern (D) bool S_ISDIR( mode_t mode )  { return S_ISTYPE( mode, S_IFDIR );  }
-    extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO );  }
-    extern (D) bool S_ISREG( mode_t mode )  { return S_ISTYPE( mode, S_IFREG );  }
-    extern (D) bool S_ISLNK( mode_t mode )  { return S_ISTYPE( mode, S_IFLNK );  }
-    extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
-
     enum UTIME_NOW = -1;
     enum UTIME_OMIT = -2;
-
-    // Since FreeBSD 11:
-    version (none)
-    {
-        int utimensat(int dirfd, const char *pathname,
-            ref const(timespec)[2] times, int flags);
-        int futimens(int fd, ref const(timespec)[2] times);
-    }
 }
 else version (NetBSD)
 {
@@ -1237,40 +1103,9 @@
         uint32_t[2]  st_spare;
     }
 
-    enum S_IRUSR    = 0x100; // octal 0000400
-    enum S_IWUSR    = 0x080; // octal 0000200
-    enum S_IXUSR    = 0x040; // octal 0000100
-    enum S_IRWXU    = 0x1C0; // octal 0000700
-
-    enum S_IRGRP    = 0x020;  // octal 0000040
-    enum S_IWGRP    = 0x010;  // octal 0000020
-    enum S_IXGRP    = 0x008;  // octal 0000010
-    enum S_IRWXG    = 0x038;  // octal 0000070
-
-    enum S_IROTH    = 0x4; // 0000004
-    enum S_IWOTH    = 0x2; // 0000002
-    enum S_IXOTH    = 0x1; // 0000001
-    enum S_IRWXO    = 0x7; // 0000007
-
     enum S_ISUID    = 0x800; // octal 0004000
     enum S_ISGID    = 0x400; // octal 0002000
     enum S_ISVTX    = 0x200; // octal 0001000
-
-    private
-    {
-        extern (D) bool S_ISTYPE( mode_t mode, uint mask )
-        {
-            return ( mode & S_IFMT ) == mask;
-        }
-    }
-
-    extern (D) bool S_ISBLK( mode_t mode )  { return S_ISTYPE( mode, S_IFBLK );  }
-    extern (D) bool S_ISCHR( mode_t mode )  { return S_ISTYPE( mode, S_IFCHR );  }
-    extern (D) bool S_ISDIR( mode_t mode )  { return S_ISTYPE( mode, S_IFDIR );  }
-    extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO );  }
-    extern (D) bool S_ISREG( mode_t mode )  { return S_ISTYPE( mode, S_IFREG );  }
-    extern (D) bool S_ISLNK( mode_t mode )  { return S_ISTYPE( mode, S_IFLNK );  }
-    extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
 }
 else version (OpenBSD)
 {
@@ -1322,32 +1157,9 @@
       }
     }
 
-    enum S_IRUSR    = 0x100; // octal 0000400
-    enum S_IWUSR    = 0x080; // octal 0000200
-    enum S_IXUSR    = 0x040; // octal 0000100
-    enum S_IRWXU    = 0x1C0; // octal 0000700
-
-    enum S_IRGRP    = 0x020;  // octal 0000040
-    enum S_IWGRP    = 0x010;  // octal 0000020
-    enum S_IXGRP    = 0x008;  // octal 0000010
-    enum S_IRWXG    = 0x038;  // octal 0000070
-
-    enum S_IROTH    = 0x4; // 0000004
-    enum S_IWOTH    = 0x2; // 0000002
-    enum S_IXOTH    = 0x1; // 0000001
-    enum S_IRWXO    = 0x7; // 0000007
-
     enum S_ISUID    = 0x800; // octal 0004000
     enum S_ISGID    = 0x400; // octal 0002000
     enum S_ISVTX    = 0x200; // octal 0001000
-
-    extern (D) bool S_ISBLK(mode_t mode)  { return (mode & S_IFMT) == S_IFBLK;  }
-    extern (D) bool S_ISCHR(mode_t mode)  { return (mode & S_IFMT) == S_IFCHR;  }
-    extern (D) bool S_ISDIR(mode_t mode)  { return (mode & S_IFMT) == S_IFDIR;  }
-    extern (D) bool S_ISFIFO(mode_t mode) { return (mode & S_IFMT) == S_IFIFO;  }
-    extern (D) bool S_ISREG(mode_t mode)  { return (mode & S_IFMT) == S_IFREG;  }
-    extern (D) bool S_ISLNK(mode_t mode)  { return (mode & S_IFMT) == S_IFLNK;  }
-    extern (D) bool S_ISSOCK(mode_t mode) { return (mode & S_IFMT) == S_IFSOCK; }
 }
 else version (DragonFlyBSD)
 {
@@ -1376,40 +1188,9 @@
             int64_t   st_qspare2;
     }
 
-    enum S_IRUSR    = 0x100; // octal 0000400
-    enum S_IWUSR    = 0x080; // octal 0000200
-    enum S_IXUSR    = 0x040; // octal 0000100
-    enum S_IRWXU    = 0x1C0; // octal 0000700
-
-    enum S_IRGRP    = 0x020;  // octal 0000040
-    enum S_IWGRP    = 0x010;  // octal 0000020
-    enum S_IXGRP    = 0x008;  // octal 0000010
-    enum S_IRWXG    = 0x038;  // octal 0000070
-
-    enum S_IROTH    = 0x4; // 0000004
-    enum S_IWOTH    = 0x2; // 0000002
-    enum S_IXOTH    = 0x1; // 0000001
-    enum S_IRWXO    = 0x7; // 0000007
-
     enum S_ISUID    = 0x800; // octal 0004000
     enum S_ISGID    = 0x400; // octal 0002000
     enum S_ISVTX    = 0x200; // octal 0001000
-
-    private
-    {
-        extern (D) bool S_ISTYPE( mode_t mode, uint mask )
-        {
-            return ( mode & S_IFMT ) == mask;
-        }
-    }
-
-    extern (D) bool S_ISBLK( mode_t mode )  { return S_ISTYPE( mode, S_IFBLK );  }
-    extern (D) bool S_ISCHR( mode_t mode )  { return S_ISTYPE( mode, S_IFCHR );  }
-    extern (D) bool S_ISDIR( mode_t mode )  { return S_ISTYPE( mode, S_IFDIR );  }
-    extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO );  }
-    extern (D) bool S_ISREG( mode_t mode )  { return S_ISTYPE( mode, S_IFREG );  }
-    extern (D) bool S_ISLNK( mode_t mode )  { return S_ISTYPE( mode, S_IFLNK );  }
-    extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
 }
 else version (Solaris)
 {
@@ -1525,6 +1306,242 @@
 
     }
 
+    enum S_ISUID = 0x800;
+    enum S_ISGID = 0x400;
+    enum S_ISVTX = 0x200;
+}
+else
+{
+    static assert(false, "Unsupported platform");
+}
+
+/*
+S_IRWXU
+    S_IRUSR
+    S_IWUSR
+    S_IXUSR
+S_IRWXG
+    S_IRGRP
+    S_IWGRP
+    S_IXGRP
+S_IRWXO
+    S_IROTH
+    S_IWOTH
+    S_IXOTH
+
+S_ISBLK(m)
+S_ISCHR(m)
+S_ISDIR(m)
+S_ISFIFO(m)
+S_ISREG(m)
+S_ISLNK(m)
+S_ISSOCK(m)
+ */
+
+version (CRuntime_Glibc)
+{
+    enum S_IRUSR    = 0x100; // octal 0400
+    enum S_IWUSR    = 0x080; // octal 0200
+    enum S_IXUSR    = 0x040; // octal 0100
+    enum S_IRWXU    = S_IRUSR | S_IWUSR | S_IXUSR;
+
+    enum S_IRGRP    = S_IRUSR >> 3;
+    enum S_IWGRP    = S_IWUSR >> 3;
+    enum S_IXGRP    = S_IXUSR >> 3;
+    enum S_IRWXG    = S_IRWXU >> 3;
+
+    enum S_IROTH    = S_IRGRP >> 3;
+    enum S_IWOTH    = S_IWGRP >> 3;
+    enum S_IXOTH    = S_IXGRP >> 3;
+    enum S_IRWXO    = S_IRWXG >> 3;
+
+    private
+    {
+        extern (D) bool S_ISTYPE( mode_t mode, uint mask )
+        {
+            return ( mode & S_IFMT ) == mask;
+        }
+    }
+
+    extern (D) bool S_ISBLK( mode_t mode )  { return S_ISTYPE( mode, S_IFBLK );  }
+    extern (D) bool S_ISCHR( mode_t mode )  { return S_ISTYPE( mode, S_IFCHR );  }
+    extern (D) bool S_ISDIR( mode_t mode )  { return S_ISTYPE( mode, S_IFDIR );  }
+    extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO );  }
+    extern (D) bool S_ISREG( mode_t mode )  { return S_ISTYPE( mode, S_IFREG );  }
+    extern (D) bool S_ISLNK( mode_t mode )  { return S_ISTYPE( mode, S_IFLNK );  }
+    extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
+
+    int utimensat(int dirfd, const char *pathname,
+        ref const(timespec)[2] times, int flags);
+    int futimens(int fd, ref const(timespec)[2] times);
+}
+else version (Darwin)
+{
+    enum S_IRUSR    = 0x100;  // octal 0400
+    enum S_IWUSR    = 0x080;  // octal 0200
+    enum S_IXUSR    = 0x040;  // octal 0100
+    enum S_IRWXU    = S_IRUSR | S_IWUSR | S_IXUSR;
+
+    enum S_IRGRP    = S_IRUSR >> 3;
+    enum S_IWGRP    = S_IWUSR >> 3;
+    enum S_IXGRP    = S_IXUSR >> 3;
+    enum S_IRWXG    = S_IRWXU >> 3;
+
+    enum S_IROTH    = S_IRGRP >> 3;
+    enum S_IWOTH    = S_IWGRP >> 3;
+    enum S_IXOTH    = S_IXGRP >> 3;
+    enum S_IRWXO    = S_IRWXG >> 3;
+
+    private
+    {
+        extern (D) bool S_ISTYPE( mode_t mode, uint mask )
+        {
+            return ( mode & S_IFMT ) == mask;
+        }
+    }
+
+    extern (D) bool S_ISBLK( mode_t mode )  { return S_ISTYPE( mode, S_IFBLK );  }
+    extern (D) bool S_ISCHR( mode_t mode )  { return S_ISTYPE( mode, S_IFCHR );  }
+    extern (D) bool S_ISDIR( mode_t mode )  { return S_ISTYPE( mode, S_IFDIR );  }
+    extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO );  }
+    extern (D) bool S_ISREG( mode_t mode )  { return S_ISTYPE( mode, S_IFREG );  }
+    extern (D) bool S_ISLNK( mode_t mode )  { return S_ISTYPE( mode, S_IFLNK );  }
+    extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
+}
+else version (FreeBSD)
+{
+    enum S_IRUSR    = 0x100; // octal 0000400
+    enum S_IWUSR    = 0x080; // octal 0000200
+    enum S_IXUSR    = 0x040; // octal 0000100
+    enum S_IRWXU    = 0x1C0; // octal 0000700
+
+    enum S_IRGRP    = 0x020;  // octal 0000040
+    enum S_IWGRP    = 0x010;  // octal 0000020
+    enum S_IXGRP    = 0x008;  // octal 0000010
+    enum S_IRWXG    = 0x038;  // octal 0000070
+
+    enum S_IROTH    = 0x4; // 0000004
+    enum S_IWOTH    = 0x2; // 0000002
+    enum S_IXOTH    = 0x1; // 0000001
+    enum S_IRWXO    = 0x7; // 0000007
+
+    private
+    {
+        extern (D) bool S_ISTYPE( mode_t mode, uint mask )
+        {
+            return ( mode & S_IFMT ) == mask;
+        }
+    }
+
+    extern (D) bool S_ISBLK( mode_t mode )  { return S_ISTYPE( mode, S_IFBLK );  }
+    extern (D) bool S_ISCHR( mode_t mode )  { return S_ISTYPE( mode, S_IFCHR );  }
+    extern (D) bool S_ISDIR( mode_t mode )  { return S_ISTYPE( mode, S_IFDIR );  }
+    extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO );  }
+    extern (D) bool S_ISREG( mode_t mode )  { return S_ISTYPE( mode, S_IFREG );  }
+    extern (D) bool S_ISLNK( mode_t mode )  { return S_ISTYPE( mode, S_IFLNK );  }
+    extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
+
+    // Since FreeBSD 11:
+    version (none)
+    {
+        int utimensat(int dirfd, const char *pathname,
+            ref const(timespec)[2] times, int flags);
+        int futimens(int fd, ref const(timespec)[2] times);
+    }
+}
+else version (NetBSD)
+{
+    enum S_IRUSR    = 0x100; // octal 0000400
+    enum S_IWUSR    = 0x080; // octal 0000200
+    enum S_IXUSR    = 0x040; // octal 0000100
+    enum S_IRWXU    = 0x1C0; // octal 0000700
+
+    enum S_IRGRP    = 0x020;  // octal 0000040
+    enum S_IWGRP    = 0x010;  // octal 0000020
+    enum S_IXGRP    = 0x008;  // octal 0000010
+    enum S_IRWXG    = 0x038;  // octal 0000070
+
+    enum S_IROTH    = 0x4; // 0000004
+    enum S_IWOTH    = 0x2; // 0000002
+    enum S_IXOTH    = 0x1; // 0000001
+    enum S_IRWXO    = 0x7; // 0000007
+
+    private
+    {
+        extern (D) bool S_ISTYPE( mode_t mode, uint mask )
+        {
+            return ( mode & S_IFMT ) == mask;
+        }
+    }
+
+    extern (D) bool S_ISBLK( mode_t mode )  { return S_ISTYPE( mode, S_IFBLK );  }
+    extern (D) bool S_ISCHR( mode_t mode )  { return S_ISTYPE( mode, S_IFCHR );  }
+    extern (D) bool S_ISDIR( mode_t mode )  { return S_ISTYPE( mode, S_IFDIR );  }
+    extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO );  }
+    extern (D) bool S_ISREG( mode_t mode )  { return S_ISTYPE( mode, S_IFREG );  }
+    extern (D) bool S_ISLNK( mode_t mode )  { return S_ISTYPE( mode, S_IFLNK );  }
+    extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
+}
+else version (OpenBSD)
+{
+    enum S_IRUSR    = 0x100; // octal 0000400
+    enum S_IWUSR    = 0x080; // octal 0000200
+    enum S_IXUSR    = 0x040; // octal 0000100
+    enum S_IRWXU    = 0x1C0; // octal 0000700
+
+    enum S_IRGRP    = 0x020;  // octal 0000040
+    enum S_IWGRP    = 0x010;  // octal 0000020
+    enum S_IXGRP    = 0x008;  // octal 0000010
+    enum S_IRWXG    = 0x038;  // octal 0000070
+
+    enum S_IROTH    = 0x4; // 0000004
+    enum S_IWOTH    = 0x2; // 0000002
+    enum S_IXOTH    = 0x1; // 0000001
+    enum S_IRWXO    = 0x7; // 0000007
+
+    extern (D) bool S_ISBLK(mode_t mode)  { return (mode & S_IFMT) == S_IFBLK;  }
+    extern (D) bool S_ISCHR(mode_t mode)  { return (mode & S_IFMT) == S_IFCHR;  }
+    extern (D) bool S_ISDIR(mode_t mode)  { return (mode & S_IFMT) == S_IFDIR;  }
+    extern (D) bool S_ISFIFO(mode_t mode) { return (mode & S_IFMT) == S_IFIFO;  }
+    extern (D) bool S_ISREG(mode_t mode)  { return (mode & S_IFMT) == S_IFREG;  }
+    extern (D) bool S_ISLNK(mode_t mode)  { return (mode & S_IFMT) == S_IFLNK;  }
+    extern (D) bool S_ISSOCK(mode_t mode) { return (mode & S_IFMT) == S_IFSOCK; }
+}
+else version (DragonFlyBSD)
+{
+    enum S_IRUSR    = 0x100; // octal 0000400
+    enum S_IWUSR    = 0x080; // octal 0000200
+    enum S_IXUSR    = 0x040; // octal 0000100
+    enum S_IRWXU    = 0x1C0; // octal 0000700
+
+    enum S_IRGRP    = 0x020;  // octal 0000040
+    enum S_IWGRP    = 0x010;  // octal 0000020
+    enum S_IXGRP    = 0x008;  // octal 0000010
+    enum S_IRWXG    = 0x038;  // octal 0000070
+
+    enum S_IROTH    = 0x4; // 0000004
+    enum S_IWOTH    = 0x2; // 0000002
+    enum S_IXOTH    = 0x1; // 0000001
+    enum S_IRWXO    = 0x7; // 0000007
+
+    private
+    {
+        extern (D) bool S_ISTYPE( mode_t mode, uint mask )
+        {
+            return ( mode & S_IFMT ) == mask;
+        }
+    }
+
+    extern (D) bool S_ISBLK( mode_t mode )  { return S_ISTYPE( mode, S_IFBLK );  }
+    extern (D) bool S_ISCHR( mode_t mode )  { return S_ISTYPE( mode, S_IFCHR );  }
+    extern (D) bool S_ISDIR( mode_t mode )  { return S_ISTYPE( mode, S_IFDIR );  }
+    extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO );  }
+    extern (D) bool S_ISREG( mode_t mode )  { return S_ISTYPE( mode, S_IFREG );  }
+    extern (D) bool S_ISLNK( mode_t mode )  { return S_ISTYPE( mode, S_IFLNK );  }
+    extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
+}
+else version (Solaris)
+{
     enum S_IRUSR = 0x100;
     enum S_IWUSR = 0x080;
     enum S_IXUSR = 0x040;
@@ -1540,10 +1557,6 @@
     enum S_IXOTH = 0x1; // 0000001
     enum S_IRWXO = 0x7; // 0000007
 
-    enum S_ISUID = 0x800;
-    enum S_ISGID = 0x400;
-    enum S_ISVTX = 0x200;
-
     private
     {
         extern (D) bool S_ISTYPE(mode_t mode, uint mask)
@@ -1564,115 +1577,6 @@
 }
 else version (CRuntime_Bionic)
 {
-    version (X86)
-    {
-        struct stat_t
-        {
-            ulong       st_dev;
-            ubyte[4]    __pad0;
-            c_ulong     __st_ino;
-            uint        st_mode;
-            uint        st_nlink;
-            c_ulong     st_uid;
-            c_ulong     st_gid;
-            ulong       st_rdev;
-            ubyte[4]    __pad3;
-
-            long        st_size;
-            c_ulong     st_blksize;
-            ulong       st_blocks;
-            c_ulong     st_atime;
-            c_ulong     st_atime_nsec;
-            c_ulong     st_mtime;
-            c_ulong     st_mtime_nsec;
-            c_ulong     st_ctime;
-            c_ulong     st_ctime_nsec;
-            ulong       st_ino;
-        }
-    }
-    else version (ARM)
-    {
-        struct stat_t
-        {
-            ulong       st_dev;
-            ubyte[4]    __pad0;
-            c_ulong     __st_ino;
-            uint        st_mode;
-            uint        st_nlink;
-            c_ulong     st_uid;
-            c_ulong     st_gid;
-            ulong       st_rdev;
-            ubyte[4]    __pad3;
-
-            long        st_size;
-            c_ulong     st_blksize;
-            ulong       st_blocks;
-            c_ulong     st_atime;
-            c_ulong     st_atime_nsec;
-            c_ulong     st_mtime;
-            c_ulong     st_mtime_nsec;
-            c_ulong     st_ctime;
-            c_ulong     st_ctime_nsec;
-            ulong       st_ino;
-        }
-    }
-    else version (AArch64)
-    {
-        struct stat_t
-        {
-            ulong       st_dev;
-            ulong       st_ino;
-            uint        st_mode;
-            uint        st_nlink;
-            uid_t       st_uid;
-            gid_t       st_gid;
-            ulong       st_rdev;
-            ulong       __pad1;
-
-            long        st_size;
-            int         st_blksize;
-            int         __pad2;
-            long        st_blocks;
-            long        st_atime;
-            ulong       st_atime_nsec;
-            long        st_mtime;
-            ulong       st_mtime_nsec;
-            long        st_ctime;
-            ulong       st_ctime_nsec;
-            uint        __unused4;
-            uint        __unused5;
-        }
-    }
-    else version (X86_64)
-    {
-        struct stat_t
-        {
-            ulong       st_dev;
-            ulong       st_ino;
-            ulong       st_nlink;
-            uint        st_mode;
-            uid_t       st_uid;
-            gid_t       st_gid;
-            uint        __pad0;
-
-            ulong       st_rdev;
-            long        st_size;
-            long        st_blksize;
-            long        st_blocks;
-            long        st_atime;
-            ulong       st_atime_nsec;
-            long        st_mtime;
-            ulong       st_mtime_nsec;
-            long        st_ctime;
-            ulong       st_ctime_nsec;
-            long[3]     __pad3;
-        }
-    }
-    else
-    {
-        static assert(false, "Architecture not supported.");
-    }
-
     enum S_IRUSR    = 0x100; // octal 0000400
     enum S_IWUSR    = 0x080; // octal 0000200
     enum S_IXUSR    = 0x040; // octal 0000100
@@ -1688,10 +1592,6 @@
     enum S_IXOTH    = 0x1; // 0000001
     enum S_IRWXO    = 0x7; // 0000007
 
-    enum S_ISUID    = 0x800; // octal 0004000
-    enum S_ISGID    = 0x400; // octal 0002000
-    enum S_ISVTX    = 0x200; // octal 0001000
-
     private
     {
         extern (D) bool S_ISTYPE( uint mode, uint mask )
@@ -1730,229 +1630,7 @@
         S_IWOTH    = S_IWGRP >> 3,
         S_IXOTH    = S_IXGRP >> 3,
         S_IRWXO    = S_IRWXG >> 3,
-
-        S_ISUID    = 0x800, // octal 04000
-        S_ISGID    = 0x400, // octal 02000
-        S_ISVTX    = 0x200, // octal 01000
     }
-    version (ARM)
-    {
-        struct stat_t
-        {
-            dev_t st_dev;
-            int __st_dev_padding;
-            c_long __st_ino_truncated;
-            mode_t st_mode;
-            nlink_t st_nlink;
-
-            uid_t st_uid;
-            gid_t st_gid;
-            dev_t st_rdev;
-            int __st_rdev_padding;
-            off_t st_size;
-            blksize_t st_blksize;
-            blkcnt_t st_blocks;
-
-            timespec st_atim;
-            timespec st_mtim;
-            timespec st_ctim;
-            ino_t st_ino;
-
-            extern(D) @safe @property inout pure nothrow
-            {
-                ref inout(time_t) st_atime() return { return st_atim.tv_sec; }
-                ref inout(time_t) st_mtime() return { return st_mtim.tv_sec; }
-                ref inout(time_t) st_ctime() return { return st_ctim.tv_sec; }
-            }
-        }
-    }
-    else version (AArch64)
-    {
-        struct stat_t
-        {
-            dev_t st_dev;
-            ino_t st_ino;
-            mode_t st_mode;
-            nlink_t st_nlink;
-
-            uid_t st_uid;
-            gid_t st_gid;
-            dev_t st_rdev;
-            c_ulong __pad;
-            off_t st_size;
-            blksize_t st_blksize;
-            int __pad2;
-            blkcnt_t st_blocks;
-
-            timespec st_atim;
-            timespec st_mtim;
-            timespec st_ctim;
-            uint[2] __unused;
-
-            extern(D) @safe @property inout pure nothrow
-            {
-                ref inout(time_t) st_atime() return { return st_atim.tv_sec; }
-                ref inout(time_t) st_mtime() return { return st_mtim.tv_sec; }
-                ref inout(time_t) st_ctime() return { return st_ctim.tv_sec; }
-            }
-        }
-    }
-    else version (X86_64)
-    {
-        struct stat_t
-        {
-            dev_t st_dev;
-            ino_t st_ino;
-            nlink_t st_nlink;
-
-            mode_t st_mode;
-            uid_t st_uid;
-            gid_t st_gid;
-            uint   __pad0;
-            dev_t st_rdev;
-            off_t st_size;
-            blksize_t st_blksize;
-            blkcnt_t st_blocks;
-
-            timespec st_atim;
-            timespec st_mtim;
-            timespec st_ctim;
-
-            c_long[3] __unused;
-
-            extern(D) @safe @property inout pure nothrow
-            {
-                ref inout(time_t) st_atime() return { return st_atim.tv_sec; }
-                ref inout(time_t) st_mtime() return { return st_mtim.tv_sec; }
-                ref inout(time_t) st_ctime() return { return st_ctim.tv_sec; }
-            }
-        }
-    }
-    else version (X86)
-    {
-        struct stat_t
-        {
-            dev_t st_dev;
-            int __st_dev_padding;
-            c_long __st_ino_truncated;
-            mode_t st_mode;
-            nlink_t st_nlink;
-
-            uid_t st_uid;
-            gid_t st_gid;
-            dev_t st_rdev;
-            int __st_rdev_padding;
-            off_t st_size;
-            blksize_t st_blksize;
-            blkcnt_t st_blocks;
-
-            timespec st_atim;
-            timespec st_mtim;
-            timespec st_ctim;
-            ino_t st_ino;
-
-            extern(D) @safe @property inout pure nothrow
-            {
-                ref inout(time_t) st_atime() return { return st_atim.tv_sec; }
-                ref inout(time_t) st_mtime() return { return st_mtim.tv_sec; }
-                ref inout(time_t) st_ctime() return { return st_ctim.tv_sec; }
-            }
-        }
-    }
-    else version (MIPS64)
-    {
-        struct stat_t
-        {
-            dev_t st_dev;
-            int[3] __pad1;
-            ino_t st_ino;
-            mode_t st_mode;
-            nlink_t st_nlink;
-
-            uid_t st_uid;
-            gid_t st_gid;
-            dev_t st_rdev;
-            uint[2] __pad2;
-            off_t st_size;
-            int __pad3;
-
-            timespec st_atim;
-            timespec st_mtim;
-            timespec st_ctim;
-            blksize_t st_blksize;
-            uint __pad4;
-            blkcnt_t st_blocks;
-            int[14] __pad5;
-
-            extern(D) @safe @property inout pure nothrow
-            {
-                ref inout(time_t) st_atime() return { return st_atim.tv_sec; }
-                ref inout(time_t) st_mtime() return { return st_mtim.tv_sec; }
-                ref inout(time_t) st_ctime() return { return st_ctim.tv_sec; }
-            }
-        }
-    }
-    else version (PPC64)
-    {
-        struct stat_t
-        {
-            dev_t st_dev;
-            ino_t st_ino;
-            nlink_t st_nlink;
-            mode_t st_mode;
-
-            uid_t st_uid;
-            gid_t st_gid;
-            dev_t st_rdev;
-            off_t st_size;
-            blksize_t st_blksize;
-            blkcnt_t st_blocks;
-
-            timespec st_atim;
-            timespec st_mtim;
-            timespec st_ctim;
-            c_ulong[3] __unused;
-
-            extern(D) @safe @property inout pure nothrow
-            {
-                ref inout(time_t) st_atime() return { return st_atim.tv_sec; }
-                ref inout(time_t) st_mtime() return { return st_mtim.tv_sec; }
-                ref inout(time_t) st_ctime() return { return st_ctim.tv_sec; }
-            }
-        }
-    }
-    else version (SystemZ)
-    {
-        struct stat_t
-        {
-            dev_t st_dev;
-            ino_t st_ino;
-            nlink_t st_nlink;
-            mode_t st_mode;
-
-            uid_t st_uid;
-            gid_t st_gid;
-            dev_t st_rdev;
-            off_t st_size;
-
-            timespec st_atim;
-            timespec st_mtim;
-            timespec st_ctim;
-
-            blksize_t st_blksize;
-            blkcnt_t st_blocks;
-            c_ulong[3] __unused;
-
-            extern(D) @safe @property inout pure nothrow
-            {
-                ref inout(time_t) st_atime() return { return st_atim.tv_sec; }
-                ref inout(time_t) st_mtime() return { return st_mtim.tv_sec; }
-                ref inout(time_t) st_ctime() return { return st_ctim.tv_sec; }
-            }
-        }
-    }
-    else
-        static assert("Unsupported platform");
 
     private
     {
@@ -1975,170 +1653,6 @@
 }
 else version (CRuntime_UClibc)
 {
-    version (X86_64)
-    {
-        struct stat_t
-        {
-            dev_t       st_dev;
-            ino_t       st_ino;
-            nlink_t     st_nlink;
-            mode_t      st_mode;
-            uid_t       st_uid;
-            gid_t       st_gid;
-            uint        __pad0;
-            dev_t       st_rdev;
-            off_t       st_size;
-            blksize_t   st_blksize;
-            blkcnt_t    st_blocks;
-            time_t      st_atime;
-            ulong_t     st_atimensec;
-            time_t      st_mtime;
-            ulong_t     st_mtimensec;
-            time_t      st_ctime;
-            ulong_t     st_ctimensec;
-            slong_t[3]     __unused;
-        }
-    }
-    else version (MIPS_O32)
-    {
-        struct stat_t
-        {
-            c_ulong     st_dev;
-            c_long[3]   st_pad1;
-            ino_t       st_ino;
-            mode_t      st_mode;
-            nlink_t     st_nlink;
-            uid_t       st_uid;
-            gid_t       st_gid;
-            c_ulong     st_rdev;
-            static if (!__USE_FILE_OFFSET64)
-            {
-                c_long[2]   st_pad2;
-                off_t       st_size;
-                c_long      st_pad3;
-            }
-            else
-            {
-                c_long[3]   st_pad2;
-                off_t       st_size;
-            }
-            static if (__USE_MISC || __USE_XOPEN2K8)
-            {
-                timespec    st_atim;
-                timespec    st_mtim;
-                timespec    st_ctim;
-                extern(D) @safe @property inout pure nothrow
-                {
-                    ref inout(time_t) st_atime() return { return st_atim.tv_sec; }
-                    ref inout(time_t) st_mtime() return { return st_mtim.tv_sec; }
-                    ref inout(time_t) st_ctime() return { return st_ctim.tv_sec; }
-                }
-            }
-            else
-            {
-                time_t      st_atime;
-                c_ulong     st_atimensec;
-                time_t      st_mtime;
-                c_ulong     st_mtimensec;
-                time_t      st_ctime;
-                c_ulong     st_ctimensec;
-            }
-            blksize_t   st_blksize;
-            static if (!__USE_FILE_OFFSET64)
-            {
-                blkcnt_t    st_blocks;
-            }
-            else
-            {
-                c_long      st_pad4;
-                blkcnt_t    st_blocks;
-            }
-            c_long[14]  st_pad5;
-        }
-    }
-    else version (ARM)
-    {
-        private
-        {
-            alias __dev_t = ulong;
-            alias __ino_t = c_ulong;
-            alias __ino64_t = ulong;
-            alias __mode_t = uint;
-            alias __nlink_t = size_t;
-            alias __uid_t = uint;
-            alias __gid_t = uint;
-            alias __off_t = c_long;
-            alias __off64_t = long;
-            alias __blksize_t = c_long;
-            alias __blkcnt_t = c_long;
-            alias __blkcnt64_t = long;
-            alias __timespec = timespec;
-            alias __time_t = time_t;
-        }
-        struct stat_t
-        {
-            __dev_t st_dev;
-            ushort __pad1;
-
-            static if (!__USE_FILE_OFFSET64)
-            {
-                __ino_t st_ino;
-            }
-            else
-            {
-                __ino_t __st_ino;
-            }
-            __mode_t st_mode;
-            __nlink_t st_nlink;
-            __uid_t st_uid;
-            __gid_t st_gid;
-            __dev_t st_rdev;
-            ushort __pad2;
-
-            static if (!__USE_FILE_OFFSET64)
-            {
-                __off_t st_size;
-            }
-            else
-            {
-                __off64_t st_size;
-            }
-            __blksize_t st_blksize;
-
-            static if (!__USE_FILE_OFFSET64)
-            {
-                __blkcnt_t st_blocks;
-            }
-            else
-            {
-                __blkcnt64_t st_blocks;
-            }
-
-            __time_t st_atime;
-            c_ulong st_atimensec;
-            __time_t st_mtime;
-            c_ulong st_mtimensec;
-            __time_t st_ctime;
-            c_ulong st_ctimensec;
-
-            static if (!__USE_FILE_OFFSET64)
-            {
-                c_ulong __unused4;
-                c_ulong __unused5;
-            }
-            else
-            {
-                __ino64_t st_ino;
-            }
-        }
-        static if (__USE_FILE_OFFSET64)
-            static assert(stat_t.sizeof == 104);
-        else
-            static assert(stat_t.sizeof == 88);
-    }
-    else
-        static assert(0, "unimplemented");
-
     enum S_IRUSR    = 0x100; // octal 0400
     enum S_IWUSR    = 0x080; // octal 0200
     enum S_IXUSR    = 0x040; // octal 0100
@@ -2154,10 +1668,6 @@
     enum S_IXOTH    = S_IXGRP >> 3;
     enum S_IRWXO    = S_IRWXG >> 3;
 
-    enum S_ISUID    = 0x800; // octal 04000
-    enum S_ISGID    = 0x400; // octal 02000
-    enum S_ISVTX    = 0x200; // octal 01000
-
     private
     {
         extern (D) bool S_ISTYPE( mode_t mode, uint mask )
@@ -2174,16 +1684,6 @@
     extern (D) bool S_ISLNK( mode_t mode )  { return S_ISTYPE( mode, S_IFLNK );  }
     extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
 
-    static if ( true /*__USE_POSIX199309*/ )
-    {
-        extern bool S_TYPEISMQ( stat_t* buf )  { return false; }
-        extern bool S_TYPEISSEM( stat_t* buf ) { return false; }
-        extern bool S_TYPEISSHM( stat_t* buf ) { return false; }
-    }
-
-    enum UTIME_NOW = 0x3fffffff;
-    enum UTIME_OMIT = 0x3ffffffe;
-
     int utimensat(int dirfd, const char *pathname,
     ref const(timespec)[2] times, int flags);
     int futimens(int fd, ref const(timespec)[2] times);
@@ -2193,6 +1693,17 @@
     static assert(false, "Unsupported platform");
 }
 
+/*
+int    chmod(const scope char*, mode_t);
+int    fchmod(int, mode_t);
+int    fstat(int, stat*);
+int    lstat(const scope char*, stat*);
+int    mkdir(const scope char*, mode_t);
+int    mkfifo(const scope char*, mode_t);
+int    stat(const scope char*, stat*);
+mode_t umask(mode_t);
+*/
+
 int    chmod(const scope char*, mode_t);
 int    fchmod(int, mode_t);
 //int    fstat(int, stat_t*);
@@ -2385,11 +1896,9 @@
 S_IFDIR
 S_IFLNK
 S_IFSOCK
-
-int mknod(in 3char*, mode_t, dev_t);
 */
 
-version (CRuntime_Glibc)
+version (linux)
 {
     enum S_IFMT     = 0xF000; // octal 0170000
     enum S_IFBLK    = 0x6000; // octal 0060000
@@ -2399,8 +1908,6 @@
     enum S_IFDIR    = 0x4000; // octal 0040000
     enum S_IFLNK    = 0xA000; // octal 0120000
     enum S_IFSOCK   = 0xC000; // octal 0140000
-
-    int mknod(const scope char*, mode_t, dev_t);
 }
 else version (Darwin)
 {
@@ -2412,8 +1919,6 @@
     enum S_IFDIR    = 0x4000; // octal 0040000
     enum S_IFLNK    = 0xA000; // octal 0120000
     enum S_IFSOCK   = 0xC000; // octal 0140000
-
-    int mknod(const scope char*, mode_t, dev_t);
 }
 else version (FreeBSD)
 {
@@ -2425,7 +1930,72 @@
     enum S_IFDIR    = 0x4000; // octal 0040000
     enum S_IFLNK    = 0xA000; // octal 0120000
     enum S_IFSOCK   = 0xC000; // octal 0140000
+}
+else version (NetBSD)
+{
+    enum S_IFMT     = 0xF000; // octal 0170000
+    enum S_IFBLK    = 0x6000; // octal 0060000
+    enum S_IFCHR    = 0x2000; // octal 0020000
+    enum S_IFIFO    = 0x1000; // octal 0010000
+    enum S_IFREG    = 0x8000; // octal 0100000
+    enum S_IFDIR    = 0x4000; // octal 0040000
+    enum S_IFLNK    = 0xA000; // octal 0120000
+    enum S_IFSOCK   = 0xC000; // octal 0140000
+}
+else version (OpenBSD)
+{
+    enum S_IFMT     = 0xF000; // octal 0170000
+    enum S_IFBLK    = 0x6000; // octal 0060000
+    enum S_IFCHR    = 0x2000; // octal 0020000
+    enum S_IFIFO    = 0x1000; // octal 0010000
+    enum S_IFREG    = 0x8000; // octal 0100000
+    enum S_IFDIR    = 0x4000; // octal 0040000
+    enum S_IFLNK    = 0xA000; // octal 0120000
+    enum S_IFSOCK   = 0xC000; // octal 0140000
+}
+else version (DragonFlyBSD)
+{
+    enum S_IFMT     = 0xF000; // octal 0170000
+    enum S_IFBLK    = 0x6000; // octal 0060000
+    enum S_IFCHR    = 0x2000; // octal 0020000
+    enum S_IFIFO    = 0x1000; // octal 0010000
+    enum S_IFREG    = 0x8000; // octal 0100000
+    enum S_IFDIR    = 0x4000; // octal 0040000
+    enum S_IFLNK    = 0xA000; // octal 0120000
+    enum S_IFSOCK   = 0xC000; // octal 0140000
+}
+else version (Solaris)
+{
+    enum S_IFMT = 0xF000;
+    enum S_IFBLK = 0x6000;
+    enum S_IFCHR = 0x2000;
+    enum S_IFIFO = 0x1000;
+    enum S_IFREG = 0x8000;
+    enum S_IFDIR = 0x4000;
+    enum S_IFLNK = 0xA000;
+    enum S_IFSOCK = 0xC000;
+    enum S_IFDOOR = 0xD000;
+    enum S_IFPORT = 0xE000;
+}
+else
+{
+    static assert(false, "Unsupported platform");
+}
 
+/*
+int mknod(const scope char*, mode_t, dev_t);
+*/
+
+version (CRuntime_Glibc)
+{
+    int mknod(const scope char*, mode_t, dev_t);
+}
+else version (Darwin)
+{
+    int mknod(const scope char*, mode_t, dev_t);
+}
+else version (FreeBSD)
+{
     version (GNU)
     {
         int mknod(const scope char*, mode_t, dev_t);
@@ -2440,97 +2010,30 @@
 }
 else version (NetBSD)
 {
-    enum S_IFMT     = 0xF000; // octal 0170000
-    enum S_IFBLK    = 0x6000; // octal 0060000
-    enum S_IFCHR    = 0x2000; // octal 0020000
-    enum S_IFIFO    = 0x1000; // octal 0010000
-    enum S_IFREG    = 0x8000; // octal 0100000
-    enum S_IFDIR    = 0x4000; // octal 0040000
-    enum S_IFLNK    = 0xA000; // octal 0120000
-    enum S_IFSOCK   = 0xC000; // octal 0140000
-
     int mknod(const scope char*, mode_t, dev_t);
 }
 else version (OpenBSD)
 {
-    enum S_IFMT     = 0xF000; // octal 0170000
-    enum S_IFBLK    = 0x6000; // octal 0060000
-    enum S_IFCHR    = 0x2000; // octal 0020000
-    enum S_IFIFO    = 0x1000; // octal 0010000
-    enum S_IFREG    = 0x8000; // octal 0100000
-    enum S_IFDIR    = 0x4000; // octal 0040000
-    enum S_IFLNK    = 0xA000; // octal 0120000
-    enum S_IFSOCK   = 0xC000; // octal 0140000
-
     int mknod(const scope char*, mode_t, dev_t);
 }
 else version (DragonFlyBSD)
 {
-    enum S_IFMT     = 0xF000; // octal 0170000
-    enum S_IFBLK    = 0x6000; // octal 0060000
-    enum S_IFCHR    = 0x2000; // octal 0020000
-    enum S_IFIFO    = 0x1000; // octal 0010000
-    enum S_IFREG    = 0x8000; // octal 0100000
-    enum S_IFDIR    = 0x4000; // octal 0040000
-    enum S_IFLNK    = 0xA000; // octal 0120000
-    enum S_IFSOCK   = 0xC000; // octal 0140000
-
     int mknod(const scope char*, mode_t, dev_t);
 }
 else version (Solaris)
 {
-    enum S_IFMT = 0xF000;
-    enum S_IFBLK = 0x6000;
-    enum S_IFCHR = 0x2000;
-    enum S_IFIFO = 0x1000;
-    enum S_IFREG = 0x8000;
-    enum S_IFDIR = 0x4000;
-    enum S_IFLNK = 0xA000;
-    enum S_IFSOCK = 0xC000;
-    enum S_IFDOOR = 0xD000;
-    enum S_IFPORT = 0xE000;
-
     int mknod(const scope char*, mode_t, dev_t);
 }
 else version (CRuntime_Bionic)
 {
-    enum S_IFMT     = 0xF000; // octal 0170000
-    enum S_IFBLK    = 0x6000; // octal 0060000
-    enum S_IFCHR    = 0x2000; // octal 0020000
-    enum S_IFIFO    = 0x1000; // octal 0010000
-    enum S_IFREG    = 0x8000; // octal 0100000
-    enum S_IFDIR    = 0x4000; // octal 0040000
-    enum S_IFLNK    = 0xA000; // octal 0120000
-    enum S_IFSOCK   = 0xC000; // octal 0140000
-
     int mknod(const scope char*, mode_t, dev_t);
 }
 else version (CRuntime_Musl)
 {
-    enum {
-        S_IFMT     = 0xF000, // octal 0170000
-        S_IFBLK    = 0x6000, // octal 0060000
-        S_IFCHR    = 0x2000, // octal 0020000
-        S_IFIFO    = 0x1000, // octal 0010000
-        S_IFREG    = 0x8000, // octal 0100000
-        S_IFDIR    = 0x4000, // octal 0040000
-        S_IFLNK    = 0xA000, // octal 0120000
-        S_IFSOCK   = 0xC000, // octal 0140000
-    }
-
     int mknod(const scope char*, mode_t, dev_t);
 }
 else version (CRuntime_UClibc)
 {
-    enum S_IFMT     = 0xF000; // octal 0170000
-    enum S_IFBLK    = 0x6000; // octal 0060000
-    enum S_IFCHR    = 0x2000; // octal 0020000
-    enum S_IFIFO    = 0x1000; // octal 0010000
-    enum S_IFREG    = 0x8000; // octal 0100000
-    enum S_IFDIR    = 0x4000; // octal 0040000
-    enum S_IFLNK    = 0xA000; // octal 0120000
-    enum S_IFSOCK   = 0xC000; // octal 0140000
-
     int mknod(const scope char*, mode_t, dev_t);
 }
 else
diff --git a/libphobos/libdruntime/core/sys/posix/sys/types.d b/libphobos/libdruntime/core/sys/posix/sys/types.d
index abcea99..02cf799 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/types.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/types.d
@@ -86,7 +86,7 @@
 uid_t
 */
 
-version (CRuntime_Glibc)
+version (linux)
 {
   static if ( __USE_FILE_OFFSET64 )
   {
@@ -108,71 +108,40 @@
     alias int       pid_t;
     //size_t (defined in core.stdc.stddef)
     alias c_long    ssize_t;
-    alias slong_t   time_t;
     alias uint      uid_t;
-}
-else version (CRuntime_Musl)
-{
-    version (AArch64)
-    {
-        alias int    blksize_t;
-        alias uint   nlink_t;
-    }
-    else version (MIPS64)
-    {
-        alias c_long blksize_t;
-        alias uint   nlink_t;
-    }
-    else version (RISCV64)
-    {
-        alias int    blksize_t;
-        alias uint   nlink_t;
-    }
-    else
-    {
-        alias c_long blksize_t;
-        alias c_ulong nlink_t;
-    }
-    alias long       dev_t;
-    alias long       blkcnt_t;
-    alias ulong      ino_t;
-    alias long       off_t;
-    alias int        pid_t;
-    alias uint       uid_t;
-    alias uint       gid_t;
 
-    /**
-     * Musl versions before v1.2.0 (up to v1.1.24) had different
-     * definitions for `time_t` for 32 bits.
-     * This was changed to always be 64 bits in v1.2.0:
-     * https://musl.libc.org/time64.html
-     * This change was only for 32 bits system and
-     * didn't affect 64 bits systems
-     *
-     * To check previous definitions, `grep` for `time_t` in `arch/`,
-     * and the result should be (in v1.1.24):
-     * ---
-     * // arch/riscv64/bits/alltypes.h.in:20:TYPEDEF long time_t;
-     * // arch/s390x/bits/alltypes.h.in:17:TYPEDEF long time_t;
-     * // arch/sh/bits/alltypes.h.in:21:TYPEDEF long time_t;
-     * ---
-     *
-     * In order to be compatible with old versions of Musl,
-     * one can recompile druntime with `CRuntime_Musl_Pre_Time64`.
-     */
-    version (D_X32)
-        alias long   time_t;
-    else version (CRuntime_Musl_Pre_Time64)
-        alias c_long time_t;
+    version (CRuntime_Musl)
+    {
+        /**
+         * Musl versions before v1.2.0 (up to v1.1.24) had different
+         * definitions for `time_t` for 32 bits.
+         * This was changed to always be 64 bits in v1.2.0:
+         * https://musl.libc.org/time64.html
+         * This change was only for 32 bits system and
+         * didn't affect 64 bits systems
+         *
+         * To check previous definitions, `grep` for `time_t` in `arch/`,
+         * and the result should be (in v1.1.24):
+         * ---
+         * // arch/riscv64/bits/alltypes.h.in:20:TYPEDEF long time_t;
+         * // arch/s390x/bits/alltypes.h.in:17:TYPEDEF long time_t;
+         * // arch/sh/bits/alltypes.h.in:21:TYPEDEF long time_t;
+         * ---
+         *
+         * In order to be compatible with old versions of Musl,
+         * one can recompile druntime with `CRuntime_Musl_Pre_Time64`.
+         */
+        version (D_X32)
+           alias long   time_t;
+        else version (CRuntime_Musl_Pre_Time64)
+            alias c_long time_t;
+        else
+            alias long  time_t;
+    }
     else
-        alias long   time_t;
-
-    alias c_long     clock_t;
-    alias c_ulong    pthread_t;
-    version (D_LP64)
-        alias c_long ssize_t;
-    else
-        alias int    ssize_t;
+    {
+        alias slong_t   time_t;
+    }
 }
 else version (Darwin)
 {
@@ -311,67 +280,6 @@
     alias c_long time_t;
     alias uint uid_t;
 }
-else version (CRuntime_Bionic)
-{
-    alias c_ulong   blkcnt_t;
-    alias c_ulong   blksize_t;
-    alias size_t    dev_t;
-    alias uint      gid_t;
-    alias c_ulong   ino_t;
-    alias c_long    off_t;
-    alias int       pid_t;
-    alias c_long    ssize_t;
-    alias c_long    time_t;
-    alias uint      uid_t;
-
-    version (D_LP64)
-    {
-        alias uint      mode_t;
-        alias uint      nlink_t;
-    }
-    else
-    {
-        alias ushort    mode_t;
-        alias ushort    nlink_t;
-    }
-}
-else version (CRuntime_UClibc)
-{
-    static if ( __USE_FILE_OFFSET64 )
-    {
-        alias long      blkcnt_t;
-        alias ulong     ino_t;
-        alias long      off_t;
-    }
-    else
-    {
-        alias slong_t   blkcnt_t;
-        alias ulong_t   ino_t;
-        alias slong_t   off_t;
-    }
-
-    version (D_LP64)
-    {
-        alias ino_t ino64_t;
-        alias off_t off64_t;
-    }
-    else
-    {
-        alias ulong ino64_t;
-        alias long off64_t;
-    }
-
-    alias slong_t   blksize_t;
-    alias c_ulong   dev_t;
-    alias uint      gid_t;
-    alias uint      mode_t;
-    alias uint      nlink_t;
-    alias int       pid_t;
-    //size_t (defined in core.stdc.stddef)
-    alias c_long    ssize_t;
-    alias slong_t   time_t;
-    alias uint      uid_t;
-}
 else
 {
     static assert(false, "Unsupported platform");
@@ -390,7 +298,7 @@
 useconds_t
 */
 
-version (CRuntime_Glibc)
+version (linux)
 {
   static if ( __USE_FILE_OFFSET64 )
   {
@@ -483,53 +391,6 @@
     alias id_t zoneid_t;
     alias id_t ctid_t;
 }
-else version (CRuntime_Bionic)
-{
-    alias c_ulong  fsblkcnt_t;
-    alias c_ulong  fsfilcnt_t;
-    alias c_long   clock_t;
-    alias uint     id_t;
-    alias int      key_t;
-    alias c_long   suseconds_t;
-    alias uint     useconds_t; // Updated in Lollipop
-}
-else version (CRuntime_Musl)
-{
-  static if ( __USE_FILE_OFFSET64 )
-  {
-    alias ulong     fsblkcnt_t;
-    alias ulong     fsfilcnt_t;
-  }
-  else
-  {
-    alias ulong_t   fsblkcnt_t;
-    alias ulong_t   fsfilcnt_t;
-  }
-    alias uint mode_t;
-    alias uint id_t;
-    version (D_X32)
-        alias long susseconds_t;
-    else
-        alias c_long suseconds_t;
-}
-else version (CRuntime_UClibc)
-{
-  static if ( __USE_FILE_OFFSET64 )
-  {
-    alias ulong     fsblkcnt_t;
-    alias ulong     fsfilcnt_t;
-  }
-  else
-  {
-    alias ulong_t   fsblkcnt_t;
-    alias ulong_t   fsfilcnt_t;
-  }
-    alias slong_t   clock_t;
-    alias uint      id_t;
-    alias int       key_t;
-    alias slong_t   suseconds_t;
-    alias uint      useconds_t;
-}
 else
 {
     static assert(false, "Unsupported platform");
@@ -896,6 +757,8 @@
     }
 
     alias int pthread_once_t;
+
+    alias c_ulong pthread_t;
 }
 else version (Darwin)
 {
diff --git a/libphobos/libdruntime/core/sys/posix/sys/wait.d b/libphobos/libdruntime/core/sys/posix/sys/wait.d
index dada64f..91b9c9e 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/wait.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/wait.d
@@ -38,7 +38,81 @@
 /*
 WNOHANG
 WUNTRACED
+*/
 
+version (linux)
+{
+    enum WNOHANG        = 1;
+    enum WUNTRACED      = 2;
+
+    private
+    {
+        enum __W_CONTINUED = 0xFFFF;
+    }
+}
+else version (Darwin)
+{
+    enum WNOHANG        = 1;
+    enum WUNTRACED      = 2;
+
+    private
+    {
+        enum _WSTOPPED = 0x7F; // octal 0177
+    }
+}
+else version (FreeBSD)
+{
+    enum WNOHANG        = 1;
+    enum WUNTRACED      = 2;
+
+    private
+    {
+        enum _WSTOPPED = 0x7F; // octal 0177
+        enum __W_CONTINUED = 0x13;
+    }
+}
+else version (NetBSD)
+{
+    enum WNOHANG        = 1;
+    enum WUNTRACED      = 2;
+
+    private
+    {
+        enum _WSTOPPED = 0x7F; // octal 0177
+    }
+}
+else version (OpenBSD)
+{
+    enum WNOHANG        = 1;
+    enum WUNTRACED      = 2;
+
+    private
+    {
+        enum _WSTOPPED   = 0x7F;   // octal 0177
+        enum _WCONTINUED = 0xFFFF; // octal 0177777
+    }
+}
+else version (DragonFlyBSD)
+{
+    enum WNOHANG        = 1;
+    enum WUNTRACED      = 2;
+
+    private
+    {
+        enum _WSTOPPED = 0x7F; // octal 0177
+    }
+}
+else version (Solaris)
+{
+    enum WNOHANG        = 64;
+    enum WUNTRACED      = 4;
+}
+else
+{
+    static assert(false, "Unsupported platform");
+}
+
+/*
 WEXITSTATUS
 WIFCONTINUED
 WIFEXITED
@@ -46,22 +120,14 @@
 WIFSTOPPED
 WSTOPSIG
 WTERMSIG
-
-pid_t wait(int*);
-pid_t waitpid(pid_t, int*, int);
 */
 
 version (CRuntime_Glibc)
 {
     @safe pure:
 
-    enum WNOHANG        = 1;
-    enum WUNTRACED      = 2;
-
     private
     {
-        enum __W_CONTINUED = 0xFFFF;
-
         extern (D) int __WTERMSIG( int status ) { return status & 0x7F; }
     }
 
@@ -85,14 +151,6 @@
 {
     @safe pure:
 
-    enum WNOHANG        = 1;
-    enum WUNTRACED      = 2;
-
-    private
-    {
-        enum _WSTOPPED = 0x7F; // octal 0177
-    }
-
     extern (D) int _WSTATUS(int status)         { return (status & 0x7F);           }
     extern (D) int  WEXITSTATUS( int status )   { return (status >> 8);             }
     extern (D) int  WIFCONTINUED( int status )  { return status == 0x13;            }
@@ -109,14 +167,6 @@
 {
     @safe pure:
 
-    enum WNOHANG        = 1;
-    enum WUNTRACED      = 2;
-
-    private
-    {
-        enum _WSTOPPED = 0x7F; // octal 0177
-    }
-
     extern (D) int _WSTATUS(int status)         { return (status & 0x7F);           }
     extern (D) int  WEXITSTATUS( int status )   { return (status >> 8);             }
     extern (D) int  WIFCONTINUED( int status )  { return status == 0x13;            }
@@ -133,14 +183,6 @@
 {
     @safe pure:
 
-    enum WNOHANG        = 1;
-    enum WUNTRACED      = 2;
-
-    private
-    {
-        enum _WSTOPPED = 0x7F; // octal 0177
-    }
-
     extern (D) int _WSTATUS(int status)         { return (status & 0x7F);           }
     extern (D) int  WEXITSTATUS( int status )   { return (status >> 8);             }
     extern (D) int  WIFCONTINUED( int status )  { return status == 0x13;            }
@@ -157,15 +199,6 @@
 {
     @safe pure:
 
-    enum WNOHANG        = 1;
-    enum WUNTRACED      = 2;
-
-    private
-    {
-        enum _WSTOPPED   = 0x7F;   // octal 0177
-        enum _WCONTINUED = 0xFFFF; // octal 0177777
-    }
-
     extern (D) int _WSTATUS(int status)         { return (status & 0x7F);                     }
     extern (D) int  WEXITSTATUS(int status)   { return (status >> 8) & 0xFF;                  }
     extern (D) int  WIFCONTINUED(int status)  { return (status & _WCONTINUED) == _WCONTINUED; }
@@ -182,14 +215,6 @@
 {
     @safe pure:
 
-    enum WNOHANG        = 1;
-    enum WUNTRACED      = 2;
-
-    private
-    {
-        enum _WSTOPPED = 0x7F; // octal 0177
-    }
-
     extern (D) int _WSTATUS(int status)         { return (status & 0x7F);           }
     extern (D) int  WEXITSTATUS( int status )   { return (status >> 8);             }
     extern (D) int  WIFCONTINUED( int status )  { return status == 0x13;            }
@@ -206,9 +231,6 @@
 {
     @safe pure:
 
-    enum WNOHANG        = 64;
-    enum WUNTRACED      = 4;
-
     extern (D) int WEXITSTATUS(int status) { return (status >> 8) & 0xff; }
     extern (D) int WIFCONTINUED(int status) { return (status & 0xffff) == 0xffff; }
     extern (D) bool WIFEXITED(int status) { return (status & 0xff) == 0;     }
@@ -220,10 +242,6 @@
 else version (CRuntime_Bionic)
 {
     @safe pure:
-
-    enum WNOHANG   = 1;
-    enum WUNTRACED = 2;
-
     extern (D) int  WEXITSTATUS( int status ) { return ( status & 0xFF00 ) >> 8; }
     extern (D) bool WIFEXITED( int status ) { return WTERMSIG(status) == 0; }
     extern (D) bool WIFSIGNALED( int status ) { return WTERMSIG(status + 1) >= 2; }
@@ -234,10 +252,6 @@
 else version (CRuntime_Musl)
 {
     @safe pure:
-
-    enum WNOHANG        = 1;
-    enum WUNTRACED      = 2;
-
     extern (D) int  WEXITSTATUS( int status ) { return ( status & 0xFF00 ) >> 8; }
     extern (D) int  WIFCONTINUED( int status ) { return status == 0xffff; }
     extern (D) bool WIFEXITED( int status ) { return WTERMSIG( status ) == 0; }
@@ -250,13 +264,8 @@
 {
     @safe pure:
 
-    enum WNOHANG        = 1;
-    enum WUNTRACED      = 2;
-
     private
     {
-        enum __W_CONTINUED = 0xFFFF;
-
         extern (D) int __WTERMSIG( int status ) { return status & 0x7F; }
     }
 
@@ -288,6 +297,11 @@
     static assert(false, "Unsupported platform");
 }
 
+/*
+pid_t wait(int*);
+pid_t waitpid(pid_t, int*, int);
+*/
+
 pid_t wait(int*);
 pid_t waitpid(pid_t, int*, int);
 
@@ -306,11 +320,9 @@
     P_PID,
     P_PGID
 }
-
-int waitid(idtype_t, id_t, siginfo_t*, int);
 */
 
-version (CRuntime_Glibc)
+version (linux)
 {
     enum WEXITED    = 4;
     enum WSTOPPED   = 2;
@@ -323,8 +335,6 @@
         P_PID,
         P_PGID
     }
-
-    int waitid(idtype_t, id_t, siginfo_t*, int);
 }
 else version (Darwin)
 {
@@ -339,8 +349,6 @@
         P_PID,
         P_PGID
     }
-
-    int waitid(idtype_t, id_t, siginfo_t*, int);
 }
 else version (FreeBSD)
 {
@@ -369,8 +377,6 @@
         P_CPUID,
         P_PSETID
     }
-
-    int waitid(idtype_t, id_t, siginfo_t*, int);
 }
 else version (NetBSD)
 {
@@ -419,50 +425,51 @@
         P_CPUID,        /* CPU identifier.                      */
         P_PSETID,       /* Processor set identifier             */
     }
+}
+else
+{
+    static assert(false, "Unsupported platform");
+}
 
+/*
+int waitid(idtype_t, id_t, siginfo_t*, int);
+*/
+
+version (CRuntime_Glibc)
+{
+    int waitid(idtype_t, id_t, siginfo_t*, int);
+}
+else version (Darwin)
+{
+    int waitid(idtype_t, id_t, siginfo_t*, int);
+}
+else version (FreeBSD)
+{
+    int waitid(idtype_t, id_t, siginfo_t*, int);
+}
+else version (NetBSD)
+{
+}
+else version (OpenBSD)
+{
+}
+else version (DragonFlyBSD)
+{
+}
+else version (Solaris)
+{
     int waitid(idtype_t, id_t, siginfo_t*, int);
 }
 else version (CRuntime_Bionic)
 {
-    enum WEXITED    = 4;
-    enum WSTOPPED   = 2;
-    enum WCONTINUED = 8;
-    enum WNOWAIT    = 0x01000000;
-
-    alias int idtype_t;
-
     int waitid(idtype_t, id_t, siginfo_t*, int);
 }
 else version (CRuntime_Musl)
 {
-    enum WEXITED    = 4;
-    enum WSTOPPED   = 2;
-    enum WCONTINUED = 8;
-    enum WNOWAIT    = 0x01000000;
-
-    enum idtype_t
-    {
-        P_ALL,
-        P_PID,
-        P_PGID
-    }
-
     int waitid(idtype_t, id_t, siginfo_t*, int);
 }
 else version (CRuntime_UClibc)
 {
-    enum WEXITED    = 4;
-    enum WSTOPPED   = 2;
-    enum WCONTINUED = 8;
-    enum WNOWAIT    = 0x01000000;
-
-    enum idtype_t
-    {
-        P_ALL,
-        P_PID,
-        P_PGID
-    }
-
     int waitid(idtype_t, id_t, siginfo_t*, int);
 }
 else
diff --git a/libphobos/libdruntime/core/sys/posix/termios.d b/libphobos/libdruntime/core/sys/posix/termios.d
index 5de6785..357060b 100644
--- a/libphobos/libdruntime/core/sys/posix/termios.d
+++ b/libphobos/libdruntime/core/sys/posix/termios.d
@@ -129,20 +129,9 @@
 TCION
 TCOOFF
 TCOON
-
-speed_t cfgetispeed(const scope termios*);
-speed_t cfgetospeed(const scope termios*);
-int     cfsetispeed(termios*, speed_t);
-int     cfsetospeed(termios*, speed_t);
-int     tcdrain(int);
-int     tcflow(int, int);
-int     tcflush(int, int);
-int     tcgetattr(int, termios*);
-int     tcsendbreak(int, int);
-int     tcsetattr(int, int, const scope termios*);
 */
 
-version (CRuntime_Glibc)
+version (linux)
 {
     alias ubyte cc_t;
     alias uint  speed_t;
@@ -239,17 +228,6 @@
     enum TCION      = 3;
     enum TCOOFF     = 0;
     enum TCOON      = 1;
-
-    speed_t cfgetispeed(const scope termios*);
-    speed_t cfgetospeed(const scope termios*);
-    int     cfsetispeed(termios*, speed_t);
-    int     cfsetospeed(termios*, speed_t);
-    int     tcdrain(int);
-    int     tcflow(int, int);
-    int     tcflush(int, int);
-    int     tcgetattr(int, termios*);
-    int     tcsendbreak(int, int);
-    int     tcsetattr(int, int, const scope termios*);
 }
 else version (Darwin)
 {
@@ -347,18 +325,6 @@
     enum TCION      = 4;
     enum TCOOFF     = 1;
     enum TCOON      = 2;
-
-    speed_t cfgetispeed(const scope termios*);
-    speed_t cfgetospeed(const scope termios*);
-    int     cfsetispeed(termios*, speed_t);
-    int     cfsetospeed(termios*, speed_t);
-    int     tcdrain(int);
-    int     tcflow(int, int);
-    int     tcflush(int, int);
-    int     tcgetattr(int, termios*);
-    int     tcsendbreak(int, int);
-    int     tcsetattr(int, int, const scope termios*);
-
 }
 else version (FreeBSD)
 {
@@ -456,17 +422,6 @@
     enum TCION      = 4;
     enum TCOOFF     = 1;
     enum TCOON      = 2;
-
-    speed_t cfgetispeed(const scope termios*);
-    speed_t cfgetospeed(const scope termios*);
-    int     cfsetispeed(termios*, speed_t);
-    int     cfsetospeed(termios*, speed_t);
-    int     tcdrain(int);
-    int     tcflow(int, int);
-    int     tcflush(int, int);
-    int     tcgetattr(int, termios*);
-    int     tcsendbreak(int, int);
-    int     tcsetattr(int, int, const scope termios*);
 }
 else version (DragonFlyBSD)
 {
@@ -564,17 +519,6 @@
     enum TCION      = 4;
     enum TCOOFF     = 1;
     enum TCOON      = 2;
-
-    speed_t cfgetispeed(const scope termios*);
-    speed_t cfgetospeed(const scope termios*);
-    int     cfsetispeed(termios*, speed_t);
-    int     cfsetospeed(termios*, speed_t);
-    int     tcdrain(int);
-    int     tcflow(int, int);
-    int     tcflush(int, int);
-    int     tcgetattr(int, termios*);
-    int     tcsendbreak(int, int);
-    int     tcsetattr(int, int, const scope termios*);
 }
 else version (NetBSD)
 {
@@ -672,17 +616,6 @@
     enum TCION      = 4;
     enum TCOOFF     = 1;
     enum TCOON      = 2;
-
-    speed_t cfgetispeed(const scope termios*);
-    speed_t cfgetospeed(const scope termios*);
-    int     cfsetispeed(termios*, speed_t);
-    int     cfsetospeed(termios*, speed_t);
-    int     tcdrain(int);
-    int     tcflow(int, int);
-    int     tcflush(int, int);
-    int     tcgetattr(int, termios*);
-    int     tcsendbreak(int, int);
-    int     tcsetattr(int, int, const scope termios*);
 }
 else version (OpenBSD)
 {
@@ -780,17 +713,6 @@
     enum TCION      = 4;
     enum TCOOFF     = 1;
     enum TCOON      = 2;
-
-    speed_t cfgetispeed(const scope termios*);
-    speed_t cfgetospeed(const scope termios*);
-    int     cfsetispeed(termios*, speed_t);
-    int     cfsetospeed(termios*, speed_t);
-    int     tcdrain(int);
-    int     tcflow(int, int);
-    int     tcflush(int, int);
-    int     tcgetattr(int, termios*);
-    int     tcsendbreak(int, int);
-    int     tcsetattr(int, int, const scope termios*);
 }
 else version (Solaris)
 {
@@ -909,11 +831,102 @@
     enum B307200 = 21;
     enum B460800 = 22;
     enum B921600 = 23;
+}
 
-    /*
-     * POSIX termios functions
-     * These functions get mapped into ioctls.
-     */
+/*
+speed_t cfgetispeed(const scope termios*);
+speed_t cfgetospeed(const scope termios*);
+int     cfsetispeed(termios*, speed_t);
+int     cfsetospeed(termios*, speed_t);
+int     tcdrain(int);
+int     tcflow(int, int);
+int     tcflush(int, int);
+int     tcgetattr(int, termios*);
+int     tcsendbreak(int, int);
+int     tcsetattr(int, int, const scope termios*);
+*/
+
+version (CRuntime_Glibc)
+{
+    speed_t cfgetispeed(const scope termios*);
+    speed_t cfgetospeed(const scope termios*);
+    int     cfsetispeed(termios*, speed_t);
+    int     cfsetospeed(termios*, speed_t);
+    int     tcdrain(int);
+    int     tcflow(int, int);
+    int     tcflush(int, int);
+    int     tcgetattr(int, termios*);
+    int     tcsendbreak(int, int);
+    int     tcsetattr(int, int, const scope termios*);
+}
+else version (Darwin)
+{
+    speed_t cfgetispeed(const scope termios*);
+    speed_t cfgetospeed(const scope termios*);
+    int     cfsetispeed(termios*, speed_t);
+    int     cfsetospeed(termios*, speed_t);
+    int     tcdrain(int);
+    int     tcflow(int, int);
+    int     tcflush(int, int);
+    int     tcgetattr(int, termios*);
+    int     tcsendbreak(int, int);
+    int     tcsetattr(int, int, const scope termios*);
+
+}
+else version (FreeBSD)
+{
+    speed_t cfgetispeed(const scope termios*);
+    speed_t cfgetospeed(const scope termios*);
+    int     cfsetispeed(termios*, speed_t);
+    int     cfsetospeed(termios*, speed_t);
+    int     tcdrain(int);
+    int     tcflow(int, int);
+    int     tcflush(int, int);
+    int     tcgetattr(int, termios*);
+    int     tcsendbreak(int, int);
+    int     tcsetattr(int, int, const scope termios*);
+}
+else version (DragonFlyBSD)
+{
+    speed_t cfgetispeed(const scope termios*);
+    speed_t cfgetospeed(const scope termios*);
+    int     cfsetispeed(termios*, speed_t);
+    int     cfsetospeed(termios*, speed_t);
+    int     tcdrain(int);
+    int     tcflow(int, int);
+    int     tcflush(int, int);
+    int     tcgetattr(int, termios*);
+    int     tcsendbreak(int, int);
+    int     tcsetattr(int, int, const scope termios*);
+}
+else version (NetBSD)
+{
+    speed_t cfgetispeed(const scope termios*);
+    speed_t cfgetospeed(const scope termios*);
+    int     cfsetispeed(termios*, speed_t);
+    int     cfsetospeed(termios*, speed_t);
+    int     tcdrain(int);
+    int     tcflow(int, int);
+    int     tcflush(int, int);
+    int     tcgetattr(int, termios*);
+    int     tcsendbreak(int, int);
+    int     tcsetattr(int, int, const scope termios*);
+}
+else version (OpenBSD)
+{
+    speed_t cfgetispeed(const scope termios*);
+    speed_t cfgetospeed(const scope termios*);
+    int     cfsetispeed(termios*, speed_t);
+    int     cfsetospeed(termios*, speed_t);
+    int     tcdrain(int);
+    int     tcflow(int, int);
+    int     tcflush(int, int);
+    int     tcgetattr(int, termios*);
+    int     tcsendbreak(int, int);
+    int     tcsetattr(int, int, const scope termios*);
+}
+else version (Solaris)
+{
     speed_t cfgetospeed(const scope termios*);
     int     cfsetospeed(termios*, speed_t);
     speed_t cfgetispeed(const scope termios*);
@@ -927,108 +940,6 @@
 }
 else version (CRuntime_UClibc)
 {
-    alias ubyte cc_t;
-    alias uint  speed_t;
-    alias uint  tcflag_t;
-
-    enum NCCS   = 32;
-
-    struct termios
-    {
-        tcflag_t   c_iflag;
-        tcflag_t   c_oflag;
-        tcflag_t   c_cflag;
-        tcflag_t   c_lflag;
-        cc_t       c_line;
-        cc_t[NCCS] c_cc;
-        speed_t    c_ispeed;
-        speed_t    c_ospeed;
-    }
-
-    enum VINTR      = 0;
-    enum VQUIT      = 1;
-    enum VERASE     = 2;
-    enum VKILL      = 3;
-    enum VEOF       = 4;
-    enum VTIME      = 5;
-    enum VMIN       = 6;
-    enum VSWTC      = 7;
-    enum VSTART     = 8;
-    enum VSTOP      = 9;
-    enum VSUSP      = 10;
-    enum VEOL       = 11;
-    enum VREPRINT   = 12;
-    enum VDISCARD   = 13;
-    enum VWERASE    = 14;
-    enum VLNEXT     = 15;
-    enum VEOL2      = 16;
-
-    enum BRKINT     = 0x0000002; // 0000002
-    enum ICRNL      = 0x0000100; // 0000400
-    enum IGNBRK     = 0x0000001; // 0000001
-    enum IGNCR      = 0x0000080; // 0000200
-    enum IGNPAR     = 0x0000004; // 0000004
-    enum INLCR      = 0x0000040; // 0000100
-    enum INPCK      = 0x0000010; // 0000020
-    enum ISTRIP     = 0x0000020; // 0000040
-    enum IXOFF      = 0x0001000; // 0010000
-    enum IXON       = 0x0000400; // 0002000
-    enum PARMRK     = 0x0000008; // 0000010
-
-    enum OPOST      = 0x0000001; // 0000001
-
-    enum B0         = 0x0000000; // 0000000
-    enum B50        = 0x0000001; // 0000001
-    enum B75        = 0x0000002; // 0000002
-    enum B110       = 0x0000003; // 0000003
-    enum B134       = 0x0000004; // 0000004
-    enum B150       = 0x0000005; // 0000005
-    enum B200       = 0x0000006; // 0000006
-    enum B300       = 0x0000007; // 0000007
-    enum B600       = 0x0000008; // 0000010
-    enum B1200      = 0x0000009; // 0000011
-    enum B1800      = 0x000000A; // 0000012
-    enum B2400      = 0x000000B; // 0000013
-    enum B4800      = 0x000000C; // 0000014
-    enum B9600      = 0x000000D; // 0000015
-    enum B19200     = 0x000000E; // 0000016
-    enum B38400     = 0x000000F; // 0000017
-
-    enum CSIZE      = 0x0000030; // 0000060
-    enum   CS5      = 0x0000000; // 0000000
-    enum   CS6      = 0x0000010; // 0000020
-    enum   CS7      = 0x0000020; // 0000040
-    enum   CS8      = 0x0000030; // 0000060
-    enum CSTOPB     = 0x0000040; // 0000100
-    enum CREAD      = 0x0000080; // 0000200
-    enum PARENB     = 0x0000100; // 0000400
-    enum PARODD     = 0x0000200; // 0001000
-    enum HUPCL      = 0x0000400; // 0002000
-    enum CLOCAL     = 0x0000800; // 0004000
-
-    enum ECHO       = 0x0000008; // 0000010
-    enum ECHOE      = 0x0000010; // 0000020
-    enum ECHOK      = 0x0000020; // 0000040
-    enum ECHONL     = 0x0000040; // 0000100
-    enum ICANON     = 0x0000002; // 0000002
-    enum IEXTEN     = 0x0008000; // 0100000
-    enum ISIG       = 0x0000001; // 0000001
-    enum NOFLSH     = 0x0000080; // 0000200
-    enum TOSTOP     = 0x0000100; // 0000400
-
-    enum TCSANOW    = 0;
-    enum TCSADRAIN  = 1;
-    enum TCSAFLUSH  = 2;
-
-    enum TCIFLUSH   = 0;
-    enum TCOFLUSH   = 1;
-    enum TCIOFLUSH  = 2;
-
-    enum TCIOFF     = 2;
-    enum TCION      = 3;
-    enum TCOOFF     = 0;
-    enum TCOON      = 1;
-
     speed_t cfgetispeed(const scope termios*);
     speed_t cfgetospeed(const scope termios*);
     int     cfsetispeed(termios*, speed_t);
diff --git a/libphobos/libdruntime/core/sys/posix/ucontext.d b/libphobos/libdruntime/core/sys/posix/ucontext.d
index e38aa96..20297f5 100644
--- a/libphobos/libdruntime/core/sys/posix/ucontext.d
+++ b/libphobos/libdruntime/core/sys/posix/ucontext.d
@@ -63,9 +63,8 @@
 }
 */
 
-version (CRuntime_Glibc)
+version (linux)
 {
-
     version (X86_64)
     {
         enum
@@ -146,7 +145,8 @@
             mcontext_t      uc_mcontext;
             sigset_t        uc_sigmask;
             _libc_fpstate   __fpregs_mem;
-            ulong[4]        __ssp;
+            version (CRuntime_Glibc)
+                ulong[4]    __ssp;
         }
     }
     else version (X86)
@@ -218,7 +218,8 @@
             mcontext_t      uc_mcontext;
             sigset_t        uc_sigmask;
             _libc_fpstate   __fpregs_mem;
-            c_ulong[4]      __ssp;
+            version (CRuntime_Glibc)
+                c_ulong[4]  __ssp;
         }
     }
     else version (HPPA)
@@ -788,139 +789,6 @@
     else
         static assert(0, "unimplemented");
 }
-else version (CRuntime_Musl)
-{
-    version (AArch64)
-    {
-        struct mcontext_t
-        {
-            real[18+256] __regs;
-        }
-
-        struct ucontext_t
-        {
-            c_ulong     uc_flags;
-            ucontext_t* uc_link;
-            stack_t     uc_stack;
-            sigset_t    uc_sigmask;
-            mcontext_t  uc_mcontext;
-        }
-    }
-    else version (ARM)
-    {
-        struct mcontext_t
-        {
-            c_ulong[21] __regs;
-        }
-
-        struct ucontext_t
-        {
-            c_ulong     uc_flags;
-            ucontext_t* uc_link;
-            stack_t     uc_stack;
-            mcontext_t  uc_mcontext;
-            sigset_t    uc_sigmask;
-            ulong[64]   uc_regspace;
-        }
-    }
-    else version (IBMZ_Any)
-    {
-        struct mcontext_t
-        {
-            c_ulong[18] __regs1;
-            uint[18]    __regs2;
-            double[16]  __regs3;
-        }
-
-        struct ucontext_t
-        {
-            c_ulong     uc_flags;
-            ucontext_t* uc_link;
-            stack_t     uc_stack;
-            mcontext_t  uc_mcontext;
-            sigset_t    uc_sigmask;
-        }
-    }
-    else version (MIPS_Any)
-    {
-        version (MIPS_N32)
-        {
-            struct mcontext_t
-            {
-                ulong[32]  __mc1;
-                double[32] __mc2;
-                ulong[9]   __mc3;
-                uint[4]    __mc4;
-            }
-        }
-        else version (MIPS64)
-        {
-            struct mcontext_t
-            {
-                ulong[32]  __mc1;
-                double[32] __mc2;
-                ulong[9]   __mc3;
-                uint[4]    __mc4;
-            }
-        }
-        else
-        {
-            struct mcontext_t
-            {
-                uint[2]    __mc1;
-                ulong[65]  __mc2;
-                uint[5]    __mc3;
-                ulong[2]   __mc4;
-                uint[6]    __mc5;
-            }
-        }
-
-        struct ucontext_t
-        {
-            c_ulong     uc_flags;
-            ucontext_t* uc_link;
-            stack_t     uc_stack;
-            mcontext_t  uc_mcontext;
-            sigset_t    uc_sigmask;
-        }
-    }
-    else version (X86)
-    {
-        struct mcontext_t
-        {
-            uint[22] __space;
-        }
-
-        struct ucontext_t
-        {
-            c_ulong     uc_flags;
-            ucontext_t* uc_link;
-            stack_t     uc_stack;
-            mcontext_t  uc_mcontext;
-            sigset_t    uc_sigmask;
-            c_ulong[28] __fpregs_mem;
-        }
-    }
-    else version (X86_64)
-    {
-        struct mcontext_t
-        {
-            ulong[32] __space;
-        }
-
-        struct ucontext_t
-        {
-            c_ulong     uc_flags;
-            ucontext_t* uc_link;
-            stack_t     uc_stack;
-            mcontext_t  uc_mcontext;
-            sigset_t    uc_sigmask;
-            ulong[64]   __fpregs_mem;
-        }
-    }
-    else
-        static assert(0, "unimplemented");
-}
 else version (Darwin)
 {
     private
@@ -1722,186 +1590,6 @@
         }
     }
 }
-else version (CRuntime_UClibc)
-{
-    version (X86_64)
-    {
-        enum
-        {
-            REG_R8 = 0,
-            REG_R9,
-            REG_R10,
-            REG_R11,
-            REG_R12,
-            REG_R13,
-            REG_R14,
-            REG_R15,
-            REG_RDI,
-            REG_RSI,
-            REG_RBP,
-            REG_RBX,
-            REG_RDX,
-            REG_RAX,
-            REG_RCX,
-            REG_RSP,
-            REG_RIP,
-            REG_EFL,
-            REG_CSGSFS,     /* Actually short cs, gs, fs, __pad0.  */
-            REG_ERR,
-            REG_TRAPNO,
-            REG_OLDMASK,
-            REG_CR2
-        }
-
-        alias sigcontext mcontext_t;
-
-        struct ucontext_t
-        {
-            c_ulong         uc_flags;
-            ucontext_t*     uc_link;
-            stack_t         uc_stack;
-            mcontext_t      uc_mcontext;
-            sigset_t        uc_sigmask;
-        }
-    }
-    else version (MIPS32)
-    {
-        alias greg_t    = ulong;
-        enum NGREG      = 32;
-        enum NFPREG     = 32;
-        alias gregset_t = greg_t[NGREG];
-
-        struct fpregset_t
-        {
-            union fp_r
-            {
-                double[NFPREG]  fp_dregs;
-                struct _fp_fregs
-                {
-                    float   _fp_fregs;
-                    uint    _fp_pad;
-                }
-                _fp_fregs[NFPREG] fp_fregs;
-            }
-        }
-
-        version (MIPS_O32)
-        {
-            struct mcontext_t
-            {
-                uint regmask;
-                uint status;
-                greg_t pc;
-                gregset_t gregs;
-                fpregset_t fpregs;
-                uint fp_owned;
-                uint fpc_csr;
-                uint fpc_eir;
-                uint used_math;
-                uint dsp;
-                greg_t mdhi;
-                greg_t mdlo;
-                c_ulong hi1;
-                c_ulong lo1;
-                c_ulong hi2;
-                c_ulong lo2;
-                c_ulong hi3;
-                c_ulong lo3;
-            }
-        }
-        else
-        {
-            struct mcontext_t
-            {
-                gregset_t gregs;
-                fpregset_t fpregs;
-                greg_t mdhi;
-                greg_t hi1;
-                greg_t hi2;
-                greg_t hi3;
-                greg_t mdlo;
-                greg_t lo1;
-                greg_t lo2;
-                greg_t lo3;
-                greg_t pc;
-                uint fpc_csr;
-                uint used_math;
-                uint dsp;
-                uint reserved;
-            }
-        }
-
-        struct ucontext_t
-        {
-            c_ulong uc_flags;
-            ucontext_t* uc_link;
-            stack_t uc_stack;
-            mcontext_t uc_mcontext;
-            sigset_t uc_sigmask;
-        }
-    }
-    else version (ARM)
-    {
-        enum
-        {
-            R0 = 0,
-            R1 = 1,
-            R2 = 2,
-            R3 = 3,
-            R4 = 4,
-            R5 = 5,
-            R6 = 6,
-            R7 = 7,
-            R8 = 8,
-            R9 = 9,
-            R10 = 10,
-            R11 = 11,
-            R12 = 12,
-            R13 = 13,
-            R14 = 14,
-            R15 = 15
-        }
-
-        struct sigcontext
-        {
-            c_ulong trap_no;
-            c_ulong error_code;
-            c_ulong oldmask;
-            c_ulong arm_r0;
-            c_ulong arm_r1;
-            c_ulong arm_r2;
-            c_ulong arm_r3;
-            c_ulong arm_r4;
-            c_ulong arm_r5;
-            c_ulong arm_r6;
-            c_ulong arm_r7;
-            c_ulong arm_r8;
-            c_ulong arm_r9;
-            c_ulong arm_r10;
-            c_ulong arm_fp;
-            c_ulong arm_ip;
-            c_ulong arm_sp;
-            c_ulong arm_lr;
-            c_ulong arm_pc;
-            c_ulong arm_cpsr;
-            c_ulong fault_address;
-        }
-
-        alias sigcontext mcontext_t;
-
-        struct ucontext_t
-        {
-            c_ulong uc_flags;
-            ucontext_t* uc_link;
-            stack_t uc_stack;
-            mcontext_t uc_mcontext;
-            sigset_t uc_sigmask;
-            align(8) c_ulong[128] uc_regspace;
-        }
-    }
-    else
-        static assert(0, "unimplemented");
-}
 
 //
 // Obsolescent (OB)
diff --git a/libphobos/libdruntime/core/sys/solaris/dlfcn.d b/libphobos/libdruntime/core/sys/solaris/dlfcn.d
index 4f69bfd..343f003 100644
--- a/libphobos/libdruntime/core/sys/solaris/dlfcn.d
+++ b/libphobos/libdruntime/core/sys/solaris/dlfcn.d
@@ -14,21 +14,6 @@
 public import core.sys.posix.dlfcn;
 import core.stdc.config;
 
-// enum RTLD_LAZY = 0x00001; // POSIX
-// enum RTLD_NOW = 0x00002; // POSIX
-enum RTLD_NOLOAD = 0x00004;
-enum RTLD_DEEPBIND = 0x00008;
-
-// enum RTLD_GLOBAL = 0x00100; // POSIX
-// enum RTLD_LOCAL = 0; // POSIX
-enum RTLD_PARENT   = 0x00200;
-enum RTLD_GROUP    = 0x00400;
-enum RTLD_WORLD    = 0x00800;
-enum RTLD_NODELETE = 0x01000;
-enum RTLD_FIRST    = 0x02000;
-enum RTLD_CONFGEN  = 0x10000;
-
-
 enum
 {
     RTLD_NEXT    = cast(void *)-1,
@@ -58,21 +43,12 @@
 
 int dldump(const scope char*, const scope char*, int);
 
-struct Dl_info
-{
-    const(char)* dli_fname;
-    void*        dli_fbase;
-    const(char)* dli_sname;
-    void*        dli_saddr;
-}
-
 enum
 {
     RTLD_DL_SYMENT = 1,
     RTLD_DL_LINKMAP = 2,
 }
 
-int dladdr(const(void)*, Dl_info*);
 int dladdr1(void*, Dl_info*, void**, int);
 
 enum
diff --git a/libphobos/libdruntime/core/sys/windows/wingdi.d b/libphobos/libdruntime/core/sys/windows/wingdi.d
index 279f6be..ba45c27 100644
--- a/libphobos/libdruntime/core/sys/windows/wingdi.d
+++ b/libphobos/libdruntime/core/sys/windows/wingdi.d
@@ -4191,8 +4191,8 @@
     DWORD GetGlyphOutlineA(HDC, UINT, UINT, LPGLYPHMETRICS, DWORD, PVOID, const(MAT2)*);
     DWORD GetGlyphOutlineW(HDC, UINT, UINT, LPGLYPHMETRICS, DWORD, PVOID, const(MAT2)*);
     int GetGraphicsMode(HDC);
-    BOOL GetICMProfileA(HDC, DWORD, LPSTR);
-    BOOL GetICMProfileW(HDC, DWORD, LPWSTR);
+    BOOL GetICMProfileA(HDC, LPDWORD, LPSTR);
+    BOOL GetICMProfileW(HDC, LPDWORD, LPWSTR);
     DWORD GetKerningPairsA(HDC, DWORD, LPKERNINGPAIR);
     DWORD GetKerningPairsW(HDC, DWORD, LPKERNINGPAIR);
     BOOL GetLogColorSpaceA(HCOLORSPACE, LPLOGCOLORSPACEA, DWORD);
diff --git a/libphobos/libdruntime/core/thread/osthread.d b/libphobos/libdruntime/core/thread/osthread.d
index fe4d24f..ca36809 100644
--- a/libphobos/libdruntime/core/thread/osthread.d
+++ b/libphobos/libdruntime/core/thread/osthread.d
@@ -247,15 +247,6 @@
 class Thread : ThreadBase
 {
     //
-    // Main process thread
-    //
-    version (FreeBSD)
-    {
-        // set when suspend failed and should be retried, see Issue 13416
-        private shared bool m_suspendagain;
-    }
-
-    //
     // Standard thread data
     //
     version (Windows)
@@ -2019,7 +2010,6 @@
             // subtract own thread
             assert(cnt >= 1);
             --cnt;
-        Lagain:
             // wait for semaphore notifications
             for (; cnt; --cnt)
             {
@@ -2030,20 +2020,6 @@
                     errno = 0;
                 }
             }
-            version (FreeBSD)
-            {
-                // avoid deadlocks, see Issue 13416
-                t = ThreadBase.sm_tbeg.toThread;
-                while (t)
-                {
-                    auto tn = t.next;
-                    if (t.m_suspendagain && suspend(t))
-                        ++cnt;
-                    t = tn.toThread;
-                }
-                if (cnt)
-                    goto Lagain;
-            }
         }
     }
 }
@@ -2480,7 +2456,6 @@
                 status = sigdelset( &sigres, resumeSignalNumber );
                 assert( status == 0 );
 
-                version (FreeBSD) obj.m_suspendagain = false;
                 status = sem_post( &suspendCount );
                 assert( status == 0 );
 
@@ -2491,19 +2466,6 @@
                     obj.m_curr.tstack = obj.m_curr.bstack;
                 }
             }
-
-            // avoid deadlocks on FreeBSD, see Issue 13416
-            version (FreeBSD)
-            {
-                auto obj = Thread.getThis();
-                if (THR_IN_CRITICAL(obj.m_addr))
-                {
-                    obj.m_suspendagain = true;
-                    if (sem_post(&suspendCount)) assert(0);
-                    return;
-                }
-            }
-
             callWithStackShell(&op);
         }
 
@@ -2517,29 +2479,6 @@
         {
 
         }
-
-        // HACK libthr internal (thr_private.h) macro, used to
-        // avoid deadlocks in signal handler, see Issue 13416
-        version (FreeBSD) bool THR_IN_CRITICAL(pthread_t p) nothrow @nogc
-        {
-            import core.sys.posix.config : c_long;
-            import core.sys.posix.sys.types : lwpid_t;
-
-            // If the begin of pthread would be changed in libthr (unlikely)
-            // we'll run into undefined behavior, compare with thr_private.h.
-            static struct pthread
-            {
-                c_long tid;
-                static struct umutex { lwpid_t owner; uint flags; uint[2] ceilings; uint[4] spare; }
-                umutex lock;
-                uint cycle;
-                int locklevel;
-                int critical_count;
-                // ...
-            }
-            auto priv = cast(pthread*)p;
-            return priv.locklevel > 0 || priv.critical_count > 0;
-        }
     }
 }
 else
diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d
index c989caa..7bb6bec 100644
--- a/libphobos/libdruntime/object.d
+++ b/libphobos/libdruntime/object.d
@@ -180,7 +180,30 @@
     /**
      * Test whether $(D this) is equal to $(D o).
      * The default implementation only compares by identity (using the $(D is) operator).
-     * Generally, overrides for $(D opEquals) should attempt to compare objects by their contents.
+     * Generally, overrides and overloads for $(D opEquals) should attempt to compare objects by their contents.
+     * A class will most likely want to add an overload that takes your specific type as the argument
+     * and does the content comparison. Then you can override this and forward it to your specific
+     * typed overload with a cast. Remember to check for `null` on the typed overload.
+     *
+     * Examples:
+     * ---
+     * class Child {
+     *    int contents;
+     *    // the typed overload first. It can use all the attribute you want
+     *    bool opEquals(const Child c) const @safe pure nothrow @nogc
+     *    {
+     *        if (c is null)
+     *            return false;
+     *        return this.contents == c.contents;
+     *    }
+     *
+     *    // and now the generic override forwards with a cast
+     *    override bool opEquals(Object o)
+     *    {
+     *        return this.opEquals(cast(Child) o);
+     *    }
+     * }
+     * ---
      */
     bool opEquals(Object o)
     {
@@ -237,41 +260,50 @@
     }
 }
 
-bool opEquals(Object lhs, Object rhs)
+/++
+    Implementation for class opEquals override. Calls the class-defined methods after a null check.
+    Please note this is not nogc right now, even if your implementation is, because of
+    the typeinfo name string compare. This is because of dmd's dll implementation. However,
+    it can infer to @safe if your class' opEquals is.
++/
+bool opEquals(LHS, RHS)(LHS lhs, RHS rhs) if (is(LHS : const Object) && is(RHS : const Object))
 {
-    // If aliased to the same object or both null => equal
-    if (lhs is rhs) return true;
-
-    // If either is null => non-equal
-    if (lhs is null || rhs is null) return false;
-
-    if (!lhs.opEquals(rhs)) return false;
-
-    // If same exact type => one call to method opEquals
-    if (typeid(lhs) is typeid(rhs) ||
-        !__ctfe && typeid(lhs).opEquals(typeid(rhs)))
-            /* CTFE doesn't like typeid much. 'is' works, but opEquals doesn't
-            (issue 7147). But CTFE also guarantees that equal TypeInfos are
-            always identical. So, no opEquals needed during CTFE. */
+    static if (__traits(compiles, lhs.opEquals(rhs)) && __traits(compiles, rhs.opEquals(lhs)))
     {
-        return true;
+        // If aliased to the same object or both null => equal
+        if (lhs is rhs) return true;
+
+        // If either is null => non-equal
+        if (lhs is null || rhs is null) return false;
+
+        if (!lhs.opEquals(rhs)) return false;
+
+        // If same exact type => one call to method opEquals
+        if (typeid(lhs) is typeid(rhs) ||
+            !__ctfe && typeid(lhs).opEquals(typeid(rhs)))
+                /* CTFE doesn't like typeid much. 'is' works, but opEquals doesn't
+                (issue 7147). But CTFE also guarantees that equal TypeInfos are
+                always identical. So, no opEquals needed during CTFE. */
+        {
+            return true;
+        }
+
+        // General case => symmetric calls to method opEquals
+        return rhs.opEquals(lhs);
     }
+    else
+    {
+        // this is a compatibility hack for the old const cast behavior
+        // if none of the new overloads compile, we'll go back plain Object,
+        // including casting away const. It does this through the pointer
+        // to bypass any opCast that may be present on the original class.
+        return .opEquals!(Object, Object)(*cast(Object*) &lhs, *cast(Object*) &rhs);
 
-    // General case => symmetric calls to method opEquals
-    return rhs.opEquals(lhs);
-}
-
-/************************
-* Returns true if lhs and rhs are equal.
-*/
-bool opEquals(const Object lhs, const Object rhs)
-{
-    // A hack for the moment.
-    return opEquals(cast()lhs, cast()rhs);
+    }
 }
 
 /// If aliased to the same object or both null => equal
-@system unittest
+@system unittest // this one is not @safe because it goes through the Object base method
 {
     class F { int flag; this(int flag) { this.flag = flag; } }
 
@@ -291,7 +323,8 @@
 }
 
 /// If same exact type => one call to method opEquals
-@system unittest
+/// This test passes `@safe` because it defines a new opEquals with `@safe`
+@safe unittest
 {
     class F
     {
@@ -302,9 +335,9 @@
             this.flag = flag;
         }
 
-        override bool opEquals(const Object o)
+        bool opEquals(const F o) const @safe nothrow pure
         {
-            return flag == (cast(F) o).flag;
+            return flag == o.flag;
         }
     }
 
@@ -314,7 +347,7 @@
 }
 
 /// General case => symmetric calls to method opEquals
-@system unittest
+@safe unittest
 {
     int fEquals, gEquals;
 
@@ -331,10 +364,10 @@
     {
         this(int flag) { super(flag); }
 
-        override bool opEquals(const Object o)
+        bool opEquals(const Base o) @safe
         {
             fEquals++;
-            return flag == (cast(Base) o).flag;
+            return flag == o.flag;
         }
     }
 
@@ -342,10 +375,10 @@
     {
         this(int flag) { super(flag); }
 
-        override bool opEquals(const Object o)
+        bool opEquals(const Base o) @safe
         {
             gEquals++;
-            return flag == (cast(Base) o).flag;
+            return flag == o.flag;
         }
     }
 
@@ -354,6 +387,114 @@
     assert(gEquals == 1);
 }
 
+/++
+    This test shows an example for a comprehensive inheritance equality chain too.
++/
+unittest
+{
+    static class Base
+    {
+        int member;
+
+        this(int member) pure @safe nothrow @nogc
+        {
+            this.member = member;
+        }
+
+        override bool opEquals(Object rhs) const
+        {
+            return this.opEquals(cast(Base) rhs);
+        }
+
+        bool opEquals(const Base rhs) const @nogc pure nothrow @safe
+        {
+            if (rhs is null)
+                return false;
+            return this.member == rhs.member;
+        }
+    }
+
+    // works through the direct class with attributes enabled, except for pure and nogc in the current TypeInfo implementation
+    bool testThroughBase() nothrow @safe
+    {
+        Base b1 = new Base(0);
+        Base b2 = new Base(0);
+        assert(b1 == b2);
+        Base b3 = new Base(1);
+        assert(b1 != b3);
+        return true;
+    }
+
+    static assert(testThroughBase());
+
+    // also works through the base class interface thanks to the override, but no more attributes
+    bool testThroughObject()
+    {
+        Object o1 = new Base(0);
+        Object o2 = new Base(0);
+        assert(o1 == o2);
+        Object o3 = new Base(1);
+        assert(o1 != o3);
+        return true;
+    }
+
+    static assert(testThroughObject());
+
+    // Each time you make a child, you want to override all old opEquals
+    // and add a new overload for the new child.
+    static class Child : Base
+    {
+        int member2;
+
+        this(int member, int member2) pure @safe nothrow @nogc
+        {
+            super(member);
+            this.member2 = member2;
+        }
+
+        // override the whole chain so it works consistently though any base
+        override bool opEquals(Object rhs) const
+        {
+            return this.opEquals(cast(Child) rhs);
+        }
+        override bool opEquals(const Base rhs) const
+        {
+            return this.opEquals(cast(const Child) rhs);
+        }
+        // and then add the new overload, if necessary, to handle new members
+        bool opEquals(const Child rhs) const @nogc pure nothrow @safe
+        {
+            if (rhs is null)
+                return false;
+            // can call back to the devirtualized base test with implicit conversion
+            // then compare the new member too. or we could have just compared the base
+            // member directly here as well.
+            return Base.opEquals(rhs) && this.member2 == rhs.member2;
+        }
+
+        // a mixin template, of course, could automate this.
+    }
+
+    bool testThroughChild()
+    {
+        Child a = new Child(0, 0);
+        Child b = new Child(0, 1);
+        assert(a != b);
+
+        Base ba = a;
+        Base bb = b;
+        assert(ba != bb);
+
+        Object oa = a;
+        Object ob = b;
+        assert(oa != ob);
+
+        return true;
+    }
+
+    static assert(testThroughChild());
+}
+
 // To cover const Object opEquals
 @system unittest
 {
@@ -396,7 +537,8 @@
  */
 struct Interface
 {
-    TypeInfo_Class   classinfo;  /// .classinfo for this interface (not for containing class)
+    /// Class info returned by `typeid` for this interface (not for containing class)
+    TypeInfo_Class   classinfo;
     void*[]     vtbl;
     size_t      offset;     /// offset to Interface 'this' from Object 'this'
 }
@@ -447,13 +589,17 @@
 
     override bool opEquals(Object o)
     {
+        return opEquals(cast(TypeInfo) o);
+    }
+
+    bool opEquals(const TypeInfo ti) @safe nothrow const
+    {
         /* TypeInfo instances are singletons, but duplicates can exist
          * across DLL's. Therefore, comparing for a name match is
          * sufficient.
          */
-        if (this is o)
+        if (this is ti)
             return true;
-        auto ti = cast(const TypeInfo)o;
         return ti && this.toString() == ti.toString();
     }
 
@@ -462,7 +608,7 @@
         auto anotherObj = new Object();
 
         assert(typeid(void).opEquals(typeid(void)));
-        assert(!typeid(void).opEquals(anotherObj));
+        assert(typeid(void) != anotherObj); // calling .opEquals here directly is a type mismatch
     }
 
     /**
@@ -1397,13 +1543,13 @@
 /**
  * Runtime type information about a class.
  * Can be retrieved from an object instance by using the
- * $(DDSUBLINK spec/property,classinfo, .classinfo) property.
+ * $(DDSUBLINK spec/expression,typeid_expressions,typeid expression).
  */
 class TypeInfo_Class : TypeInfo
 {
     override string toString() const pure { return name; }
 
-    override bool opEquals(Object o)
+    override bool opEquals(const TypeInfo o) const
     {
         if (this is o)
             return true;
@@ -1739,12 +1885,8 @@
             return false;
         else if (xopEquals)
         {
-            version (GNU)
-            {   // BUG: GDC and DMD use different calling conventions
-                return (*xopEquals)(p2, p1);
-            }
-            else
-                return (*xopEquals)(p1, p2);
+            const dg = _memberFunc(p2, xopEquals);
+            return dg.xopEquals(p1);
         }
         else if (p1 == p2)
             return true;
@@ -1766,12 +1908,8 @@
                     return true;
                 else if (xopCmp)
                 {
-                    version (GNU)
-                    {   // BUG: GDC and DMD use different calling conventions
-                        return (*xopCmp)(p1, p2);
-                    }
-                    else
-                        return (*xopCmp)(p2, p1);
+                    const dg = _memberFunc(p1, xopCmp);
+                    return dg.xopCmp(p2);
                 }
                 else
                     // BUG: relies on the GC not moving objects
@@ -1876,6 +2014,28 @@
         TypeInfo m_arg2;
     }
     immutable(void)* m_RTInfo;                // data for precise GC
+
+    // The xopEquals and xopCmp members are function pointers to member
+    // functions, which is not guaranteed to share the same ABI, as it is not
+    // known whether the `this` parameter is the first or second argument.
+    // This wrapper is to convert it to a delegate which will always pass the
+    // `this` parameter in the correct way.
+    private struct _memberFunc
+    {
+        union
+        {
+            struct // delegate
+            {
+                const void* ptr;
+                const void* funcptr;
+            }
+            @safe pure nothrow
+            {
+                bool delegate(in void*) xopEquals;
+                int delegate(in void*) xopCmp;
+            }
+        }
+    }
 }
 
 @system unittest
@@ -2715,7 +2875,7 @@
     _aaClear(*cast(AA *) &aa);
 }
 
-/* ditto */
+/** ditto */
 void clear(Value, Key)(Value[Key]* aa)
 {
     _aaClear(*cast(AA *) aa);
@@ -2762,21 +2922,21 @@
     return aa;
 }
 
-/* ditto */
+/** ditto */
 T rehash(T : Value[Key], Value, Key)(T* aa)
 {
     _aaRehash(cast(AA*)aa, typeid(Value[Key]));
     return *aa;
 }
 
-/* ditto */
+/** ditto */
 T rehash(T : shared Value[Key], Value, Key)(T aa)
 {
     _aaRehash(cast(AA*)&aa, typeid(Value[Key]));
     return aa;
 }
 
-/* ditto */
+/** ditto */
 T rehash(T : shared Value[Key], Value, Key)(T* aa)
 {
     _aaRehash(cast(AA*)aa, typeid(Value[Key]));
@@ -2784,8 +2944,8 @@
 }
 
 /***********************************
- * Create a new associative array of the same size and copy the contents of the
- * associative array into it.
+ * Creates a new associative array of the same size and copies the contents of
+ * the associative array into it.
  * Params:
  *      aa =     The associative array.
  */
@@ -2826,7 +2986,7 @@
     return result;
 }
 
-/* ditto */
+/** ditto */
 V[K] dup(T : V[K], K, V)(T* aa)
 {
     return (*aa).dup;
@@ -2853,11 +3013,27 @@
 }
 
 /***********************************
- * Returns a forward range over the keys of the associative array.
+ * Returns a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
+ * which will iterate over the keys of the associative array. The keys are
+ * returned by reference.
+ *
+ * If structural changes are made to the array (removing or adding keys), all
+ * ranges previously obtained through this function are invalidated. The
+ * following example program will dereference a null pointer:
+ *
+ *---
+ * import std.stdio : writeln;
+ *
+ * auto dict = ["k1": 1, "k2": 2];
+ * auto keyRange = dict.byKey;
+ * dict.clear;
+ * writeln(keyRange.front);    // Segmentation fault
+ *---
+ *
  * Params:
  *      aa =     The associative array.
  * Returns:
- *      A forward range.
+ *      A forward range referencing the keys of the associative array.
  */
 auto byKey(T : V[K], K, V)(T aa) pure nothrow @nogc @safe
 {
@@ -2880,7 +3056,7 @@
     return Result(_aaToRange(aa));
 }
 
-/* ditto */
+/** ditto */
 auto byKey(T : V[K], K, V)(T* aa) pure nothrow @nogc
 {
     return (*aa).byKey();
@@ -2889,7 +3065,7 @@
 ///
 @safe unittest
 {
-    auto dict = [1: 0, 2: 0];
+    auto dict = [1: "v1", 2: "v2"];
     int sum;
     foreach (v; dict.byKey)
         sum += v;
@@ -2898,11 +3074,27 @@
 }
 
 /***********************************
- * Returns a forward range over the values of the associative array.
+ * Returns a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
+ * which will iterate over the values of the associative array. The values are
+ * returned by reference.
+ *
+ * If structural changes are made to the array (removing or adding keys), all
+ * ranges previously obtained through this function are invalidated. The
+ * following example program will dereference a null pointer:
+ *
+ *---
+ * import std.stdio : writeln;
+ *
+ * auto dict = ["k1": 1, "k2": 2];
+ * auto valueRange = dict.byValue;
+ * dict.clear;
+ * writeln(valueRange.front);    // Segmentation fault
+ *---
+ *
  * Params:
  *      aa =     The associative array.
  * Returns:
- *      A forward range.
+ *      A forward range referencing the values of the associative array.
  */
 auto byValue(T : V[K], K, V)(T aa) pure nothrow @nogc @safe
 {
@@ -2925,7 +3117,7 @@
     return Result(_aaToRange(aa));
 }
 
-/* ditto */
+/** ditto */
 auto byValue(T : V[K], K, V)(T* aa) pure nothrow @nogc
 {
     return (*aa).byValue();
@@ -2943,11 +3135,35 @@
 }
 
 /***********************************
- * Returns a forward range over the key value pairs of the associative array.
+ * Returns a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
+ * which will iterate over the key-value pairs of the associative array. The
+ * returned pairs are represented by an opaque type with `.key` and `.value`
+ * properties for accessing references to the key and value of the pair,
+ * respectively.
+ *
+ * If structural changes are made to the array (removing or adding keys), all
+ * ranges previously obtained through this function are invalidated. The
+ * following example program will dereference a null pointer:
+ *
+ *---
+ * import std.stdio : writeln;
+ *
+ * auto dict = ["k1": 1, "k2": 2];
+ * auto kvRange = dict.byKeyValue;
+ * dict.clear;
+ * writeln(kvRange.front.key, ": ", kvRange.front.value);    // Segmentation fault
+ *---
+ *
+ * Note that this is a low-level interface to iterating over the associative
+ * array and is not compatible withth the
+ * $(LINK2 $(ROOT_DIR)phobos/std_typecons.html#.Tuple,`Tuple`) type in Phobos.
+ * For compatibility with `Tuple`, use
+ * $(LINK2 $(ROOT_DIR)phobos/std_array.html#.byPair,std.array.byPair) instead.
+ *
  * Params:
  *      aa =     The associative array.
  * Returns:
- *      A forward range.
+ *      A forward range referencing the pairs of the associative array.
  */
 auto byKeyValue(T : V[K], K, V)(T aa) pure nothrow @nogc @safe
 {
@@ -2987,7 +3203,7 @@
     return Result(_aaToRange(aa));
 }
 
-/* ditto */
+/** ditto */
 auto byKeyValue(T : V[K], K, V)(T* aa) pure nothrow @nogc
 {
     return (*aa).byKeyValue();
@@ -2999,18 +3215,21 @@
     auto dict = ["k1": 1, "k2": 2];
     int sum;
     foreach (e; dict.byKeyValue)
+    {
+        assert(e.key[1] == e.value + '0');
         sum += e.value;
+    }
 
     assert(sum == 3);
 }
 
 /***********************************
- * Returns a dynamic array, the elements of which are the keys in the
- * associative array.
+ * Returns a newly allocated dynamic array containing a copy of the keys from
+ * the associative array.
  * Params:
  *      aa =     The associative array.
  * Returns:
- *      A dynamic array.
+ *      A dynamic array containing a copy of the keys.
  */
 Key[] keys(T : Value[Key], Value, Key)(T aa) @property
 {
@@ -3028,7 +3247,7 @@
     return res;
 }
 
-/* ditto */
+/** ditto */
 Key[] keys(T : Value[Key], Value, Key)(T *aa) @property
 {
     return (*aa).keys;
@@ -3089,12 +3308,12 @@
 }
 
 /***********************************
- * Returns a dynamic array, the elements of which are the values in the
- * associative array.
+ * Returns a newly allocated dynamic array containing a copy of the values from
+ * the associative array.
  * Params:
  *      aa =     The associative array.
  * Returns:
- *      A dynamic array.
+ *      A dynamic array containing a copy of the values.
  */
 Value[] values(T : Value[Key], Value, Key)(T aa) @property
 {
@@ -3112,7 +3331,7 @@
     return res;
 }
 
-/* ditto */
+/** ditto */
 Value[] values(T : Value[Key], Value, Key)(T *aa) @property
 {
     return (*aa).values;
@@ -3188,12 +3407,13 @@
     return p ? *p : defaultValue;
 }
 
-/* ditto */
+/** ditto */
 inout(V) get(K, V)(inout(V[K])* aa, K key, lazy inout(V) defaultValue)
 {
     return (*aa).get(key, defaultValue);
 }
 
+///
 @safe unittest
 {
     auto aa = ["k1": 1];
@@ -4651,8 +4871,6 @@
 public import core.internal.array.construction : _d_arraysetctor;
 public import core.internal.array.capacity: _d_arraysetlengthTImpl;
 
-public import core.lifetime : _d_delstructImpl;
-
 public import core.internal.dassert: _d_assert_fail;
 
 public import core.internal.destruction: __ArrayDtor;
@@ -4664,6 +4882,9 @@
 public import core.internal.switch_: __switch;
 public import core.internal.switch_: __switch_error;
 
+public import core.lifetime : _d_delstructImpl;
+public import core.lifetime : _d_newThrowable;
+
 public @trusted @nogc nothrow pure extern (C) void _d_delThrowable(scope Throwable);
 
 // Compare class and interface objects for ordering.
diff --git a/libphobos/libdruntime/rt/dmain2.d b/libphobos/libdruntime/rt/dmain2.d
index b363e3f..47b67f1 100644
--- a/libphobos/libdruntime/rt/dmain2.d
+++ b/libphobos/libdruntime/rt/dmain2.d
@@ -624,7 +624,7 @@
             {
                 WSink caption;
                 if (t)
-                    caption.sink(t.classinfo.name);
+                    caption.sink(typeid(t).name);
 
                 // Avoid static user32.dll dependency for console applications
                 // by loading it dynamically as needed
diff --git a/libphobos/libdruntime/rt/util/typeinfo.d b/libphobos/libdruntime/rt/util/typeinfo.d
index d06254c..26c24c4 100644
--- a/libphobos/libdruntime/rt/util/typeinfo.d
+++ b/libphobos/libdruntime/rt/util/typeinfo.d
@@ -367,7 +367,10 @@
 private class TypeInfoArrayGeneric(T, Base = T) : Select!(is(T == Base), TypeInfo_Array, TypeInfoArrayGeneric!Base)
 {
     static if (is(T == Base))
-        override bool opEquals(Object o) { return TypeInfo.opEquals(o); }
+        override bool opEquals(const Object o) const @safe nothrow { return TypeInfo.opEquals(cast(const TypeInfo) o); }
+
+    alias opEquals = typeof(super).opEquals;
+    alias opEquals = TypeInfo.opEquals;
 
     override string toString() const { return (T[]).stringof; }
 
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE
index b60fa17..2babfbe 100644
--- a/libphobos/src/MERGE
+++ b/libphobos/src/MERGE
@@ -1,4 +1,4 @@
-4687883231eba3bda7691321f2af107fdb3d0a44
+896b1d0e1e8b69bccac0e180ecd1b42a70f95d5b
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/phobos repository.
diff --git a/libphobos/src/Makefile.am b/libphobos/src/Makefile.am
index 94c6f4d..75f8397 100644
--- a/libphobos/src/Makefile.am
+++ b/libphobos/src/Makefile.am
@@ -89,11 +89,12 @@
 	std/algorithm/mutation.d std/algorithm/package.d \
 	std/algorithm/searching.d std/algorithm/setops.d \
 	std/algorithm/sorting.d std/array.d std/ascii.d std/base64.d \
-	std/bigint.d std/bitmanip.d std/compiler.d std/complex.d \
-	std/concurrency.d std/container/array.d std/container/binaryheap.d \
-	std/container/dlist.d std/container/package.d std/container/rbtree.d \
-	std/container/slist.d std/container/util.d std/conv.d std/csv.d \
-	std/datetime/date.d std/datetime/interval.d std/datetime/package.d \
+	std/bigint.d std/bitmanip.d std/checkedint.d std/compiler.d \
+	std/complex.d std/concurrency.d std/container/array.d \
+	std/container/binaryheap.d std/container/dlist.d \
+	std/container/package.d std/container/rbtree.d std/container/slist.d \
+	std/container/util.d std/conv.d std/csv.d std/datetime/date.d \
+	std/datetime/interval.d std/datetime/package.d \
 	std/datetime/stopwatch.d std/datetime/systime.d \
 	std/datetime/timezone.d std/demangle.d std/digest/crc.d \
 	std/digest/digest.d std/digest/hmac.d std/digest/md.d \
diff --git a/libphobos/src/Makefile.in b/libphobos/src/Makefile.in
index a4101eb..f2395e2 100644
--- a/libphobos/src/Makefile.in
+++ b/libphobos/src/Makefile.in
@@ -159,8 +159,9 @@
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/algorithm/sorting.lo \
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/array.lo std/ascii.lo \
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/base64.lo std/bigint.lo \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/bitmanip.lo std/compiler.lo \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/complex.lo \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/bitmanip.lo \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/checkedint.lo \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/compiler.lo std/complex.lo \
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/concurrency.lo \
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/container/array.lo \
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/container/binaryheap.lo \
@@ -549,11 +550,12 @@
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/algorithm/mutation.d std/algorithm/package.d \
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/algorithm/searching.d std/algorithm/setops.d \
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/algorithm/sorting.d std/array.d std/ascii.d std/base64.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/bigint.d std/bitmanip.d std/compiler.d std/complex.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/concurrency.d std/container/array.d std/container/binaryheap.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/container/dlist.d std/container/package.d std/container/rbtree.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/container/slist.d std/container/util.d std/conv.d std/csv.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/datetime/date.d std/datetime/interval.d std/datetime/package.d \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/bigint.d std/bitmanip.d std/checkedint.d std/compiler.d \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/complex.d std/concurrency.d std/container/array.d \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/container/binaryheap.d std/container/dlist.d \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/container/package.d std/container/rbtree.d std/container/slist.d \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/container/util.d std/conv.d std/csv.d std/datetime/date.d \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/datetime/interval.d std/datetime/package.d \
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/datetime/stopwatch.d std/datetime/systime.d \
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/datetime/timezone.d std/demangle.d std/digest/crc.d \
 @ENABLE_LIBDRUNTIME_ONLY_FALSE@	std/digest/digest.d std/digest/hmac.d std/digest/md.d \
@@ -717,6 +719,7 @@
 std/base64.lo: std/$(am__dirstamp)
 std/bigint.lo: std/$(am__dirstamp)
 std/bitmanip.lo: std/$(am__dirstamp)
+std/checkedint.lo: std/$(am__dirstamp)
 std/compiler.lo: std/$(am__dirstamp)
 std/complex.lo: std/$(am__dirstamp)
 std/concurrency.lo: std/$(am__dirstamp)
diff --git a/libphobos/src/index.dd b/libphobos/src/index.dd
index 8613a3c..cbc173d 100644
--- a/libphobos/src/index.dd
+++ b/libphobos/src/index.dd
@@ -84,7 +84,7 @@
     )
     $(LEADINGROW Data integrity)
     $(TR
-        $(TDNW $(MREF std,experimental,checkedint))
+        $(TDNW $(MREF std,checkedint))
         $(TD Checked integral types.)
     )
     $(TR
diff --git a/libphobos/src/std/array.d b/libphobos/src/std/array.d
index ffdda8e..b86e0f9 100644
--- a/libphobos/src/std/array.d
+++ b/libphobos/src/std/array.d
@@ -117,7 +117,7 @@
     alias E = ForeachType!Range;
     static if (hasLength!Range)
     {
-        auto length = r.length;
+        const length = r.length;
         if (length == 0)
             return null;
 
@@ -126,12 +126,35 @@
         auto result = (() @trusted => uninitializedArray!(Unqual!E[])(length))();
 
         // Every element of the uninitialized array must be initialized
-        size_t i;
-        foreach (e; r)
+        size_t cnt; //Number of elements that have been initialized
+        try
         {
-            emplaceRef!E(result[i], e);
-            ++i;
+            foreach (e; r)
+            {
+                emplaceRef!E(result[cnt], e);
+                ++cnt;
+            }
+        } catch (Exception e)
+        {
+            //https://issues.dlang.org/show_bug.cgi?id=22185
+            //Make any uninitialized elements safely destructible.
+            foreach (ref elem; result[cnt..$])
+            {
+                import core.internal.lifetime : emplaceInitializer;
+                emplaceInitializer(elem);
+            }
+            throw e;
         }
+        /*
+            https://issues.dlang.org/show_bug.cgi?id=22673
+
+            We preallocated an array, we should ensure that enough range elements
+            were gathered such that every slot in the array is filled. If not, the GC
+            will collect the allocated array, leading to the `length - cnt` left over elements
+            being collected too - despite their contents having no guarantee of destructibility.
+         */
+        assert(length == cnt,
+               "Range .length property was not equal to the length yielded by the range before becoming empty");
         return (() @trusted => cast(E[]) result)();
     }
     else
@@ -439,6 +462,91 @@
         assert(equal(r, [S(1), S(1)]));
     });
 }
+//https://issues.dlang.org/show_bug.cgi?id=22673
+@system unittest
+{
+    struct LyingRange
+    {
+        enum size_t length = 100;
+        enum theRealLength = 50;
+        size_t idx = 0;
+        bool empty()
+        {
+            return idx <= theRealLength;
+        }
+        void popFront()
+        {
+            ++idx;
+        }
+        size_t front()
+        {
+            return idx;
+        }
+    }
+    static assert(hasLength!LyingRange);
+    LyingRange rng;
+    import std.exception : assertThrown;
+    assertThrown!Error(array(rng));
+}
+//https://issues.dlang.org/show_bug.cgi?id=22185
+@system unittest
+{
+    import std.stdio;
+    static struct ThrowingCopy
+    {
+        int x = 420;
+        this(ref return scope ThrowingCopy rhs)
+        {
+            rhs.x = 420;
+            //
+            throw new Exception("This throws");
+        }
+        ~this()
+        {
+            /*
+                Any time this destructor runs, it should be running on "valid"
+                data. This is is mimicked by having a .init other than 0 (the value the memory
+                practically will be from the GC).
+            */
+            if (x != 420)
+            {
+                //This will only trigger during GC finalization so avoid writefln for now.
+                printf("Destructor failure in ThrowingCopy(%d) @ %p", x, &this);
+                assert(x == 420, "unittest destructor failed");
+            }
+        }
+    }
+    static struct LyingThrowingRange
+    {
+        enum size_t length = 100;
+        enum size_t evilRealLength = 50;
+        size_t idx;
+        ThrowingCopy front()
+        {
+            return ThrowingCopy(12);
+        }
+        bool empty()
+        {
+            return idx == evilRealLength;
+        }
+        void popFront()
+        {
+            ++idx;
+        }
+    }
+    static assert(hasLength!LyingThrowingRange);
+    import std.exception : assertThrown;
+    {
+        assertThrown(array(LyingThrowingRange()));
+    }
+    import core.memory : GC;
+    /*
+        Force a collection early. Doesn't always actually finalize the bad objects
+        but trying to collect soon after the allocation is thrown away means any potential failures
+        will happen earlier.
+    */
+    GC.collect();
+}
 
 /**
 Returns a newly allocated associative array from a range of key/value tuples
@@ -939,6 +1047,11 @@
 // from rt/lifetime.d
 private extern(C) void[] _d_newarrayU(const TypeInfo ti, size_t length) pure nothrow;
 
+// from rt/tracegc.d
+version (D_ProfileGC)
+private extern (C) void[] _d_newarrayUTrace(string file, size_t line,
+    string funcname, const scope TypeInfo ti, size_t length) pure nothrow;
+
 private auto arrayAllocImpl(bool minimallyInitialized, T, I...)(I sizes) nothrow
 {
     static assert(I.length <= nDimensions!T,
@@ -992,7 +1105,15 @@
               _d_newarrayU returns a void[], but with the length set according
               to E.sizeof.
             +/
-            *(cast(void[]*)&ret) = _d_newarrayU(typeid(E[]), size);
+            version (D_ProfileGC)
+            {
+                // FIXME: file, line, function should be propagated from the
+                // caller, not here.
+                *(cast(void[]*)&ret) = _d_newarrayUTrace(__FILE__, __LINE__,
+                    __FUNCTION__, typeid(E[]), size);
+            }
+            else
+                *(cast(void[]*)&ret) = _d_newarrayU(typeid(E[]), size);
             static if (minimallyInitialized && hasIndirections!E)
                 // _d_newarrayU would have asserted if the multiplication below
                 // had overflowed, so we don't have to check it again.
diff --git a/libphobos/src/std/checkedint.d b/libphobos/src/std/checkedint.d
new file mode 100644
index 0000000..635c420
--- /dev/null
+++ b/libphobos/src/std/checkedint.d
@@ -0,0 +1,3591 @@
+// Written in the D programming language.
+/**
+$(SCRIPT inhibitQuickIndex = 1;)
+
+This module defines facilities for efficient checking of integral operations
+against overflow, casting with loss of precision, unexpected change of sign,
+etc. The checking (and possibly correction) can be done at operation level, for
+example $(LREF opChecked)$(D !"+"(x, y, overflow)) adds two integrals `x` and
+`y` and sets `overflow` to `true` if an overflow occurred. The flag `overflow`
+(a `bool` passed by reference) is not touched if the operation succeeded, so the
+same flag can be reused for a sequence of operations and tested at the end.
+
+Issuing individual checked operations is flexible and efficient but often
+tedious. The $(LREF Checked) facility offers encapsulated integral wrappers that
+do all checking internally and have configurable behavior upon erroneous
+results. For example, `Checked!int` is a type that behaves like `int` but aborts
+execution immediately whenever involved in an operation that produces the
+arithmetically wrong result. The accompanying convenience function $(LREF
+checked) uses type deduction to convert a value `x` of integral type `T` to
+`Checked!T` by means of `checked(x)`. For example:
+
+---
+void main()
+{
+    import std.checkedint, std.stdio;
+    writeln((checked(5) + 7).get); // 12
+    writeln((checked(10) * 1000 * 1000 * 1000).get); // Overflow
+}
+---
+
+Similarly, $(D checked(-1) > uint(0)) aborts execution (even though the built-in
+comparison $(D int(-1) > uint(0)) is surprisingly true due to language's
+conversion rules modeled after C). Thus, `Checked!int` is a virtually drop-in
+replacement for `int` useable in debug builds, to be replaced by `int` in
+release mode if efficiency demands it.
+
+`Checked`  has customizable behavior with the help of a second type parameter,
+`Hook`. Depending on what methods `Hook` defines, core operations on the
+underlying integral may be verified for overflow or completely redefined. If
+`Hook` defines no method at all and carries no state, there is no change in
+behavior, i.e. $(D Checked!(int, void)) is a wrapper around `int` that adds no
+customization at all.
+
+This module provides a few predefined hooks (below) that add useful behavior to
+`Checked`:
+
+$(BOOKTABLE ,
+    $(TR $(TD $(LREF Abort)) $(TD
+        fails every incorrect operation with a message to $(REF
+        stderr, std, stdio) followed by a call to `assert(0)`. It is the default
+        second parameter, i.e. `Checked!short` is the same as
+        $(D Checked!(short, Abort)).
+    ))
+    $(TR $(TD $(LREF Throw)) $(TD
+        fails every incorrect operation by throwing an exception.
+    ))
+    $(TR $(TD $(LREF Warn)) $(TD
+        prints incorrect operations to $(REF stderr, std, stdio)
+        but otherwise preserves the built-in behavior.
+    ))
+    $(TR $(TD $(LREF ProperCompare)) $(TD
+        fixes the comparison operators `==`, `!=`, `<`, `<=`, `>`, and `>=`
+        to return correct results in all circumstances,
+        at a slight cost in efficiency. For example,
+        $(D Checked!(uint, ProperCompare)(1) > -1) is `true`,
+        which is not the case for the built-in comparison. Also, comparing
+        numbers for equality with floating-point numbers only passes if the
+        integral can be converted to the floating-point number precisely,
+        so as to preserve transitivity of equality.
+    ))
+    $(TR $(TD $(LREF WithNaN)) $(TD
+        reserves a special "Not a Number" (NaN) value akin to the homonym value
+        reserved for floating-point values. Once a $(D Checked!(X, WithNaN))
+        gets this special value, it preserves and propagates it until
+        reassigned. $(LREF isNaN) can be used to query whether the object
+        is not a number.
+    ))
+    $(TR $(TD $(LREF Saturate)) $(TD
+        implements saturating arithmetic, i.e. $(D Checked!(int, Saturate))
+        "stops" at `int.max` for all operations that would cause an `int` to
+        overflow toward infinity, and at `int.min` for all operations that would
+        correspondingly overflow toward negative infinity.
+    ))
+)
+
+
+These policies may be used alone, e.g. $(D Checked!(uint, WithNaN)) defines a
+`uint`-like type that reaches a stable NaN state for all erroneous operations.
+They may also be "stacked" on top of each other, owing to the property that a
+checked integral emulates an actual integral, which means another checked
+integral can be built on top of it. Some combinations of interest include:
+
+$(BOOKTABLE ,
+    $(TR $(TD $(D Checked!(Checked!int, ProperCompare))))
+    $(TR $(TD
+defines an `int` with fixed
+comparison operators that will fail with `assert(0)` upon overflow. (Recall that
+`Abort` is the default policy.) The order in which policies are combined is
+important because the outermost policy (`ProperCompare` in this case) has the
+first crack at intercepting an operator. The converse combination $(D
+Checked!(Checked!(int, ProperCompare))) is meaningless because `Abort` will
+intercept comparison and will fail without giving `ProperCompare` a chance to
+intervene.
+    ))
+    $(TR $(TD))
+    $(TR $(TDNW $(D Checked!(Checked!(int, ProperCompare), WithNaN))))
+    $(TR $(TD
+defines an `int`-like
+type that supports a NaN value. For values that are not NaN, comparison works
+properly. Again the composition order is important; $(D Checked!(Checked!(int,
+WithNaN), ProperCompare)) does not have good semantics because `ProperCompare`
+intercepts comparisons before the numbers involved are tested for NaN.
+    ))
+)
+
+The hook's members are looked up statically in a Design by Introspection manner
+and are all optional. The table below illustrates the members that a hook type
+may define and their influence over the behavior of the `Checked` type using it.
+In the table, `hook` is an alias for `Hook` if the type `Hook` does not
+introduce any state, or an object of type `Hook` otherwise.
+
+$(TABLE ,
+$(TR $(TH `Hook` member) $(TH Semantics in $(D Checked!(T, Hook)))
+)
+$(TR $(TD `defaultValue`) $(TD If defined, `Hook.defaultValue!T` is used as the
+default initializer of the payload.)
+)
+$(TR $(TD `min`) $(TD If defined, `Hook.min!T` is used as the minimum value of
+the payload.)
+)
+$(TR $(TD `max`) $(TD If defined, `Hook.max!T` is used as the maximum value of
+the payload.)
+)
+$(TR $(TD `hookOpCast`) $(TD If defined, `hook.hookOpCast!U(get)` is forwarded
+to unconditionally when the payload is to be cast to type `U`.)
+)
+$(TR $(TD `onBadCast`) $(TD If defined and `hookOpCast` is $(I not) defined,
+`onBadCast!U(get)` is forwarded to when the payload is to be cast to type `U`
+and the cast would lose information or force a change of sign.)
+)
+$(TR $(TD `hookOpEquals`) $(TD If defined, $(D hook.hookOpEquals(get, rhs)) is
+forwarded to unconditionally when the payload is compared for equality against
+value `rhs` of integral, floating point, or Boolean type.)
+)
+$(TR $(TD `hookOpCmp`) $(TD If defined, $(D hook.hookOpCmp(get, rhs)) is
+forwarded to unconditionally when the payload is compared for ordering against
+value `rhs` of integral, floating point, or Boolean type.)
+)
+$(TR $(TD `hookOpUnary`) $(TD If defined, `hook.hookOpUnary!op(get)` (where `op`
+is the operator symbol) is forwarded to for unary operators `-` and `~`. In
+addition, for unary operators `++` and `--`, `hook.hookOpUnary!op(payload)` is
+called, where `payload` is a reference to the value wrapped by `Checked` so the
+hook can change it.)
+)
+$(TR $(TD `hookOpBinary`) $(TD If defined, $(D hook.hookOpBinary!op(get, rhs))
+(where `op` is the operator symbol and `rhs` is the right-hand side operand) is
+forwarded to unconditionally for binary operators `+`,  `-`, `*`, `/`, `%`,
+`^^`, `&`, `|`, `^`, `<<`, `>>`, and `>>>`.)
+)
+$(TR $(TD `hookOpBinaryRight`) $(TD If defined, $(D
+hook.hookOpBinaryRight!op(lhs, get)) (where `op` is the operator symbol and
+`lhs` is the left-hand side operand) is forwarded to unconditionally for binary
+operators `+`,  `-`, `*`, `/`, `%`, `^^`, `&`, `|`, `^`, `<<`, `>>`, and `>>>`.)
+)
+$(TR $(TD `onOverflow`) $(TD If defined, `hook.onOverflow!op(get)` is forwarded
+to for unary operators that overflow but only if `hookOpUnary` is not defined.
+Unary `~` does not overflow; unary `-` overflows only when the most negative
+value of a signed type is negated, and the result of the hook call is returned.
+When the increment or decrement operators overflow, the payload is assigned the
+result of `hook.onOverflow!op(get)`. When a binary operator overflows, the
+result of $(D hook.onOverflow!op(get, rhs)) is returned, but only if `Hook` does
+not define `hookOpBinary`.)
+)
+$(TR $(TD `hookOpOpAssign`) $(TD If defined, $(D hook.hookOpOpAssign!op(payload,
+rhs)) (where `op` is the operator symbol and `rhs` is the right-hand side
+operand) is forwarded to unconditionally for binary operators `+=`,  `-=`, `*=`, `/=`, `%=`,
+`^^=`, `&=`, `|=`, `^=`, `<<=`, `>>=`, and `>>>=`.)
+)
+$(TR $(TD `onLowerBound`) $(TD If defined, $(D hook.onLowerBound(value, bound))
+(where `value` is the value being assigned) is forwarded to when the result of
+binary operators `+=`,  `-=`, `*=`, `/=`, `%=`, `^^=`, `&=`, `|=`, `^=`, `<<=`, `>>=`,
+and `>>>=` is smaller than the smallest value representable by `T`.)
+)
+$(TR $(TD `onUpperBound`) $(TD If defined, $(D hook.onUpperBound(value, bound))
+(where `value` is the value being assigned) is forwarded to when the result of
+binary operators `+=`,  `-=`, `*=`, `/=`, `%=`, `^^=`, `&=`, `|=`, `^=`, `<<=`, `>>=`,
+and `>>>=` is larger than the largest value representable by `T`.)
+)
+$(TR $(TD `hookToHash`) $(TD If defined, $(D hook.hookToHash(payload))
+(where `payload` is a reference to the value wrapped by Checked) is forwarded
+to when `toHash` is called on a Checked type. Custom hashing can be implemented
+in a `Hook`, otherwise the built-in hashing is used.)
+)
+)
+
+Source: $(PHOBOSSRC std/checkedint.d)
+*/
+module std.checkedint;
+import std.traits : isFloatingPoint, isIntegral, isNumeric, isUnsigned, Unqual;
+
+///
+@safe unittest
+{
+    int[] concatAndAdd(int[] a, int[] b, int offset)
+    {
+        // Aborts on overflow on size computation
+        auto r = new int[(checked(a.length) + b.length).get];
+        // Aborts on overflow on element computation
+        foreach (i; 0 .. a.length)
+            r[i] = (a[i] + checked(offset)).get;
+        foreach (i; 0 .. b.length)
+            r[i + a.length] = (b[i] + checked(offset)).get;
+        return r;
+    }
+    assert(concatAndAdd([1, 2, 3], [4, 5], -1) == [0, 1, 2, 3, 4]);
+}
+
+
+/// `Saturate` stops at an overflow
+@safe unittest
+{
+    auto x = (cast(byte) 127).checked!Saturate;
+    assert(x == 127);
+    x++;
+    assert(x == 127);
+}
+
+/// `WithNaN` has a special "Not a Number" (NaN) value akin to the homonym value reserved for floating-point values
+@safe unittest
+{
+    auto x = 100.checked!WithNaN;
+    assert(x == 100);
+    x /= 0;
+    assert(x.isNaN);
+}
+
+/// `ProperCompare` fixes the comparison operators ==, !=, <, <=, >, and >= to return correct results
+@safe unittest
+{
+    uint x = 1;
+    auto y = x.checked!ProperCompare;
+    assert(x < -1); // built-in comparison
+    assert(y > -1); // ProperCompare
+}
+
+/// `Throw` fails every incorrect operation by throwing an exception
+@safe unittest
+{
+    import std.exception : assertThrown;
+    auto x = -1.checked!Throw;
+    assertThrown(x / 0);
+    assertThrown(x + int.min);
+    assertThrown(x == uint.max);
+}
+
+/**
+Checked integral type wraps an integral `T` and customizes its behavior with the
+help of a `Hook` type. The type wrapped must be one of the predefined integrals
+(unqualified), or another instance of `Checked`.
+
+Params:
+    T    = type that is wrapped in the `Checked` type
+    Hook = hook type that customizes the behavior of the `Checked` type
+*/
+struct Checked(T, Hook = Abort)
+if (isIntegral!T || is(T == Checked!(U, H), U, H))
+{
+    import std.algorithm.comparison : among;
+    import std.experimental.allocator.common : stateSize;
+    import std.format.spec : FormatSpec;
+    import std.range.primitives : isInputRange, ElementType;
+    import std.traits : hasMember, isSomeChar;
+
+    /**
+    The type of the integral subject to checking.
+    */
+    alias Representation = T;
+
+    // state {
+    static if (hasMember!(Hook, "defaultValue"))
+        private T payload = Hook.defaultValue!T;
+    else
+        private T payload;
+    /**
+    `hook` is a member variable if it has state, or an alias for `Hook`
+    otherwise.
+    */
+    static if (stateSize!Hook > 0) Hook hook;
+    else alias hook = Hook;
+    // } state
+
+    // get
+    /**
+    Returns:
+        A copy of the underlying value.
+    */
+    auto get() inout { return payload; }
+    ///
+    @safe unittest
+    {
+        auto x = checked(ubyte(42));
+        static assert(is(typeof(x.get()) == ubyte));
+        assert(x.get == 42);
+        const y = checked(ubyte(42));
+        static assert(is(typeof(y.get()) == const ubyte));
+        assert(y.get == 42);
+    }
+
+    /**
+    Defines the minimum and maximum. These values are hookable by defining
+    `Hook.min` and/or `Hook.max`.
+    */
+    static if (hasMember!(Hook, "min"))
+    {
+        enum Checked!(T, Hook) min = Checked!(T, Hook)(Hook.min!T);
+        ///
+        @safe unittest
+        {
+            assert(Checked!short.min == -32768);
+            assert(Checked!(short, WithNaN).min == -32767);
+            assert(Checked!(uint, WithNaN).max == uint.max - 1);
+        }
+    }
+    else
+    {
+        /// ditto
+        enum Checked!(T, Hook) min = Checked(T.min);
+    }
+    static if (hasMember!(Hook, "max"))
+    {
+        /// ditto
+        enum Checked!(T, Hook) max = Checked(Hook.max!T);
+    }
+    else
+    {
+        /// ditto
+        enum Checked!(T, Hook) max = Checked(T.max);
+    }
+
+    /**
+    Constructor taking a value properly convertible to the underlying type. `U`
+    may be either an integral that can be converted to `T` without a loss, or
+    another `Checked` instance whose representation may be in turn converted to
+    `T` without a loss.
+    */
+    this(U)(U rhs)
+    if (valueConvertible!(U, T) ||
+        !isIntegral!T && is(typeof(T(rhs))) ||
+        is(U == Checked!(V, W), V, W) &&
+            is(typeof(Checked!(T, Hook)(rhs.get))))
+    {
+        static if (isIntegral!U)
+            payload = rhs;
+        else
+            payload = rhs.payload;
+    }
+    ///
+    @safe unittest
+    {
+        auto a = checked(42L);
+        assert(a == 42);
+        auto b = Checked!long(4242); // convert 4242 to long
+        assert(b == 4242);
+    }
+
+    /**
+    Assignment operator. Has the same constraints as the constructor.
+
+    Params:
+        rhs = The value to assign
+
+    Returns:
+        A reference to `this`
+    */
+    ref Checked opAssign(U)(U rhs) return
+    if (is(typeof(Checked!(T, Hook)(rhs))))
+    {
+        static if (isIntegral!U)
+            payload = rhs;
+        else
+            payload = rhs.payload;
+        return this;
+    }
+    ///
+    @safe unittest
+    {
+        Checked!long a;
+        a = 42L;
+        assert(a == 42);
+        a = 4242;
+        assert(a == 4242);
+    }
+
+    ///
+    @safe unittest
+    {
+        Checked!long a, b;
+        a = b = 3;
+        assert(a == 3 && b == 3);
+    }
+
+    /**
+    Construct from a decimal string. The conversion follows the same rules as
+    $(REF to, std, conv) converting a string to the wrapped `T` type.
+
+    Params:
+        str = an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
+              of characters
+    */
+    this(Range)(Range str)
+    if (isInputRange!Range && isSomeChar!(ElementType!Range))
+    {
+        import std.conv : to;
+
+        this(to!T(str));
+    }
+
+    /**
+    $(REF to, std, conv) can convert a string to a `Checked!T`:
+    */
+    @system unittest
+    {
+        import std.conv : to;
+
+        const a = to!long("1234");
+        const b = to!(Checked!long)("1234");
+        assert(a == b);
+    }
+
+    // opCast
+    /**
+    Casting operator to integral, `bool`, or floating point type.
+
+    If a cast to a floating-point type is requested and `Hook` defines
+    `onBadCast`, the cast is verified by ensuring $(D get == cast(T)
+    U(get)). If that is not `true`, `hook.onBadCast!U(get)` is returned.
+
+    If a cast to an integral type is requested and `Hook` defines `onBadCast`,
+    the cast is verified by ensuring `get` and $(D cast(U)
+    get) are the same arithmetic number. (Note that `int(-1)` and
+    `uint(1)` are different values arithmetically although they have the same
+    bitwise representation and compare equal by language rules.) If the numbers
+    are not arithmetically equal, `hook.onBadCast!U(get)` is
+    returned.
+
+    Params:
+        U = The type to cast to
+
+    Returns:
+        If `Hook`     defines `hookOpCast`, the call immediately returns
+        `hook.hookOpCast!U(get)`. Otherwise, casting to `bool` yields $(D
+        get != 0) and casting to another integral that can represent all
+        values of `T` returns `get` promoted to `U`.
+    */
+    U opCast(U, this _)()
+    if (isIntegral!U || isFloatingPoint!U || is(U == bool))
+    {
+        static if (hasMember!(Hook, "hookOpCast"))
+        {
+            return hook.hookOpCast!U(payload);
+        }
+        else static if (is(U == bool))
+        {
+            return payload != 0;
+        }
+        else static if (valueConvertible!(T, U))
+        {
+            return payload;
+        }
+        // may lose bits or precision
+        else static if (!hasMember!(Hook, "onBadCast"))
+        {
+            return cast(U) payload;
+        }
+        else
+        {
+            if (isUnsigned!T || !isUnsigned!U ||
+                    T.sizeof > U.sizeof || payload >= 0)
+            {
+                auto result = cast(U) payload;
+                // If signedness is different, we need additional checks
+                if (result == payload &&
+                        (!isUnsigned!T || isUnsigned!U || result >= 0))
+                    return result;
+            }
+            return hook.onBadCast!U(payload);
+        }
+    }
+    ///
+    @safe unittest
+    {
+        assert(cast(uint) checked(42) == 42);
+        assert(cast(uint) checked!WithNaN(-42) == uint.max);
+    }
+
+    // opEquals
+    /**
+    Compares `this` against `rhs` for equality.
+
+    If `U` is also an instance of `Checked`, both hooks (left- and right-hand
+    side) are introspected for the method `hookOpEquals`. If both define it,
+    priority is given to the left-hand side.
+
+    Params:
+        rhs = Right-hand side to compare for equality
+
+    Returns:
+        If `Hook` defines `hookOpEquals`, the function forwards to $(D
+        hook.hookOpEquals(get, rhs)). Otherwise, the result of the
+        built-in operation $(D get == rhs) is returned.
+
+    */
+    bool opEquals(U, this _)(U rhs)
+    if (isIntegral!U || isFloatingPoint!U || is(U == bool) ||
+        is(U == Checked!(V, W), V, W) && is(typeof(this == rhs.payload)))
+    {
+        static if (is(U == Checked!(V, W), V, W))
+        {
+            alias R = typeof(payload + rhs.payload);
+            static if (is(Hook == W))
+            {
+                // Use the lhs hook if there
+                return this == rhs.payload;
+            }
+            else static if (valueConvertible!(T, R) && valueConvertible!(V, R))
+            {
+                return payload == rhs.payload;
+            }
+            else static if (hasMember!(Hook, "hookOpEquals"))
+            {
+                return hook.hookOpEquals(payload, rhs.payload);
+            }
+            else static if (hasMember!(W, "hookOpEquals"))
+            {
+                return rhs.hook.hookOpEquals(rhs.payload, payload);
+            }
+            else
+            {
+                return payload == rhs.payload;
+            }
+        }
+        else static if (hasMember!(Hook, "hookOpEquals"))
+            return hook.hookOpEquals(payload, rhs);
+        else static if (isIntegral!U || isFloatingPoint!U || is(U == bool))
+            return payload == rhs;
+    }
+
+    ///
+    static if (is(T == int) && is(Hook == void)) @safe unittest
+    {
+        import std.traits : isUnsigned;
+
+        static struct MyHook
+        {
+            static bool thereWereErrors;
+            static bool hookOpEquals(L, R)(L lhs, R rhs)
+            {
+                if (lhs != rhs) return false;
+                static if (isUnsigned!L && !isUnsigned!R)
+                {
+                    if (lhs > 0 && rhs < 0) thereWereErrors = true;
+                }
+                else static if (isUnsigned!R && !isUnsigned!L)
+                    if (lhs < 0 && rhs > 0) thereWereErrors = true;
+                // Preserve built-in behavior.
+                return true;
+            }
+        }
+        auto a = checked!MyHook(-42);
+        assert(a == uint(-42));
+        assert(MyHook.thereWereErrors);
+        MyHook.thereWereErrors = false;
+        assert(checked!MyHook(uint(-42)) == -42);
+        assert(MyHook.thereWereErrors);
+        static struct MyHook2
+        {
+            static bool hookOpEquals(L, R)(L lhs, R rhs)
+            {
+                return lhs == rhs;
+            }
+        }
+        MyHook.thereWereErrors = false;
+        assert(checked!MyHook2(uint(-42)) == a);
+        // Hook on left hand side takes precedence, so no errors
+        assert(!MyHook.thereWereErrors);
+    }
+
+    // toHash
+    /**
+    Generates a hash for `this`. If `Hook` defines `hookToHash`, the call
+    immediately returns `hook.hookToHash(payload)`. If `Hook` does not
+    implement `hookToHash`, but it has state, a hash will be generated for
+    the `Hook` using the built-in function and it will be xored with the
+    hash of the `payload`.
+
+    Returns:
+        The hash of `this` instance.
+
+    */
+    size_t toHash() const nothrow @safe
+    {
+        static if (hasMember!(Hook, "hookToHash"))
+        {
+            return hook.hookToHash(payload);
+        }
+        else static if (stateSize!Hook > 0)
+        {
+            static if (hasMember!(typeof(payload), "toHash"))
+            {
+                return payload.toHash() ^ hashOf(hook);
+            }
+            else
+            {
+                return hashOf(payload) ^ hashOf(hook);
+            }
+        }
+        else static if (hasMember!(typeof(payload), "toHash"))
+        {
+            return payload.toHash();
+        }
+        else
+        {
+            return .hashOf(payload);
+        }
+    }
+
+    /// ditto
+    size_t toHash(this _)() shared const nothrow @safe
+    {
+        import core.atomic : atomicLoad, MemoryOrder;
+        static if (is(typeof(this.payload.atomicLoad!(MemoryOrder.acq)) P))
+        {
+            auto payload = __ctfe ? cast(P) this.payload
+                                  : this.payload.atomicLoad!(MemoryOrder.acq);
+        }
+        else
+        {
+            alias payload = this.payload;
+        }
+
+        static if (hasMember!(Hook, "hookToHash"))
+        {
+            return hook.hookToHash(payload);
+        }
+        else static if (stateSize!Hook > 0)
+        {
+            static if (hasMember!(typeof(payload), "toHash"))
+            {
+                return payload.toHash() ^ hashOf(hook);
+            }
+            else
+            {
+                return hashOf(payload) ^ hashOf(hook);
+            }
+        }
+        else static if (hasMember!(typeof(payload), "toHash"))
+        {
+            return payload.toHash();
+        }
+        else
+        {
+            return .hashOf(payload);
+        }
+    }
+
+    /**
+    Writes a string representation of this to a `sink`.
+
+    Params:
+      sink = A `Char` accepting
+             $(REF_ALTTEXT output range, isOutputRange, std,range,primitives).
+      fmt  = A $(REF FormatSpec, std, format) which controls how this
+             is formatted.
+    */
+    void toString(Writer, Char)(scope ref Writer sink, scope const ref FormatSpec!Char fmt) const
+    {
+        import std.format.write : formatValue;
+        if (fmt.spec == 's')
+            return formatValue(sink, this, fmt);
+        else
+            return formatValue(sink, payload, fmt);
+    }
+
+    /**
+    `toString` is rarely directly invoked; the usual way of using it is via
+    $(REF format, std, format):
+    */
+    @system unittest
+    {
+        import std.format;
+
+        assert(format("%04d", checked(15)) == "0015");
+        assert(format("0x%02x", checked(15)) == "0x0f");
+    }
+
+    // opCmp
+    /**
+
+    Compares `this` against `rhs` for ordering. If `Hook` defines `hookOpCmp`,
+    the function forwards to $(D hook.hookOpCmp(get, rhs)). Otherwise, the
+    result of the built-in comparison operation is returned.
+
+    If `U` is also an instance of `Checked`, both hooks (left- and right-hand
+    side) are introspected for the method `hookOpCmp`. If both define it,
+    priority is given to the left-hand side.
+
+    Params:
+        rhs   = The right-hand side operand
+        U     = either the type of `rhs` or the underlying type
+                if `rhs` is a `Checked` instance
+        Hook1 = If `rhs` is a `Checked` instance, `Hook1` represents
+                the instance's behavior hook
+
+    Returns:
+        The result of `hookOpCmp` if `hook` defines `hookOpCmp`. If
+        `U` is an instance of `Checked` and `hook` does not define
+        `hookOpCmp`, result of `rhs.hook.hookOpCmp` is returned.
+        If none of the instances specify the behavior via `hookOpCmp`,
+        `-1` is returned if `lhs` is lesser than `rhs`, `1` if `lhs`
+        is greater than `rhs` and `0` on equality.
+    */
+    auto opCmp(U, this _)(const U rhs) //const pure @safe nothrow @nogc
+    if (isIntegral!U || isFloatingPoint!U || is(U == bool))
+    {
+        static if (hasMember!(Hook, "hookOpCmp"))
+        {
+            return hook.hookOpCmp(payload, rhs);
+        }
+        else static if (valueConvertible!(T, U) || valueConvertible!(U, T))
+        {
+            return payload < rhs ? -1 : payload > rhs;
+        }
+        else static if (isFloatingPoint!U)
+        {
+            U lhs = payload;
+            return lhs < rhs ? U(-1.0)
+                : lhs > rhs ? U(1.0)
+                : lhs == rhs ? U(0.0) : U.init;
+        }
+        else
+        {
+            return payload < rhs ? -1 : payload > rhs;
+        }
+    }
+
+    /// ditto
+    auto opCmp(U, Hook1, this _)(Checked!(U, Hook1) rhs)
+    {
+        alias R = typeof(payload + rhs.payload);
+        static if (valueConvertible!(T, R) && valueConvertible!(U, R))
+        {
+            return payload < rhs.payload ? -1 : payload > rhs.payload;
+        }
+        else static if (is(Hook == Hook1))
+        {
+            // Use the lhs hook
+            return this.opCmp(rhs.payload);
+        }
+        else static if (hasMember!(Hook, "hookOpCmp"))
+        {
+            return hook.hookOpCmp(get, rhs.get);
+        }
+        else static if (hasMember!(Hook1, "hookOpCmp"))
+        {
+            return -rhs.hook.hookOpCmp(rhs.payload, get);
+        }
+        else
+        {
+            return payload < rhs.payload ? -1 : payload > rhs.payload;
+        }
+    }
+
+    ///
+    static if (is(T == int) && is(Hook == void)) @safe unittest
+    {
+        import std.traits : isUnsigned;
+
+        static struct MyHook
+        {
+            static bool thereWereErrors;
+            static int hookOpCmp(L, R)(L lhs, R rhs)
+            {
+                static if (isUnsigned!L && !isUnsigned!R)
+                {
+                    if (rhs < 0 && rhs >= lhs)
+                        thereWereErrors = true;
+                }
+                else static if (isUnsigned!R && !isUnsigned!L)
+                {
+                    if (lhs < 0 && lhs >= rhs)
+                        thereWereErrors = true;
+                }
+                // Preserve built-in behavior.
+                return lhs < rhs ? -1 : lhs > rhs;
+            }
+        }
+        auto a = checked!MyHook(-42);
+        assert(a > uint(42));
+        assert(MyHook.thereWereErrors);
+        static struct MyHook2
+        {
+            static int hookOpCmp(L, R)(L lhs, R rhs)
+            {
+                // Default behavior
+                return lhs < rhs ? -1 : lhs > rhs;
+            }
+        }
+        MyHook.thereWereErrors = false;
+        assert(Checked!(uint, MyHook2)(uint(-42)) <= a);
+        //assert(Checked!(uint, MyHook2)(uint(-42)) >= a);
+        // Hook on left hand side takes precedence, so no errors
+        assert(!MyHook.thereWereErrors);
+        assert(a <= Checked!(uint, MyHook2)(uint(-42)));
+        assert(MyHook.thereWereErrors);
+    }
+
+    // For coverage
+    static if (is(T == int) && is(Hook == void)) @safe unittest
+    {
+        assert(checked(42) <= checked!void(42));
+        assert(checked!void(42) <= checked(42u));
+        assert(checked!void(42) <= checked!(void*)(42u));
+    }
+
+    // opUnary
+    /**
+
+    Defines unary operators `+`, `-`, `~`, `++`, and `--`. Unary `+` is not
+    overridable and always has built-in behavior (returns `this`). For the
+    others, if `Hook` defines `hookOpUnary`, `opUnary` forwards to $(D
+    Checked!(typeof(hook.hookOpUnary!op(get)),
+    Hook)(hook.hookOpUnary!op(get))).
+
+    If `Hook` does not define `hookOpUnary` but defines `onOverflow`, `opUnary`
+    forwards to `hook.onOverflow!op(get)` in case an overflow occurs.
+    For `++` and `--`, the payload is assigned from the result of the call to
+    `onOverflow`.
+
+    Note that unary `-` is considered to overflow if `T` is a signed integral of
+    32 or 64 bits and is equal to the most negative value. This is because that
+    value has no positive negation.
+
+    Params:
+        op = The unary operator
+
+    Returns:
+        A `Checked` instance representing the result of the unary
+        operation
+    */
+    auto opUnary(string op, this _)()
+    if (op == "+" || op == "-" || op == "~")
+    {
+        static if (op == "+")
+            return Checked(this); // "+" is not hookable
+        else static if (hasMember!(Hook, "hookOpUnary"))
+        {
+            auto r = hook.hookOpUnary!op(payload);
+            return Checked!(typeof(r), Hook)(r);
+        }
+        else static if (op == "-" && isIntegral!T && T.sizeof >= 4 &&
+                !isUnsigned!T && hasMember!(Hook, "onOverflow"))
+        {
+            static assert(is(typeof(-payload) == typeof(payload)));
+            bool overflow;
+            import core.checkedint : negs;
+            auto r = negs(payload, overflow);
+            if (overflow) r = hook.onOverflow!op(payload);
+            return Checked(r);
+        }
+        else
+            return Checked(mixin(op ~ "payload"));
+    }
+
+    /// ditto
+    ref Checked opUnary(string op)() return
+    if (op == "++" || op == "--")
+    {
+        static if (hasMember!(Hook, "hookOpUnary"))
+            hook.hookOpUnary!op(payload);
+        else static if (hasMember!(Hook, "onOverflow"))
+        {
+            static if (op == "++")
+            {
+                if (payload == max.payload)
+                    payload = hook.onOverflow!"++"(payload);
+                else
+                    ++payload;
+            }
+            else
+            {
+                if (payload == min.payload)
+                    payload = hook.onOverflow!"--"(payload);
+                else
+                    --payload;
+            }
+        }
+        else
+            mixin(op ~ "payload;");
+        return this;
+    }
+
+    ///
+    static if (is(T == int) && is(Hook == void)) @safe unittest
+    {
+        static struct MyHook
+        {
+            static bool thereWereErrors;
+            static L hookOpUnary(string x, L)(L lhs)
+            {
+                if (x == "-" && lhs == -lhs) thereWereErrors = true;
+                return -lhs;
+            }
+        }
+        auto a = checked!MyHook(long.min);
+        assert(a == -a);
+        assert(MyHook.thereWereErrors);
+        auto b = checked!void(42);
+        assert(++b == 43);
+    }
+
+    // opBinary
+    /**
+
+    Defines binary operators `+`, `-`, `*`, `/`, `%`, `^^`, `&`, `|`, `^`, `<<`, `>>`,
+    and `>>>`. If `Hook` defines `hookOpBinary`, `opBinary` forwards to $(D
+    Checked!(typeof(hook.hookOpBinary!op(get, rhs)),
+    Hook)(hook.hookOpBinary!op(get, rhs))).
+
+    If `Hook` does not define `hookOpBinary` but defines `onOverflow`,
+    `opBinary` forwards to `hook.onOverflow!op(get, rhs)` in case an
+    overflow occurs.
+
+    If two `Checked` instances are involved in a binary operation and both
+    define `hookOpBinary`, the left-hand side hook has priority. If both define
+    `onOverflow`, a compile-time error occurs.
+
+    Params:
+        op    = The binary operator
+        rhs   = The right hand side operand
+        U     = If `rhs` is a `Checked` instance, `U` represents
+                the underlying instance type
+        Hook1 = If `rhs` is a `Checked` instance, `Hook1` represents
+                the instance's behavior hook
+
+    Returns:
+        A `Checked` instance representing the result of the binary
+        operation
+    */
+    auto opBinary(string op, Rhs)(const Rhs rhs)
+    if (isIntegral!Rhs || isFloatingPoint!Rhs || is(Rhs == bool))
+    {
+        return opBinaryImpl!(op, Rhs, typeof(this))(rhs);
+    }
+
+    /// ditto
+    auto opBinary(string op, Rhs)(const Rhs rhs) const
+    if (isIntegral!Rhs || isFloatingPoint!Rhs || is(Rhs == bool))
+    {
+        return opBinaryImpl!(op, Rhs, typeof(this))(rhs);
+    }
+
+    private auto opBinaryImpl(string op, Rhs, this _)(const Rhs rhs)
+    {
+        alias R = typeof(mixin("payload" ~ op ~ "rhs"));
+        static assert(is(typeof(mixin("payload" ~ op ~ "rhs")) == R));
+        static if (isIntegral!R) alias Result = Checked!(R, Hook);
+        else alias Result = R;
+
+        static if (hasMember!(Hook, "hookOpBinary"))
+        {
+            auto r = hook.hookOpBinary!op(payload, rhs);
+            return Checked!(typeof(r), Hook)(r);
+        }
+        else static if (is(Rhs == bool))
+        {
+            return mixin("this" ~ op ~ "ubyte(rhs)");
+        }
+        else static if (isFloatingPoint!Rhs)
+        {
+            return mixin("payload" ~ op ~ "rhs");
+        }
+        else static if (hasMember!(Hook, "onOverflow"))
+        {
+            bool overflow;
+            auto r = opChecked!op(payload, rhs, overflow);
+            if (overflow) r = hook.onOverflow!op(payload, rhs);
+            return Result(r);
+        }
+        else
+        {
+            // Default is built-in behavior
+            return Result(mixin("payload" ~ op ~ "rhs"));
+        }
+    }
+
+    /// ditto
+    auto opBinary(string op, U, Hook1)(Checked!(U, Hook1) rhs)
+    {
+        return opBinaryImpl2!(op, U, Hook1, typeof(this))(rhs);
+    }
+
+    /// ditto
+    auto opBinary(string op, U, Hook1)(Checked!(U, Hook1) rhs) const
+    {
+        return opBinaryImpl2!(op, U, Hook1, typeof(this))(rhs);
+    }
+
+    private
+    auto opBinaryImpl2(string op, U, Hook1, this _)(Checked!(U, Hook1) rhs)
+    {
+        alias R = typeof(get + rhs.payload);
+        static if (valueConvertible!(T, R) && valueConvertible!(U, R) ||
+            is(Hook == Hook1))
+        {
+            // Delegate to lhs
+            return mixin("this" ~ op ~ "rhs.payload");
+        }
+        else static if (hasMember!(Hook, "hookOpBinary"))
+        {
+            return hook.hookOpBinary!op(payload, rhs);
+        }
+        else static if (hasMember!(Hook1, "hookOpBinary"))
+        {
+            // Delegate to rhs
+            return mixin("this.payload" ~ op ~ "rhs");
+        }
+        else static if (hasMember!(Hook, "onOverflow") &&
+            !hasMember!(Hook1, "onOverflow"))
+        {
+            // Delegate to lhs
+            return mixin("this" ~ op ~ "rhs.payload");
+        }
+        else static if (hasMember!(Hook1, "onOverflow") &&
+            !hasMember!(Hook, "onOverflow"))
+        {
+            // Delegate to rhs
+            return mixin("this.payload" ~ op ~ "rhs");
+        }
+        else
+        {
+            static assert(0, "Conflict between lhs and rhs hooks," ~
+                " use .get on one side to disambiguate.");
+        }
+    }
+
+    static if (is(T == int) && is(Hook == void)) @safe unittest
+    {
+        const a = checked(42);
+        assert(a + 1 == 43);
+        assert(a + checked(uint(42)) == 84);
+        assert(checked(42) + checked!void(42u) == 84);
+        assert(checked!void(42) + checked(42u) == 84);
+
+        static struct MyHook
+        {
+            static uint tally;
+            static auto hookOpBinary(string x, L, R)(L lhs, R rhs)
+            {
+                ++tally;
+                return mixin("lhs" ~ x ~ "rhs");
+            }
+        }
+        assert(checked!MyHook(42) + checked(42u) == 84);
+        assert(checked!void(42) + checked!MyHook(42u) == 84);
+        assert(MyHook.tally == 2);
+    }
+
+    // opBinaryRight
+    /**
+
+    Defines binary operators `+`, `-`, `*`, `/`, `%`, `^^`, `&`, `|`, `^`, `<<`,
+    `>>`, and `>>>` for the case when a built-in numeric or Boolean type is on
+    the left-hand side, and a `Checked` instance is on the right-hand side.
+
+    Params:
+        op  = The binary operator
+        lhs = The left hand side operand
+
+    Returns:
+        A `Checked` instance representing the result of the binary
+        operation
+
+    */
+    auto opBinaryRight(string op, Lhs)(const Lhs lhs)
+    if (isIntegral!Lhs || isFloatingPoint!Lhs || is(Lhs == bool))
+    {
+        return opBinaryRightImpl!(op, Lhs, typeof(this))(lhs);
+    }
+
+    /// ditto
+    auto opBinaryRight(string op, Lhs)(const Lhs lhs) const
+    if (isIntegral!Lhs || isFloatingPoint!Lhs || is(Lhs == bool))
+    {
+        return opBinaryRightImpl!(op, Lhs, typeof(this))(lhs);
+    }
+
+    private auto opBinaryRightImpl(string op, Lhs, this _)(const Lhs lhs)
+    {
+        static if (hasMember!(Hook, "hookOpBinaryRight"))
+        {
+            auto r = hook.hookOpBinaryRight!op(lhs, payload);
+            return Checked!(typeof(r), Hook)(r);
+        }
+        else static if (hasMember!(Hook, "hookOpBinary"))
+        {
+            auto r = hook.hookOpBinary!op(lhs, payload);
+            return Checked!(typeof(r), Hook)(r);
+        }
+        else static if (is(Lhs == bool))
+        {
+            return mixin("ubyte(lhs)" ~ op ~ "this");
+        }
+        else static if (isFloatingPoint!Lhs)
+        {
+            return mixin("lhs" ~ op ~ "payload");
+        }
+        else static if (hasMember!(Hook, "onOverflow"))
+        {
+            bool overflow;
+            auto r = opChecked!op(lhs, T(payload), overflow);
+            if (overflow) r = hook.onOverflow!op(lhs, payload);
+            return Checked!(typeof(r), Hook)(r);
+        }
+        else
+        {
+            // Default is built-in behavior
+            auto r = mixin("lhs" ~ op ~ "T(payload)");
+            return Checked!(typeof(r), Hook)(r);
+        }
+    }
+
+    static if (is(T == int) && is(Hook == void)) @safe unittest
+    {
+        assert(1 + checked(1) == 2);
+        static uint tally;
+        static struct MyHook
+        {
+            static auto hookOpBinaryRight(string x, L, R)(L lhs, R rhs)
+            {
+                ++tally;
+                return mixin("lhs" ~ x ~ "rhs");
+            }
+        }
+        assert(1 + checked!MyHook(1) == 2);
+        assert(tally == 1);
+
+        immutable x1 = checked(1);
+        assert(1 + x1 == 2);
+        immutable x2 = checked!MyHook(1);
+        assert(1 + x2 == 2);
+        assert(tally == 2);
+    }
+
+    // opOpAssign
+    /**
+
+    Defines operators `+=`, `-=`, `*=`, `/=`, `%=`, `^^=`, `&=`, `|=`, `^=`,
+    `<<=`, `>>=`, and `>>>=`.
+
+    If `Hook` defines `hookOpOpAssign`, `opOpAssign` forwards to
+    `hook.hookOpOpAssign!op(payload, rhs)`, where `payload` is a reference to
+    the internally held data so the hook can change it.
+
+    Otherwise, the operator first evaluates $(D auto result =
+    opBinary!op(payload, rhs).payload), which is subject to the hooks in
+    `opBinary`. Then, if `result` is less than $(D Checked!(T, Hook).min) and if
+    `Hook` defines `onLowerBound`, the payload is assigned from $(D
+    hook.onLowerBound(result, min)). If `result` is greater than $(D Checked!(T,
+    Hook).max) and if `Hook` defines `onUpperBound`, the payload is assigned
+    from $(D hook.onUpperBound(result, min)).
+
+    If the right-hand side is also a Checked but with a different hook or
+    underlying type, the hook and underlying type of this Checked takes
+    precedence.
+
+    In all other cases, the built-in behavior is carried out.
+
+    Params:
+    op = The operator involved (without the `"="`, e.g. `"+"` for `"+="` etc)
+    rhs = The right-hand side of the operator (left-hand side is `this`)
+
+    Returns: A reference to `this`.
+    */
+    ref Checked opOpAssign(string op, Rhs)(const Rhs rhs) return
+    if (isIntegral!Rhs || isFloatingPoint!Rhs || is(Rhs == bool))
+    {
+        static assert(is(typeof(mixin("payload" ~ op ~ "=rhs")) == T));
+
+        static if (hasMember!(Hook, "hookOpOpAssign"))
+        {
+            hook.hookOpOpAssign!op(payload, rhs);
+        }
+        else
+        {
+            alias R = typeof(get + rhs);
+            auto r = opBinary!op(rhs).get;
+            import std.conv : unsigned;
+
+            static if (ProperCompare.hookOpCmp(R.min, min.get) < 0 &&
+                hasMember!(Hook, "onLowerBound"))
+            {
+                if (ProperCompare.hookOpCmp(r, min.get) < 0)
+                {
+                    // Example: Checked!uint(1) += int(-3)
+                    payload = hook.onLowerBound(r, min.get);
+                    return this;
+                }
+            }
+            static if (ProperCompare.hookOpCmp(max.get, R.max) < 0 &&
+                hasMember!(Hook, "onUpperBound"))
+            {
+                if (ProperCompare.hookOpCmp(r, max.get) > 0)
+                {
+                    // Example: Checked!uint(1) += long(uint.max)
+                    payload = hook.onUpperBound(r, max.get);
+                    return this;
+                }
+            }
+            payload = cast(T) r;
+        }
+        return this;
+    }
+
+    /// ditto
+    ref Checked opOpAssign(string op, Rhs)(const Rhs rhs) return
+    if (is(Rhs == Checked!(RhsT, RhsHook), RhsT, RhsHook))
+    {
+        return opOpAssign!(op, typeof(rhs.payload))(rhs.payload);
+    }
+
+    ///
+    static if (is(T == int) && is(Hook == void)) @safe unittest
+    {
+        static struct MyHook
+        {
+            static bool thereWereErrors;
+            static T onLowerBound(Rhs, T)(Rhs rhs, T bound)
+            {
+                thereWereErrors = true;
+                return bound;
+            }
+            static T onUpperBound(Rhs, T)(Rhs rhs, T bound)
+            {
+                thereWereErrors = true;
+                return bound;
+            }
+        }
+        auto x = checked!MyHook(byte.min);
+        x -= 1;
+        assert(MyHook.thereWereErrors);
+        MyHook.thereWereErrors = false;
+        x = byte.max;
+        x += 1;
+        assert(MyHook.thereWereErrors);
+    }
+}
+
+///
+@safe @nogc pure nothrow unittest
+{
+    // Hook that ignores all problems.
+    static struct Ignore
+    {
+        @nogc nothrow pure @safe static:
+        Dst onBadCast(Dst, Src)(Src src) { return cast(Dst) src; }
+        Lhs onLowerBound(Rhs, T)(Rhs rhs, T bound) { return cast(T) rhs; }
+        T onUpperBound(Rhs, T)(Rhs rhs, T bound) { return cast(T) rhs; }
+        bool hookOpEquals(Lhs, Rhs)(Lhs lhs, Rhs rhs) { return lhs == rhs; }
+        int hookOpCmp(Lhs, Rhs)(Lhs lhs, Rhs rhs) { return (lhs > rhs) - (lhs < rhs); }
+        typeof(~Lhs()) onOverflow(string x, Lhs)(ref Lhs lhs) { return mixin(x ~ "lhs"); }
+        typeof(Lhs() + Rhs()) onOverflow(string x, Lhs, Rhs)(Lhs lhs, Rhs rhs)
+        {
+            static if (x == "/")
+                return typeof(lhs / rhs).min;
+            else
+                return mixin("lhs" ~ x ~ "rhs");
+        }
+    }
+
+    auto x = Checked!(int, Ignore)(5) + 7;
+}
+
+
+/**
+
+Convenience function that turns an integral into the corresponding `Checked`
+instance by using template argument deduction. The hook type may be specified
+(by default `Abort`).
+
+Params:
+    Hook  = type that customizes the behavior, by default `Abort`
+    T     = type represetinfg the underlying represantion of the `Checked` instance
+    value = the actual value of the representation
+
+Returns:
+    A `Checked` instance customized by the provided `Hook` and `value`
+*/
+Checked!(T, Hook) checked(Hook = Abort, T)(const T value)
+if (is(typeof(Checked!(T, Hook)(value))))
+{
+    return Checked!(T, Hook)(value);
+}
+
+///
+@safe unittest
+{
+    static assert(is(typeof(checked(42)) == Checked!int));
+    assert(checked(42) == Checked!int(42));
+    static assert(is(typeof(checked!WithNaN(42)) == Checked!(int, WithNaN)));
+    assert(checked!WithNaN(42) == Checked!(int, WithNaN)(42));
+}
+
+// get
+@safe unittest
+{
+    void test(T)()
+    {
+        assert(Checked!(T, void)(ubyte(22)).get == 22);
+    }
+    test!ubyte;
+    test!(const ubyte);
+    test!(immutable ubyte);
+}
+
+@system unittest
+{
+    // https://issues.dlang.org/show_bug.cgi?id=21758
+    assert(4 * checked(5L) == 20);
+    assert(20 / checked(5L) == 4);
+    assert(2 ^^ checked(3L) == 8);
+    assert(12 % checked(5L) == 2);
+    assert((0xff & checked(3L)) == 3);
+    assert((0xf0 | checked(3L)) == 0xf3);
+    assert((0xff ^ checked(3L)) == 0xfc);
+}
+
+// Abort
+/**
+
+Force all integral errors to fail by printing an error message to `stderr` and
+then abort the program. `Abort` is the default second argument for `Checked`.
+
+*/
+struct Abort
+{
+static:
+    /**
+
+    Called automatically upon a bad cast (one that loses precision or attempts
+    to convert a negative value to an unsigned type). The source type is `Src`
+    and the destination type is `Dst`.
+
+    Params:
+        src = Souce operand
+
+    Returns:
+        Nominally the result is the desired value of the cast operation,
+        which will be forwarded as the result of the cast. For `Abort`, the
+        function never returns because it aborts the program.
+    */
+    Dst onBadCast(Dst, Src)(Src src)
+    {
+        Warn.onBadCast!Dst(src);
+        assert(0);
+    }
+
+    /**
+
+    Called automatically upon a bounds error.
+
+    Params:
+    rhs = The right-hand side value in the assignment, after the operator has
+    been evaluated
+    bound = The value of the bound being violated
+
+    Returns: Nominally the result is the desired value of the operator, which
+    will be forwarded as result. For `Abort`, the function never returns because
+    it aborts the program.
+
+    */
+    T onLowerBound(Rhs, T)(Rhs rhs, T bound)
+    {
+        Warn.onLowerBound(rhs, bound);
+        assert(0);
+    }
+    /// ditto
+    T onUpperBound(Rhs, T)(Rhs rhs, T bound)
+    {
+        Warn.onUpperBound(rhs, bound);
+        assert(0);
+    }
+
+    /**
+
+    Called automatically upon a comparison for equality. In case of a erroneous
+    comparison (one that would make a signed negative value appear equal to an
+    unsigned positive value), this hook issues `assert(0)` which terminates the
+    application.
+
+    Params:
+    lhs = The first argument of `Checked`, e.g. `int` if the left-hand side of
+      the operator is `Checked!int`
+    rhs = The right-hand side type involved in the operator
+
+    Returns: Upon a correct comparison, returns the result of the comparison.
+    Otherwise, the function terminates the application so it never returns.
+
+    */
+    static bool hookOpEquals(Lhs, Rhs)(Lhs lhs, Rhs rhs)
+    {
+        bool error;
+        auto result = opChecked!"=="(lhs, rhs, error);
+        if (error)
+        {
+            Warn.hookOpEquals(lhs, rhs);
+            assert(0);
+        }
+        return result;
+    }
+
+    /**
+
+    Called automatically upon a comparison for ordering using one of the
+    operators `<`, `<=`, `>`, or `>=`. In case the comparison is erroneous (i.e.
+    it would make a signed negative value appear greater than or equal to an
+    unsigned positive value), then application is terminated with `assert(0)`.
+    Otherwise, the three-state result is returned (positive if $(D lhs > rhs),
+    negative if $(D lhs < rhs), `0` otherwise).
+
+    Params:
+    lhs = The first argument of `Checked`, e.g. `int` if the left-hand side of
+      the operator is `Checked!int`
+    rhs = The right-hand side type involved in the operator
+
+    Returns: For correct comparisons, returns a positive integer if $(D lhs >
+    rhs), a negative integer if  $(D lhs < rhs), `0` if the two are equal. Upon
+    a mistaken comparison such as $(D int(-1) < uint(0)), the function never
+    returns because it aborts the program.
+
+    */
+    int hookOpCmp(Lhs, Rhs)(Lhs lhs, Rhs rhs)
+    {
+        bool error;
+        auto result = opChecked!"cmp"(lhs, rhs, error);
+        if (error)
+        {
+            Warn.hookOpCmp(lhs, rhs);
+            assert(0);
+        }
+        return result;
+    }
+
+    /**
+
+    Called automatically upon an overflow during a unary or binary operation.
+
+    Params:
+    x = The operator, e.g. `-`
+    lhs = The left-hand side (or sole) argument
+    rhs = The right-hand side type involved in the operator
+
+    Returns: Nominally the result is the desired value of the operator, which
+    will be forwarded as result. For `Abort`, the function never returns because
+    it aborts the program.
+
+    */
+    typeof(~Lhs()) onOverflow(string x, Lhs)(Lhs lhs)
+    {
+        Warn.onOverflow!x(lhs);
+        assert(0);
+    }
+    /// ditto
+    typeof(Lhs() + Rhs()) onOverflow(string x, Lhs, Rhs)(Lhs lhs, Rhs rhs)
+    {
+        Warn.onOverflow!x(lhs, rhs);
+        assert(0);
+    }
+}
+
+///
+@safe unittest
+{
+    void test(T)()
+    {
+        Checked!(int, Abort) x;
+        x = 42;
+        auto x1 = cast(T) x;
+        assert(x1 == 42);
+        //x1 += long(int.max);
+    }
+    test!short;
+    test!(const short);
+    test!(immutable short);
+}
+
+
+// Throw
+/**
+
+Force all integral errors to fail by throwing an exception of type
+`Throw.CheckFailure`. The message coming with the error is similar to the one
+printed by `Warn`.
+
+*/
+struct Throw
+{
+    /**
+    Exception type thrown upon any failure.
+    */
+    static class CheckFailure : Exception
+    {
+        /**
+        Params:
+            f    = format specifier
+            vals = actual values for the format specifier
+        */
+        this(T...)(string f, T vals)
+        {
+            import std.format : format;
+            super(format(f, vals));
+        }
+    }
+
+    /**
+
+    Called automatically upon a bad cast (one that loses precision or attempts
+    to convert a negative value to an unsigned type). The source type is `Src`
+    and the destination type is `Dst`.
+
+    Params:
+        src = source operand
+
+    Returns:
+        Nominally the result is the desired value of the cast operation,
+        which will be forwarded as the result of the cast. For `Throw`, the
+        function never returns because it throws an exception.
+
+    Throws:
+        `CheckFailure` on bad cast
+    */
+    static Dst onBadCast(Dst, Src)(Src src)
+    {
+        throw new CheckFailure("Erroneous cast: cast(%s) %s(%s)",
+            Dst.stringof, Src.stringof, src);
+    }
+
+    /**
+
+    Called automatically upon a bounds error.
+
+    Params:
+        rhs = The right-hand side value in the assignment, after the operator has
+        been evaluated
+        bound = The value of the bound being violated
+
+    Returns:
+        Nominally the result is the desired value of the operator, which
+        will be forwarded as result. For `Throw`, the function never returns because
+        it throws.
+
+    Throws:
+        `CheckFailure` on overflow
+
+    */
+    static T onLowerBound(Rhs, T)(Rhs rhs, T bound)
+    {
+        throw new CheckFailure("Lower bound error: %s(%s) < %s(%s)",
+            Rhs.stringof, rhs, T.stringof, bound);
+    }
+    /// ditto
+    static T onUpperBound(Rhs, T)(Rhs rhs, T bound)
+    {
+        throw new CheckFailure("Upper bound error: %s(%s) > %s(%s)",
+            Rhs.stringof, rhs, T.stringof, bound);
+    }
+
+    /**
+
+    Called automatically upon a comparison for equality. Throws upon an
+    erroneous comparison (one that would make a signed negative value appear
+    equal to an unsigned positive value).
+
+    Params:
+    lhs = The first argument of `Checked`, e.g. `int` if the left-hand side of
+      the operator is `Checked!int`
+    rhs = The right-hand side type involved in the operator
+
+    Returns: The result of the comparison.
+
+    Throws: `CheckFailure` if the comparison is mathematically erroneous.
+
+    */
+    static bool hookOpEquals(L, R)(L lhs, R rhs)
+    {
+        bool error;
+        auto result = opChecked!"=="(lhs, rhs, error);
+        if (error)
+        {
+            throw new CheckFailure("Erroneous comparison: %s(%s) == %s(%s)",
+                L.stringof, lhs, R.stringof, rhs);
+        }
+        return result;
+    }
+
+    /**
+
+    Called automatically upon a comparison for ordering using one of the
+    operators `<`, `<=`, `>`, or `>=`. In case the comparison is erroneous (i.e.
+    it would make a signed negative value appear greater than or equal to an
+    unsigned positive value), throws a `Throw.CheckFailure` exception.
+    Otherwise, the three-state result is returned (positive if $(D lhs > rhs),
+    negative if $(D lhs < rhs), `0` otherwise).
+
+    Params:
+    lhs = The first argument of `Checked`, e.g. `int` if the left-hand side of
+      the operator is `Checked!int`
+    rhs = The right-hand side type involved in the operator
+
+    Returns: For correct comparisons, returns a positive integer if $(D lhs >
+    rhs), a negative integer if  $(D lhs < rhs), `0` if the two are equal.
+
+    Throws: Upon a mistaken comparison such as $(D int(-1) < uint(0)), the
+    function never returns because it throws a `Throw.CheckedFailure` exception.
+
+    */
+    static int hookOpCmp(Lhs, Rhs)(Lhs lhs, Rhs rhs)
+    {
+        bool error;
+        auto result = opChecked!"cmp"(lhs, rhs, error);
+        if (error)
+        {
+            throw new CheckFailure("Erroneous ordering comparison: %s(%s) and %s(%s)",
+                Lhs.stringof, lhs, Rhs.stringof, rhs);
+        }
+        return result;
+    }
+
+    /**
+
+    Called automatically upon an overflow during a unary or binary operation.
+
+    Params:
+        x = The operator, e.g. `-`
+        lhs = The left-hand side (or sole) argument
+        rhs = The right-hand side type involved in the operator
+
+    Returns:
+        Nominally the result is the desired value of the operator, which
+        will be forwarded as result. For `Throw`, the function never returns because
+        it throws an exception.
+
+    Throws:
+        `CheckFailure` on overflow
+
+    */
+    static typeof(~Lhs()) onOverflow(string x, Lhs)(Lhs lhs)
+    {
+        throw new CheckFailure("Overflow on unary operator: %s%s(%s)",
+            x, Lhs.stringof, lhs);
+    }
+    /// ditto
+    static typeof(Lhs() + Rhs()) onOverflow(string x, Lhs, Rhs)(Lhs lhs, Rhs rhs)
+    {
+        throw new CheckFailure("Overflow on binary operator: %s(%s) %s %s(%s)",
+            Lhs.stringof, lhs, x, Rhs.stringof, rhs);
+    }
+}
+
+///
+@safe unittest
+{
+    void test(T)()
+    {
+        Checked!(int, Throw) x;
+        x = 42;
+        auto x1 = cast(T) x;
+        assert(x1 == 42);
+        x = T.max + 1;
+        import std.exception : assertThrown, assertNotThrown;
+        assertThrown(cast(T) x);
+        x = x.max;
+        assertThrown(x += 42);
+        assertThrown(x += 42L);
+        x = x.min;
+        assertThrown(-x);
+        assertThrown(x -= 42);
+        assertThrown(x -= 42L);
+        x = -1;
+        assertNotThrown(x == -1);
+        assertThrown(x == uint(-1));
+        assertNotThrown(x <= -1);
+        assertThrown(x <= uint(-1));
+    }
+    test!short;
+    test!(const short);
+    test!(immutable short);
+}
+
+// Warn
+/**
+Hook that prints to `stderr` a trace of all integral errors, without affecting
+default behavior.
+*/
+struct Warn
+{
+    import std.stdio : writefln;
+static:
+    /**
+
+    Called automatically upon a bad cast from `src` to type `Dst` (one that
+    loses precision or attempts to convert a negative value to an unsigned
+    type).
+
+    Params:
+    src = The source of the cast
+    Dst = The target type of the cast
+
+    Returns: `cast(Dst) src`
+
+    */
+    Dst onBadCast(Dst, Src)(Src src)
+    {
+        trustedStderr.writefln("Erroneous cast: cast(%s) %s(%s)",
+            Dst.stringof, Src.stringof, src);
+        return cast(Dst) src;
+    }
+
+    /**
+
+    Called automatically upon a bad `opOpAssign` call (one that loses precision
+    or attempts to convert a negative value to an unsigned type).
+
+    Params:
+    rhs = The right-hand side value in the assignment, after the operator has
+    been evaluated
+    bound = The bound being violated
+
+    Returns: `cast(T) rhs`
+    */
+    T onLowerBound(Rhs, T)(Rhs rhs, T bound)
+    {
+        trustedStderr.writefln("Lower bound error: %s(%s) < %s(%s)",
+            Rhs.stringof, rhs, T.stringof, bound);
+        return cast(T) rhs;
+    }
+    /// ditto
+    T onUpperBound(Rhs, T)(Rhs rhs, T bound)
+    {
+        trustedStderr.writefln("Upper bound error: %s(%s) > %s(%s)",
+            Rhs.stringof, rhs, T.stringof, bound);
+        return cast(T) rhs;
+    }
+
+    /**
+
+    Called automatically upon a comparison for equality. In case of an Erroneous
+    comparison (one that would make a signed negative value appear equal to an
+    unsigned positive value), writes a warning message to `stderr` as a side
+    effect.
+
+    Params:
+    lhs = The first argument of `Checked`, e.g. `int` if the left-hand side of
+      the operator is `Checked!int`
+    rhs = The right-hand side type involved in the operator
+
+    Returns: In all cases the function returns the built-in result of $(D lhs ==
+    rhs).
+
+    */
+    bool hookOpEquals(Lhs, Rhs)(Lhs lhs, Rhs rhs)
+    {
+        bool error;
+        auto result = opChecked!"=="(lhs, rhs, error);
+        if (error)
+        {
+            trustedStderr.writefln("Erroneous comparison: %s(%s) == %s(%s)",
+                Lhs.stringof, lhs, Rhs.stringof, rhs);
+            return lhs == rhs;
+        }
+        return result;
+    }
+
+    ///
+    @safe unittest
+    {
+        auto x = checked!Warn(-42);
+        // Passes
+        assert(x == -42);
+        // Passes but prints a warning
+        // assert(x == uint(-42));
+    }
+
+    /**
+
+    Called automatically upon a comparison for ordering using one of the
+    operators `<`, `<=`, `>`, or `>=`. In case the comparison is erroneous (i.e.
+    it would make a signed negative value appear greater than or equal to an
+    unsigned positive value), then a warning message is printed to `stderr`.
+
+    Params:
+    lhs = The first argument of `Checked`, e.g. `int` if the left-hand side of
+      the operator is `Checked!int`
+    rhs = The right-hand side type involved in the operator
+
+    Returns: In all cases, returns $(D lhs < rhs ? -1 : lhs > rhs). The result
+    is  not autocorrected in case of an erroneous comparison.
+
+    */
+    int hookOpCmp(Lhs, Rhs)(Lhs lhs, Rhs rhs)
+    {
+        bool error;
+        auto result = opChecked!"cmp"(lhs, rhs, error);
+        if (error)
+        {
+            trustedStderr.writefln("Erroneous ordering comparison: %s(%s) and %s(%s)",
+                Lhs.stringof, lhs, Rhs.stringof, rhs);
+            return lhs < rhs ? -1 : lhs > rhs;
+        }
+        return result;
+    }
+
+    ///
+    @safe unittest
+    {
+        auto x = checked!Warn(-42);
+        // Passes
+        assert(x <= -42);
+        // Passes but prints a warning
+        // assert(x <= uint(-42));
+    }
+
+    /**
+
+    Called automatically upon an overflow during a unary or binary operation.
+
+    Params:
+        x   = The operator involved
+        Lhs = The first argument of `Checked`, e.g. `int` if the left-hand side of
+              the operator is `Checked!int`
+        Rhs = The right-hand side type involved in the operator
+
+    Returns:
+        $(D mixin(x ~ "lhs")) for unary, $(D mixin("lhs" ~ x ~ "rhs")) for
+        binary
+
+    */
+    typeof(~Lhs()) onOverflow(string x, Lhs)(ref Lhs lhs)
+    {
+        trustedStderr.writefln("Overflow on unary operator: %s%s(%s)",
+            x, Lhs.stringof, lhs);
+        return mixin(x ~ "lhs");
+    }
+    /// ditto
+    typeof(Lhs() + Rhs()) onOverflow(string x, Lhs, Rhs)(Lhs lhs, Rhs rhs)
+    {
+        trustedStderr.writefln("Overflow on binary operator: %s(%s) %s %s(%s)",
+            Lhs.stringof, lhs, x, Rhs.stringof, rhs);
+        static if (x == "/")               // Issue 20743: mixin below would cause SIGFPE on POSIX
+            return typeof(lhs / rhs).min;  // or EXCEPTION_INT_OVERFLOW on Windows
+        else
+            return mixin("lhs" ~ x ~ "rhs");
+    }
+
+    // This is safe because we do not assign to the reference returned by
+    // `stderr`. The ability for the caller to do that is why `stderr` is not
+    // safe in the general case.
+    private @property auto ref trustedStderr() @trusted
+    {
+        import std.stdio : stderr;
+
+        return stderr;
+    }
+}
+
+///
+@safe unittest
+{
+    auto x = checked!Warn(42);
+    short x1 = cast(short) x;
+    //x += long(int.max);
+    auto y = checked!Warn(cast(const int) 42);
+    short y1 = cast(const byte) y;
+}
+
+@system unittest
+{
+    auto a = checked!Warn(int.min);
+    auto b = checked!Warn(-1);
+    auto x = checked!Abort(int.min);
+    auto y = checked!Abort(-1);
+
+    // Temporarily redirect output to stderr to make sure we get the right output.
+    import std.file : exists, remove;
+    import std.process : uniqueTempPath;
+    import std.stdio : stderr;
+    auto tmpname = uniqueTempPath;
+    scope(exit) if (exists(tmpname)) remove(tmpname);
+    auto t = stderr;
+    stderr.open(tmpname, "w");
+    // Open a new scope to minimize code ran with stderr redirected.
+    {
+        scope(exit) stderr = t;
+        assert(a / b == a * b);
+        import std.exception : assertThrown;
+        import core.exception : AssertError;
+        assertThrown!AssertError(x / y);
+    }
+    import std.file : readText;
+    import std.ascii : newline;
+    auto witness = readText(tmpname);
+    auto expected =
+"Overflow on binary operator: int(-2147483648) / const(int)(-1)" ~ newline ~
+"Overflow on binary operator: int(-2147483648) * const(int)(-1)" ~ newline ~
+"Overflow on binary operator: int(-2147483648) / const(int)(-1)" ~ newline;
+    assert(witness == expected, "'" ~ witness ~ "'");
+}
+
+// https://issues.dlang.org/show_bug.cgi?id=22249
+@safe unittest
+{
+    alias _ = Warn.onLowerBound!(int, int);
+}
+
+// ProperCompare
+/**
+
+Hook that provides arithmetically correct comparisons for equality and ordering.
+Comparing an object of type $(D Checked!(X, ProperCompare)) against another
+integral (for equality or ordering) ensures that no surprising conversions from
+signed to unsigned integral occur before the comparison. Using $(D Checked!(X,
+ProperCompare)) on either side of a comparison for equality against a
+floating-point number makes sure the integral can be properly converted to the
+floating point type, thus making sure equality is transitive.
+
+*/
+struct ProperCompare
+{
+    /**
+    Hook for `==` and `!=` that ensures comparison against integral values has
+    the behavior expected by the usual arithmetic rules. The built-in semantics
+    yield surprising behavior when comparing signed values against unsigned
+    values for equality, for example $(D uint.max == -1) or $(D -1_294_967_296 ==
+    3_000_000_000u). The call $(D hookOpEquals(x, y)) returns `true` if and only
+    if `x` and `y` represent the same arithmetic number.
+
+    If one of the numbers is an integral and the other is a floating-point
+    number, $(D hookOpEquals(x, y)) returns `true` if and only if the integral
+    can be converted exactly (without approximation) to the floating-point
+    number. This is in order to preserve transitivity of equality: if $(D
+    hookOpEquals(x, y)) and $(D hookOpEquals(y, z)) then $(D hookOpEquals(y,
+    z)), in case `x`, `y`, and `z` are a mix of integral and floating-point
+    numbers.
+
+    Params:
+    lhs = The left-hand side of the comparison for equality
+    rhs = The right-hand side of the comparison for equality
+
+    Returns:
+    The result of the comparison, `true` if the values are equal
+    */
+    static bool hookOpEquals(L, R)(L lhs, R rhs)
+    {
+        alias C = typeof(lhs + rhs);
+        static if (isFloatingPoint!C)
+        {
+            static if (!isFloatingPoint!L)
+            {
+                return hookOpEquals(rhs, lhs);
+            }
+            else static if (!isFloatingPoint!R)
+            {
+                static assert(isFloatingPoint!L && !isFloatingPoint!R);
+                auto rhs1 = C(rhs);
+                return lhs == rhs1 && cast(R) rhs1 == rhs;
+            }
+            else
+                return lhs == rhs;
+        }
+        else
+        {
+            bool error;
+            auto result = opChecked!"=="(lhs, rhs, error);
+            if (error)
+            {
+                // Only possible error is a wrong "true"
+                return false;
+            }
+            return result;
+        }
+    }
+
+    /**
+    Hook for `<`, `<=`, `>`, and `>=` that ensures comparison against integral
+    values has the behavior expected by the usual arithmetic rules. The built-in
+    semantics yield surprising behavior when comparing signed values against
+    unsigned values, for example $(D 0u < -1). The call $(D hookOpCmp(x, y))
+    returns `-1` if and only if `x` is smaller than `y` in abstract arithmetic
+    sense.
+
+    If one of the numbers is an integral and the other is a floating-point
+    number, $(D hookOpEquals(x, y)) returns a floating-point number that is `-1`
+    if `x < y`, `0` if `x == y`, `1` if `x > y`, and `NaN` if the floating-point
+    number is `NaN`.
+
+    Params:
+    lhs = The left-hand side of the comparison for ordering
+    rhs = The right-hand side of the comparison for ordering
+
+    Returns:
+    The result of the comparison (negative if $(D lhs < rhs), positive if $(D
+    lhs > rhs), `0` if the values are equal)
+    */
+    static auto hookOpCmp(L, R)(L lhs, R rhs)
+    {
+        alias C = typeof(lhs + rhs);
+        static if (isFloatingPoint!C)
+        {
+            return lhs < rhs
+                ? C(-1)
+                : lhs > rhs ? C(1) : lhs == rhs ? C(0) : C.init;
+        }
+        else
+        {
+            static if (!valueConvertible!(L, C) || !valueConvertible!(R, C))
+            {
+                static assert(isUnsigned!C);
+                static assert(isUnsigned!L != isUnsigned!R);
+                if (!isUnsigned!L && lhs < 0)
+                    return -1;
+                if (!isUnsigned!R && rhs < 0)
+                    return 1;
+            }
+            return lhs < rhs ? -1 : lhs > rhs;
+        }
+    }
+}
+
+///
+@safe unittest
+{
+    alias opEqualsProper = ProperCompare.hookOpEquals;
+    assert(opEqualsProper(42, 42));
+    assert(opEqualsProper(42.0, 42.0));
+    assert(opEqualsProper(42u, 42));
+    assert(opEqualsProper(42, 42u));
+    assert(-1 == 4294967295u);
+    assert(!opEqualsProper(-1, 4294967295u));
+    assert(!opEqualsProper(const uint(-1), -1));
+    assert(!opEqualsProper(uint(-1), -1.0));
+    assert(3_000_000_000U == -1_294_967_296);
+    assert(!opEqualsProper(3_000_000_000U, -1_294_967_296));
+}
+
+@safe unittest
+{
+    alias opCmpProper = ProperCompare.hookOpCmp;
+    assert(opCmpProper(42, 42) == 0);
+    assert(opCmpProper(42, 42.0) == 0);
+    assert(opCmpProper(41, 42.0) < 0);
+    assert(opCmpProper(42, 41.0) > 0);
+    import std.math.traits : isNaN;
+    assert(isNaN(opCmpProper(41, double.init)));
+    assert(opCmpProper(42u, 42) == 0);
+    assert(opCmpProper(42, 42u) == 0);
+    assert(opCmpProper(-1, uint(-1)) < 0);
+    assert(opCmpProper(uint(-1), -1) > 0);
+    assert(opCmpProper(-1.0, -1) == 0);
+}
+
+@safe unittest
+{
+    auto x1 = Checked!(uint, ProperCompare)(42u);
+    assert(x1.get < -1);
+    assert(x1 > -1);
+}
+
+// WithNaN
+/**
+
+Hook that reserves a special value as a "Not a Number" representative. For
+signed integrals, the reserved value is `T.min`. For signed integrals, the
+reserved value is `T.max`.
+
+The default value of a $(D Checked!(X, WithNaN)) is its NaN value, so care must
+be taken that all variables are explicitly initialized. Any arithmetic and logic
+operation involving at least on NaN becomes NaN itself. All of $(D a == b), $(D
+a < b), $(D a > b), $(D a <= b), $(D a >= b) yield `false` if at least one of
+`a` and `b` is NaN.
+
+*/
+struct WithNaN
+{
+static:
+    /**
+    The default value used for values not explicitly initialized. It is the NaN
+    value, i.e. `T.min` for signed integrals and `T.max` for unsigned integrals.
+    */
+    enum T defaultValue(T) = T.min == 0 ? T.max : T.min;
+    /**
+    The maximum value representable is `T.max` for signed integrals, $(D
+    T.max - 1) for unsigned integrals. The minimum value representable is $(D
+    T.min + 1) for signed integrals, `0` for unsigned integrals.
+    */
+    enum T max(T) = cast(T) (T.min == 0 ? T.max - 1 : T.max);
+    /// ditto
+    enum T min(T) = cast(T) (T.min == 0 ? T(0) : T.min + 1);
+
+    /**
+    If `rhs` is `WithNaN.defaultValue!Rhs`, returns
+    `WithNaN.defaultValue!Lhs`. Otherwise, returns $(D cast(Lhs) rhs).
+
+    Params:
+    rhs = the value being cast (`Rhs` is the first argument to `Checked`)
+    Lhs = the target type of the cast
+
+    Returns: The result of the cast operation.
+    */
+    Lhs hookOpCast(Lhs, Rhs)(Rhs rhs)
+    {
+        static if (is(Lhs == bool))
+        {
+            return rhs != defaultValue!Rhs && rhs != 0;
+        }
+        else static if (valueConvertible!(Rhs, Lhs))
+        {
+            return rhs != defaultValue!Rhs ? Lhs(rhs) : defaultValue!Lhs;
+        }
+        else
+        {
+            // Not value convertible, only viable option is rhs fits within the
+            // bounds of Lhs
+            static if (ProperCompare.hookOpCmp(Rhs.min, Lhs.min) < 0)
+            {
+                // Example: hookOpCast!short(int(42)), hookOpCast!uint(int(42))
+                if (ProperCompare.hookOpCmp(rhs, Lhs.min) < 0)
+                    return defaultValue!Lhs;
+            }
+            static if (ProperCompare.hookOpCmp(Rhs.max, Lhs.max) > 0)
+            {
+                // Example: hookOpCast!int(uint(42))
+                if (ProperCompare.hookOpCmp(rhs, Lhs.max) > 0)
+                    return defaultValue!Lhs;
+            }
+            return cast(Lhs) rhs;
+        }
+    }
+
+    ///
+    @safe unittest
+    {
+        auto x = checked!WithNaN(422);
+        assert((cast(ubyte) x) == 255);
+        x = checked!WithNaN(-422);
+        assert((cast(byte) x) == -128);
+        assert(cast(short) x == -422);
+        assert(cast(bool) x);
+        x = x.init; // set back to NaN
+        assert(x != true);
+        assert(x != false);
+    }
+
+    /**
+
+    Returns `false` if $(D lhs == WithNaN.defaultValue!Lhs), $(D lhs == rhs)
+    otherwise.
+
+    Params:
+    lhs = The left-hand side of the comparison (`Lhs` is the first argument to
+    `Checked`)
+    rhs = The right-hand side of the comparison
+
+    Returns: `lhs != WithNaN.defaultValue!Lhs && lhs == rhs`
+    */
+    bool hookOpEquals(Lhs, Rhs)(Lhs lhs, Rhs rhs)
+    {
+        return lhs != defaultValue!Lhs && lhs == rhs;
+    }
+
+    /**
+
+    If $(D lhs == WithNaN.defaultValue!Lhs), returns `double.init`. Otherwise,
+    has the same semantics as the default comparison.
+
+    Params:
+    lhs = The left-hand side of the comparison (`Lhs` is the first argument to
+    `Checked`)
+    rhs = The right-hand side of the comparison
+
+    Returns: `double.init` if `lhs == WitnNaN.defaultValue!Lhs`, `-1.0` if $(D
+    lhs < rhs), `0.0` if $(D lhs == rhs), `1.0` if $(D lhs > rhs).
+
+    */
+    double hookOpCmp(Lhs, Rhs)(Lhs lhs, Rhs rhs)
+    {
+        if (lhs == defaultValue!Lhs) return double.init;
+        return lhs < rhs
+            ? -1.0
+            : lhs > rhs ? 1.0 : lhs == rhs ? 0.0 : double.init;
+    }
+
+    ///
+    @safe unittest
+    {
+        Checked!(int, WithNaN) x;
+        assert(!(x < 0) && !(x > 0) && !(x == 0));
+        x = 1;
+        assert(x > 0 && !(x < 0) && !(x == 0));
+    }
+
+    /**
+    Defines hooks for unary operators `-`, `~`, `++`, and `--`.
+
+    For `-` and `~`, if $(D v == WithNaN.defaultValue!T), returns
+    `WithNaN.defaultValue!T`. Otherwise, the semantics is the same as for the
+    built-in operator.
+
+    For `++` and `--`, if $(D v == WithNaN.defaultValue!Lhs) or the operation
+    would result in an overflow, sets `v` to `WithNaN.defaultValue!T`.
+    Otherwise, the semantics is the same as for the built-in operator.
+
+    Params:
+    x = The operator symbol
+    v = The left-hand side of the comparison (`T` is the first argument to
+    `Checked`)
+
+    Returns: $(UL $(LI For $(D x == "-" || x == "~"): If  $(D v ==
+    WithNaN.defaultValue!T), the function returns `WithNaN.defaultValue!T`.
+    Otherwise it returns the normal result of the operator.) $(LI For $(D x ==
+    "++" || x == "--"): The function returns `void`.))
+
+    */
+    auto hookOpUnary(string x, T)(ref T v)
+    {
+        static if (x == "-" || x == "~")
+        {
+            return v != defaultValue!T ? mixin(x ~ "v") : v;
+        }
+        else static if (x == "++")
+        {
+            static if (defaultValue!T == T.min)
+            {
+                if (v != defaultValue!T)
+                {
+                    if (v == T.max) v = defaultValue!T;
+                    else ++v;
+                }
+            }
+            else
+            {
+                static assert(defaultValue!T == T.max);
+                if (v != defaultValue!T) ++v;
+            }
+        }
+        else static if (x == "--")
+        {
+            if (v != defaultValue!T) --v;
+        }
+    }
+
+    ///
+    @safe unittest
+    {
+        Checked!(int, WithNaN) x;
+        ++x;
+        assert(x.isNaN);
+        x = 1;
+        assert(!x.isNaN);
+        x = -x;
+        ++x;
+        assert(!x.isNaN);
+    }
+
+    @safe unittest // for coverage
+    {
+        Checked!(uint, WithNaN) y;
+        ++y;
+        assert(y.isNaN);
+    }
+
+    /**
+    Defines hooks for binary operators `+`, `-`, `*`, `/`, `%`, `^^`, `&`, `|`,
+     `^`, `<<`, `>>`, and `>>>` for cases where a `Checked` object is the
+    left-hand side operand. If $(D lhs == WithNaN.defaultValue!Lhs), returns
+    $(D WithNaN.defaultValue!(typeof(lhs + rhs))) without evaluating the
+    operand. Otherwise, evaluates the operand. If evaluation does not overflow,
+    returns the result. Otherwise, returns $(D WithNaN.defaultValue!(typeof(lhs +
+    rhs))).
+
+    Params:
+    x = The operator symbol
+    lhs = The left-hand side operand (`Lhs` is the first argument to `Checked`)
+    rhs = The right-hand side operand
+
+    Returns: If $(D lhs != WithNaN.defaultValue!Lhs) and the operator does not
+    overflow, the function returns the same result as the built-in operator. In
+    all other cases, returns $(D WithNaN.defaultValue!(typeof(lhs + rhs))).
+    */
+    auto hookOpBinary(string x, L, R)(L lhs, R rhs)
+    {
+        alias Result = typeof(lhs + rhs);
+        if (lhs != defaultValue!L)
+        {
+            bool error;
+            auto result = opChecked!x(lhs, rhs, error);
+            if (!error) return result;
+        }
+        return defaultValue!Result;
+    }
+
+    ///
+    @safe unittest
+    {
+        Checked!(int, WithNaN) x;
+        assert((x + 1).isNaN);
+        x = 100;
+        assert(!(x + 1).isNaN);
+    }
+
+    /**
+    Defines hooks for binary operators `+`, `-`, `*`, `/`, `%`, `^^`, `&`, `|`,
+     `^`, `<<`, `>>`, and `>>>` for cases where a `Checked` object is the
+    right-hand side operand. If $(D rhs == WithNaN.defaultValue!Rhs), returns
+    $(D WithNaN.defaultValue!(typeof(lhs + rhs))) without evaluating the
+    operand. Otherwise, evaluates the operand. If evaluation does not overflow,
+    returns the result. Otherwise, returns $(D WithNaN.defaultValue!(typeof(lhs +
+    rhs))).
+
+    Params:
+    x = The operator symbol
+    lhs = The left-hand side operand
+    rhs = The right-hand side operand (`Rhs` is the first argument to `Checked`)
+
+    Returns: If $(D rhs != WithNaN.defaultValue!Rhs) and the operator does not
+    overflow, the function returns the same result as the built-in operator. In
+    all other cases, returns $(D WithNaN.defaultValue!(typeof(lhs + rhs))).
+    */
+    auto hookOpBinaryRight(string x, L, R)(L lhs, R rhs)
+    {
+        alias Result = typeof(lhs + rhs);
+        if (rhs != defaultValue!R)
+        {
+            bool error;
+            auto result = opChecked!x(lhs, rhs, error);
+            if (!error) return result;
+        }
+        return defaultValue!Result;
+    }
+    ///
+    @safe unittest
+    {
+        Checked!(int, WithNaN) x;
+        assert((1 + x).isNaN);
+        x = 100;
+        assert(!(1 + x).isNaN);
+    }
+
+    /**
+
+    Defines hooks for binary operators `+=`, `-=`, `*=`, `/=`, `%=`, `^^=`,
+    `&=`, `|=`, `^=`, `<<=`, `>>=`, and `>>>=` for cases where a `Checked`
+    object is the left-hand side operand. If $(D lhs ==
+    WithNaN.defaultValue!Lhs), no action is carried. Otherwise, evaluates the
+    operand. If evaluation does not overflow and fits in `Lhs` without loss of
+    information or change of sign, sets `lhs` to the result. Otherwise, sets
+    `lhs` to `WithNaN.defaultValue!Lhs`.
+
+    Params:
+    x = The operator symbol (without the `=`)
+    lhs = The left-hand side operand (`Lhs` is the first argument to `Checked`)
+    rhs = The right-hand side operand
+
+    Returns: `void`
+    */
+    void hookOpOpAssign(string x, L, R)(ref L lhs, R rhs)
+    {
+        if (lhs == defaultValue!L)
+            return;
+        bool error;
+        auto temp = opChecked!x(lhs, rhs, error);
+        lhs = error
+            ? defaultValue!L
+            : hookOpCast!L(temp);
+    }
+
+    ///
+    @safe unittest
+    {
+        Checked!(int, WithNaN) x;
+        x += 4;
+        assert(x.isNaN);
+        x = 0;
+        x += 4;
+        assert(!x.isNaN);
+        x += int.max;
+        assert(x.isNaN);
+    }
+}
+
+///
+@safe unittest
+{
+    auto x1 = Checked!(int, WithNaN)();
+    assert(x1.isNaN);
+    assert(x1.get == int.min);
+    assert(x1 != x1);
+    assert(!(x1 < x1));
+    assert(!(x1 > x1));
+    assert(!(x1 == x1));
+    ++x1;
+    assert(x1.isNaN);
+    assert(x1.get == int.min);
+    --x1;
+    assert(x1.isNaN);
+    assert(x1.get == int.min);
+    x1 = 42;
+    assert(!x1.isNaN);
+    assert(x1 == x1);
+    assert(x1 <= x1);
+    assert(x1 >= x1);
+    static assert(x1.min == int.min + 1);
+    x1 += long(int.max);
+}
+
+/**
+Queries whether a $(D Checked!(T, WithNaN)) object is not a number (NaN).
+
+Params:
+    x = the `Checked` instance queried
+
+Returns:
+    `true` if `x` is a NaN, `false` otherwise
+*/
+bool isNaN(T)(const Checked!(T, WithNaN) x)
+{
+    return x.get == x.init.get;
+}
+
+///
+@safe unittest
+{
+    auto x1 = Checked!(int, WithNaN)();
+    assert(x1.isNaN);
+    x1 = 1;
+    assert(!x1.isNaN);
+    x1 = x1.init;
+    assert(x1.isNaN);
+}
+
+@safe unittest
+{
+    void test1(T)()
+    {
+        auto x1 = Checked!(T, WithNaN)();
+        assert(x1.isNaN);
+        assert(x1.get == int.min);
+        assert(x1 != x1);
+        assert(!(x1 < x1));
+        assert(!(x1 > x1));
+        assert(!(x1 == x1));
+        assert(x1.get == int.min);
+        auto x2 = Checked!(T, WithNaN)(42);
+        assert(!x2.isNaN);
+        assert(x2 == x2);
+        assert(x2 <= x2);
+        assert(x2 >= x2);
+        static assert(x2.min == T.min + 1);
+    }
+    test1!int;
+    test1!(const int);
+    test1!(immutable int);
+
+    void test2(T)()
+    {
+        auto x1 = Checked!(T, WithNaN)();
+        assert(x1.get == T.min);
+        assert(x1 != x1);
+        assert(!(x1 < x1));
+        assert(!(x1 > x1));
+        assert(!(x1 == x1));
+        ++x1;
+        assert(x1.get == T.min);
+        --x1;
+        assert(x1.get == T.min);
+        x1 = 42;
+        assert(x1 == x1);
+        assert(x1 <= x1);
+        assert(x1 >= x1);
+        static assert(x1.min == T.min + 1);
+        x1 += long(T.max);
+    }
+    test2!int;
+}
+
+@safe unittest
+{
+    alias Smart(T) = Checked!(Checked!(T, ProperCompare), WithNaN);
+    Smart!int x1;
+    assert(x1 != x1);
+    x1 = -1;
+    assert(x1 < 1u);
+    auto x2 = Smart!(const int)(42);
+}
+
+// Saturate
+/**
+
+Hook that implements $(I saturation), i.e. any arithmetic operation that would
+overflow leaves the result at its extreme value (`min` or `max` depending on the
+direction of the overflow).
+
+Saturation is not sticky; if a value reaches its saturation value, another
+operation may take it back to normal range.
+
+*/
+struct Saturate
+{
+static:
+    /**
+
+    Implements saturation for operators `+=`, `-=`, `*=`, `/=`, `%=`, `^^=`, `&=`, `|=`, `^=`, `<<=`, `>>=`,
+    and `>>>=`. This hook is called if the result of the binary operation does
+    not fit in `Lhs` without loss of information or a change in sign.
+
+    Params:
+    Rhs = The right-hand side type in the assignment, after the operation has
+    been computed
+    bound = The bound being violated
+
+    Returns: `Lhs.max` if $(D rhs >= 0), `Lhs.min` otherwise.
+
+    */
+    T onLowerBound(Rhs, T)(Rhs, T bound)
+    {
+        return bound;
+    }
+    /// ditto
+    T onUpperBound(Rhs, T)(Rhs, T bound)
+    {
+        return bound;
+    }
+    ///
+    @safe unittest
+    {
+        auto x = checked!Saturate(short(100));
+        x += 33000;
+        assert(x == short.max);
+        x -= 70000;
+        assert(x == short.min);
+    }
+
+    /**
+
+    Implements saturation for operators `+`, `-` (unary and binary), `*`, `/`,
+    `%`, `^^`, `&`, `|`, `^`, `<<`, `>>`, and `>>>`.
+
+    For unary `-`, `onOverflow` is called if $(D lhs == Lhs.min) and `Lhs` is a
+    signed type. The function returns `Lhs.max`.
+
+    For binary operators, the result is as follows: $(UL $(LI `Lhs.max` if the
+    result overflows in the positive direction, on division by `0`, or on
+    shifting right by a negative value) $(LI `Lhs.min` if the result overflows
+    in the negative direction) $(LI `0` if `lhs` is being shifted left by a
+    negative value, or shifted right by a large positive value))
+
+    Params:
+        x   = The operator involved in the `opAssign` operation
+        Lhs = The left-hand side type of the operator (`Lhs` is the first argument to
+              `Checked`)
+        Rhs = The right-hand side type in the operator
+
+    Returns: The saturated result of the operator.
+
+    */
+    auto onOverflow(string x, Lhs)(Lhs)
+    {
+        static assert(x == "-" || x == "++" || x == "--");
+        return x == "--" ? Lhs.min : Lhs.max;
+    }
+    /// ditto
+    typeof(Lhs() + Rhs()) onOverflow(string x, Lhs, Rhs)(Lhs lhs, Rhs rhs)
+    {
+        static if (x == "+")
+            return rhs >= 0 ? Lhs.max : Lhs.min;
+        else static if (x == "*")
+            return (lhs >= 0) == (rhs >= 0) ? Lhs.max : Lhs.min;
+        else static if (x == "^^")
+            return lhs > 0 || !(rhs & 1) ? Lhs.max : Lhs.min;
+        else static if (x == "-")
+            return rhs >= 0 ? Lhs.min : Lhs.max;
+        else static if (x == "/" || x == "%")
+            return Lhs.max;
+        else static if (x == "<<")
+            return rhs >= 0 ? Lhs.max : 0;
+        else static if (x == ">>" || x == ">>>")
+            return rhs >= 0 ? 0 : Lhs.max;
+        else
+            static assert(false);
+    }
+    ///
+    @safe unittest
+    {
+        assert(checked!Saturate(int.max) + 1 == int.max);
+        assert(checked!Saturate(100) ^^ 10 == int.max);
+        assert(checked!Saturate(-100) ^^ 10 == int.max);
+        assert(checked!Saturate(100) / 0 == int.max);
+        assert(checked!Saturate(100) << -1 == 0);
+        assert(checked!Saturate(100) << 33 == int.max);
+        assert(checked!Saturate(100) >> -1 == int.max);
+        assert(checked!Saturate(100) >> 33 == 0);
+    }
+}
+
+///
+@safe unittest
+{
+    auto x = checked!Saturate(int.max);
+    ++x;
+    assert(x == int.max);
+    --x;
+    assert(x == int.max - 1);
+    x = int.min;
+    assert(-x == int.max);
+    x -= 42;
+    assert(x == int.min);
+    assert(x * -2 == int.max);
+}
+
+/*
+Yields `true` if `T1` is "value convertible" (by C's "value preserving" rule,
+see $(HTTP c-faq.com/expr/preservingrules.html)) to `T2`, where the two are
+integral types. That is, all of values in `T1` are also in `T2`. For example
+`int` is value convertible to `long` but not to `uint` or `ulong`.
+*/
+private enum valueConvertible(T1, T2) = isIntegral!T1 && isIntegral!T2 &&
+    is(T1 : T2) && (
+        isUnsigned!T1 == isUnsigned!T2 || // same signedness
+        !isUnsigned!T2 && T2.sizeof > T1.sizeof // safely convertible
+    );
+
+/**
+
+Defines binary operations with overflow checking for any two integral types.
+The result type obeys the language rules (even when they may be
+counterintuitive), and `overflow` is set if an overflow occurs (including
+inadvertent change of signedness, e.g. `-1` is converted to `uint`).
+Conceptually the behavior is:
+
+$(OL $(LI Perform the operation in infinite precision)
+$(LI If the infinite-precision result fits in the result type, return it and
+do not touch `overflow`)
+$(LI Otherwise, set `overflow` to `true` and return an unspecified value)
+)
+
+The implementation exploits properties of types and operations to minimize
+additional work.
+
+Params:
+x = The binary operator involved, e.g. `/`
+lhs = The left-hand side of the operator
+rhs = The right-hand side of the operator
+overflow = The overflow indicator (assigned `true` in case there's an error)
+
+Returns:
+The result of the operation, which is the same as the built-in operator
+*/
+typeof(mixin(x == "cmp" ? "0" : ("L() " ~ x ~ " R()")))
+opChecked(string x, L, R)(const L lhs, const R rhs, ref bool overflow)
+if (isIntegral!L && isIntegral!R)
+{
+    static if (x == "cmp")
+        alias Result = int;
+    else
+        alias Result = typeof(mixin("L() " ~ x ~ " R()"));
+
+    import core.checkedint : addu, adds, subs, muls, subu, mulu;
+    import std.algorithm.comparison : among;
+    static if (x == "==")
+    {
+        alias C = typeof(lhs + rhs);
+        static if (valueConvertible!(L, C) && valueConvertible!(R, C))
+        {
+            // Values are converted to R before comparison, cool.
+            return lhs == rhs;
+        }
+        else
+        {
+            static assert(isUnsigned!C);
+            static assert(isUnsigned!L != isUnsigned!R);
+            if (lhs != rhs) return false;
+            // R(lhs) and R(rhs) have the same bit pattern, yet may be
+            // different due to signedness change.
+            static if (!isUnsigned!R)
+            {
+                if (rhs >= 0)
+                    return true;
+            }
+            else
+            {
+                if (lhs >= 0)
+                    return true;
+            }
+            overflow = true;
+            return true;
+        }
+    }
+    else static if (x == "cmp")
+    {
+        alias C = typeof(lhs + rhs);
+        static if (!valueConvertible!(L, C) || !valueConvertible!(R, C))
+        {
+            static assert(isUnsigned!C);
+            static assert(isUnsigned!L != isUnsigned!R);
+            if (!isUnsigned!L && lhs < 0)
+            {
+                overflow = true;
+                return -1;
+            }
+            if (!isUnsigned!R && rhs < 0)
+            {
+                overflow = true;
+                return 1;
+            }
+        }
+        return lhs < rhs ? -1 : lhs > rhs;
+    }
+    else static if (x.among("<<", ">>", ">>>"))
+    {
+        // Handle shift separately from all others. The test below covers
+        // negative rhs as well.
+        import std.conv : unsigned;
+        if (unsigned(rhs) > 8 * Result.sizeof) goto fail;
+        return mixin("lhs" ~ x ~ "rhs");
+    }
+    else static if (x.among("&", "|", "^"))
+    {
+        // Nothing to check
+        return mixin("lhs" ~ x ~ "rhs");
+    }
+    else static if (x == "^^")
+    {
+        // Exponentiation is weird, handle separately
+        return pow(lhs, rhs, overflow);
+    }
+    else static if (valueConvertible!(L, Result) &&
+            valueConvertible!(R, Result))
+    {
+        static if (L.sizeof < Result.sizeof && R.sizeof < Result.sizeof &&
+            x.among("+", "-", "*"))
+        {
+            // No checks - both are value converted and result is in range
+            return mixin("lhs" ~ x ~ "rhs");
+        }
+        else static if (x == "+")
+        {
+            static if (isUnsigned!Result) alias impl = addu;
+            else alias impl = adds;
+            return impl(Result(lhs), Result(rhs), overflow);
+        }
+        else static if (x == "-")
+        {
+            static if (isUnsigned!Result) alias impl = subu;
+            else alias impl = subs;
+            return impl(Result(lhs), Result(rhs), overflow);
+        }
+        else static if (x == "*")
+        {
+            static if (!isUnsigned!L && !isUnsigned!R &&
+                is(L == Result))
+            {
+                if (lhs == Result.min && rhs == -1) goto fail;
+            }
+            static if (isUnsigned!Result) alias impl = mulu;
+            else alias impl = muls;
+            return impl(Result(lhs), Result(rhs), overflow);
+        }
+        else static if (x == "/" || x == "%")
+        {
+            static if (!isUnsigned!L && !isUnsigned!R &&
+                is(L == Result) && x == "/")
+            {
+                if (lhs == Result.min && rhs == -1) goto fail;
+            }
+            if (rhs == 0) goto fail;
+            return mixin("lhs" ~ x ~ "rhs");
+        }
+        else static assert(0, x);
+    }
+    else // Mixed signs
+    {
+        static assert(isUnsigned!Result);
+        static assert(isUnsigned!L != isUnsigned!R);
+        static if (x == "+")
+        {
+            static if (!isUnsigned!L)
+            {
+                if (lhs < 0)
+                    return subu(Result(rhs), Result(-lhs), overflow);
+            }
+            else static if (!isUnsigned!R)
+            {
+                if (rhs < 0)
+                    return subu(Result(lhs), Result(-rhs), overflow);
+            }
+            return addu(Result(lhs), Result(rhs), overflow);
+        }
+        else static if (x == "-")
+        {
+            static if (!isUnsigned!L)
+            {
+                if (lhs < 0) goto fail;
+            }
+            else static if (!isUnsigned!R)
+            {
+                if (rhs < 0)
+                    return addu(Result(lhs), Result(-rhs), overflow);
+            }
+            return subu(Result(lhs), Result(rhs), overflow);
+        }
+        else static if (x == "*")
+        {
+            static if (!isUnsigned!L)
+            {
+                if (lhs < 0) goto fail;
+            }
+            else static if (!isUnsigned!R)
+            {
+                if (rhs < 0) goto fail;
+            }
+            return mulu(Result(lhs), Result(rhs), overflow);
+        }
+        else static if (x == "/" || x == "%")
+        {
+            static if (!isUnsigned!L)
+            {
+                if (lhs < 0 || rhs == 0) goto fail;
+            }
+            else static if (!isUnsigned!R)
+            {
+                if (rhs <= 0) goto fail;
+            }
+            return mixin("Result(lhs)" ~ x ~ "Result(rhs)");
+        }
+        else static assert(0, x);
+    }
+    debug assert(false);
+fail:
+    overflow = true;
+    return Result(0);
+}
+
+///
+@safe unittest
+{
+    bool overflow;
+    assert(opChecked!"+"(const short(1), short(1), overflow) == 2 && !overflow);
+    assert(opChecked!"+"(1, 1, overflow) == 2 && !overflow);
+    assert(opChecked!"+"(1, 1u, overflow) == 2 && !overflow);
+    assert(opChecked!"+"(-1, 1u, overflow) == 0 && !overflow);
+    assert(opChecked!"+"(1u, -1, overflow) == 0 && !overflow);
+}
+
+///
+@safe unittest
+{
+    bool overflow;
+    assert(opChecked!"-"(1, 1, overflow) == 0 && !overflow);
+    assert(opChecked!"-"(1, 1u, overflow) == 0 && !overflow);
+    assert(opChecked!"-"(1u, -1, overflow) == 2 && !overflow);
+    assert(opChecked!"-"(-1, 1u, overflow) == 0 && overflow);
+}
+
+@safe unittest
+{
+    bool overflow;
+    assert(opChecked!"*"(2, 3, overflow) == 6 && !overflow);
+    assert(opChecked!"*"(2, 3u, overflow) == 6 && !overflow);
+    assert(opChecked!"*"(1u, -1, overflow) == 0 && overflow);
+    //assert(mul(-1, 1u, overflow) == uint.max - 1 && overflow);
+}
+
+@safe unittest
+{
+    bool overflow;
+    assert(opChecked!"/"(6, 3, overflow) == 2 && !overflow);
+    assert(opChecked!"/"(6, 3, overflow) == 2 && !overflow);
+    assert(opChecked!"/"(6u, 3, overflow) == 2 && !overflow);
+    assert(opChecked!"/"(6, 3u, overflow) == 2 && !overflow);
+    assert(opChecked!"/"(11, 0, overflow) == 0 && overflow);
+    overflow = false;
+    assert(opChecked!"/"(6u, 0, overflow) == 0 && overflow);
+    overflow = false;
+    assert(opChecked!"/"(-6, 2u, overflow) == 0 && overflow);
+    overflow = false;
+    assert(opChecked!"/"(-6, 0u, overflow) == 0 && overflow);
+    overflow = false;
+    assert(opChecked!"cmp"(0u, -6, overflow) == 1 && overflow);
+    overflow = false;
+    assert(opChecked!"|"(1, 2, overflow) == 3 && !overflow);
+}
+
+/*
+Exponentiation function used by the implementation of operator `^^`.
+*/
+private pure @safe nothrow @nogc
+auto pow(L, R)(const L lhs, const R rhs, ref bool overflow)
+if (isIntegral!L && isIntegral!R)
+{
+    if (rhs <= 1)
+    {
+        if (rhs == 0) return 1;
+        static if (!isUnsigned!R)
+            return rhs == 1
+                ? lhs
+                : (rhs == -1 && (lhs == 1 || lhs == -1)) ? lhs : 0;
+        else
+            return lhs;
+    }
+
+    typeof(lhs ^^ rhs) b = void;
+    static if (!isUnsigned!L && isUnsigned!(typeof(b)))
+    {
+        // Need to worry about mixed-sign stuff
+        if (lhs < 0)
+        {
+            if (rhs & 1)
+            {
+                if (lhs < 0) overflow = true;
+                return 0;
+            }
+            b = -lhs;
+        }
+        else
+        {
+            b = lhs;
+        }
+    }
+    else
+    {
+        b = lhs;
+    }
+    if (b == 1) return 1;
+    if (b == -1) return (rhs & 1) ? -1 : 1;
+    if (rhs > 63)
+    {
+        overflow = true;
+        return 0;
+    }
+
+    assert((b > 1 || b < -1) && rhs > 1);
+    return powImpl(b, cast(uint) rhs, overflow);
+}
+
+// Inspiration: http://www.stepanovpapers.com/PAM.pdf
+pure @safe nothrow @nogc
+private T powImpl(T)(T b, uint e, ref bool overflow)
+if (isIntegral!T && T.sizeof >= 4)
+{
+    assert(e > 1);
+
+    import core.checkedint : muls, mulu;
+    static if (isUnsigned!T) alias mul = mulu;
+    else alias mul = muls;
+
+    T r = b;
+    --e;
+    // Loop invariant: r * (b ^^ e) is the actual result
+    for (;; e /= 2)
+    {
+        if (e % 2)
+        {
+            r = mul(r, b, overflow);
+            if (e == 1) break;
+        }
+        b = mul(b, b, overflow);
+    }
+    return r;
+}
+
+@safe unittest
+{
+    static void testPow(T)(T x, uint e)
+    {
+        bool overflow;
+        assert(opChecked!"^^"(T(0), 0, overflow) == 1);
+        assert(opChecked!"^^"(-2, T(0), overflow) == 1);
+        assert(opChecked!"^^"(-2, T(1), overflow) == -2);
+        assert(opChecked!"^^"(-1, -1, overflow) == -1);
+        assert(opChecked!"^^"(-2, 1, overflow) == -2);
+        assert(opChecked!"^^"(-2, -1, overflow) == 0);
+        assert(opChecked!"^^"(-2, 4u, overflow) == 16);
+        assert(!overflow);
+        assert(opChecked!"^^"(-2, 3u, overflow) == 0);
+        assert(overflow);
+        overflow = false;
+        assert(opChecked!"^^"(3, 64u, overflow) == 0);
+        assert(overflow);
+        overflow = false;
+        foreach (uint i; 0 .. e)
+        {
+            assert(opChecked!"^^"(x, i, overflow) == x ^^ i);
+            assert(!overflow);
+        }
+        assert(opChecked!"^^"(x, e, overflow) == x ^^ e);
+        assert(overflow);
+    }
+
+    testPow!int(3, 21);
+    testPow!uint(3, 21);
+    testPow!long(3, 40);
+    testPow!ulong(3, 41);
+}
+
+version (StdUnittest) private struct CountOverflows
+{
+    uint calls;
+    auto onOverflow(string op, Lhs)(Lhs lhs)
+    {
+        ++calls;
+        return mixin(op ~ "lhs");
+    }
+    auto onOverflow(string op, Lhs, Rhs)(Lhs lhs, Rhs rhs)
+    {
+        ++calls;
+        return mixin("lhs" ~ op ~ "rhs");
+    }
+    T onLowerBound(Rhs, T)(Rhs rhs, T)
+    {
+        ++calls;
+        return cast(T) rhs;
+    }
+    T onUpperBound(Rhs, T)(Rhs rhs, T)
+    {
+        ++calls;
+        return cast(T) rhs;
+    }
+}
+
+// opBinary
+@nogc nothrow pure @safe unittest
+{
+    static struct CountOpBinary
+    {
+        uint calls;
+        auto hookOpBinary(string op, Lhs, Rhs)(Lhs lhs, Rhs rhs)
+        {
+            ++calls;
+            return mixin("lhs" ~ op ~ "rhs");
+        }
+    }
+    auto x = Checked!(const int, void)(42), y = Checked!(immutable int, void)(142);
+    assert(x + y == 184);
+    assert(x + 100 == 142);
+    assert(y - x == 100);
+    assert(200 - x == 158);
+    assert(y * x == 142 * 42);
+    assert(x / 1 == 42);
+    assert(x % 20 == 2);
+
+    auto x1 = Checked!(int, CountOverflows)(42);
+    assert(x1 + 0 == 42);
+    assert(x1 + false == 42);
+    assert(is(typeof(x1 + 0.5) == double));
+    assert(x1 + 0.5 == 42.5);
+    assert(x1.hook.calls == 0);
+    assert(x1 + int.max == int.max + 42);
+    assert(x1.hook.calls == 1);
+    assert(x1 * 2 == 84);
+    assert(x1.hook.calls == 1);
+    assert(x1 / 2 == 21);
+    assert(x1.hook.calls == 1);
+    assert(x1 % 20 == 2);
+    assert(x1.hook.calls == 1);
+    assert(x1 << 2 == 42 << 2);
+    assert(x1.hook.calls == 1);
+    assert(x1 << 42 == x1.get << x1.get);
+    assert(x1.hook.calls == 2);
+    x1 = int.min;
+    assert(x1 - 1 == int.max);
+    assert(x1.hook.calls == 3);
+
+    auto x2 = Checked!(int, CountOpBinary)(42);
+    assert(x2 + 1 == 43);
+    assert(x2.hook.calls == 1);
+
+    auto x3 = Checked!(uint, CountOverflows)(42u);
+    assert(x3 + 1 == 43);
+    assert(x3.hook.calls == 0);
+    assert(x3 - 1 == 41);
+    assert(x3.hook.calls == 0);
+    assert(x3 + (-42) == 0);
+    assert(x3.hook.calls == 0);
+    assert(x3 - (-42) == 84);
+    assert(x3.hook.calls == 0);
+    assert(x3 * 2 == 84);
+    assert(x3.hook.calls == 0);
+    assert(x3 * -2 == -84);
+    assert(x3.hook.calls == 1);
+    assert(x3 / 2 == 21);
+    assert(x3.hook.calls == 1);
+    assert(x3 / -2 == 0);
+    assert(x3.hook.calls == 2);
+    assert(x3 ^^ 2 == 42 * 42);
+    assert(x3.hook.calls == 2);
+
+    auto x4 = Checked!(int, CountOverflows)(42);
+    assert(x4 + 1 == 43);
+    assert(x4.hook.calls == 0);
+    assert(x4 + 1u == 43);
+    assert(x4.hook.calls == 0);
+    assert(x4 - 1 == 41);
+    assert(x4.hook.calls == 0);
+    assert(x4 * 2 == 84);
+    assert(x4.hook.calls == 0);
+    x4 = -2;
+    assert(x4 + 2u == 0);
+    assert(x4.hook.calls == 0);
+    assert(x4 * 2u == -4);
+    assert(x4.hook.calls == 1);
+
+    auto x5 = Checked!(int, CountOverflows)(3);
+    assert(x5 ^^ 0 == 1);
+    assert(x5 ^^ 1 == 3);
+    assert(x5 ^^ 2 == 9);
+    assert(x5 ^^ 3 == 27);
+    assert(x5 ^^ 4 == 81);
+    assert(x5 ^^ 5 == 81 * 3);
+    assert(x5 ^^ 6 == 81 * 9);
+}
+
+// opBinaryRight
+@nogc nothrow pure @safe unittest
+{
+    auto x1 = Checked!(int, CountOverflows)(42);
+    assert(1 + x1 == 43);
+    assert(true + x1 == 43);
+    assert(0.5 + x1 == 42.5);
+    auto x2 = Checked!(int, void)(42);
+    assert(x1 + x2 == 84);
+    assert(x2 + x1   == 84);
+}
+
+// opOpAssign
+@safe unittest
+{
+    auto x1 = Checked!(int, CountOverflows)(3);
+    assert((x1 += 2) == 5);
+    x1 *= 2_000_000_000L;
+    assert(x1.hook.calls == 1);
+    x1 *= -2_000_000_000L;
+    assert(x1.hook.calls == 2);
+
+    auto x2 = Checked!(ushort, CountOverflows)(ushort(3));
+    assert((x2 += 2) == 5);
+    assert(x2.hook.calls == 0);
+    assert((x2 += ushort.max) == cast(ushort) (ushort(5) + ushort.max));
+    assert(x2.hook.calls == 1);
+
+    auto x3 = Checked!(uint, CountOverflows)(3u);
+    x3 *= ulong(2_000_000_000);
+    assert(x3.hook.calls == 1);
+}
+
+// opAssign
+@safe unittest
+{
+    Checked!(int, void) x;
+    x = 42;
+    assert(x.get == 42);
+    x = x;
+    assert(x.get == 42);
+    x = short(43);
+    assert(x.get == 43);
+    x = ushort(44);
+    assert(x.get == 44);
+}
+
+@safe unittest
+{
+    static assert(!is(typeof(Checked!(short, void)(ushort(42)))));
+    static assert(!is(typeof(Checked!(int, void)(long(42)))));
+    static assert(!is(typeof(Checked!(int, void)(ulong(42)))));
+    assert(Checked!(short, void)(short(42)).get == 42);
+    assert(Checked!(int, void)(ushort(42)).get == 42);
+}
+
+// opCast
+@nogc nothrow pure @safe unittest
+{
+    static assert(is(typeof(cast(float) Checked!(int, void)(42)) == float));
+    assert(cast(float) Checked!(int, void)(42) == 42);
+
+    assert(is(typeof(cast(long) Checked!(int, void)(42)) == long));
+    assert(cast(long) Checked!(int, void)(42) == 42);
+    static assert(is(typeof(cast(long) Checked!(uint, void)(42u)) == long));
+    assert(cast(long) Checked!(uint, void)(42u) == 42);
+
+    auto x = Checked!(int, void)(42);
+    if (x) {} else assert(0);
+    x = 0;
+    if (x) assert(0);
+
+    static struct Hook1
+    {
+        uint calls;
+        Dst hookOpCast(Dst, Src)(Src value)
+        {
+            ++calls;
+            return 42;
+        }
+    }
+    auto y = Checked!(long, Hook1)(long.max);
+    assert(cast(int) y == 42);
+    assert(cast(uint) y == 42);
+    assert(y.hook.calls == 2);
+
+    static struct Hook2
+    {
+        uint calls;
+        Dst onBadCast(Dst, Src)(Src value)
+        {
+            ++calls;
+            return 42;
+        }
+    }
+    auto x1 = Checked!(uint, Hook2)(100u);
+    assert(cast(ushort) x1 == 100);
+    assert(cast(short) x1 == 100);
+    assert(cast(float) x1 == 100);
+    assert(cast(double) x1 == 100);
+    assert(cast(real) x1 == 100);
+    assert(x1.hook.calls == 0);
+    assert(cast(int) x1 == 100);
+    assert(x1.hook.calls == 0);
+    x1 = uint.max;
+    assert(cast(int) x1 == 42);
+    assert(x1.hook.calls == 1);
+
+    auto x2 = Checked!(int, Hook2)(-100);
+    assert(cast(short) x2 == -100);
+    assert(cast(ushort) x2 == 42);
+    assert(cast(uint) x2 == 42);
+    assert(cast(ulong) x2 == 42);
+    assert(x2.hook.calls == 3);
+}
+
+// opEquals
+@nogc nothrow pure @safe unittest
+{
+    assert(Checked!(int, void)(42) == 42L);
+    assert(42UL == Checked!(int, void)(42));
+
+    static struct Hook1
+    {
+        uint calls;
+        bool hookOpEquals(Lhs, Rhs)(const Lhs lhs, const Rhs rhs)
+        {
+            ++calls;
+            return lhs != rhs;
+        }
+    }
+    auto x1 = Checked!(int, Hook1)(100);
+    assert(x1 != Checked!(long, Hook1)(100));
+    assert(x1.hook.calls == 1);
+    assert(x1 != 100u);
+    assert(x1.hook.calls == 2);
+
+    static struct Hook2
+    {
+        uint calls;
+        bool hookOpEquals(Lhs, Rhs)(Lhs lhs, Rhs rhs)
+        {
+            ++calls;
+            return false;
+        }
+    }
+    auto x2 = Checked!(int, Hook2)(-100);
+    assert(x2 != x1);
+    // For coverage: lhs has no hookOpEquals, rhs does
+    assert(Checked!(uint, void)(100u) != x2);
+    // For coverage: different types, neither has a hookOpEquals
+    assert(Checked!(uint, void)(100u) == Checked!(int, void*)(100));
+    assert(x2.hook.calls == 0);
+    assert(x2 != -100);
+    assert(x2.hook.calls == 1);
+    assert(x2 != cast(uint) -100);
+    assert(x2.hook.calls == 2);
+    x2 = 100;
+    assert(x2 != cast(uint) 100);
+    assert(x2.hook.calls == 3);
+    x2 = -100;
+
+    auto x3 = Checked!(uint, Hook2)(100u);
+    assert(x3 != 100);
+    x3 = uint.max;
+    assert(x3 != -1);
+
+    assert(x2 != x3);
+}
+
+// opCmp
+@nogc nothrow pure @safe unittest
+{
+    Checked!(int, void) x;
+    assert(x <= x);
+    assert(x < 45);
+    assert(x < 45u);
+    assert(x > -45);
+    assert(x < 44.2);
+    assert(x > -44.2);
+    assert(!(x < double.init));
+    assert(!(x > double.init));
+    assert(!(x <= double.init));
+    assert(!(x >= double.init));
+
+    static struct Hook1
+    {
+        uint calls;
+        int hookOpCmp(Lhs, Rhs)(Lhs lhs, Rhs rhs)
+        {
+            ++calls;
+            return 0;
+        }
+    }
+    auto x1 = Checked!(int, Hook1)(42);
+    assert(!(x1 < 43u));
+    assert(!(43u < x1));
+    assert(x1.hook.calls == 2);
+
+    static struct Hook2
+    {
+        uint calls;
+        int hookOpCmp(Lhs, Rhs)(Lhs lhs, Rhs rhs)
+        {
+            ++calls;
+            return ProperCompare.hookOpCmp(lhs, rhs);
+        }
+    }
+    auto x2 = Checked!(int, Hook2)(-42);
+    assert(x2 < 43u);
+    assert(43u > x2);
+    assert(x2.hook.calls == 2);
+    x2 = 42;
+    assert(x2 > 41u);
+
+    auto x3 = Checked!(uint, Hook2)(42u);
+    assert(x3 > 41);
+    assert(x3 > -41);
+}
+
+// opUnary
+@nogc nothrow pure @safe unittest
+{
+    auto x = Checked!(int, void)(42);
+    assert(x == +x);
+    static assert(is(typeof(-x) == typeof(x)));
+    assert(-x == Checked!(int, void)(-42));
+    static assert(is(typeof(~x) == typeof(x)));
+    assert(~x == Checked!(int, void)(~42));
+    assert(++x == 43);
+    assert(--x == 42);
+
+    static struct Hook1
+    {
+        uint calls;
+        auto hookOpUnary(string op, T)(T value) if (op == "-")
+        {
+            ++calls;
+            return T(42);
+        }
+        auto hookOpUnary(string op, T)(T value) if (op == "~")
+        {
+            ++calls;
+            return T(43);
+        }
+    }
+    auto x1 = Checked!(int, Hook1)(100);
+    assert(is(typeof(-x1) == typeof(x1)));
+    assert(-x1 == Checked!(int, Hook1)(42));
+    assert(is(typeof(~x1) == typeof(x1)));
+    assert(~x1 == Checked!(int, Hook1)(43));
+    assert(x1.hook.calls == 2);
+
+    static struct Hook2
+    {
+        uint calls;
+        void hookOpUnary(string op, T)(ref T value) if (op == "++")
+        {
+            ++calls;
+            --value;
+        }
+        void hookOpUnary(string op, T)(ref T value) if (op == "--")
+        {
+            ++calls;
+            ++value;
+        }
+    }
+    auto x2 = Checked!(int, Hook2)(100);
+    assert(++x2 == 99);
+    assert(x2 == 99);
+    assert(--x2 == 100);
+    assert(x2 == 100);
+
+    auto x3 = Checked!(int, CountOverflows)(int.max - 1);
+    assert(++x3 == int.max);
+    assert(x3.hook.calls == 0);
+    assert(++x3 == int.min);
+    assert(x3.hook.calls == 1);
+    assert(-x3 == int.min);
+    assert(x3.hook.calls == 2);
+
+    x3 = int.min + 1;
+    assert(--x3 == int.min);
+    assert(x3.hook.calls == 2);
+    assert(--x3 == int.max);
+    assert(x3.hook.calls == 3);
+}
+
+//
+@nogc nothrow pure @safe unittest
+{
+    Checked!(int, void) x;
+    assert(x == x);
+    assert(x == +x);
+    assert(x == -x);
+    ++x;
+    assert(x == 1);
+    x++;
+    assert(x == 2);
+
+    x = 42;
+    assert(x == 42);
+    const short _short = 43;
+    x = _short;
+    assert(x == _short);
+    ushort _ushort = 44;
+    x = _ushort;
+    assert(x == _ushort);
+    assert(x == 44.0);
+    assert(x != 44.1);
+    assert(x < 45);
+    assert(x < 44.2);
+    assert(x > -45);
+    assert(x > -44.2);
+
+    assert(cast(long) x == 44);
+    assert(cast(short) x == 44);
+
+    const Checked!(uint, void) y;
+    assert(y <= y);
+    assert(y == 0);
+    assert(y < x);
+    x = -1;
+    assert(x > y);
+}
+
+@nogc nothrow pure @safe unittest
+{
+    alias cint = Checked!(int, void);
+    cint a = 1, b = 2;
+    a += b;
+    assert(a == cint(3));
+
+    alias ccint = Checked!(cint, Saturate);
+    ccint c = 14;
+    a += c;
+    assert(a == cint(17));
+}
+
+// toHash
+@safe unittest
+{
+    assert(checked(42).toHash() == checked(42).toHash());
+    assert(checked(12).toHash() != checked(19).toHash());
+
+    static struct Hook1
+    {
+        static size_t hookToHash(T)(T payload) nothrow @trusted
+        {
+            static if (size_t.sizeof == 4)
+            {
+                return typeid(payload).getHash(&payload) ^ 0xFFFF_FFFF;
+            }
+            else
+            {
+                return typeid(payload).getHash(&payload) ^ 0xFFFF_FFFF_FFFF_FFFF;
+            }
+
+        }
+    }
+
+    auto a = checked!Hook1(78);
+    auto b = checked!Hook1(78);
+    assert(a.toHash() == b.toHash());
+
+    assert(checked!Hook1(12).toHash() != checked!Hook1(13).toHash());
+
+    static struct Hook2
+    {
+        static if (size_t.sizeof == 4)
+        {
+            static size_t hashMask = 0xFFFF_0000;
+        }
+        else
+        {
+            static size_t hashMask = 0xFFFF_0000_FFFF_0000;
+        }
+
+        static size_t hookToHash(T)(T payload) nothrow @trusted
+        {
+            return typeid(payload).getHash(&payload) ^ hashMask;
+        }
+    }
+
+    auto x = checked!Hook2(1901);
+    auto y = checked!Hook2(1989);
+
+    assert((() nothrow @safe => x.toHash() == x.toHash())());
+
+    assert(x.toHash() == x.toHash());
+    assert(x.toHash() != y.toHash());
+    assert(checked!Hook1(1901).toHash() != x.toHash());
+
+    immutable z = checked!Hook1(1901);
+    immutable t = checked!Hook1(1901);
+    immutable w = checked!Hook2(1901);
+
+    assert(z.toHash() == t.toHash());
+    assert(z.toHash() != x.toHash());
+    assert(z.toHash() != w.toHash());
+
+    const long c = 0xF0F0F0F0;
+    const long d = 0xF0F0F0F0;
+
+    assert(checked!Hook1(c).toHash() != checked!Hook2(c));
+    assert(checked!Hook1(c).toHash() != checked!Hook1(d));
+
+    // Hook with state, does not implement hookToHash
+    static struct Hook3
+    {
+        ulong var1 = ulong.max;
+        uint var2 = uint.max;
+    }
+
+    assert(checked!Hook3(12).toHash() != checked!Hook3(13).toHash());
+    assert(checked!Hook3(13).toHash() == checked!Hook3(13).toHash());
+
+    // Hook with no state and no hookToHash, payload has its own hashing function
+    auto x1 = Checked!(Checked!int, ProperCompare)(123);
+    auto x2 = Checked!(Checked!int, ProperCompare)(123);
+    auto x3 = Checked!(Checked!int, ProperCompare)(144);
+
+    assert(x1.toHash() == x2.toHash());
+    assert(x1.toHash() != x3.toHash());
+    assert(x2.toHash() != x3.toHash());
+
+    // Check shared.
+    {
+        shared shared0 = checked(12345678);
+        shared shared1 = checked!Hook1(123456789);
+        shared shared2 = checked!Hook2(234567891);
+        shared shared3 = checked!Hook3(345678912);
+        assert(shared0.toHash() == hashOf(shared0));
+        assert(shared1.toHash() == hashOf(shared1));
+        assert(shared2.toHash() == hashOf(shared2));
+        assert(shared3.toHash() == hashOf(shared3));
+    }
+}
+
+///
+@safe unittest
+{
+    struct MyHook
+    {
+        static size_t hookToHash(T)(const T payload) nothrow @trusted
+        {
+            return .hashOf(payload);
+        }
+    }
+
+    int[Checked!(int, MyHook)] aa;
+    Checked!(int, MyHook) var = 42;
+    aa[var] = 100;
+
+    assert(aa[var] == 100);
+
+    int[Checked!(int, Abort)] bb;
+    Checked!(int, Abort) var2 = 42;
+    bb[var2] = 100;
+
+    assert(bb[var2] == 100);
+}
diff --git a/libphobos/src/std/complex.d b/libphobos/src/std/complex.d
index 756d1ca..485b548 100644
--- a/libphobos/src/std/complex.d
+++ b/libphobos/src/std/complex.d
@@ -1015,6 +1015,14 @@
 @safe pure nothrow @nogc unittest
 {
     static import std.math;
+
+    int ceqrel(T)(const Complex!T x, const Complex!T y) @safe pure nothrow @nogc
+    {
+        import std.math.operations : feqrel;
+        const r = feqrel(x.re, y.re);
+        const i = feqrel(x.im, y.im);
+        return r < i ? r : i;
+    }
     assert(ceqrel(tan(complex(1.0, 0.0)), complex(std.math.tan(1.0), 0.0)) >= double.mant_dig - 2);
     assert(ceqrel(tan(complex(0.0, 1.0)), complex(0.0, std.math.tanh(1.0))) >= double.mant_dig - 2);
 }
@@ -1705,14 +1713,11 @@
     auto b = log10(complex(0.0, 1.0)) * 2.0;
     auto c = log10(complex(sqrt(2.0) / 2, sqrt(2.0) / 2)) * 4.0;
     assert(isClose(b, c, 0.0, 1e-15));
-
-    assert(ceqrel(log10(complex(-100.0L, 0.0L)), complex(2.0L, PI / LN10)) >= real.mant_dig - 1);
-    assert(ceqrel(log10(complex(-100.0L, -0.0L)), complex(2.0L, -PI / LN10)) >= real.mant_dig - 1);
 }
 
 @safe pure nothrow @nogc unittest
 {
-    import std.math.constants : PI;
+    import std.math.constants : LN10, PI;
     import std.math.operations : isClose;
 
     auto a = log10(fromPolar(1.0, PI / 6.0));
@@ -1732,6 +1737,9 @@
 
     auto f = log10(complex(-1.0L, 0.0L));
     assert(isClose(f, complex(0.0L, 1.36437635384184134748L), 0.0, 1e-15));
+
+    assert(ceqrel(log10(complex(-100.0L, 0.0L)), complex(2.0L, PI / LN10)) >= real.mant_dig - 1);
+    assert(ceqrel(log10(complex(-100.0L, -0.0L)), complex(2.0L, -PI / LN10)) >= real.mant_dig - 1);
 }
 
 /**
@@ -1771,9 +1779,6 @@
     assert(pow(a, 3) == a * a * a);
     assert(pow(a, -2) == 1.0 / (a * a));
     assert(isClose(pow(a, -3), 1.0 / (a * a * a)));
-
-    auto b = complex(2.0);
-    assert(ceqrel(pow(b, 3), exp(3 * log(b))) >= double.mant_dig - 1);
 }
 
 /// ditto
@@ -1865,6 +1870,9 @@
 
     auto d = pow(PI, complex(2.0, -1.0));
     assert(ceqrel(d, complex(4.0790296880118296, -8.9872469554541869)) >= double.mant_dig - 1);
+
+    auto e = complex(2.0);
+    assert(ceqrel(pow(e, 3), exp(3 * log(e))) >= double.mant_dig - 1);
 }
 
 @safe pure nothrow @nogc unittest
diff --git a/libphobos/src/std/conv.d b/libphobos/src/std/conv.d
index 98df7fd..a10f4da 100644
--- a/libphobos/src/std/conv.d
+++ b/libphobos/src/std/conv.d
@@ -50,9 +50,9 @@
 public import std.ascii : LetterCase;
 
 import std.meta;
-import std.range.primitives;
+import std.range;
 import std.traits;
-import std.typecons : Flag, Yes, No, tuple;
+import std.typecons : Flag, Yes, No, tuple, isTuple;
 
 // Same as std.string.format, but "self-importing".
 // Helps reduce code and imports, particularly in static asserts.
@@ -653,6 +653,32 @@
     }}
 }
 
+// https://issues.dlang.org/show_bug.cgi?id=13551
+private T toImpl(T, S)(S value)
+if (isTuple!T)
+{
+    T t;
+    static foreach (i; 0 .. T.length)
+    {
+        t[i] = value[i].to!(typeof(T[i]));
+    }
+    return t;
+}
+
+@safe unittest
+{
+    import std.typecons : Tuple;
+
+    auto test = ["10", "20", "30"];
+    assert(test.to!(Tuple!(int, int, int)) == Tuple!(int, int, int)(10, 20, 30));
+
+    auto test1 = [1, 2];
+    assert(test1.to!(Tuple!(int, int)) == Tuple!(int, int)(1, 2));
+
+    auto test2 = [1.0, 2.0, 3.0];
+    assert(test2.to!(Tuple!(int, int, int)) == Tuple!(int, int, int)(1, 2, 3));
+}
+
 /*
   Converting static arrays forwards to their dynamic counterparts.
  */
@@ -1970,7 +1996,7 @@
 
 /// ditto
 private T toImpl(T, S)(S value, uint radix)
-if (isInputRange!S && !isInfinite!S && isSomeChar!(ElementEncodingType!S) &&
+if (isSomeFiniteCharInputRange!S &&
     isIntegral!T && is(typeof(parse!T(value, radix))))
 {
     scope(success)
diff --git a/libphobos/src/std/experimental/allocator/package.d b/libphobos/src/std/experimental/allocator/package.d
index 2804829..62f848f 100644
--- a/libphobos/src/std/experimental/allocator/package.d
+++ b/libphobos/src/std/experimental/allocator/package.d
@@ -3735,7 +3735,13 @@
             Ternary r = (() @nogc => a.resolveInternalPointer(&b[0], p))();
             assert(&p[0] == &b[0] && p.length >= b.length);
             r = a.resolveInternalPointer((() @trusted => &b[0] + b.length)(), p);
-            assert(&p[0] == &b[0] && p.length >= b.length);
+
+            /* This line randomly fails on MacOS 12.x x64
+             * https://issues.dlang.org/show_bug.cgi?id=22660
+             * Commenting it out until someone can fix it.
+             */
+            //assert(&p[0] == &b[0] && p.length >= b.length);
+
             r = a.resolveInternalPointer((() @trusted => &b[0] + b.length / 2)(), p);
             assert(&p[0] == &b[0] && p.length >= b.length);
             auto bogus = new void[b.length];
diff --git a/libphobos/src/std/experimental/checkedint.d b/libphobos/src/std/experimental/checkedint.d
index 354851b..9237341 100644
--- a/libphobos/src/std/experimental/checkedint.d
+++ b/libphobos/src/std/experimental/checkedint.d
@@ -1,3467 +1,14 @@
-// Written in the D programming language.
-/**
-$(SCRIPT inhibitQuickIndex = 1;)
-
-This module defines facilities for efficient checking of integral operations
-against overflow, casting with loss of precision, unexpected change of sign,
-etc. The checking (and possibly correction) can be done at operation level, for
-example $(LREF opChecked)$(D !"+"(x, y, overflow)) adds two integrals `x` and
-`y` and sets `overflow` to `true` if an overflow occurred. The flag `overflow`
-(a `bool` passed by reference) is not touched if the operation succeeded, so the
-same flag can be reused for a sequence of operations and tested at the end.
-
-Issuing individual checked operations is flexible and efficient but often
-tedious. The $(LREF Checked) facility offers encapsulated integral wrappers that
-do all checking internally and have configurable behavior upon erroneous
-results. For example, `Checked!int` is a type that behaves like `int` but aborts
-execution immediately whenever involved in an operation that produces the
-arithmetically wrong result. The accompanying convenience function $(LREF
-checked) uses type deduction to convert a value `x` of integral type `T` to
-`Checked!T` by means of `checked(x)`. For example:
-
----
-void main()
-{
-    import std.experimental.checkedint, std.stdio;
-    writeln((checked(5) + 7).get); // 12
-    writeln((checked(10) * 1000 * 1000 * 1000).get); // Overflow
-}
----
-
-Similarly, $(D checked(-1) > uint(0)) aborts execution (even though the built-in
-comparison $(D int(-1) > uint(0)) is surprisingly true due to language's
-conversion rules modeled after C). Thus, `Checked!int` is a virtually drop-in
-replacement for `int` useable in debug builds, to be replaced by `int` in
-release mode if efficiency demands it.
-
-`Checked`  has customizable behavior with the help of a second type parameter,
-`Hook`. Depending on what methods `Hook` defines, core operations on the
-underlying integral may be verified for overflow or completely redefined. If
-`Hook` defines no method at all and carries no state, there is no change in
-behavior, i.e. $(D Checked!(int, void)) is a wrapper around `int` that adds no
-customization at all.
-
-This module provides a few predefined hooks (below) that add useful behavior to
-`Checked`:
-
-$(BOOKTABLE ,
-    $(TR $(TD $(LREF Abort)) $(TD
-        fails every incorrect operation with a message to $(REF
-        stderr, std, stdio) followed by a call to `assert(0)`. It is the default
-        second parameter, i.e. `Checked!short` is the same as
-        $(D Checked!(short, Abort)).
-    ))
-    $(TR $(TD $(LREF Throw)) $(TD
-        fails every incorrect operation by throwing an exception.
-    ))
-    $(TR $(TD $(LREF Warn)) $(TD
-        prints incorrect operations to $(REF stderr, std, stdio)
-        but otherwise preserves the built-in behavior.
-    ))
-    $(TR $(TD $(LREF ProperCompare)) $(TD
-        fixes the comparison operators `==`, `!=`, `<`, `<=`, `>`, and `>=`
-        to return correct results in all circumstances,
-        at a slight cost in efficiency. For example,
-        $(D Checked!(uint, ProperCompare)(1) > -1) is `true`,
-        which is not the case for the built-in comparison. Also, comparing
-        numbers for equality with floating-point numbers only passes if the
-        integral can be converted to the floating-point number precisely,
-        so as to preserve transitivity of equality.
-    ))
-    $(TR $(TD $(LREF WithNaN)) $(TD
-        reserves a special "Not a Number" (NaN) value akin to the homonym value
-        reserved for floating-point values. Once a $(D Checked!(X, WithNaN))
-        gets this special value, it preserves and propagates it until
-        reassigned. $(LREF isNaN) can be used to query whether the object
-        is not a number.
-    ))
-    $(TR $(TD $(LREF Saturate)) $(TD
-        implements saturating arithmetic, i.e. $(D Checked!(int, Saturate))
-        "stops" at `int.max` for all operations that would cause an `int` to
-        overflow toward infinity, and at `int.min` for all operations that would
-        correspondingly overflow toward negative infinity.
-    ))
-)
-
-
-These policies may be used alone, e.g. $(D Checked!(uint, WithNaN)) defines a
-`uint`-like type that reaches a stable NaN state for all erroneous operations.
-They may also be "stacked" on top of each other, owing to the property that a
-checked integral emulates an actual integral, which means another checked
-integral can be built on top of it. Some combinations of interest include:
-
-$(BOOKTABLE ,
-    $(TR $(TD $(D Checked!(Checked!int, ProperCompare))))
-    $(TR $(TD
-defines an `int` with fixed
-comparison operators that will fail with `assert(0)` upon overflow. (Recall that
-`Abort` is the default policy.) The order in which policies are combined is
-important because the outermost policy (`ProperCompare` in this case) has the
-first crack at intercepting an operator. The converse combination $(D
-Checked!(Checked!(int, ProperCompare))) is meaningless because `Abort` will
-intercept comparison and will fail without giving `ProperCompare` a chance to
-intervene.
-    ))
-    $(TR $(TD))
-    $(TR $(TDNW $(D Checked!(Checked!(int, ProperCompare), WithNaN))))
-    $(TR $(TD
-defines an `int`-like
-type that supports a NaN value. For values that are not NaN, comparison works
-properly. Again the composition order is important; $(D Checked!(Checked!(int,
-WithNaN), ProperCompare)) does not have good semantics because `ProperCompare`
-intercepts comparisons before the numbers involved are tested for NaN.
-    ))
-)
-
-The hook's members are looked up statically in a Design by Introspection manner
-and are all optional. The table below illustrates the members that a hook type
-may define and their influence over the behavior of the `Checked` type using it.
-In the table, `hook` is an alias for `Hook` if the type `Hook` does not
-introduce any state, or an object of type `Hook` otherwise.
-
-$(TABLE ,
-$(TR $(TH `Hook` member) $(TH Semantics in $(D Checked!(T, Hook)))
-)
-$(TR $(TD `defaultValue`) $(TD If defined, `Hook.defaultValue!T` is used as the
-default initializer of the payload.)
-)
-$(TR $(TD `min`) $(TD If defined, `Hook.min!T` is used as the minimum value of
-the payload.)
-)
-$(TR $(TD `max`) $(TD If defined, `Hook.max!T` is used as the maximum value of
-the payload.)
-)
-$(TR $(TD `hookOpCast`) $(TD If defined, `hook.hookOpCast!U(get)` is forwarded
-to unconditionally when the payload is to be cast to type `U`.)
-)
-$(TR $(TD `onBadCast`) $(TD If defined and `hookOpCast` is $(I not) defined,
-`onBadCast!U(get)` is forwarded to when the payload is to be cast to type `U`
-and the cast would lose information or force a change of sign.)
-)
-$(TR $(TD `hookOpEquals`) $(TD If defined, $(D hook.hookOpEquals(get, rhs)) is
-forwarded to unconditionally when the payload is compared for equality against
-value `rhs` of integral, floating point, or Boolean type.)
-)
-$(TR $(TD `hookOpCmp`) $(TD If defined, $(D hook.hookOpCmp(get, rhs)) is
-forwarded to unconditionally when the payload is compared for ordering against
-value `rhs` of integral, floating point, or Boolean type.)
-)
-$(TR $(TD `hookOpUnary`) $(TD If defined, `hook.hookOpUnary!op(get)` (where `op`
-is the operator symbol) is forwarded to for unary operators `-` and `~`. In
-addition, for unary operators `++` and `--`, `hook.hookOpUnary!op(payload)` is
-called, where `payload` is a reference to the value wrapped by `Checked` so the
-hook can change it.)
-)
-$(TR $(TD `hookOpBinary`) $(TD If defined, $(D hook.hookOpBinary!op(get, rhs))
-(where `op` is the operator symbol and `rhs` is the right-hand side operand) is
-forwarded to unconditionally for binary operators `+`,  `-`, `*`, `/`, `%`,
-`^^`, `&`, `|`, `^`, `<<`, `>>`, and `>>>`.)
-)
-$(TR $(TD `hookOpBinaryRight`) $(TD If defined, $(D
-hook.hookOpBinaryRight!op(lhs, get)) (where `op` is the operator symbol and
-`lhs` is the left-hand side operand) is forwarded to unconditionally for binary
-operators `+`,  `-`, `*`, `/`, `%`, `^^`, `&`, `|`, `^`, `<<`, `>>`, and `>>>`.)
-)
-$(TR $(TD `onOverflow`) $(TD If defined, `hook.onOverflow!op(get)` is forwarded
-to for unary operators that overflow but only if `hookOpUnary` is not defined.
-Unary `~` does not overflow; unary `-` overflows only when the most negative
-value of a signed type is negated, and the result of the hook call is returned.
-When the increment or decrement operators overflow, the payload is assigned the
-result of `hook.onOverflow!op(get)`. When a binary operator overflows, the
-result of $(D hook.onOverflow!op(get, rhs)) is returned, but only if `Hook` does
-not define `hookOpBinary`.)
-)
-$(TR $(TD `hookOpOpAssign`) $(TD If defined, $(D hook.hookOpOpAssign!op(payload,
-rhs)) (where `op` is the operator symbol and `rhs` is the right-hand side
-operand) is forwarded to unconditionally for binary operators `+=`,  `-=`, `*=`, `/=`, `%=`,
-`^^=`, `&=`, `|=`, `^=`, `<<=`, `>>=`, and `>>>=`.)
-)
-$(TR $(TD `onLowerBound`) $(TD If defined, $(D hook.onLowerBound(value, bound))
-(where `value` is the value being assigned) is forwarded to when the result of
-binary operators `+=`,  `-=`, `*=`, `/=`, `%=`, `^^=`, `&=`, `|=`, `^=`, `<<=`, `>>=`,
-and `>>>=` is smaller than the smallest value representable by `T`.)
-)
-$(TR $(TD `onUpperBound`) $(TD If defined, $(D hook.onUpperBound(value, bound))
-(where `value` is the value being assigned) is forwarded to when the result of
-binary operators `+=`,  `-=`, `*=`, `/=`, `%=`, `^^=`, `&=`, `|=`, `^=`, `<<=`, `>>=`,
-and `>>>=` is larger than the largest value representable by `T`.)
-)
-$(TR $(TD `hookToHash`) $(TD If defined, $(D hook.hookToHash(payload))
-(where `payload` is a reference to the value wrapped by Checked) is forwarded
-to when `toHash` is called on a Checked type. Custom hashing can be implemented
-in a `Hook`, otherwise the built-in hashing is used.)
-)
-)
-
-Source: $(PHOBOSSRC std/experimental/checkedint.d)
-*/
-module std.experimental.checkedint;
-import std.traits : isFloatingPoint, isIntegral, isNumeric, isUnsigned, Unqual;
-
-///
-@safe unittest
-{
-    int[] concatAndAdd(int[] a, int[] b, int offset)
-    {
-        // Aborts on overflow on size computation
-        auto r = new int[(checked(a.length) + b.length).get];
-        // Aborts on overflow on element computation
-        foreach (i; 0 .. a.length)
-            r[i] = (a[i] + checked(offset)).get;
-        foreach (i; 0 .. b.length)
-            r[i + a.length] = (b[i] + checked(offset)).get;
-        return r;
-    }
-    assert(concatAndAdd([1, 2, 3], [4, 5], -1) == [0, 1, 2, 3, 4]);
-}
-
-
-/// `Saturate` stops at an overflow
-@safe unittest
-{
-    auto x = (cast(byte) 127).checked!Saturate;
-    assert(x == 127);
-    x++;
-    assert(x == 127);
-}
-
-/// `WithNaN` has a special "Not a Number" (NaN) value akin to the homonym value reserved for floating-point values
-@safe unittest
-{
-    auto x = 100.checked!WithNaN;
-    assert(x == 100);
-    x /= 0;
-    assert(x.isNaN);
-}
-
-/// `ProperCompare` fixes the comparison operators ==, !=, <, <=, >, and >= to return correct results
-@safe unittest
-{
-    uint x = 1;
-    auto y = x.checked!ProperCompare;
-    assert(x < -1); // built-in comparison
-    assert(y > -1); // ProperCompare
-}
-
-/// `Throw` fails every incorrect operation by throwing an exception
-@safe unittest
-{
-    import std.exception : assertThrown;
-    auto x = -1.checked!Throw;
-    assertThrown(x / 0);
-    assertThrown(x + int.min);
-    assertThrown(x == uint.max);
-}
 
 /**
-Checked integral type wraps an integral `T` and customizes its behavior with the
-help of a `Hook` type. The type wrapped must be one of the predefined integrals
-(unqualified), or another instance of `Checked`.
-*/
-struct Checked(T, Hook = Abort)
-if (isIntegral!T || is(T == Checked!(U, H), U, H))
-{
-    import std.algorithm.comparison : among;
-    import std.experimental.allocator.common : stateSize;
-    import std.format.spec : FormatSpec;
-    import std.range.primitives : isInputRange, ElementType;
-    import std.traits : hasMember, isSomeChar;
-
-    /**
-    The type of the integral subject to checking.
-    */
-    alias Representation = T;
-
-    // state {
-    static if (hasMember!(Hook, "defaultValue"))
-        private T payload = Hook.defaultValue!T;
-    else
-        private T payload;
-    /**
-    `hook` is a member variable if it has state, or an alias for `Hook`
-    otherwise.
-    */
-    static if (stateSize!Hook > 0) Hook hook;
-    else alias hook = Hook;
-    // } state
-
-    // get
-    /**
-    Returns a copy of the underlying value.
-    */
-    auto get() inout { return payload; }
-    ///
-    @safe unittest
-    {
-        auto x = checked(ubyte(42));
-        static assert(is(typeof(x.get()) == ubyte));
-        assert(x.get == 42);
-        const y = checked(ubyte(42));
-        static assert(is(typeof(y.get()) == const ubyte));
-        assert(y.get == 42);
-    }
-
-    /**
-    Defines the minimum and maximum. These values are hookable by defining
-    `Hook.min` and/or `Hook.max`.
-    */
-    static if (hasMember!(Hook, "min"))
-    {
-        enum Checked!(T, Hook) min = Checked!(T, Hook)(Hook.min!T);
-        ///
-        @safe unittest
-        {
-            assert(Checked!short.min == -32768);
-            assert(Checked!(short, WithNaN).min == -32767);
-            assert(Checked!(uint, WithNaN).max == uint.max - 1);
-        }
-    }
-    else
-        enum Checked!(T, Hook) min = Checked(T.min);
-    /// ditto
-    static if (hasMember!(Hook, "max"))
-        enum Checked!(T, Hook) max = Checked(Hook.max!T);
-    else
-        enum Checked!(T, Hook) max = Checked(T.max);
-
-    /**
-    Constructor taking a value properly convertible to the underlying type. `U`
-    may be either an integral that can be converted to `T` without a loss, or
-    another `Checked` instance whose representation may be in turn converted to
-    `T` without a loss.
-    */
-    this(U)(U rhs)
-    if (valueConvertible!(U, T) ||
-        !isIntegral!T && is(typeof(T(rhs))) ||
-        is(U == Checked!(V, W), V, W) &&
-            is(typeof(Checked!(T, Hook)(rhs.get))))
-    {
-        static if (isIntegral!U)
-            payload = rhs;
-        else
-            payload = rhs.payload;
-    }
-    ///
-    @safe unittest
-    {
-        auto a = checked(42L);
-        assert(a == 42);
-        auto b = Checked!long(4242); // convert 4242 to long
-        assert(b == 4242);
-    }
-
-    /**
-    Assignment operator. Has the same constraints as the constructor.
-    */
-    ref Checked opAssign(U)(U rhs) return
-    if (is(typeof(Checked!(T, Hook)(rhs))))
-    {
-        static if (isIntegral!U)
-            payload = rhs;
-        else
-            payload = rhs.payload;
-        return this;
-    }
-    ///
-    @safe unittest
-    {
-        Checked!long a;
-        a = 42L;
-        assert(a == 42);
-        a = 4242;
-        assert(a == 4242);
-    }
-
-    ///
-    @safe unittest
-    {
-        Checked!long a, b;
-        a = b = 3;
-        assert(a == 3 && b == 3);
-    }
-
-    /**
-    Construct from a decimal string. The conversion follows the same rules as
-    $(REF to, std, conv) converting a string to the wrapped `T` type.
-
-    Params:
-        str = an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
-              of characters
-    */
-    this(Range)(Range str)
-    if (isInputRange!Range && isSomeChar!(ElementType!Range))
-    {
-        import std.conv : to;
-
-        this(to!T(str));
-    }
-
-    /**
-    $(REF to, std, conv) can convert a string to a `Checked!T`:
-    */
-    @system unittest
-    {
-        import std.conv : to;
-
-        const a = to!long("1234");
-        const b = to!(Checked!long)("1234");
-        assert(a == b);
-    }
-
-    // opCast
-    /**
-    Casting operator to integral, `bool`, or floating point type. If `Hook`
-    defines `hookOpCast`, the call immediately returns
-    `hook.hookOpCast!U(get)`. Otherwise, casting to `bool` yields $(D
-    get != 0) and casting to another integral that can represent all
-    values of `T` returns `get` promoted to `U`.
-
-    If a cast to a floating-point type is requested and `Hook` defines
-    `onBadCast`, the cast is verified by ensuring $(D get == cast(T)
-    U(get)). If that is not `true`, `hook.onBadCast!U(get)` is returned.
-
-    If a cast to an integral type is requested and `Hook` defines `onBadCast`,
-    the cast is verified by ensuring `get` and $(D cast(U)
-    get) are the same arithmetic number. (Note that `int(-1)` and
-    `uint(1)` are different values arithmetically although they have the same
-    bitwise representation and compare equal by language rules.) If the numbers
-    are not arithmetically equal, `hook.onBadCast!U(get)` is
-    returned.
-
-    */
-    U opCast(U, this _)()
-    if (isIntegral!U || isFloatingPoint!U || is(U == bool))
-    {
-        static if (hasMember!(Hook, "hookOpCast"))
-        {
-            return hook.hookOpCast!U(payload);
-        }
-        else static if (is(U == bool))
-        {
-            return payload != 0;
-        }
-        else static if (valueConvertible!(T, U))
-        {
-            return payload;
-        }
-        // may lose bits or precision
-        else static if (!hasMember!(Hook, "onBadCast"))
-        {
-            return cast(U) payload;
-        }
-        else
-        {
-            if (isUnsigned!T || !isUnsigned!U ||
-                    T.sizeof > U.sizeof || payload >= 0)
-            {
-                auto result = cast(U) payload;
-                // If signedness is different, we need additional checks
-                if (result == payload &&
-                        (!isUnsigned!T || isUnsigned!U || result >= 0))
-                    return result;
-            }
-            return hook.onBadCast!U(payload);
-        }
-    }
-    ///
-    @safe unittest
-    {
-        assert(cast(uint) checked(42) == 42);
-        assert(cast(uint) checked!WithNaN(-42) == uint.max);
-    }
-
-    // opEquals
-    /**
-    Compares `this` against `rhs` for equality. If `Hook` defines
-    `hookOpEquals`, the function forwards to $(D
-    hook.hookOpEquals(get, rhs)). Otherwise, the result of the
-    built-in operation $(D get == rhs) is returned.
-
-    If `U` is also an instance of `Checked`, both hooks (left- and right-hand
-    side) are introspected for the method `hookOpEquals`. If both define it,
-    priority is given to the left-hand side.
-
-    */
-    bool opEquals(U, this _)(U rhs)
-    if (isIntegral!U || isFloatingPoint!U || is(U == bool) ||
-        is(U == Checked!(V, W), V, W) && is(typeof(this == rhs.payload)))
-    {
-        static if (is(U == Checked!(V, W), V, W))
-        {
-            alias R = typeof(payload + rhs.payload);
-            static if (is(Hook == W))
-            {
-                // Use the lhs hook if there
-                return this == rhs.payload;
-            }
-            else static if (valueConvertible!(T, R) && valueConvertible!(V, R))
-            {
-                return payload == rhs.payload;
-            }
-            else static if (hasMember!(Hook, "hookOpEquals"))
-            {
-                return hook.hookOpEquals(payload, rhs.payload);
-            }
-            else static if (hasMember!(W, "hookOpEquals"))
-            {
-                return rhs.hook.hookOpEquals(rhs.payload, payload);
-            }
-            else
-            {
-                return payload == rhs.payload;
-            }
-        }
-        else static if (hasMember!(Hook, "hookOpEquals"))
-            return hook.hookOpEquals(payload, rhs);
-        else static if (isIntegral!U || isFloatingPoint!U || is(U == bool))
-            return payload == rhs;
-    }
-
-    ///
-    static if (is(T == int) && is(Hook == void)) @safe unittest
-    {
-        import std.traits : isUnsigned;
-
-        static struct MyHook
-        {
-            static bool thereWereErrors;
-            static bool hookOpEquals(L, R)(L lhs, R rhs)
-            {
-                if (lhs != rhs) return false;
-                static if (isUnsigned!L && !isUnsigned!R)
-                {
-                    if (lhs > 0 && rhs < 0) thereWereErrors = true;
-                }
-                else static if (isUnsigned!R && !isUnsigned!L)
-                    if (lhs < 0 && rhs > 0) thereWereErrors = true;
-                // Preserve built-in behavior.
-                return true;
-            }
-        }
-        auto a = checked!MyHook(-42);
-        assert(a == uint(-42));
-        assert(MyHook.thereWereErrors);
-        MyHook.thereWereErrors = false;
-        assert(checked!MyHook(uint(-42)) == -42);
-        assert(MyHook.thereWereErrors);
-        static struct MyHook2
-        {
-            static bool hookOpEquals(L, R)(L lhs, R rhs)
-            {
-                return lhs == rhs;
-            }
-        }
-        MyHook.thereWereErrors = false;
-        assert(checked!MyHook2(uint(-42)) == a);
-        // Hook on left hand side takes precedence, so no errors
-        assert(!MyHook.thereWereErrors);
-    }
-
-    // toHash
-    /**
-    Generates a hash for `this`. If `Hook` defines `hookToHash`, the call
-    immediately returns `hook.hookToHash(payload)`. If `Hook` does not
-    implement `hookToHash`, but it has state, a hash will be generated for
-    the `Hook` using the built-in function and it will be xored with the
-    hash of the `payload`.
-    */
-    size_t toHash() const nothrow @safe
-    {
-        static if (hasMember!(Hook, "hookToHash"))
-        {
-            return hook.hookToHash(payload);
-        }
-        else static if (stateSize!Hook > 0)
-        {
-            static if (hasMember!(typeof(payload), "toHash"))
-            {
-                return payload.toHash() ^ hashOf(hook);
-            }
-            else
-            {
-                return hashOf(payload) ^ hashOf(hook);
-            }
-        }
-        else static if (hasMember!(typeof(payload), "toHash"))
-        {
-            return payload.toHash();
-        }
-        else
-        {
-            return .hashOf(payload);
-        }
-    }
-
-    /// ditto
-    size_t toHash(this _)() shared const nothrow @safe
-    {
-        import core.atomic : atomicLoad, MemoryOrder;
-        static if (is(typeof(this.payload.atomicLoad!(MemoryOrder.acq)) P))
-        {
-            auto payload = __ctfe ? cast(P) this.payload
-                                  : this.payload.atomicLoad!(MemoryOrder.acq);
-        }
-        else
-        {
-            alias payload = this.payload;
-        }
-
-        static if (hasMember!(Hook, "hookToHash"))
-        {
-            return hook.hookToHash(payload);
-        }
-        else static if (stateSize!Hook > 0)
-        {
-            static if (hasMember!(typeof(payload), "toHash"))
-            {
-                return payload.toHash() ^ hashOf(hook);
-            }
-            else
-            {
-                return hashOf(payload) ^ hashOf(hook);
-            }
-        }
-        else static if (hasMember!(typeof(payload), "toHash"))
-        {
-            return payload.toHash();
-        }
-        else
-        {
-            return .hashOf(payload);
-        }
-    }
-
-    /**
-    Writes a string representation of this to a `sink`.
-
-    Params:
-      sink = A `Char` accepting
-             $(REF_ALTTEXT output range, isOutputRange, std,range,primitives).
-      fmt  = A $(REF FormatSpec, std, format) which controls how this
-             is formatted.
-    */
-    void toString(Writer, Char)(scope ref Writer sink, scope const ref FormatSpec!Char fmt) const
-    {
-        import std.format.write : formatValue;
-        if (fmt.spec == 's')
-            return formatValue(sink, this, fmt);
-        else
-            return formatValue(sink, payload, fmt);
-    }
-
-    /**
-    `toString` is rarely directly invoked; the usual way of using it is via
-    $(REF format, std, format):
-    */
-    @system unittest
-    {
-        import std.format;
-
-        assert(format("%04d", checked(15)) == "0015");
-        assert(format("0x%02x", checked(15)) == "0x0f");
-    }
-
-    // opCmp
-    /**
-
-    Compares `this` against `rhs` for ordering. If `Hook` defines `hookOpCmp`,
-    the function forwards to $(D hook.hookOpCmp(get, rhs)). Otherwise, the
-    result of the built-in comparison operation is returned.
-
-    If `U` is also an instance of `Checked`, both hooks (left- and right-hand
-    side) are introspected for the method `hookOpCmp`. If both define it,
-    priority is given to the left-hand side.
-
-    */
-    auto opCmp(U, this _)(const U rhs) //const pure @safe nothrow @nogc
-    if (isIntegral!U || isFloatingPoint!U || is(U == bool))
-    {
-        static if (hasMember!(Hook, "hookOpCmp"))
-        {
-            return hook.hookOpCmp(payload, rhs);
-        }
-        else static if (valueConvertible!(T, U) || valueConvertible!(U, T))
-        {
-            return payload < rhs ? -1 : payload > rhs;
-        }
-        else static if (isFloatingPoint!U)
-        {
-            U lhs = payload;
-            return lhs < rhs ? U(-1.0)
-                : lhs > rhs ? U(1.0)
-                : lhs == rhs ? U(0.0) : U.init;
-        }
-        else
-        {
-            return payload < rhs ? -1 : payload > rhs;
-        }
-    }
-
-    /// ditto
-    auto opCmp(U, Hook1, this _)(Checked!(U, Hook1) rhs)
-    {
-        alias R = typeof(payload + rhs.payload);
-        static if (valueConvertible!(T, R) && valueConvertible!(U, R))
-        {
-            return payload < rhs.payload ? -1 : payload > rhs.payload;
-        }
-        else static if (is(Hook == Hook1))
-        {
-            // Use the lhs hook
-            return this.opCmp(rhs.payload);
-        }
-        else static if (hasMember!(Hook, "hookOpCmp"))
-        {
-            return hook.hookOpCmp(get, rhs.get);
-        }
-        else static if (hasMember!(Hook1, "hookOpCmp"))
-        {
-            return -rhs.hook.hookOpCmp(rhs.payload, get);
-        }
-        else
-        {
-            return payload < rhs.payload ? -1 : payload > rhs.payload;
-        }
-    }
-
-    ///
-    static if (is(T == int) && is(Hook == void)) @safe unittest
-    {
-        import std.traits : isUnsigned;
-
-        static struct MyHook
-        {
-            static bool thereWereErrors;
-            static int hookOpCmp(L, R)(L lhs, R rhs)
-            {
-                static if (isUnsigned!L && !isUnsigned!R)
-                {
-                    if (rhs < 0 && rhs >= lhs)
-                        thereWereErrors = true;
-                }
-                else static if (isUnsigned!R && !isUnsigned!L)
-                {
-                    if (lhs < 0 && lhs >= rhs)
-                        thereWereErrors = true;
-                }
-                // Preserve built-in behavior.
-                return lhs < rhs ? -1 : lhs > rhs;
-            }
-        }
-        auto a = checked!MyHook(-42);
-        assert(a > uint(42));
-        assert(MyHook.thereWereErrors);
-        static struct MyHook2
-        {
-            static int hookOpCmp(L, R)(L lhs, R rhs)
-            {
-                // Default behavior
-                return lhs < rhs ? -1 : lhs > rhs;
-            }
-        }
-        MyHook.thereWereErrors = false;
-        assert(Checked!(uint, MyHook2)(uint(-42)) <= a);
-        //assert(Checked!(uint, MyHook2)(uint(-42)) >= a);
-        // Hook on left hand side takes precedence, so no errors
-        assert(!MyHook.thereWereErrors);
-        assert(a <= Checked!(uint, MyHook2)(uint(-42)));
-        assert(MyHook.thereWereErrors);
-    }
-
-    // For coverage
-    static if (is(T == int) && is(Hook == void)) @safe unittest
-    {
-        assert(checked(42) <= checked!void(42));
-        assert(checked!void(42) <= checked(42u));
-        assert(checked!void(42) <= checked!(void*)(42u));
-    }
-
-    // opUnary
-    /**
-
-    Defines unary operators `+`, `-`, `~`, `++`, and `--`. Unary `+` is not
-    overridable and always has built-in behavior (returns `this`). For the
-    others, if `Hook` defines `hookOpUnary`, `opUnary` forwards to $(D
-    Checked!(typeof(hook.hookOpUnary!op(get)),
-    Hook)(hook.hookOpUnary!op(get))).
-
-    If `Hook` does not define `hookOpUnary` but defines `onOverflow`, `opUnary`
-    forwards to `hook.onOverflow!op(get)` in case an overflow occurs.
-    For `++` and `--`, the payload is assigned from the result of the call to
-    `onOverflow`.
-
-    Note that unary `-` is considered to overflow if `T` is a signed integral of
-    32 or 64 bits and is equal to the most negative value. This is because that
-    value has no positive negation.
-
-    */
-    auto opUnary(string op, this _)()
-    if (op == "+" || op == "-" || op == "~")
-    {
-        static if (op == "+")
-            return Checked(this); // "+" is not hookable
-        else static if (hasMember!(Hook, "hookOpUnary"))
-        {
-            auto r = hook.hookOpUnary!op(payload);
-            return Checked!(typeof(r), Hook)(r);
-        }
-        else static if (op == "-" && isIntegral!T && T.sizeof >= 4 &&
-                !isUnsigned!T && hasMember!(Hook, "onOverflow"))
-        {
-            static assert(is(typeof(-payload) == typeof(payload)));
-            bool overflow;
-            import core.checkedint : negs;
-            auto r = negs(payload, overflow);
-            if (overflow) r = hook.onOverflow!op(payload);
-            return Checked(r);
-        }
-        else
-            return Checked(mixin(op ~ "payload"));
-    }
-
-    /// ditto
-    ref Checked opUnary(string op)() return
-    if (op == "++" || op == "--")
-    {
-        static if (hasMember!(Hook, "hookOpUnary"))
-            hook.hookOpUnary!op(payload);
-        else static if (hasMember!(Hook, "onOverflow"))
-        {
-            static if (op == "++")
-            {
-                if (payload == max.payload)
-                    payload = hook.onOverflow!"++"(payload);
-                else
-                    ++payload;
-            }
-            else
-            {
-                if (payload == min.payload)
-                    payload = hook.onOverflow!"--"(payload);
-                else
-                    --payload;
-            }
-        }
-        else
-            mixin(op ~ "payload;");
-        return this;
-    }
-
-    ///
-    static if (is(T == int) && is(Hook == void)) @safe unittest
-    {
-        static struct MyHook
-        {
-            static bool thereWereErrors;
-            static L hookOpUnary(string x, L)(L lhs)
-            {
-                if (x == "-" && lhs == -lhs) thereWereErrors = true;
-                return -lhs;
-            }
-        }
-        auto a = checked!MyHook(long.min);
-        assert(a == -a);
-        assert(MyHook.thereWereErrors);
-        auto b = checked!void(42);
-        assert(++b == 43);
-    }
-
-    // opBinary
-    /**
-
-    Defines binary operators `+`, `-`, `*`, `/`, `%`, `^^`, `&`, `|`, `^`, `<<`, `>>`,
-    and `>>>`. If `Hook` defines `hookOpBinary`, `opBinary` forwards to $(D
-    Checked!(typeof(hook.hookOpBinary!op(get, rhs)),
-    Hook)(hook.hookOpBinary!op(get, rhs))).
-
-    If `Hook` does not define `hookOpBinary` but defines `onOverflow`,
-    `opBinary` forwards to `hook.onOverflow!op(get, rhs)` in case an
-    overflow occurs.
-
-    If two `Checked` instances are involved in a binary operation and both
-    define `hookOpBinary`, the left-hand side hook has priority. If both define
-    `onOverflow`, a compile-time error occurs.
-
-    */
-    auto opBinary(string op, Rhs)(const Rhs rhs)
-    if (isIntegral!Rhs || isFloatingPoint!Rhs || is(Rhs == bool))
-    {
-        return opBinaryImpl!(op, Rhs, typeof(this))(rhs);
-    }
-
-    /// ditto
-    auto opBinary(string op, Rhs)(const Rhs rhs) const
-    if (isIntegral!Rhs || isFloatingPoint!Rhs || is(Rhs == bool))
-    {
-        return opBinaryImpl!(op, Rhs, typeof(this))(rhs);
-    }
-
-    private auto opBinaryImpl(string op, Rhs, this _)(const Rhs rhs)
-    {
-        alias R = typeof(mixin("payload" ~ op ~ "rhs"));
-        static assert(is(typeof(mixin("payload" ~ op ~ "rhs")) == R));
-        static if (isIntegral!R) alias Result = Checked!(R, Hook);
-        else alias Result = R;
-
-        static if (hasMember!(Hook, "hookOpBinary"))
-        {
-            auto r = hook.hookOpBinary!op(payload, rhs);
-            return Checked!(typeof(r), Hook)(r);
-        }
-        else static if (is(Rhs == bool))
-        {
-            return mixin("this" ~ op ~ "ubyte(rhs)");
-        }
-        else static if (isFloatingPoint!Rhs)
-        {
-            return mixin("payload" ~ op ~ "rhs");
-        }
-        else static if (hasMember!(Hook, "onOverflow"))
-        {
-            bool overflow;
-            auto r = opChecked!op(payload, rhs, overflow);
-            if (overflow) r = hook.onOverflow!op(payload, rhs);
-            return Result(r);
-        }
-        else
-        {
-            // Default is built-in behavior
-            return Result(mixin("payload" ~ op ~ "rhs"));
-        }
-    }
-
-    /// ditto
-    auto opBinary(string op, U, Hook1)(Checked!(U, Hook1) rhs)
-    {
-        return opBinaryImpl2!(op, U, Hook1, typeof(this))(rhs);
-    }
-
-    /// ditto
-    auto opBinary(string op, U, Hook1)(Checked!(U, Hook1) rhs) const
-    {
-        return opBinaryImpl2!(op, U, Hook1, typeof(this))(rhs);
-    }
-
-    private
-    auto opBinaryImpl2(string op, U, Hook1, this _)(Checked!(U, Hook1) rhs)
-    {
-        alias R = typeof(get + rhs.payload);
-        static if (valueConvertible!(T, R) && valueConvertible!(U, R) ||
-            is(Hook == Hook1))
-        {
-            // Delegate to lhs
-            return mixin("this" ~ op ~ "rhs.payload");
-        }
-        else static if (hasMember!(Hook, "hookOpBinary"))
-        {
-            return hook.hookOpBinary!op(payload, rhs);
-        }
-        else static if (hasMember!(Hook1, "hookOpBinary"))
-        {
-            // Delegate to rhs
-            return mixin("this.payload" ~ op ~ "rhs");
-        }
-        else static if (hasMember!(Hook, "onOverflow") &&
-            !hasMember!(Hook1, "onOverflow"))
-        {
-            // Delegate to lhs
-            return mixin("this" ~ op ~ "rhs.payload");
-        }
-        else static if (hasMember!(Hook1, "onOverflow") &&
-            !hasMember!(Hook, "onOverflow"))
-        {
-            // Delegate to rhs
-            return mixin("this.payload" ~ op ~ "rhs");
-        }
-        else
-        {
-            static assert(0, "Conflict between lhs and rhs hooks," ~
-                " use .get on one side to disambiguate.");
-        }
-    }
-
-    static if (is(T == int) && is(Hook == void)) @safe unittest
-    {
-        const a = checked(42);
-        assert(a + 1 == 43);
-        assert(a + checked(uint(42)) == 84);
-        assert(checked(42) + checked!void(42u) == 84);
-        assert(checked!void(42) + checked(42u) == 84);
-
-        static struct MyHook
-        {
-            static uint tally;
-            static auto hookOpBinary(string x, L, R)(L lhs, R rhs)
-            {
-                ++tally;
-                return mixin("lhs" ~ x ~ "rhs");
-            }
-        }
-        assert(checked!MyHook(42) + checked(42u) == 84);
-        assert(checked!void(42) + checked!MyHook(42u) == 84);
-        assert(MyHook.tally == 2);
-    }
-
-    // opBinaryRight
-    /**
-
-    Defines binary operators `+`, `-`, `*`, `/`, `%`, `^^`, `&`, `|`, `^`, `<<`,
-    `>>`, and `>>>` for the case when a built-in numeric or Boolean type is on
-    the left-hand side, and a `Checked` instance is on the right-hand side.
-
-    */
-    auto opBinaryRight(string op, Lhs)(const Lhs lhs)
-    if (isIntegral!Lhs || isFloatingPoint!Lhs || is(Lhs == bool))
-    {
-        return opBinaryRightImpl!(op, Lhs, typeof(this))(lhs);
-    }
-
-    /// ditto
-    auto opBinaryRight(string op, Lhs)(const Lhs lhs) const
-    if (isIntegral!Lhs || isFloatingPoint!Lhs || is(Lhs == bool))
-    {
-        return opBinaryRightImpl!(op, Lhs, typeof(this))(lhs);
-    }
-
-    private auto opBinaryRightImpl(string op, Lhs, this _)(const Lhs lhs)
-    {
-        static if (hasMember!(Hook, "hookOpBinaryRight"))
-        {
-            auto r = hook.hookOpBinaryRight!op(lhs, payload);
-            return Checked!(typeof(r), Hook)(r);
-        }
-        else static if (hasMember!(Hook, "hookOpBinary"))
-        {
-            auto r = hook.hookOpBinary!op(lhs, payload);
-            return Checked!(typeof(r), Hook)(r);
-        }
-        else static if (is(Lhs == bool))
-        {
-            return mixin("ubyte(lhs)" ~ op ~ "this");
-        }
-        else static if (isFloatingPoint!Lhs)
-        {
-            return mixin("lhs" ~ op ~ "payload");
-        }
-        else static if (hasMember!(Hook, "onOverflow"))
-        {
-            bool overflow;
-            auto r = opChecked!op(lhs, T(payload), overflow);
-            if (overflow) r = hook.onOverflow!op(lhs, payload);
-            return Checked!(typeof(r), Hook)(r);
-        }
-        else
-        {
-            // Default is built-in behavior
-            auto r = mixin("lhs" ~ op ~ "T(payload)");
-            return Checked!(typeof(r), Hook)(r);
-        }
-    }
-
-    static if (is(T == int) && is(Hook == void)) @safe unittest
-    {
-        assert(1 + checked(1) == 2);
-        static uint tally;
-        static struct MyHook
-        {
-            static auto hookOpBinaryRight(string x, L, R)(L lhs, R rhs)
-            {
-                ++tally;
-                return mixin("lhs" ~ x ~ "rhs");
-            }
-        }
-        assert(1 + checked!MyHook(1) == 2);
-        assert(tally == 1);
-
-        immutable x1 = checked(1);
-        assert(1 + x1 == 2);
-        immutable x2 = checked!MyHook(1);
-        assert(1 + x2 == 2);
-        assert(tally == 2);
-    }
-
-    // opOpAssign
-    /**
-
-    Defines operators `+=`, `-=`, `*=`, `/=`, `%=`, `^^=`, `&=`, `|=`, `^=`,
-    `<<=`, `>>=`, and `>>>=`.
-
-    If `Hook` defines `hookOpOpAssign`, `opOpAssign` forwards to
-    `hook.hookOpOpAssign!op(payload, rhs)`, where `payload` is a reference to
-    the internally held data so the hook can change it.
-
-    Otherwise, the operator first evaluates $(D auto result =
-    opBinary!op(payload, rhs).payload), which is subject to the hooks in
-    `opBinary`. Then, if `result` is less than $(D Checked!(T, Hook).min) and if
-    `Hook` defines `onLowerBound`, the payload is assigned from $(D
-    hook.onLowerBound(result, min)). If `result` is greater than $(D Checked!(T,
-    Hook).max) and if `Hook` defines `onUpperBound`, the payload is assigned
-    from $(D hook.onUpperBound(result, min)).
-
-    If the right-hand side is also a Checked but with a different hook or
-    underlying type, the hook and underlying type of this Checked takes
-    precedence.
-
-    In all other cases, the built-in behavior is carried out.
-
-    Params:
-    op = The operator involved (without the `"="`, e.g. `"+"` for `"+="` etc)
-    rhs = The right-hand side of the operator (left-hand side is `this`)
-
-    Returns: A reference to `this`.
-    */
-    ref Checked opOpAssign(string op, Rhs)(const Rhs rhs) return
-    if (isIntegral!Rhs || isFloatingPoint!Rhs || is(Rhs == bool))
-    {
-        static assert(is(typeof(mixin("payload" ~ op ~ "=rhs")) == T));
-
-        static if (hasMember!(Hook, "hookOpOpAssign"))
-        {
-            hook.hookOpOpAssign!op(payload, rhs);
-        }
-        else
-        {
-            alias R = typeof(get + rhs);
-            auto r = opBinary!op(rhs).get;
-            import std.conv : unsigned;
-
-            static if (ProperCompare.hookOpCmp(R.min, min.get) < 0 &&
-                hasMember!(Hook, "onLowerBound"))
-            {
-                if (ProperCompare.hookOpCmp(r, min.get) < 0)
-                {
-                    // Example: Checked!uint(1) += int(-3)
-                    payload = hook.onLowerBound(r, min.get);
-                    return this;
-                }
-            }
-            static if (ProperCompare.hookOpCmp(max.get, R.max) < 0 &&
-                hasMember!(Hook, "onUpperBound"))
-            {
-                if (ProperCompare.hookOpCmp(r, max.get) > 0)
-                {
-                    // Example: Checked!uint(1) += long(uint.max)
-                    payload = hook.onUpperBound(r, max.get);
-                    return this;
-                }
-            }
-            payload = cast(T) r;
-        }
-        return this;
-    }
-
-    /// ditto
-    ref Checked opOpAssign(string op, Rhs)(const Rhs rhs) return
-    if (is(Rhs == Checked!(RhsT, RhsHook), RhsT, RhsHook))
-    {
-        return opOpAssign!(op, typeof(rhs.payload))(rhs.payload);
-    }
-
-    ///
-    static if (is(T == int) && is(Hook == void)) @safe unittest
-    {
-        static struct MyHook
-        {
-            static bool thereWereErrors;
-            static T onLowerBound(Rhs, T)(Rhs rhs, T bound)
-            {
-                thereWereErrors = true;
-                return bound;
-            }
-            static T onUpperBound(Rhs, T)(Rhs rhs, T bound)
-            {
-                thereWereErrors = true;
-                return bound;
-            }
-        }
-        auto x = checked!MyHook(byte.min);
-        x -= 1;
-        assert(MyHook.thereWereErrors);
-        MyHook.thereWereErrors = false;
-        x = byte.max;
-        x += 1;
-        assert(MyHook.thereWereErrors);
-    }
-}
-
-/**
-
-Convenience function that turns an integral into the corresponding `Checked`
-instance by using template argument deduction. The hook type may be specified
-(by default `Abort`).
-
-*/
-Checked!(T, Hook) checked(Hook = Abort, T)(const T value)
-if (is(typeof(Checked!(T, Hook)(value))))
-{
-    return Checked!(T, Hook)(value);
-}
-
-///
-@safe unittest
-{
-    static assert(is(typeof(checked(42)) == Checked!int));
-    assert(checked(42) == Checked!int(42));
-    static assert(is(typeof(checked!WithNaN(42)) == Checked!(int, WithNaN)));
-    assert(checked!WithNaN(42) == Checked!(int, WithNaN)(42));
-}
-
-// get
-@safe unittest
-{
-    void test(T)()
-    {
-        assert(Checked!(T, void)(ubyte(22)).get == 22);
-    }
-    test!ubyte;
-    test!(const ubyte);
-    test!(immutable ubyte);
-}
-
-@system unittest
-{
-    // https://issues.dlang.org/show_bug.cgi?id=21758
-    assert(4 * checked(5L) == 20);
-    assert(20 / checked(5L) == 4);
-    assert(2 ^^ checked(3L) == 8);
-    assert(12 % checked(5L) == 2);
-    assert((0xff & checked(3L)) == 3);
-    assert((0xf0 | checked(3L)) == 0xf3);
-    assert((0xff ^ checked(3L)) == 0xfc);
-}
-
-// Abort
-/**
-
-Force all integral errors to fail by printing an error message to `stderr` and
-then abort the program. `Abort` is the default second argument for `Checked`.
-
-*/
-struct Abort
-{
-static:
-    /**
-
-    Called automatically upon a bad cast (one that loses precision or attempts
-    to convert a negative value to an unsigned type). The source type is `Src`
-    and the destination type is `Dst`.
-
-    Params:
-    src = The source of the cast
-
-    Returns: Nominally the result is the desired value of the cast operation,
-    which will be forwarded as the result of the cast. For `Abort`, the
-    function never returns because it aborts the program.
-
-    */
-    Dst onBadCast(Dst, Src)(Src src)
-    {
-        Warn.onBadCast!Dst(src);
-        assert(0);
-    }
-
-    /**
-
-    Called automatically upon a bounds error.
-
-    Params:
-    rhs = The right-hand side value in the assignment, after the operator has
-    been evaluated
-    bound = The value of the bound being violated
-
-    Returns: Nominally the result is the desired value of the operator, which
-    will be forwarded as result. For `Abort`, the function never returns because
-    it aborts the program.
-
-    */
-    T onLowerBound(Rhs, T)(Rhs rhs, T bound)
-    {
-        Warn.onLowerBound(rhs, bound);
-        assert(0);
-    }
-    /// ditto
-    T onUpperBound(Rhs, T)(Rhs rhs, T bound)
-    {
-        Warn.onUpperBound(rhs, bound);
-        assert(0);
-    }
-
-    /**
-
-    Called automatically upon a comparison for equality. In case of a erroneous
-    comparison (one that would make a signed negative value appear equal to an
-    unsigned positive value), this hook issues `assert(0)` which terminates the
-    application.
-
-    Params:
-    lhs = The first argument of `Checked`, e.g. `int` if the left-hand side of
-      the operator is `Checked!int`
-    rhs = The right-hand side type involved in the operator
-
-    Returns: Upon a correct comparison, returns the result of the comparison.
-    Otherwise, the function terminates the application so it never returns.
-
-    */
-    static bool hookOpEquals(Lhs, Rhs)(Lhs lhs, Rhs rhs)
-    {
-        bool error;
-        auto result = opChecked!"=="(lhs, rhs, error);
-        if (error)
-        {
-            Warn.hookOpEquals(lhs, rhs);
-            assert(0);
-        }
-        return result;
-    }
-
-    /**
-
-    Called automatically upon a comparison for ordering using one of the
-    operators `<`, `<=`, `>`, or `>=`. In case the comparison is erroneous (i.e.
-    it would make a signed negative value appear greater than or equal to an
-    unsigned positive value), then application is terminated with `assert(0)`.
-    Otherwise, the three-state result is returned (positive if $(D lhs > rhs),
-    negative if $(D lhs < rhs), `0` otherwise).
-
-    Params:
-    lhs = The first argument of `Checked`, e.g. `int` if the left-hand side of
-      the operator is `Checked!int`
-    rhs = The right-hand side type involved in the operator
-
-    Returns: For correct comparisons, returns a positive integer if $(D lhs >
-    rhs), a negative integer if  $(D lhs < rhs), `0` if the two are equal. Upon
-    a mistaken comparison such as $(D int(-1) < uint(0)), the function never
-    returns because it aborts the program.
-
-    */
-    int hookOpCmp(Lhs, Rhs)(Lhs lhs, Rhs rhs)
-    {
-        bool error;
-        auto result = opChecked!"cmp"(lhs, rhs, error);
-        if (error)
-        {
-            Warn.hookOpCmp(lhs, rhs);
-            assert(0);
-        }
-        return result;
-    }
-
-    /**
-
-    Called automatically upon an overflow during a unary or binary operation.
-
-    Params:
-    x = The operator, e.g. `-`
-    lhs = The left-hand side (or sole) argument
-    rhs = The right-hand side type involved in the operator
-
-    Returns: Nominally the result is the desired value of the operator, which
-    will be forwarded as result. For `Abort`, the function never returns because
-    it aborts the program.
-
-    */
-    typeof(~Lhs()) onOverflow(string x, Lhs)(Lhs lhs)
-    {
-        Warn.onOverflow!x(lhs);
-        assert(0);
-    }
-    /// ditto
-    typeof(Lhs() + Rhs()) onOverflow(string x, Lhs, Rhs)(Lhs lhs, Rhs rhs)
-    {
-        Warn.onOverflow!x(lhs, rhs);
-        assert(0);
-    }
-}
-
-@safe unittest
-{
-    void test(T)()
-    {
-        Checked!(int, Abort) x;
-        x = 42;
-        auto x1 = cast(T) x;
-        assert(x1 == 42);
-        //x1 += long(int.max);
-    }
-    test!short;
-    test!(const short);
-    test!(immutable short);
-}
-
-
-// Throw
-/**
-
-Force all integral errors to fail by throwing an exception of type
-`Throw.CheckFailure`. The message coming with the error is similar to the one
-printed by `Warn`.
-
-*/
-struct Throw
-{
-    /**
-    Exception type thrown upon any failure.
-    */
-    static class CheckFailure : Exception
-    {
-        this(T...)(string f, T vals)
-        {
-            import std.format : format;
-            super(format(f, vals));
-        }
-    }
-
-    /**
-
-    Called automatically upon a bad cast (one that loses precision or attempts
-    to convert a negative value to an unsigned type). The source type is `Src`
-    and the destination type is `Dst`.
-
-    Params:
-    src = The source of the cast
-
-    Returns: Nominally the result is the desired value of the cast operation,
-    which will be forwarded as the result of the cast. For `Throw`, the
-    function never returns because it throws an exception.
-
-    */
-    static Dst onBadCast(Dst, Src)(Src src)
-    {
-        throw new CheckFailure("Erroneous cast: cast(%s) %s(%s)",
-            Dst.stringof, Src.stringof, src);
-    }
-
-    /**
-
-    Called automatically upon a bounds error.
-
-    Params:
-    rhs = The right-hand side value in the assignment, after the operator has
-    been evaluated
-    bound = The value of the bound being violated
-
-    Returns: Nominally the result is the desired value of the operator, which
-    will be forwarded as result. For `Throw`, the function never returns because
-    it throws.
-
-    */
-    static T onLowerBound(Rhs, T)(Rhs rhs, T bound)
-    {
-        throw new CheckFailure("Lower bound error: %s(%s) < %s(%s)",
-            Rhs.stringof, rhs, T.stringof, bound);
-    }
-    /// ditto
-    static T onUpperBound(Rhs, T)(Rhs rhs, T bound)
-    {
-        throw new CheckFailure("Upper bound error: %s(%s) > %s(%s)",
-            Rhs.stringof, rhs, T.stringof, bound);
-    }
-
-    /**
-
-    Called automatically upon a comparison for equality. Throws upon an
-    erroneous comparison (one that would make a signed negative value appear
-    equal to an unsigned positive value).
-
-    Params:
-    lhs = The first argument of `Checked`, e.g. `int` if the left-hand side of
-      the operator is `Checked!int`
-    rhs = The right-hand side type involved in the operator
-
-    Returns: The result of the comparison.
-
-    Throws: `CheckFailure` if the comparison is mathematically erroneous.
-
-    */
-    static bool hookOpEquals(L, R)(L lhs, R rhs)
-    {
-        bool error;
-        auto result = opChecked!"=="(lhs, rhs, error);
-        if (error)
-        {
-            throw new CheckFailure("Erroneous comparison: %s(%s) == %s(%s)",
-                L.stringof, lhs, R.stringof, rhs);
-        }
-        return result;
-    }
-
-    /**
-
-    Called automatically upon a comparison for ordering using one of the
-    operators `<`, `<=`, `>`, or `>=`. In case the comparison is erroneous (i.e.
-    it would make a signed negative value appear greater than or equal to an
-    unsigned positive value), throws a `Throw.CheckFailure` exception.
-    Otherwise, the three-state result is returned (positive if $(D lhs > rhs),
-    negative if $(D lhs < rhs), `0` otherwise).
-
-    Params:
-    lhs = The first argument of `Checked`, e.g. `int` if the left-hand side of
-      the operator is `Checked!int`
-    rhs = The right-hand side type involved in the operator
-
-    Returns: For correct comparisons, returns a positive integer if $(D lhs >
-    rhs), a negative integer if  $(D lhs < rhs), `0` if the two are equal.
-
-    Throws: Upon a mistaken comparison such as $(D int(-1) < uint(0)), the
-    function never returns because it throws a `Throw.CheckedFailure` exception.
-
-    */
-    static int hookOpCmp(Lhs, Rhs)(Lhs lhs, Rhs rhs)
-    {
-        bool error;
-        auto result = opChecked!"cmp"(lhs, rhs, error);
-        if (error)
-        {
-            throw new CheckFailure("Erroneous ordering comparison: %s(%s) and %s(%s)",
-                Lhs.stringof, lhs, Rhs.stringof, rhs);
-        }
-        return result;
-    }
-
-    /**
-
-    Called automatically upon an overflow during a unary or binary operation.
-
-    Params:
-    x = The operator, e.g. `-`
-    lhs = The left-hand side (or sole) argument
-    rhs = The right-hand side type involved in the operator
-
-    Returns: Nominally the result is the desired value of the operator, which
-    will be forwarded as result. For `Throw`, the function never returns because
-    it throws an exception.
-
-    */
-    static typeof(~Lhs()) onOverflow(string x, Lhs)(Lhs lhs)
-    {
-        throw new CheckFailure("Overflow on unary operator: %s%s(%s)",
-            x, Lhs.stringof, lhs);
-    }
-    /// ditto
-    static typeof(Lhs() + Rhs()) onOverflow(string x, Lhs, Rhs)(Lhs lhs, Rhs rhs)
-    {
-        throw new CheckFailure("Overflow on binary operator: %s(%s) %s %s(%s)",
-            Lhs.stringof, lhs, x, Rhs.stringof, rhs);
-    }
-}
-
-///
-@safe unittest
-{
-    void test(T)()
-    {
-        Checked!(int, Throw) x;
-        x = 42;
-        auto x1 = cast(T) x;
-        assert(x1 == 42);
-        x = T.max + 1;
-        import std.exception : assertThrown, assertNotThrown;
-        assertThrown(cast(T) x);
-        x = x.max;
-        assertThrown(x += 42);
-        assertThrown(x += 42L);
-        x = x.min;
-        assertThrown(-x);
-        assertThrown(x -= 42);
-        assertThrown(x -= 42L);
-        x = -1;
-        assertNotThrown(x == -1);
-        assertThrown(x == uint(-1));
-        assertNotThrown(x <= -1);
-        assertThrown(x <= uint(-1));
-    }
-    test!short;
-    test!(const short);
-    test!(immutable short);
-}
-
-// Warn
-/**
-Hook that prints to `stderr` a trace of all integral errors, without affecting
-default behavior.
-*/
-struct Warn
-{
-    import std.stdio : writefln;
-static:
-    /**
-
-    Called automatically upon a bad cast from `src` to type `Dst` (one that
-    loses precision or attempts to convert a negative value to an unsigned
-    type).
-
-    Params:
-    src = The source of the cast
-    Dst = The target type of the cast
-
-    Returns: `cast(Dst) src`
-
-    */
-    Dst onBadCast(Dst, Src)(Src src)
-    {
-        trustedStderr.writefln("Erroneous cast: cast(%s) %s(%s)",
-            Dst.stringof, Src.stringof, src);
-        return cast(Dst) src;
-    }
-
-    /**
-
-    Called automatically upon a bad `opOpAssign` call (one that loses precision
-    or attempts to convert a negative value to an unsigned type).
-
-    Params:
-    rhs = The right-hand side value in the assignment, after the operator has
-    been evaluated
-    bound = The bound being violated
-
-    Returns: `cast(T) rhs`
-    */
-    T onLowerBound(Rhs, T)(Rhs rhs, T bound)
-    {
-        trustedStderr.writefln("Lower bound error: %s(%s) < %s(%s)",
-            Rhs.stringof, rhs, T.stringof, bound);
-        return cast(T) rhs;
-    }
-    /// ditto
-    T onUpperBound(Rhs, T)(Rhs rhs, T bound)
-    {
-        trustedStderr.writefln("Upper bound error: %s(%s) > %s(%s)",
-            Rhs.stringof, rhs, T.stringof, bound);
-        return cast(T) rhs;
-    }
-
-    /**
-
-    Called automatically upon a comparison for equality. In case of an Erroneous
-    comparison (one that would make a signed negative value appear equal to an
-    unsigned positive value), writes a warning message to `stderr` as a side
-    effect.
-
-    Params:
-    lhs = The first argument of `Checked`, e.g. `int` if the left-hand side of
-      the operator is `Checked!int`
-    rhs = The right-hand side type involved in the operator
-
-    Returns: In all cases the function returns the built-in result of $(D lhs ==
-    rhs).
-
-    */
-    bool hookOpEquals(Lhs, Rhs)(Lhs lhs, Rhs rhs)
-    {
-        bool error;
-        auto result = opChecked!"=="(lhs, rhs, error);
-        if (error)
-        {
-            trustedStderr.writefln("Erroneous comparison: %s(%s) == %s(%s)",
-                Lhs.stringof, lhs, Rhs.stringof, rhs);
-            return lhs == rhs;
-        }
-        return result;
-    }
-
-    ///
-    @safe unittest
-    {
-        auto x = checked!Warn(-42);
-        // Passes
-        assert(x == -42);
-        // Passes but prints a warning
-        // assert(x == uint(-42));
-    }
-
-    /**
-
-    Called automatically upon a comparison for ordering using one of the
-    operators `<`, `<=`, `>`, or `>=`. In case the comparison is erroneous (i.e.
-    it would make a signed negative value appear greater than or equal to an
-    unsigned positive value), then a warning message is printed to `stderr`.
-
-    Params:
-    lhs = The first argument of `Checked`, e.g. `int` if the left-hand side of
-      the operator is `Checked!int`
-    rhs = The right-hand side type involved in the operator
-
-    Returns: In all cases, returns $(D lhs < rhs ? -1 : lhs > rhs). The result
-    is  not autocorrected in case of an erroneous comparison.
-
-    */
-    int hookOpCmp(Lhs, Rhs)(Lhs lhs, Rhs rhs)
-    {
-        bool error;
-        auto result = opChecked!"cmp"(lhs, rhs, error);
-        if (error)
-        {
-            trustedStderr.writefln("Erroneous ordering comparison: %s(%s) and %s(%s)",
-                Lhs.stringof, lhs, Rhs.stringof, rhs);
-            return lhs < rhs ? -1 : lhs > rhs;
-        }
-        return result;
-    }
-
-    ///
-    @safe unittest
-    {
-        auto x = checked!Warn(-42);
-        // Passes
-        assert(x <= -42);
-        // Passes but prints a warning
-        // assert(x <= uint(-42));
-    }
-
-    /**
-
-    Called automatically upon an overflow during a unary or binary operation.
-
-    Params:
-    x = The operator involved
-    Lhs = The first argument of `Checked`, e.g. `int` if the left-hand side of
-      the operator is `Checked!int`
-    Rhs = The right-hand side type involved in the operator
-
-    Returns: $(D mixin(x ~ "lhs")) for unary, $(D mixin("lhs" ~ x ~ "rhs")) for
-    binary
-
-    */
-    typeof(~Lhs()) onOverflow(string x, Lhs)(ref Lhs lhs)
-    {
-        trustedStderr.writefln("Overflow on unary operator: %s%s(%s)",
-            x, Lhs.stringof, lhs);
-        return mixin(x ~ "lhs");
-    }
-    /// ditto
-    typeof(Lhs() + Rhs()) onOverflow(string x, Lhs, Rhs)(Lhs lhs, Rhs rhs)
-    {
-        trustedStderr.writefln("Overflow on binary operator: %s(%s) %s %s(%s)",
-            Lhs.stringof, lhs, x, Rhs.stringof, rhs);
-        static if (x == "/")               // Issue 20743: mixin below would cause SIGFPE on POSIX
-            return typeof(lhs / rhs).min;  // or EXCEPTION_INT_OVERFLOW on Windows
-        else
-            return mixin("lhs" ~ x ~ "rhs");
-    }
-
-    // This is safe because we do not assign to the reference returned by
-    // `stderr`. The ability for the caller to do that is why `stderr` is not
-    // safe in the general case.
-    private @property auto ref trustedStderr() @trusted
-    {
-        import std.stdio : stderr;
-
-        return stderr;
-    }
-}
-
-///
-@safe unittest
-{
-    auto x = checked!Warn(42);
-    short x1 = cast(short) x;
-    //x += long(int.max);
-    auto y = checked!Warn(cast(const int) 42);
-    short y1 = cast(const byte) y;
-}
-
-@system unittest
-{
-    auto a = checked!Warn(int.min);
-    auto b = checked!Warn(-1);
-    auto x = checked!Abort(int.min);
-    auto y = checked!Abort(-1);
-
-    // Temporarily redirect output to stderr to make sure we get the right output.
-    import std.file : exists, remove;
-    import std.process : uniqueTempPath;
-    import std.stdio : stderr;
-    auto tmpname = uniqueTempPath;
-    scope(exit) if (exists(tmpname)) remove(tmpname);
-    auto t = stderr;
-    stderr.open(tmpname, "w");
-    // Open a new scope to minimize code ran with stderr redirected.
-    {
-        scope(exit) stderr = t;
-        assert(a / b == a * b);
-        import std.exception : assertThrown;
-        import core.exception : AssertError;
-        assertThrown!AssertError(x / y);
-    }
-    import std.file : readText;
-    import std.ascii : newline;
-    auto witness = readText(tmpname);
-    auto expected =
-"Overflow on binary operator: int(-2147483648) / const(int)(-1)" ~ newline ~
-"Overflow on binary operator: int(-2147483648) * const(int)(-1)" ~ newline ~
-"Overflow on binary operator: int(-2147483648) / const(int)(-1)" ~ newline;
-    assert(witness == expected, "'" ~ witness ~ "'");
-}
-
-// https://issues.dlang.org/show_bug.cgi?id=22249
-@safe unittest
-{
-    alias _ = Warn.onLowerBound!(int, int);
-}
-
-// ProperCompare
-/**
-
-Hook that provides arithmetically correct comparisons for equality and ordering.
-Comparing an object of type $(D Checked!(X, ProperCompare)) against another
-integral (for equality or ordering) ensures that no surprising conversions from
-signed to unsigned integral occur before the comparison. Using $(D Checked!(X,
-ProperCompare)) on either side of a comparison for equality against a
-floating-point number makes sure the integral can be properly converted to the
-floating point type, thus making sure equality is transitive.
-
-*/
-struct ProperCompare
-{
-    /**
-    Hook for `==` and `!=` that ensures comparison against integral values has
-    the behavior expected by the usual arithmetic rules. The built-in semantics
-    yield surprising behavior when comparing signed values against unsigned
-    values for equality, for example $(D uint.max == -1) or $(D -1_294_967_296 ==
-    3_000_000_000u). The call $(D hookOpEquals(x, y)) returns `true` if and only
-    if `x` and `y` represent the same arithmetic number.
-
-    If one of the numbers is an integral and the other is a floating-point
-    number, $(D hookOpEquals(x, y)) returns `true` if and only if the integral
-    can be converted exactly (without approximation) to the floating-point
-    number. This is in order to preserve transitivity of equality: if $(D
-    hookOpEquals(x, y)) and $(D hookOpEquals(y, z)) then $(D hookOpEquals(y,
-    z)), in case `x`, `y`, and `z` are a mix of integral and floating-point
-    numbers.
-
-    Params:
-    lhs = The left-hand side of the comparison for equality
-    rhs = The right-hand side of the comparison for equality
-
-    Returns:
-    The result of the comparison, `true` if the values are equal
-    */
-    static bool hookOpEquals(L, R)(L lhs, R rhs)
-    {
-        alias C = typeof(lhs + rhs);
-        static if (isFloatingPoint!C)
-        {
-            static if (!isFloatingPoint!L)
-            {
-                return hookOpEquals(rhs, lhs);
-            }
-            else static if (!isFloatingPoint!R)
-            {
-                static assert(isFloatingPoint!L && !isFloatingPoint!R);
-                auto rhs1 = C(rhs);
-                return lhs == rhs1 && cast(R) rhs1 == rhs;
-            }
-            else
-                return lhs == rhs;
-        }
-        else
-        {
-            bool error;
-            auto result = opChecked!"=="(lhs, rhs, error);
-            if (error)
-            {
-                // Only possible error is a wrong "true"
-                return false;
-            }
-            return result;
-        }
-    }
-
-    /**
-    Hook for `<`, `<=`, `>`, and `>=` that ensures comparison against integral
-    values has the behavior expected by the usual arithmetic rules. The built-in
-    semantics yield surprising behavior when comparing signed values against
-    unsigned values, for example $(D 0u < -1). The call $(D hookOpCmp(x, y))
-    returns `-1` if and only if `x` is smaller than `y` in abstract arithmetic
-    sense.
-
-    If one of the numbers is an integral and the other is a floating-point
-    number, $(D hookOpEquals(x, y)) returns a floating-point number that is `-1`
-    if `x < y`, `0` if `x == y`, `1` if `x > y`, and `NaN` if the floating-point
-    number is `NaN`.
-
-    Params:
-    lhs = The left-hand side of the comparison for ordering
-    rhs = The right-hand side of the comparison for ordering
-
-    Returns:
-    The result of the comparison (negative if $(D lhs < rhs), positive if $(D
-    lhs > rhs), `0` if the values are equal)
-    */
-    static auto hookOpCmp(L, R)(L lhs, R rhs)
-    {
-        alias C = typeof(lhs + rhs);
-        static if (isFloatingPoint!C)
-        {
-            return lhs < rhs
-                ? C(-1)
-                : lhs > rhs ? C(1) : lhs == rhs ? C(0) : C.init;
-        }
-        else
-        {
-            static if (!valueConvertible!(L, C) || !valueConvertible!(R, C))
-            {
-                static assert(isUnsigned!C);
-                static assert(isUnsigned!L != isUnsigned!R);
-                if (!isUnsigned!L && lhs < 0)
-                    return -1;
-                if (!isUnsigned!R && rhs < 0)
-                    return 1;
-            }
-            return lhs < rhs ? -1 : lhs > rhs;
-        }
-    }
-}
-
-///
-@safe unittest
-{
-    alias opEqualsProper = ProperCompare.hookOpEquals;
-    assert(opEqualsProper(42, 42));
-    assert(opEqualsProper(42.0, 42.0));
-    assert(opEqualsProper(42u, 42));
-    assert(opEqualsProper(42, 42u));
-    assert(-1 == 4294967295u);
-    assert(!opEqualsProper(-1, 4294967295u));
-    assert(!opEqualsProper(const uint(-1), -1));
-    assert(!opEqualsProper(uint(-1), -1.0));
-    assert(3_000_000_000U == -1_294_967_296);
-    assert(!opEqualsProper(3_000_000_000U, -1_294_967_296));
-}
-
-@safe unittest
-{
-    alias opCmpProper = ProperCompare.hookOpCmp;
-    assert(opCmpProper(42, 42) == 0);
-    assert(opCmpProper(42, 42.0) == 0);
-    assert(opCmpProper(41, 42.0) < 0);
-    assert(opCmpProper(42, 41.0) > 0);
-    import std.math.traits : isNaN;
-    assert(isNaN(opCmpProper(41, double.init)));
-    assert(opCmpProper(42u, 42) == 0);
-    assert(opCmpProper(42, 42u) == 0);
-    assert(opCmpProper(-1, uint(-1)) < 0);
-    assert(opCmpProper(uint(-1), -1) > 0);
-    assert(opCmpProper(-1.0, -1) == 0);
-}
-
-@safe unittest
-{
-    auto x1 = Checked!(uint, ProperCompare)(42u);
-    assert(x1.get < -1);
-    assert(x1 > -1);
-}
-
-// WithNaN
-/**
-
-Hook that reserves a special value as a "Not a Number" representative. For
-signed integrals, the reserved value is `T.min`. For signed integrals, the
-reserved value is `T.max`.
-
-The default value of a $(D Checked!(X, WithNaN)) is its NaN value, so care must
-be taken that all variables are explicitly initialized. Any arithmetic and logic
-operation involving at least on NaN becomes NaN itself. All of $(D a == b), $(D
-a < b), $(D a > b), $(D a <= b), $(D a >= b) yield `false` if at least one of
-`a` and `b` is NaN.
-
-*/
-struct WithNaN
-{
-static:
-    /**
-    The default value used for values not explicitly initialized. It is the NaN
-    value, i.e. `T.min` for signed integrals and `T.max` for unsigned integrals.
-    */
-    enum T defaultValue(T) = T.min == 0 ? T.max : T.min;
-    /**
-    The maximum value representable is `T.max` for signed integrals, $(D
-    T.max - 1) for unsigned integrals. The minimum value representable is $(D
-    T.min + 1) for signed integrals, `0` for unsigned integrals.
-    */
-    enum T max(T) = cast(T) (T.min == 0 ? T.max - 1 : T.max);
-    /// ditto
-    enum T min(T) = cast(T) (T.min == 0 ? T(0) : T.min + 1);
-
-    /**
-    If `rhs` is `WithNaN.defaultValue!Rhs`, returns
-    `WithNaN.defaultValue!Lhs`. Otherwise, returns $(D cast(Lhs) rhs).
-
-    Params:
-    rhs = the value being cast (`Rhs` is the first argument to `Checked`)
-    Lhs = the target type of the cast
-
-    Returns: The result of the cast operation.
-    */
-    Lhs hookOpCast(Lhs, Rhs)(Rhs rhs)
-    {
-        static if (is(Lhs == bool))
-        {
-            return rhs != defaultValue!Rhs && rhs != 0;
-        }
-        else static if (valueConvertible!(Rhs, Lhs))
-        {
-            return rhs != defaultValue!Rhs ? Lhs(rhs) : defaultValue!Lhs;
-        }
-        else
-        {
-            // Not value convertible, only viable option is rhs fits within the
-            // bounds of Lhs
-            static if (ProperCompare.hookOpCmp(Rhs.min, Lhs.min) < 0)
-            {
-                // Example: hookOpCast!short(int(42)), hookOpCast!uint(int(42))
-                if (ProperCompare.hookOpCmp(rhs, Lhs.min) < 0)
-                    return defaultValue!Lhs;
-            }
-            static if (ProperCompare.hookOpCmp(Rhs.max, Lhs.max) > 0)
-            {
-                // Example: hookOpCast!int(uint(42))
-                if (ProperCompare.hookOpCmp(rhs, Lhs.max) > 0)
-                    return defaultValue!Lhs;
-            }
-            return cast(Lhs) rhs;
-        }
-    }
-
-    ///
-    @safe unittest
-    {
-        auto x = checked!WithNaN(422);
-        assert((cast(ubyte) x) == 255);
-        x = checked!WithNaN(-422);
-        assert((cast(byte) x) == -128);
-        assert(cast(short) x == -422);
-        assert(cast(bool) x);
-        x = x.init; // set back to NaN
-        assert(x != true);
-        assert(x != false);
-    }
-
-    /**
-
-    Returns `false` if $(D lhs == WithNaN.defaultValue!Lhs), $(D lhs == rhs)
-    otherwise.
-
-    Params:
-    lhs = The left-hand side of the comparison (`Lhs` is the first argument to
-    `Checked`)
-    rhs = The right-hand side of the comparison
-
-    Returns: `lhs != WithNaN.defaultValue!Lhs && lhs == rhs`
-    */
-    bool hookOpEquals(Lhs, Rhs)(Lhs lhs, Rhs rhs)
-    {
-        return lhs != defaultValue!Lhs && lhs == rhs;
-    }
-
-    /**
-
-    If $(D lhs == WithNaN.defaultValue!Lhs), returns `double.init`. Otherwise,
-    has the same semantics as the default comparison.
-
-    Params:
-    lhs = The left-hand side of the comparison (`Lhs` is the first argument to
-    `Checked`)
-    rhs = The right-hand side of the comparison
-
-    Returns: `double.init` if `lhs == WitnNaN.defaultValue!Lhs`, `-1.0` if $(D
-    lhs < rhs), `0.0` if $(D lhs == rhs), `1.0` if $(D lhs > rhs).
-
-    */
-    double hookOpCmp(Lhs, Rhs)(Lhs lhs, Rhs rhs)
-    {
-        if (lhs == defaultValue!Lhs) return double.init;
-        return lhs < rhs
-            ? -1.0
-            : lhs > rhs ? 1.0 : lhs == rhs ? 0.0 : double.init;
-    }
-
-    ///
-    @safe unittest
-    {
-        Checked!(int, WithNaN) x;
-        assert(!(x < 0) && !(x > 0) && !(x == 0));
-        x = 1;
-        assert(x > 0 && !(x < 0) && !(x == 0));
-    }
-
-    /**
-    Defines hooks for unary operators `-`, `~`, `++`, and `--`.
-
-    For `-` and `~`, if $(D v == WithNaN.defaultValue!T), returns
-    `WithNaN.defaultValue!T`. Otherwise, the semantics is the same as for the
-    built-in operator.
-
-    For `++` and `--`, if $(D v == WithNaN.defaultValue!Lhs) or the operation
-    would result in an overflow, sets `v` to `WithNaN.defaultValue!T`.
-    Otherwise, the semantics is the same as for the built-in operator.
-
-    Params:
-    x = The operator symbol
-    v = The left-hand side of the comparison (`T` is the first argument to
-    `Checked`)
-
-    Returns: $(UL $(LI For $(D x == "-" || x == "~"): If  $(D v ==
-    WithNaN.defaultValue!T), the function returns `WithNaN.defaultValue!T`.
-    Otherwise it returns the normal result of the operator.) $(LI For $(D x ==
-    "++" || x == "--"): The function returns `void`.))
-
-    */
-    auto hookOpUnary(string x, T)(ref T v)
-    {
-        static if (x == "-" || x == "~")
-        {
-            return v != defaultValue!T ? mixin(x ~ "v") : v;
-        }
-        else static if (x == "++")
-        {
-            static if (defaultValue!T == T.min)
-            {
-                if (v != defaultValue!T)
-                {
-                    if (v == T.max) v = defaultValue!T;
-                    else ++v;
-                }
-            }
-            else
-            {
-                static assert(defaultValue!T == T.max);
-                if (v != defaultValue!T) ++v;
-            }
-        }
-        else static if (x == "--")
-        {
-            if (v != defaultValue!T) --v;
-        }
-    }
-
-    ///
-    @safe unittest
-    {
-        Checked!(int, WithNaN) x;
-        ++x;
-        assert(x.isNaN);
-        x = 1;
-        assert(!x.isNaN);
-        x = -x;
-        ++x;
-        assert(!x.isNaN);
-    }
-
-    @safe unittest // for coverage
-    {
-        Checked!(uint, WithNaN) y;
-        ++y;
-        assert(y.isNaN);
-    }
-
-    /**
-    Defines hooks for binary operators `+`, `-`, `*`, `/`, `%`, `^^`, `&`, `|`,
-     `^`, `<<`, `>>`, and `>>>` for cases where a `Checked` object is the
-    left-hand side operand. If $(D lhs == WithNaN.defaultValue!Lhs), returns
-    $(D WithNaN.defaultValue!(typeof(lhs + rhs))) without evaluating the
-    operand. Otherwise, evaluates the operand. If evaluation does not overflow,
-    returns the result. Otherwise, returns $(D WithNaN.defaultValue!(typeof(lhs +
-    rhs))).
-
-    Params:
-    x = The operator symbol
-    lhs = The left-hand side operand (`Lhs` is the first argument to `Checked`)
-    rhs = The right-hand side operand
-
-    Returns: If $(D lhs != WithNaN.defaultValue!Lhs) and the operator does not
-    overflow, the function returns the same result as the built-in operator. In
-    all other cases, returns $(D WithNaN.defaultValue!(typeof(lhs + rhs))).
-    */
-    auto hookOpBinary(string x, L, R)(L lhs, R rhs)
-    {
-        alias Result = typeof(lhs + rhs);
-        if (lhs != defaultValue!L)
-        {
-            bool error;
-            auto result = opChecked!x(lhs, rhs, error);
-            if (!error) return result;
-        }
-        return defaultValue!Result;
-    }
-
-    ///
-    @safe unittest
-    {
-        Checked!(int, WithNaN) x;
-        assert((x + 1).isNaN);
-        x = 100;
-        assert(!(x + 1).isNaN);
-    }
-
-    /**
-    Defines hooks for binary operators `+`, `-`, `*`, `/`, `%`, `^^`, `&`, `|`,
-     `^`, `<<`, `>>`, and `>>>` for cases where a `Checked` object is the
-    right-hand side operand. If $(D rhs == WithNaN.defaultValue!Rhs), returns
-    $(D WithNaN.defaultValue!(typeof(lhs + rhs))) without evaluating the
-    operand. Otherwise, evaluates the operand. If evaluation does not overflow,
-    returns the result. Otherwise, returns $(D WithNaN.defaultValue!(typeof(lhs +
-    rhs))).
-
-    Params:
-    x = The operator symbol
-    lhs = The left-hand side operand
-    rhs = The right-hand side operand (`Rhs` is the first argument to `Checked`)
-
-    Returns: If $(D rhs != WithNaN.defaultValue!Rhs) and the operator does not
-    overflow, the function returns the same result as the built-in operator. In
-    all other cases, returns $(D WithNaN.defaultValue!(typeof(lhs + rhs))).
-    */
-    auto hookOpBinaryRight(string x, L, R)(L lhs, R rhs)
-    {
-        alias Result = typeof(lhs + rhs);
-        if (rhs != defaultValue!R)
-        {
-            bool error;
-            auto result = opChecked!x(lhs, rhs, error);
-            if (!error) return result;
-        }
-        return defaultValue!Result;
-    }
-    ///
-    @safe unittest
-    {
-        Checked!(int, WithNaN) x;
-        assert((1 + x).isNaN);
-        x = 100;
-        assert(!(1 + x).isNaN);
-    }
-
-    /**
-
-    Defines hooks for binary operators `+=`, `-=`, `*=`, `/=`, `%=`, `^^=`,
-    `&=`, `|=`, `^=`, `<<=`, `>>=`, and `>>>=` for cases where a `Checked`
-    object is the left-hand side operand. If $(D lhs ==
-    WithNaN.defaultValue!Lhs), no action is carried. Otherwise, evaluates the
-    operand. If evaluation does not overflow and fits in `Lhs` without loss of
-    information or change of sign, sets `lhs` to the result. Otherwise, sets
-    `lhs` to `WithNaN.defaultValue!Lhs`.
-
-    Params:
-    x = The operator symbol (without the `=`)
-    lhs = The left-hand side operand (`Lhs` is the first argument to `Checked`)
-    rhs = The right-hand side operand
-
-    Returns: `void`
-    */
-    void hookOpOpAssign(string x, L, R)(ref L lhs, R rhs)
-    {
-        if (lhs == defaultValue!L)
-            return;
-        bool error;
-        auto temp = opChecked!x(lhs, rhs, error);
-        lhs = error
-            ? defaultValue!L
-            : hookOpCast!L(temp);
-    }
-
-    ///
-    @safe unittest
-    {
-        Checked!(int, WithNaN) x;
-        x += 4;
-        assert(x.isNaN);
-        x = 0;
-        x += 4;
-        assert(!x.isNaN);
-        x += int.max;
-        assert(x.isNaN);
-    }
-}
-
-///
-@safe unittest
-{
-    auto x1 = Checked!(int, WithNaN)();
-    assert(x1.isNaN);
-    assert(x1.get == int.min);
-    assert(x1 != x1);
-    assert(!(x1 < x1));
-    assert(!(x1 > x1));
-    assert(!(x1 == x1));
-    ++x1;
-    assert(x1.isNaN);
-    assert(x1.get == int.min);
-    --x1;
-    assert(x1.isNaN);
-    assert(x1.get == int.min);
-    x1 = 42;
-    assert(!x1.isNaN);
-    assert(x1 == x1);
-    assert(x1 <= x1);
-    assert(x1 >= x1);
-    static assert(x1.min == int.min + 1);
-    x1 += long(int.max);
-}
-
-/**
-Queries whether a $(D Checked!(T, WithNaN)) object is not a number (NaN).
-
-Params: x = the `Checked` instance queried
-
-Returns: `true` if `x` is a NaN, `false` otherwise
-*/
-bool isNaN(T)(const Checked!(T, WithNaN) x)
-{
-    return x.get == x.init.get;
-}
-
-///
-@safe unittest
-{
-    auto x1 = Checked!(int, WithNaN)();
-    assert(x1.isNaN);
-    x1 = 1;
-    assert(!x1.isNaN);
-    x1 = x1.init;
-    assert(x1.isNaN);
-}
-
-@safe unittest
-{
-    void test1(T)()
-    {
-        auto x1 = Checked!(T, WithNaN)();
-        assert(x1.isNaN);
-        assert(x1.get == int.min);
-        assert(x1 != x1);
-        assert(!(x1 < x1));
-        assert(!(x1 > x1));
-        assert(!(x1 == x1));
-        assert(x1.get == int.min);
-        auto x2 = Checked!(T, WithNaN)(42);
-        assert(!x2.isNaN);
-        assert(x2 == x2);
-        assert(x2 <= x2);
-        assert(x2 >= x2);
-        static assert(x2.min == T.min + 1);
-    }
-    test1!int;
-    test1!(const int);
-    test1!(immutable int);
-
-    void test2(T)()
-    {
-        auto x1 = Checked!(T, WithNaN)();
-        assert(x1.get == T.min);
-        assert(x1 != x1);
-        assert(!(x1 < x1));
-        assert(!(x1 > x1));
-        assert(!(x1 == x1));
-        ++x1;
-        assert(x1.get == T.min);
-        --x1;
-        assert(x1.get == T.min);
-        x1 = 42;
-        assert(x1 == x1);
-        assert(x1 <= x1);
-        assert(x1 >= x1);
-        static assert(x1.min == T.min + 1);
-        x1 += long(T.max);
-    }
-    test2!int;
-}
-
-@safe unittest
-{
-    alias Smart(T) = Checked!(Checked!(T, ProperCompare), WithNaN);
-    Smart!int x1;
-    assert(x1 != x1);
-    x1 = -1;
-    assert(x1 < 1u);
-    auto x2 = Smart!(const int)(42);
-}
-
-// Saturate
-/**
-
-Hook that implements $(I saturation), i.e. any arithmetic operation that would
-overflow leaves the result at its extreme value (`min` or `max` depending on the
-direction of the overflow).
-
-Saturation is not sticky; if a value reaches its saturation value, another
-operation may take it back to normal range.
-
-*/
-struct Saturate
-{
-static:
-    /**
-
-    Implements saturation for operators `+=`, `-=`, `*=`, `/=`, `%=`, `^^=`, `&=`, `|=`, `^=`, `<<=`, `>>=`,
-    and `>>>=`. This hook is called if the result of the binary operation does
-    not fit in `Lhs` without loss of information or a change in sign.
-
-    Params:
-    Rhs = The right-hand side type in the assignment, after the operation has
-    been computed
-    bound = The bound being violated
-
-    Returns: `Lhs.max` if $(D rhs >= 0), `Lhs.min` otherwise.
-
-    */
-    T onLowerBound(Rhs, T)(Rhs rhs, T bound)
-    {
-        return bound;
-    }
-    /// ditto
-    T onUpperBound(Rhs, T)(Rhs rhs, T bound)
-    {
-        return bound;
-    }
-    ///
-    @safe unittest
-    {
-        auto x = checked!Saturate(short(100));
-        x += 33000;
-        assert(x == short.max);
-        x -= 70000;
-        assert(x == short.min);
-    }
-
-    /**
-
-    Implements saturation for operators `+`, `-` (unary and binary), `*`, `/`,
-    `%`, `^^`, `&`, `|`, `^`, `<<`, `>>`, and `>>>`.
-
-    For unary `-`, `onOverflow` is called if $(D lhs == Lhs.min) and `Lhs` is a
-    signed type. The function returns `Lhs.max`.
-
-    For binary operators, the result is as follows: $(UL $(LI `Lhs.max` if the
-    result overflows in the positive direction, on division by `0`, or on
-    shifting right by a negative value) $(LI `Lhs.min` if the result overflows
-    in the negative direction) $(LI `0` if `lhs` is being shifted left by a
-    negative value, or shifted right by a large positive value))
-
-    Params:
-    x = The operator involved in the `opAssign` operation
-    Lhs = The left-hand side of the operator (`Lhs` is the first argument to
-    `Checked`)
-    Rhs = The right-hand side type in the operator
-
-    Returns: The saturated result of the operator.
-
-    */
-    auto onOverflow(string x, Lhs)(Lhs lhs)
-    {
-        static assert(x == "-" || x == "++" || x == "--");
-        return x == "--" ? Lhs.min : Lhs.max;
-    }
-    /// ditto
-    typeof(Lhs() + Rhs()) onOverflow(string x, Lhs, Rhs)(Lhs lhs, Rhs rhs)
-    {
-        static if (x == "+")
-            return rhs >= 0 ? Lhs.max : Lhs.min;
-        else static if (x == "*")
-            return (lhs >= 0) == (rhs >= 0) ? Lhs.max : Lhs.min;
-        else static if (x == "^^")
-            return lhs > 0 || !(rhs & 1) ? Lhs.max : Lhs.min;
-        else static if (x == "-")
-            return rhs >= 0 ? Lhs.min : Lhs.max;
-        else static if (x == "/" || x == "%")
-            return Lhs.max;
-        else static if (x == "<<")
-            return rhs >= 0 ? Lhs.max : 0;
-        else static if (x == ">>" || x == ">>>")
-            return rhs >= 0 ? 0 : Lhs.max;
-        else
-            static assert(false);
-    }
-    ///
-    @safe unittest
-    {
-        assert(checked!Saturate(int.max) + 1 == int.max);
-        assert(checked!Saturate(100) ^^ 10 == int.max);
-        assert(checked!Saturate(-100) ^^ 10 == int.max);
-        assert(checked!Saturate(100) / 0 == int.max);
-        assert(checked!Saturate(100) << -1 == 0);
-        assert(checked!Saturate(100) << 33 == int.max);
-        assert(checked!Saturate(100) >> -1 == int.max);
-        assert(checked!Saturate(100) >> 33 == 0);
-    }
-}
-
-///
-@safe unittest
-{
-    auto x = checked!Saturate(int.max);
-    ++x;
-    assert(x == int.max);
-    --x;
-    assert(x == int.max - 1);
-    x = int.min;
-    assert(-x == int.max);
-    x -= 42;
-    assert(x == int.min);
-    assert(x * -2 == int.max);
-}
-
-/*
-Yields `true` if `T1` is "value convertible" (by C's "value preserving" rule,
-see $(HTTP c-faq.com/expr/preservingrules.html)) to `T2`, where the two are
-integral types. That is, all of values in `T1` are also in `T2`. For example
-`int` is value convertible to `long` but not to `uint` or `ulong`.
-*/
-private enum valueConvertible(T1, T2) = isIntegral!T1 && isIntegral!T2 &&
-    is(T1 : T2) && (
-        isUnsigned!T1 == isUnsigned!T2 || // same signedness
-        !isUnsigned!T2 && T2.sizeof > T1.sizeof // safely convertible
-    );
-
-/**
-
-Defines binary operations with overflow checking for any two integral types.
-The result type obeys the language rules (even when they may be
-counterintuitive), and `overflow` is set if an overflow occurs (including
-inadvertent change of signedness, e.g. `-1` is converted to `uint`).
-Conceptually the behavior is:
-
-$(OL $(LI Perform the operation in infinite precision)
-$(LI If the infinite-precision result fits in the result type, return it and
-do not touch `overflow`)
-$(LI Otherwise, set `overflow` to `true` and return an unspecified value)
-)
-
-The implementation exploits properties of types and operations to minimize
-additional work.
-
-Params:
-x = The binary operator involved, e.g. `/`
-lhs = The left-hand side of the operator
-rhs = The right-hand side of the operator
-overflow = The overflow indicator (assigned `true` in case there's an error)
-
-Returns:
-The result of the operation, which is the same as the built-in operator
-*/
-typeof(mixin(x == "cmp" ? "0" : ("L() " ~ x ~ " R()")))
-opChecked(string x, L, R)(const L lhs, const R rhs, ref bool overflow)
-if (isIntegral!L && isIntegral!R)
-{
-    static if (x == "cmp")
-        alias Result = int;
-    else
-        alias Result = typeof(mixin("L() " ~ x ~ " R()"));
-
-    import core.checkedint : addu, adds, subs, muls, subu, mulu;
-    import std.algorithm.comparison : among;
-    static if (x == "==")
-    {
-        alias C = typeof(lhs + rhs);
-        static if (valueConvertible!(L, C) && valueConvertible!(R, C))
-        {
-            // Values are converted to R before comparison, cool.
-            return lhs == rhs;
-        }
-        else
-        {
-            static assert(isUnsigned!C);
-            static assert(isUnsigned!L != isUnsigned!R);
-            if (lhs != rhs) return false;
-            // R(lhs) and R(rhs) have the same bit pattern, yet may be
-            // different due to signedness change.
-            static if (!isUnsigned!R)
-            {
-                if (rhs >= 0)
-                    return true;
-            }
-            else
-            {
-                if (lhs >= 0)
-                    return true;
-            }
-            overflow = true;
-            return true;
-        }
-    }
-    else static if (x == "cmp")
-    {
-        alias C = typeof(lhs + rhs);
-        static if (!valueConvertible!(L, C) || !valueConvertible!(R, C))
-        {
-            static assert(isUnsigned!C);
-            static assert(isUnsigned!L != isUnsigned!R);
-            if (!isUnsigned!L && lhs < 0)
-            {
-                overflow = true;
-                return -1;
-            }
-            if (!isUnsigned!R && rhs < 0)
-            {
-                overflow = true;
-                return 1;
-            }
-        }
-        return lhs < rhs ? -1 : lhs > rhs;
-    }
-    else static if (x.among("<<", ">>", ">>>"))
-    {
-        // Handle shift separately from all others. The test below covers
-        // negative rhs as well.
-        import std.conv : unsigned;
-        if (unsigned(rhs) > 8 * Result.sizeof) goto fail;
-        return mixin("lhs" ~ x ~ "rhs");
-    }
-    else static if (x.among("&", "|", "^"))
-    {
-        // Nothing to check
-        return mixin("lhs" ~ x ~ "rhs");
-    }
-    else static if (x == "^^")
-    {
-        // Exponentiation is weird, handle separately
-        return pow(lhs, rhs, overflow);
-    }
-    else static if (valueConvertible!(L, Result) &&
-            valueConvertible!(R, Result))
-    {
-        static if (L.sizeof < Result.sizeof && R.sizeof < Result.sizeof &&
-            x.among("+", "-", "*"))
-        {
-            // No checks - both are value converted and result is in range
-            return mixin("lhs" ~ x ~ "rhs");
-        }
-        else static if (x == "+")
-        {
-            static if (isUnsigned!Result) alias impl = addu;
-            else alias impl = adds;
-            return impl(Result(lhs), Result(rhs), overflow);
-        }
-        else static if (x == "-")
-        {
-            static if (isUnsigned!Result) alias impl = subu;
-            else alias impl = subs;
-            return impl(Result(lhs), Result(rhs), overflow);
-        }
-        else static if (x == "*")
-        {
-            static if (!isUnsigned!L && !isUnsigned!R &&
-                is(L == Result))
-            {
-                if (lhs == Result.min && rhs == -1) goto fail;
-            }
-            static if (isUnsigned!Result) alias impl = mulu;
-            else alias impl = muls;
-            return impl(Result(lhs), Result(rhs), overflow);
-        }
-        else static if (x == "/" || x == "%")
-        {
-            static if (!isUnsigned!L && !isUnsigned!R &&
-                is(L == Result) && x == "/")
-            {
-                if (lhs == Result.min && rhs == -1) goto fail;
-            }
-            if (rhs == 0) goto fail;
-            return mixin("lhs" ~ x ~ "rhs");
-        }
-        else static assert(0, x);
-    }
-    else // Mixed signs
-    {
-        static assert(isUnsigned!Result);
-        static assert(isUnsigned!L != isUnsigned!R);
-        static if (x == "+")
-        {
-            static if (!isUnsigned!L)
-            {
-                if (lhs < 0)
-                    return subu(Result(rhs), Result(-lhs), overflow);
-            }
-            else static if (!isUnsigned!R)
-            {
-                if (rhs < 0)
-                    return subu(Result(lhs), Result(-rhs), overflow);
-            }
-            return addu(Result(lhs), Result(rhs), overflow);
-        }
-        else static if (x == "-")
-        {
-            static if (!isUnsigned!L)
-            {
-                if (lhs < 0) goto fail;
-            }
-            else static if (!isUnsigned!R)
-            {
-                if (rhs < 0)
-                    return addu(Result(lhs), Result(-rhs), overflow);
-            }
-            return subu(Result(lhs), Result(rhs), overflow);
-        }
-        else static if (x == "*")
-        {
-            static if (!isUnsigned!L)
-            {
-                if (lhs < 0) goto fail;
-            }
-            else static if (!isUnsigned!R)
-            {
-                if (rhs < 0) goto fail;
-            }
-            return mulu(Result(lhs), Result(rhs), overflow);
-        }
-        else static if (x == "/" || x == "%")
-        {
-            static if (!isUnsigned!L)
-            {
-                if (lhs < 0 || rhs == 0) goto fail;
-            }
-            else static if (!isUnsigned!R)
-            {
-                if (rhs <= 0) goto fail;
-            }
-            return mixin("Result(lhs)" ~ x ~ "Result(rhs)");
-        }
-        else static assert(0, x);
-    }
-    debug assert(false);
-fail:
-    overflow = true;
-    return Result(0);
-}
-
-///
-@safe unittest
-{
-    bool overflow;
-    assert(opChecked!"+"(const short(1), short(1), overflow) == 2 && !overflow);
-    assert(opChecked!"+"(1, 1, overflow) == 2 && !overflow);
-    assert(opChecked!"+"(1, 1u, overflow) == 2 && !overflow);
-    assert(opChecked!"+"(-1, 1u, overflow) == 0 && !overflow);
-    assert(opChecked!"+"(1u, -1, overflow) == 0 && !overflow);
-}
-
-///
-@safe unittest
-{
-    bool overflow;
-    assert(opChecked!"-"(1, 1, overflow) == 0 && !overflow);
-    assert(opChecked!"-"(1, 1u, overflow) == 0 && !overflow);
-    assert(opChecked!"-"(1u, -1, overflow) == 2 && !overflow);
-    assert(opChecked!"-"(-1, 1u, overflow) == 0 && overflow);
-}
-
-@safe unittest
-{
-    bool overflow;
-    assert(opChecked!"*"(2, 3, overflow) == 6 && !overflow);
-    assert(opChecked!"*"(2, 3u, overflow) == 6 && !overflow);
-    assert(opChecked!"*"(1u, -1, overflow) == 0 && overflow);
-    //assert(mul(-1, 1u, overflow) == uint.max - 1 && overflow);
-}
-
-@safe unittest
-{
-    bool overflow;
-    assert(opChecked!"/"(6, 3, overflow) == 2 && !overflow);
-    assert(opChecked!"/"(6, 3, overflow) == 2 && !overflow);
-    assert(opChecked!"/"(6u, 3, overflow) == 2 && !overflow);
-    assert(opChecked!"/"(6, 3u, overflow) == 2 && !overflow);
-    assert(opChecked!"/"(11, 0, overflow) == 0 && overflow);
-    overflow = false;
-    assert(opChecked!"/"(6u, 0, overflow) == 0 && overflow);
-    overflow = false;
-    assert(opChecked!"/"(-6, 2u, overflow) == 0 && overflow);
-    overflow = false;
-    assert(opChecked!"/"(-6, 0u, overflow) == 0 && overflow);
-    overflow = false;
-    assert(opChecked!"cmp"(0u, -6, overflow) == 1 && overflow);
-    overflow = false;
-    assert(opChecked!"|"(1, 2, overflow) == 3 && !overflow);
-}
-
-/*
-Exponentiation function used by the implementation of operator `^^`.
-*/
-private pure @safe nothrow @nogc
-auto pow(L, R)(const L lhs, const R rhs, ref bool overflow)
-if (isIntegral!L && isIntegral!R)
-{
-    if (rhs <= 1)
-    {
-        if (rhs == 0) return 1;
-        static if (!isUnsigned!R)
-            return rhs == 1
-                ? lhs
-                : (rhs == -1 && (lhs == 1 || lhs == -1)) ? lhs : 0;
-        else
-            return lhs;
-    }
-
-    typeof(lhs ^^ rhs) b = void;
-    static if (!isUnsigned!L && isUnsigned!(typeof(b)))
-    {
-        // Need to worry about mixed-sign stuff
-        if (lhs < 0)
-        {
-            if (rhs & 1)
-            {
-                if (lhs < 0) overflow = true;
-                return 0;
-            }
-            b = -lhs;
-        }
-        else
-        {
-            b = lhs;
-        }
-    }
-    else
-    {
-        b = lhs;
-    }
-    if (b == 1) return 1;
-    if (b == -1) return (rhs & 1) ? -1 : 1;
-    if (rhs > 63)
-    {
-        overflow = true;
-        return 0;
-    }
-
-    assert((b > 1 || b < -1) && rhs > 1);
-    return powImpl(b, cast(uint) rhs, overflow);
-}
-
-// Inspiration: http://www.stepanovpapers.com/PAM.pdf
-pure @safe nothrow @nogc
-private T powImpl(T)(T b, uint e, ref bool overflow)
-if (isIntegral!T && T.sizeof >= 4)
-{
-    assert(e > 1);
-
-    import core.checkedint : muls, mulu;
-    static if (isUnsigned!T) alias mul = mulu;
-    else alias mul = muls;
-
-    T r = b;
-    --e;
-    // Loop invariant: r * (b ^^ e) is the actual result
-    for (;; e /= 2)
-    {
-        if (e % 2)
-        {
-            r = mul(r, b, overflow);
-            if (e == 1) break;
-        }
-        b = mul(b, b, overflow);
-    }
-    return r;
-}
-
-@safe unittest
-{
-    static void testPow(T)(T x, uint e)
-    {
-        bool overflow;
-        assert(opChecked!"^^"(T(0), 0, overflow) == 1);
-        assert(opChecked!"^^"(-2, T(0), overflow) == 1);
-        assert(opChecked!"^^"(-2, T(1), overflow) == -2);
-        assert(opChecked!"^^"(-1, -1, overflow) == -1);
-        assert(opChecked!"^^"(-2, 1, overflow) == -2);
-        assert(opChecked!"^^"(-2, -1, overflow) == 0);
-        assert(opChecked!"^^"(-2, 4u, overflow) == 16);
-        assert(!overflow);
-        assert(opChecked!"^^"(-2, 3u, overflow) == 0);
-        assert(overflow);
-        overflow = false;
-        assert(opChecked!"^^"(3, 64u, overflow) == 0);
-        assert(overflow);
-        overflow = false;
-        foreach (uint i; 0 .. e)
-        {
-            assert(opChecked!"^^"(x, i, overflow) == x ^^ i);
-            assert(!overflow);
-        }
-        assert(opChecked!"^^"(x, e, overflow) == x ^^ e);
-        assert(overflow);
-    }
-
-    testPow!int(3, 21);
-    testPow!uint(3, 21);
-    testPow!long(3, 40);
-    testPow!ulong(3, 41);
-}
-
-version (StdUnittest) private struct CountOverflows
-{
-    uint calls;
-    auto onOverflow(string op, Lhs)(Lhs lhs)
-    {
-        ++calls;
-        return mixin(op ~ "lhs");
-    }
-    auto onOverflow(string op, Lhs, Rhs)(Lhs lhs, Rhs rhs)
-    {
-        ++calls;
-        return mixin("lhs" ~ op ~ "rhs");
-    }
-    T onLowerBound(Rhs, T)(Rhs rhs, T bound)
-    {
-        ++calls;
-        return cast(T) rhs;
-    }
-    T onUpperBound(Rhs, T)(Rhs rhs, T bound)
-    {
-        ++calls;
-        return cast(T) rhs;
-    }
-}
-
-// opBinary
-@nogc nothrow pure @safe unittest
-{
-    static struct CountOpBinary
-    {
-        uint calls;
-        auto hookOpBinary(string op, Lhs, Rhs)(Lhs lhs, Rhs rhs)
-        {
-            ++calls;
-            return mixin("lhs" ~ op ~ "rhs");
-        }
-    }
-    auto x = Checked!(const int, void)(42), y = Checked!(immutable int, void)(142);
-    assert(x + y == 184);
-    assert(x + 100 == 142);
-    assert(y - x == 100);
-    assert(200 - x == 158);
-    assert(y * x == 142 * 42);
-    assert(x / 1 == 42);
-    assert(x % 20 == 2);
-
-    auto x1 = Checked!(int, CountOverflows)(42);
-    assert(x1 + 0 == 42);
-    assert(x1 + false == 42);
-    assert(is(typeof(x1 + 0.5) == double));
-    assert(x1 + 0.5 == 42.5);
-    assert(x1.hook.calls == 0);
-    assert(x1 + int.max == int.max + 42);
-    assert(x1.hook.calls == 1);
-    assert(x1 * 2 == 84);
-    assert(x1.hook.calls == 1);
-    assert(x1 / 2 == 21);
-    assert(x1.hook.calls == 1);
-    assert(x1 % 20 == 2);
-    assert(x1.hook.calls == 1);
-    assert(x1 << 2 == 42 << 2);
-    assert(x1.hook.calls == 1);
-    assert(x1 << 42 == x1.get << x1.get);
-    assert(x1.hook.calls == 2);
-    x1 = int.min;
-    assert(x1 - 1 == int.max);
-    assert(x1.hook.calls == 3);
-
-    auto x2 = Checked!(int, CountOpBinary)(42);
-    assert(x2 + 1 == 43);
-    assert(x2.hook.calls == 1);
-
-    auto x3 = Checked!(uint, CountOverflows)(42u);
-    assert(x3 + 1 == 43);
-    assert(x3.hook.calls == 0);
-    assert(x3 - 1 == 41);
-    assert(x3.hook.calls == 0);
-    assert(x3 + (-42) == 0);
-    assert(x3.hook.calls == 0);
-    assert(x3 - (-42) == 84);
-    assert(x3.hook.calls == 0);
-    assert(x3 * 2 == 84);
-    assert(x3.hook.calls == 0);
-    assert(x3 * -2 == -84);
-    assert(x3.hook.calls == 1);
-    assert(x3 / 2 == 21);
-    assert(x3.hook.calls == 1);
-    assert(x3 / -2 == 0);
-    assert(x3.hook.calls == 2);
-    assert(x3 ^^ 2 == 42 * 42);
-    assert(x3.hook.calls == 2);
-
-    auto x4 = Checked!(int, CountOverflows)(42);
-    assert(x4 + 1 == 43);
-    assert(x4.hook.calls == 0);
-    assert(x4 + 1u == 43);
-    assert(x4.hook.calls == 0);
-    assert(x4 - 1 == 41);
-    assert(x4.hook.calls == 0);
-    assert(x4 * 2 == 84);
-    assert(x4.hook.calls == 0);
-    x4 = -2;
-    assert(x4 + 2u == 0);
-    assert(x4.hook.calls == 0);
-    assert(x4 * 2u == -4);
-    assert(x4.hook.calls == 1);
-
-    auto x5 = Checked!(int, CountOverflows)(3);
-    assert(x5 ^^ 0 == 1);
-    assert(x5 ^^ 1 == 3);
-    assert(x5 ^^ 2 == 9);
-    assert(x5 ^^ 3 == 27);
-    assert(x5 ^^ 4 == 81);
-    assert(x5 ^^ 5 == 81 * 3);
-    assert(x5 ^^ 6 == 81 * 9);
-}
-
-// opBinaryRight
-@nogc nothrow pure @safe unittest
-{
-    auto x1 = Checked!(int, CountOverflows)(42);
-    assert(1 + x1 == 43);
-    assert(true + x1 == 43);
-    assert(0.5 + x1 == 42.5);
-    auto x2 = Checked!(int, void)(42);
-    assert(x1 + x2 == 84);
-    assert(x2 + x1   == 84);
-}
-
-// opOpAssign
-@safe unittest
-{
-    auto x1 = Checked!(int, CountOverflows)(3);
-    assert((x1 += 2) == 5);
-    x1 *= 2_000_000_000L;
-    assert(x1.hook.calls == 1);
-    x1 *= -2_000_000_000L;
-    assert(x1.hook.calls == 2);
-
-    auto x2 = Checked!(ushort, CountOverflows)(ushort(3));
-    assert((x2 += 2) == 5);
-    assert(x2.hook.calls == 0);
-    assert((x2 += ushort.max) == cast(ushort) (ushort(5) + ushort.max));
-    assert(x2.hook.calls == 1);
-
-    auto x3 = Checked!(uint, CountOverflows)(3u);
-    x3 *= ulong(2_000_000_000);
-    assert(x3.hook.calls == 1);
-}
-
-// opAssign
-@safe unittest
-{
-    Checked!(int, void) x;
-    x = 42;
-    assert(x.get == 42);
-    x = x;
-    assert(x.get == 42);
-    x = short(43);
-    assert(x.get == 43);
-    x = ushort(44);
-    assert(x.get == 44);
-}
-
-@safe unittest
-{
-    static assert(!is(typeof(Checked!(short, void)(ushort(42)))));
-    static assert(!is(typeof(Checked!(int, void)(long(42)))));
-    static assert(!is(typeof(Checked!(int, void)(ulong(42)))));
-    assert(Checked!(short, void)(short(42)).get == 42);
-    assert(Checked!(int, void)(ushort(42)).get == 42);
-}
-
-// opCast
-@nogc nothrow pure @safe unittest
-{
-    static assert(is(typeof(cast(float) Checked!(int, void)(42)) == float));
-    assert(cast(float) Checked!(int, void)(42) == 42);
-
-    assert(is(typeof(cast(long) Checked!(int, void)(42)) == long));
-    assert(cast(long) Checked!(int, void)(42) == 42);
-    static assert(is(typeof(cast(long) Checked!(uint, void)(42u)) == long));
-    assert(cast(long) Checked!(uint, void)(42u) == 42);
-
-    auto x = Checked!(int, void)(42);
-    if (x) {} else assert(0);
-    x = 0;
-    if (x) assert(0);
-
-    static struct Hook1
-    {
-        uint calls;
-        Dst hookOpCast(Dst, Src)(Src value)
-        {
-            ++calls;
-            return 42;
-        }
-    }
-    auto y = Checked!(long, Hook1)(long.max);
-    assert(cast(int) y == 42);
-    assert(cast(uint) y == 42);
-    assert(y.hook.calls == 2);
-
-    static struct Hook2
-    {
-        uint calls;
-        Dst onBadCast(Dst, Src)(Src value)
-        {
-            ++calls;
-            return 42;
-        }
-    }
-    auto x1 = Checked!(uint, Hook2)(100u);
-    assert(cast(ushort) x1 == 100);
-    assert(cast(short) x1 == 100);
-    assert(cast(float) x1 == 100);
-    assert(cast(double) x1 == 100);
-    assert(cast(real) x1 == 100);
-    assert(x1.hook.calls == 0);
-    assert(cast(int) x1 == 100);
-    assert(x1.hook.calls == 0);
-    x1 = uint.max;
-    assert(cast(int) x1 == 42);
-    assert(x1.hook.calls == 1);
-
-    auto x2 = Checked!(int, Hook2)(-100);
-    assert(cast(short) x2 == -100);
-    assert(cast(ushort) x2 == 42);
-    assert(cast(uint) x2 == 42);
-    assert(cast(ulong) x2 == 42);
-    assert(x2.hook.calls == 3);
-}
-
-// opEquals
-@nogc nothrow pure @safe unittest
-{
-    assert(Checked!(int, void)(42) == 42L);
-    assert(42UL == Checked!(int, void)(42));
-
-    static struct Hook1
-    {
-        uint calls;
-        bool hookOpEquals(Lhs, Rhs)(const Lhs lhs, const Rhs rhs)
-        {
-            ++calls;
-            return lhs != rhs;
-        }
-    }
-    auto x1 = Checked!(int, Hook1)(100);
-    assert(x1 != Checked!(long, Hook1)(100));
-    assert(x1.hook.calls == 1);
-    assert(x1 != 100u);
-    assert(x1.hook.calls == 2);
-
-    static struct Hook2
-    {
-        uint calls;
-        bool hookOpEquals(Lhs, Rhs)(Lhs lhs, Rhs rhs)
-        {
-            ++calls;
-            return false;
-        }
-    }
-    auto x2 = Checked!(int, Hook2)(-100);
-    assert(x2 != x1);
-    // For coverage: lhs has no hookOpEquals, rhs does
-    assert(Checked!(uint, void)(100u) != x2);
-    // For coverage: different types, neither has a hookOpEquals
-    assert(Checked!(uint, void)(100u) == Checked!(int, void*)(100));
-    assert(x2.hook.calls == 0);
-    assert(x2 != -100);
-    assert(x2.hook.calls == 1);
-    assert(x2 != cast(uint) -100);
-    assert(x2.hook.calls == 2);
-    x2 = 100;
-    assert(x2 != cast(uint) 100);
-    assert(x2.hook.calls == 3);
-    x2 = -100;
-
-    auto x3 = Checked!(uint, Hook2)(100u);
-    assert(x3 != 100);
-    x3 = uint.max;
-    assert(x3 != -1);
-
-    assert(x2 != x3);
-}
-
-// opCmp
-@nogc nothrow pure @safe unittest
-{
-    Checked!(int, void) x;
-    assert(x <= x);
-    assert(x < 45);
-    assert(x < 45u);
-    assert(x > -45);
-    assert(x < 44.2);
-    assert(x > -44.2);
-    assert(!(x < double.init));
-    assert(!(x > double.init));
-    assert(!(x <= double.init));
-    assert(!(x >= double.init));
-
-    static struct Hook1
-    {
-        uint calls;
-        int hookOpCmp(Lhs, Rhs)(Lhs lhs, Rhs rhs)
-        {
-            ++calls;
-            return 0;
-        }
-    }
-    auto x1 = Checked!(int, Hook1)(42);
-    assert(!(x1 < 43u));
-    assert(!(43u < x1));
-    assert(x1.hook.calls == 2);
-
-    static struct Hook2
-    {
-        uint calls;
-        int hookOpCmp(Lhs, Rhs)(Lhs lhs, Rhs rhs)
-        {
-            ++calls;
-            return ProperCompare.hookOpCmp(lhs, rhs);
-        }
-    }
-    auto x2 = Checked!(int, Hook2)(-42);
-    assert(x2 < 43u);
-    assert(43u > x2);
-    assert(x2.hook.calls == 2);
-    x2 = 42;
-    assert(x2 > 41u);
-
-    auto x3 = Checked!(uint, Hook2)(42u);
-    assert(x3 > 41);
-    assert(x3 > -41);
-}
-
-// opUnary
-@nogc nothrow pure @safe unittest
-{
-    auto x = Checked!(int, void)(42);
-    assert(x == +x);
-    static assert(is(typeof(-x) == typeof(x)));
-    assert(-x == Checked!(int, void)(-42));
-    static assert(is(typeof(~x) == typeof(x)));
-    assert(~x == Checked!(int, void)(~42));
-    assert(++x == 43);
-    assert(--x == 42);
-
-    static struct Hook1
-    {
-        uint calls;
-        auto hookOpUnary(string op, T)(T value) if (op == "-")
-        {
-            ++calls;
-            return T(42);
-        }
-        auto hookOpUnary(string op, T)(T value) if (op == "~")
-        {
-            ++calls;
-            return T(43);
-        }
-    }
-    auto x1 = Checked!(int, Hook1)(100);
-    assert(is(typeof(-x1) == typeof(x1)));
-    assert(-x1 == Checked!(int, Hook1)(42));
-    assert(is(typeof(~x1) == typeof(x1)));
-    assert(~x1 == Checked!(int, Hook1)(43));
-    assert(x1.hook.calls == 2);
-
-    static struct Hook2
-    {
-        uint calls;
-        void hookOpUnary(string op, T)(ref T value) if (op == "++")
-        {
-            ++calls;
-            --value;
-        }
-        void hookOpUnary(string op, T)(ref T value) if (op == "--")
-        {
-            ++calls;
-            ++value;
-        }
-    }
-    auto x2 = Checked!(int, Hook2)(100);
-    assert(++x2 == 99);
-    assert(x2 == 99);
-    assert(--x2 == 100);
-    assert(x2 == 100);
-
-    auto x3 = Checked!(int, CountOverflows)(int.max - 1);
-    assert(++x3 == int.max);
-    assert(x3.hook.calls == 0);
-    assert(++x3 == int.min);
-    assert(x3.hook.calls == 1);
-    assert(-x3 == int.min);
-    assert(x3.hook.calls == 2);
-
-    x3 = int.min + 1;
-    assert(--x3 == int.min);
-    assert(x3.hook.calls == 2);
-    assert(--x3 == int.max);
-    assert(x3.hook.calls == 3);
-}
-
-//
-@nogc nothrow pure @safe unittest
-{
-    Checked!(int, void) x;
-    assert(x == x);
-    assert(x == +x);
-    assert(x == -x);
-    ++x;
-    assert(x == 1);
-    x++;
-    assert(x == 2);
-
-    x = 42;
-    assert(x == 42);
-    const short _short = 43;
-    x = _short;
-    assert(x == _short);
-    ushort _ushort = 44;
-    x = _ushort;
-    assert(x == _ushort);
-    assert(x == 44.0);
-    assert(x != 44.1);
-    assert(x < 45);
-    assert(x < 44.2);
-    assert(x > -45);
-    assert(x > -44.2);
-
-    assert(cast(long) x == 44);
-    assert(cast(short) x == 44);
-
-    const Checked!(uint, void) y;
-    assert(y <= y);
-    assert(y == 0);
-    assert(y < x);
-    x = -1;
-    assert(x > y);
-}
-
-@nogc nothrow pure @safe unittest
-{
-    alias cint = Checked!(int, void);
-    cint a = 1, b = 2;
-    a += b;
-    assert(a == cint(3));
-
-    alias ccint = Checked!(cint, Saturate);
-    ccint c = 14;
-    a += c;
-    assert(a == cint(17));
-}
-
-// toHash
-@safe unittest
-{
-    assert(checked(42).toHash() == checked(42).toHash());
-    assert(checked(12).toHash() != checked(19).toHash());
-
-    static struct Hook1
-    {
-        static size_t hookToHash(T)(T payload) nothrow @trusted
-        {
-            static if (size_t.sizeof == 4)
-            {
-                return typeid(payload).getHash(&payload) ^ 0xFFFF_FFFF;
-            }
-            else
-            {
-                return typeid(payload).getHash(&payload) ^ 0xFFFF_FFFF_FFFF_FFFF;
-            }
-
-        }
-    }
-
-    auto a = checked!Hook1(78);
-    auto b = checked!Hook1(78);
-    assert(a.toHash() == b.toHash());
-
-    assert(checked!Hook1(12).toHash() != checked!Hook1(13).toHash());
-
-    static struct Hook2
-    {
-        static if (size_t.sizeof == 4)
-        {
-            static size_t hashMask = 0xFFFF_0000;
-        }
-        else
-        {
-            static size_t hashMask = 0xFFFF_0000_FFFF_0000;
-        }
-
-        static size_t hookToHash(T)(T payload) nothrow @trusted
-        {
-            return typeid(payload).getHash(&payload) ^ hashMask;
-        }
-    }
-
-    auto x = checked!Hook2(1901);
-    auto y = checked!Hook2(1989);
-
-    assert((() nothrow @safe => x.toHash() == x.toHash())());
-
-    assert(x.toHash() == x.toHash());
-    assert(x.toHash() != y.toHash());
-    assert(checked!Hook1(1901).toHash() != x.toHash());
-
-    immutable z = checked!Hook1(1901);
-    immutable t = checked!Hook1(1901);
-    immutable w = checked!Hook2(1901);
-
-    assert(z.toHash() == t.toHash());
-    assert(z.toHash() != x.toHash());
-    assert(z.toHash() != w.toHash());
-
-    const long c = 0xF0F0F0F0;
-    const long d = 0xF0F0F0F0;
-
-    assert(checked!Hook1(c).toHash() != checked!Hook2(c));
-    assert(checked!Hook1(c).toHash() != checked!Hook1(d));
-
-    // Hook with state, does not implement hookToHash
-    static struct Hook3
-    {
-        ulong var1 = ulong.max;
-        uint var2 = uint.max;
-    }
-
-    assert(checked!Hook3(12).toHash() != checked!Hook3(13).toHash());
-    assert(checked!Hook3(13).toHash() == checked!Hook3(13).toHash());
-
-    // Hook with no state and no hookToHash, payload has its own hashing function
-    auto x1 = Checked!(Checked!int, ProperCompare)(123);
-    auto x2 = Checked!(Checked!int, ProperCompare)(123);
-    auto x3 = Checked!(Checked!int, ProperCompare)(144);
-
-    assert(x1.toHash() == x2.toHash());
-    assert(x1.toHash() != x3.toHash());
-    assert(x2.toHash() != x3.toHash());
-
-    // Check shared.
-    {
-        shared shared0 = checked(12345678);
-        shared shared1 = checked!Hook1(123456789);
-        shared shared2 = checked!Hook2(234567891);
-        shared shared3 = checked!Hook3(345678912);
-        assert(shared0.toHash() == hashOf(shared0));
-        assert(shared1.toHash() == hashOf(shared1));
-        assert(shared2.toHash() == hashOf(shared2));
-        assert(shared3.toHash() == hashOf(shared3));
-    }
-}
-
-///
-@safe unittest
-{
-    struct MyHook
-    {
-        static size_t hookToHash(T)(const T payload) nothrow @trusted
-        {
-            return .hashOf(payload);
-        }
-    }
-
-    int[Checked!(int, MyHook)] aa;
-    Checked!(int, MyHook) var = 42;
-    aa[var] = 100;
-
-    assert(aa[var] == 100);
-
-    int[Checked!(int, Abort)] bb;
-    Checked!(int, Abort) var2 = 42;
-    bb[var2] = 100;
-
-    assert(bb[var2] == 100);
-}
+ * This module is now deprecated, use $(MREF std, experimental)
+ * instead.
+ *
+ * Copyright: Copyright The D Language Foundation 2005 - 2015.
+ * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
+ * Authors:
+ * Source:    $(PHOBOSSRC std/experimental/checkedint.d)
+ *
+ * $(SCRIPT inhibitQuickIndex = 1;)
+ */
+deprecated module std.experimental.checkedint;
+public import std.checkedint;
diff --git a/libphobos/src/std/experimental/logger/core.d b/libphobos/src/std/experimental/logger/core.d
index 08d6cbe..afd98ad 100644
--- a/libphobos/src/std/experimental/logger/core.d
+++ b/libphobos/src/std/experimental/logger/core.d
@@ -1633,13 +1633,14 @@
     import std.concurrency : initOnce;
     initOnce!stdSharedDefaultLogger({
         auto buffer = cast(ubyte[]) _buffer;
-        return emplace!FileLogger(buffer, stderr, LogLevel.all);
+        return emplace!FileLogger(buffer, stderr, LogLevel.warning);
     }());
 
     return stdSharedDefaultLogger;
 }
 
-/** This property sets and gets the default `Logger`.
+/** This property sets and gets the default `Logger`. Unless set to another
+logger by the user, the default logger's log level is LogLevel.warning.
 
 Example:
 -------------
@@ -2007,7 +2008,7 @@
 
     auto oldunspecificLogger = sharedLog;
 
-    assert(oldunspecificLogger.logLevel == LogLevel.all,
+    assert(oldunspecificLogger.logLevel == LogLevel.warning,
          to!string(oldunspecificLogger.logLevel));
 
     assert(l.logLevel == LogLevel.all);
@@ -3063,7 +3064,7 @@
 {
     auto dl = cast(FileLogger) sharedLog;
     assert(dl !is null);
-    assert(dl.logLevel == LogLevel.all);
+    assert(dl.logLevel == LogLevel.warning);
     assert(globalLogLevel == LogLevel.all);
 
     auto tl = cast(StdForwardLogger) stdThreadLocalLog;
diff --git a/libphobos/src/std/experimental/logger/filelogger.d b/libphobos/src/std/experimental/logger/filelogger.d
index 6fd7e5f..a0bea77 100644
--- a/libphobos/src/std/experimental/logger/filelogger.d
+++ b/libphobos/src/std/experimental/logger/filelogger.d
@@ -263,7 +263,7 @@
 {
     auto dl = cast(FileLogger) sharedLog;
     assert(dl !is null);
-    assert(dl.logLevel == LogLevel.all);
+    assert(dl.logLevel == LogLevel.warning);
     assert(globalLogLevel == LogLevel.all);
 
     auto tl = cast(StdForwardLogger) stdThreadLocalLog;
diff --git a/libphobos/src/std/experimental/logger/multilogger.d b/libphobos/src/std/experimental/logger/multilogger.d
index 0751cb8..90bfb58 100644
--- a/libphobos/src/std/experimental/logger/multilogger.d
+++ b/libphobos/src/std/experimental/logger/multilogger.d
@@ -191,7 +191,7 @@
 {
     auto dl = cast(FileLogger) sharedLog;
     assert(dl !is null);
-    assert(dl.logLevel == LogLevel.all);
+    assert(dl.logLevel == LogLevel.warning);
     assert(globalLogLevel == LogLevel.all);
 
     auto tl = cast(StdForwardLogger) stdThreadLocalLog;
diff --git a/libphobos/src/std/file.d b/libphobos/src/std/file.d
index 315e054..c974ada 100644
--- a/libphobos/src/std/file.d
+++ b/libphobos/src/std/file.d
@@ -89,7 +89,7 @@
 import std.datetime.systime : Clock, SysTime, unixTimeToStdTime;
 import std.internal.cstring;
 import std.meta;
-import std.range.primitives;
+import std.range;
 import std.traits;
 import std.typecons;
 
@@ -313,8 +313,7 @@
  */
 
 void[] read(R)(R name, size_t upTo = size_t.max)
-if (isInputRange!R && isSomeChar!(ElementEncodingType!R) && !isInfinite!R &&
-    !isConvertibleToString!R)
+if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
 {
     static if (isNarrowString!R && is(immutable ElementEncodingType!R == immutable char))
         return readImpl(name, name.tempCString!FSChar(), upTo);
@@ -356,7 +355,7 @@
     import core.memory : GC;
     import std.algorithm.comparison : min;
     import std.conv : to;
-    import std.experimental.checkedint : checked;
+    import std.checkedint : checked;
 
     // A few internal configuration parameters {
     enum size_t
@@ -500,7 +499,7 @@
             $(REF UTFException, std, utf) on UTF decoding error.
 +/
 S readText(S = string, R)(auto ref R name)
-if (isSomeString!S && (isInputRange!R && !isInfinite!R && isSomeChar!(ElementType!R) || is(StringTypeOf!R)))
+if (isSomeString!S && (isSomeFiniteCharInputRange!R || is(StringTypeOf!R)))
 {
     import std.algorithm.searching : startsWith;
     import std.encoding : getBOM, BOM;
@@ -736,8 +735,7 @@
 See_also: $(REF toFile, std,stdio)
  */
 void write(R)(R name, const void[] buffer)
-if ((isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) || isSomeString!R) &&
-    !isConvertibleToString!R)
+if ((isSomeFiniteCharInputRange!R || isSomeString!R) && !isConvertibleToString!R)
 {
     static if (isNarrowString!R && is(immutable ElementEncodingType!R == immutable char))
         writeImpl(name, name.tempCString!FSChar(), buffer, false);
@@ -785,8 +783,7 @@
 Throws: $(LREF FileException) on error.
  */
 void append(R)(R name, const void[] buffer)
-if ((isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) || isSomeString!R) &&
-    !isConvertibleToString!R)
+if ((isSomeFiniteCharInputRange!R || isSomeString!R) && !isConvertibleToString!R)
 {
     static if (isNarrowString!R && is(immutable ElementEncodingType!R == immutable char))
         writeImpl(name, name.tempCString!FSChar(), buffer, true);
@@ -915,10 +912,8 @@
  * Throws: $(LREF FileException) on error.
  */
 void rename(RF, RT)(RF from, RT to)
-if ((isInputRange!RF && !isInfinite!RF && isSomeChar!(ElementEncodingType!RF) || isSomeString!RF)
-    && !isConvertibleToString!RF &&
-    (isInputRange!RT && !isInfinite!RT && isSomeChar!(ElementEncodingType!RT) || isSomeString!RT)
-    && !isConvertibleToString!RT)
+if ((isSomeFiniteCharInputRange!RF || isSomeString!RF) && !isConvertibleToString!RF &&
+    (isSomeFiniteCharInputRange!RT || isSomeString!RT) && !isConvertibleToString!RT)
 {
     // Place outside of @trusted block
     auto fromz = from.tempCString!FSChar();
@@ -1027,8 +1022,7 @@
 Throws: $(LREF FileException) on error.
  */
 void remove(R)(R name)
-if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
-    !isConvertibleToString!R)
+if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
 {
     static if (isNarrowString!R && is(immutable ElementEncodingType!R == immutable char))
         removeImpl(name, name.tempCString!FSChar());
@@ -1082,7 +1076,7 @@
 }
 
 version (Windows) private WIN32_FILE_ATTRIBUTE_DATA getFileAttributesWin(R)(R name)
-if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R))
+if (isSomeFiniteCharInputRange!R)
 {
     auto namez = name.tempCString!FSChar();
 
@@ -1137,8 +1131,7 @@
     $(LREF FileException) on error (e.g., file not found).
  */
 ulong getSize(R)(R name)
-if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
-    !isConvertibleToString!R)
+if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
 {
     version (Windows)
     {
@@ -1233,8 +1226,7 @@
 void getTimes(R)(R name,
               out SysTime accessTime,
               out SysTime modificationTime)
-if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
-    !isConvertibleToString!R)
+if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
 {
     version (Windows)
     {
@@ -1378,8 +1370,9 @@
                         out SysTime fileCreationTime,
                         out SysTime fileAccessTime,
                         out SysTime fileModificationTime)
-    if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
-        !isConvertibleToString!R);
+    if (isSomeFiniteCharInputRange!R || isConvertibleToString!R);
+    // above line contains both constraints for docs
+    // (so users know how it can be called)
 }
 else version (Windows)
 {
@@ -1387,8 +1380,7 @@
                         out SysTime fileCreationTime,
                         out SysTime fileAccessTime,
                         out SysTime fileModificationTime)
-    if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
-        !isConvertibleToString!R)
+    if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
     {
         import std.datetime.systime : FILETIMEToSysTime;
 
@@ -1509,8 +1501,7 @@
 void setTimes(R)(R name,
               SysTime accessTime,
               SysTime modificationTime)
-if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
-    !isConvertibleToString!R)
+if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
 {
     auto namez = name.tempCString!FSChar();
     static if (isNarrowString!R && is(immutable ElementEncodingType!R == immutable char))
@@ -1657,8 +1648,7 @@
         $(LREF FileException) if the given file does not exist.
 +/
 SysTime timeLastModified(R)(R name)
-if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
-    !isConvertibleToString!R)
+if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
 {
     version (Windows)
     {
@@ -1742,7 +1732,7 @@
 --------------------
 +/
 SysTime timeLastModified(R)(R name, SysTime returnIfMissing)
-if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R))
+if (isSomeFiniteCharInputRange!R)
 {
     version (Windows)
     {
@@ -1902,8 +1892,7 @@
  *    true if the file _name specified as input _exists
  */
 bool exists(R)(R name)
-if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
-    !isConvertibleToString!R)
+if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
 {
     return existsImpl(name.tempCString!FSChar());
 }
@@ -2004,8 +1993,7 @@
  Throws: $(LREF FileException) on error.
   +/
 uint getAttributes(R)(R name)
-if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
-    !isConvertibleToString!R)
+if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
 {
     version (Windows)
     {
@@ -2105,8 +2093,7 @@
         $(LREF FileException) on error.
  +/
 uint getLinkAttributes(R)(R name)
-if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
-    !isConvertibleToString!R)
+if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
 {
     version (Windows)
     {
@@ -2214,8 +2201,7 @@
         $(LREF FileException) if the given file does not exist.
  +/
 void setAttributes(R)(R name, uint attributes)
-if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
-    !isConvertibleToString!R)
+if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
 {
     version (Windows)
     {
@@ -2323,8 +2309,7 @@
         $(LREF FileException) if the given file does not exist.
   +/
 @property bool isDir(R)(R name)
-if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
-    !isConvertibleToString!R)
+if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
 {
     version (Windows)
     {
@@ -2503,8 +2488,7 @@
         $(LREF FileException) if the given file does not exist.
 +/
 @property bool isFile(R)(R name)
-if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
-    !isConvertibleToString!R)
+if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
 {
     version (Windows)
         return !name.isDir;
@@ -2679,8 +2663,7 @@
         $(LREF FileException) if the given file does not exist.
   +/
 @property bool isSymlink(R)(R name)
-if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
-    !isConvertibleToString!R)
+if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
 {
     version (Windows)
         return (getAttributes(name) & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
@@ -2860,8 +2843,7 @@
 Throws: $(LREF FileException) on error.
  */
 void chdir(R)(R pathname)
-if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
-    !isConvertibleToString!R)
+if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
 {
     // Place outside of @trusted block
     auto pathz = pathname.tempCString!FSChar();
@@ -2931,8 +2913,7 @@
     if an error occured.
  */
 void mkdir(R)(R pathname)
-if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
-    !isConvertibleToString!R)
+if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
 {
     // Place outside of @trusted block
     const pathz = pathname.tempCString!FSChar();
@@ -3135,8 +3116,7 @@
 Throws: $(LREF FileException) on error.
  */
 void rmdir(R)(R pathname)
-if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) &&
-    !isConvertibleToString!R)
+if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
 {
     // Place outside of @trusted block
     auto pathz = pathname.tempCString!FSChar();
@@ -3202,15 +3182,11 @@
         exists).
   +/
 version (StdDdoc) void symlink(RO, RL)(RO original, RL link)
-if ((isInputRange!RO && !isInfinite!RO && isSomeChar!(ElementEncodingType!RO) ||
-    isConvertibleToString!RO) &&
-    (isInputRange!RL && !isInfinite!RL && isSomeChar!(ElementEncodingType!RL) ||
-    isConvertibleToString!RL));
+if ((isSomeFiniteCharInputRange!RO || isConvertibleToString!RO) &&
+    (isSomeFiniteCharInputRange!RL || isConvertibleToString!RL));
 else version (Posix) void symlink(RO, RL)(RO original, RL link)
-if ((isInputRange!RO && !isInfinite!RO && isSomeChar!(ElementEncodingType!RO) ||
-    isConvertibleToString!RO) &&
-    (isInputRange!RL && !isInfinite!RL && isSomeChar!(ElementEncodingType!RL) ||
-    isConvertibleToString!RL))
+if ((isSomeFiniteCharInputRange!RO || isConvertibleToString!RO) &&
+    (isSomeFiniteCharInputRange!RL || isConvertibleToString!RL))
 {
     static if (isConvertibleToString!RO || isConvertibleToString!RL)
     {
@@ -3291,11 +3267,9 @@
         $(LREF FileException) on error.
   +/
 version (StdDdoc) string readLink(R)(R link)
-if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) ||
-    isConvertibleToString!R);
+if (isSomeFiniteCharInputRange!R || isConvertibleToString!R);
 else version (Posix) string readLink(R)(R link)
-if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) ||
-    isConvertibleToString!R)
+if (isSomeFiniteCharInputRange!R || isConvertibleToString!R)
 {
     static if (isConvertibleToString!R)
     {
@@ -3392,7 +3366,7 @@
 version (Windows) string getcwd() @trusted
 {
     import std.conv : to;
-    import std.experimental.checkedint : checked;
+    import std.checkedint : checked;
     /* GetCurrentDirectory's return value:
         1. function succeeds: the number of characters that are written to
     the buffer, not including the terminating null character.
@@ -4216,8 +4190,8 @@
 Throws: $(LREF FileException) on error.
  */
 void copy(RF, RT)(RF from, RT to, PreserveAttributes preserve = preserveAttributesDefault)
-if (isInputRange!RF && !isInfinite!RF && isSomeChar!(ElementEncodingType!RF) && !isConvertibleToString!RF &&
-    isInputRange!RT && !isInfinite!RT && isSomeChar!(ElementEncodingType!RT) && !isConvertibleToString!RT)
+if (isSomeFiniteCharInputRange!RF && !isConvertibleToString!RF &&
+    isSomeFiniteCharInputRange!RT && !isConvertibleToString!RT)
 {
     // Place outside of @trusted block
     auto fromz = from.tempCString!FSChar();
@@ -4781,7 +4755,7 @@
     }
 
     this(R)(R pathname, SpanMode mode, bool followSymlink)
-        if (isInputRange!R && isSomeChar!(ElementEncodingType!R))
+        if (isSomeFiniteCharInputRange!R)
     {
         _mode = mode;
         _followSymlink = followSymlink;
diff --git a/libphobos/src/std/format/package.d b/libphobos/src/std/format/package.d
index 2d57e48..6c9e9ae 100644
--- a/libphobos/src/std/format/package.d
+++ b/libphobos/src/std/format/package.d
@@ -179,10 +179,10 @@
              Depending on the number, a scientific notation or
              a natural notation is used.))
    $(TR $(TD $(B 'a') / $(B 'A'))
-        $(TD To be formatted as a real number in hexadezimal scientific notation.))
+        $(TD To be formatted as a real number in hexadecimal scientific notation.))
    $(TR $(TD $(B 'r'))
         $(TD To be formatted as raw bytes.
-             The output may not be printable and depends on endianess.))
+             The output may not be printable and depends on endianness.))
 )
 
 The $(I compound indicator) can be used to describe compound types
diff --git a/libphobos/src/std/functional.d b/libphobos/src/std/functional.d
index b251e40..bc8d368 100644
--- a/libphobos/src/std/functional.d
+++ b/libphobos/src/std/functional.d
@@ -707,19 +707,43 @@
     {
         static assert(false, "Cannot apply partial to a non-callable '" ~ fun.stringof ~ "'.");
     }
-    else // Assume fun is callable and uniquely defined.
+    else
     {
-        static if (Parameters!fun.length == 0)
+        import std.meta : Filter;
+
+        static if (__traits(compiles, __traits(getOverloads,
+            __traits(parent, fun), __traits(identifier, fun))))
+            alias overloads = __traits(getOverloads, __traits(parent, fun),
+                __traits(identifier, fun));
+        else
+            alias overloads = AliasSeq!(fun);
+
+        enum isCallableWithArg(alias fun) = Parameters!fun.length > 0 &&
+            is(typeof(arg) : Parameters!fun[0]);
+        alias candidates = Filter!(isCallableWithArg, overloads);
+
+        static if (overloads.length == 1 && Parameters!fun.length == 0)
         {
             static assert(0, "Cannot partially apply '" ~ fun.stringof ~ "'." ~
                 "'" ~ fun.stringof ~ "' has 0 arguments.");
         }
-        else static if (!is(typeof(arg) : Parameters!fun[0]))
+        else static if (candidates.length == 0)
         {
+            import std.meta : NoDuplicates, staticMap;
+
+            enum hasParameters(alias fun) = Parameters!fun.length > 0;
+            alias firstParameter(alias fun) = Parameters!fun[0];
+            alias firstParameters = NoDuplicates!(
+                staticMap!(firstParameter, Filter!(hasParameters, overloads)));
+
             string errorMsg()
             {
-                string msg = "Argument mismatch for '" ~ fun.stringof ~ "': expected " ~
-                    Parameters!fun[0].stringof ~ ", but got " ~ typeof(arg).stringof ~ ".";
+                string msg = "Argument mismatch for '" ~ fun.stringof ~
+                    "': expected " ~ firstParameters[0].stringof;
+                static foreach (firstParam; firstParameters[1 .. $])
+                    msg ~= " or " ~ firstParam.stringof;
+                msg ~= ", but got " ~ typeof(arg).stringof ~ ".";
+
                 return msg;
             }
             static assert(0, errorMsg());
@@ -727,10 +751,11 @@
         else
         {
             import std.traits : ReturnType;
-            ReturnType!fun partial(Parameters!fun[1..$] args2)
-            {
-                return fun(arg, args2);
-            }
+            static foreach (candidate; candidates)
+                ReturnType!candidate partial(Parameters!candidate[1..$] args2)
+                {
+                    return candidate(arg, args2);
+                }
         }
     }
 }
@@ -746,6 +771,22 @@
     // functions without committing to a particular type of the function.
 }
 
+// https://issues.dlang.org/show_bug.cgi?id=21457
+///
+@safe unittest
+{
+    // Overloads are resolved when the partially applied function is called
+    // with the remaining arguments.
+    struct S
+    {
+        static char fun(int i, string s) { return s[i]; }
+        static int fun(int a, int b) { return a * b; }
+    }
+    alias fun3 = partial!(S.fun, 3);
+    assert(fun3("hello") == 'l');
+    assert(fun3(10) == 30);
+}
+
 // tests for partially evaluating callables
 @safe unittest
 {
diff --git a/libphobos/src/std/json.d b/libphobos/src/std/json.d
index ea22d63..89def0f 100644
--- a/libphobos/src/std/json.d
+++ b/libphobos/src/std/json.d
@@ -19,7 +19,7 @@
 
 import std.array;
 import std.conv;
-import std.range.primitives;
+import std.range;
 import std.traits;
 
 ///
@@ -929,7 +929,7 @@
     options = enable decoding string representations of NaN/Inf as float values
 */
 JSONValue parseJSON(T)(T json, int maxDepth = -1, JSONOptions options = JSONOptions.none)
-if (isInputRange!T && !isInfinite!T && isSomeChar!(ElementEncodingType!T))
+if (isSomeFiniteCharInputRange!T)
 {
     import std.ascii : isDigit, isHexDigit, toUpper, toLower;
     import std.typecons : Nullable, Yes;
@@ -1437,7 +1437,7 @@
     options = enable decoding string representations of NaN/Inf as float values
 */
 JSONValue parseJSON(T)(T json, JSONOptions options)
-if (isInputRange!T && !isInfinite!T && isSomeChar!(ElementEncodingType!T))
+if (isSomeFiniteCharInputRange!T)
 {
     return parseJSON!T(json, -1, options);
 }
diff --git a/libphobos/src/std/path.d b/libphobos/src/std/path.d
index 2d64684..20518b8 100644
--- a/libphobos/src/std/path.d
+++ b/libphobos/src/std/path.d
@@ -98,7 +98,7 @@
 
 import std.file : getcwd;
 static import std.meta;
-import std.range.primitives;
+import std.range;
 import std.traits;
 
 version (OSX)
@@ -262,8 +262,7 @@
     from a path.
 */
 private auto ltrimDirSeparators(R)(R path)
-if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementType!R) ||
-    isNarrowString!R)
+if (isSomeFiniteCharInputRange!R || isNarrowString!R)
 {
     static if (isRandomAccessRange!R && hasSlicing!R || isNarrowString!R)
     {
@@ -3213,12 +3212,8 @@
 */
 int filenameCmp(CaseSensitive cs = CaseSensitive.osDefault, Range1, Range2)
     (Range1 filename1, Range2 filename2)
-if (isInputRange!Range1 && !isInfinite!Range1 &&
-    isSomeChar!(ElementEncodingType!Range1) &&
-    !isConvertibleToString!Range1 &&
-    isInputRange!Range2 && !isInfinite!Range2 &&
-    isSomeChar!(ElementEncodingType!Range2) &&
-    !isConvertibleToString!Range2)
+if (isSomeFiniteCharInputRange!Range1 && !isConvertibleToString!Range1 &&
+    isSomeFiniteCharInputRange!Range2 && !isConvertibleToString!Range2)
 {
     alias C1 = Unqual!(ElementEncodingType!Range1);
     alias C2 = Unqual!(ElementEncodingType!Range2);
diff --git a/libphobos/src/std/process.d b/libphobos/src/std/process.d
index 958f606..2c68f36 100644
--- a/libphobos/src/std/process.d
+++ b/libphobos/src/std/process.d
@@ -106,9 +106,8 @@
 }
 
 import std.internal.cstring;
-import std.range.primitives;
+import std.range;
 import std.stdio;
-import std.traits : isSomeChar;
 
 version (OSX)
     version = Darwin;
@@ -1527,7 +1526,7 @@
 // current user.
 version (Posix)
 private bool isExecutable(R)(R path) @trusted nothrow @nogc
-if (isInputRange!R && isSomeChar!(ElementEncodingType!R))
+if (isSomeFiniteCharInputRange!R)
 {
     return (access(path.tempCString(), X_OK) == 0);
 }
diff --git a/libphobos/src/std/range/package.d b/libphobos/src/std/range/package.d
index a21f4d0..9197134 100644
--- a/libphobos/src/std/range/package.d
+++ b/libphobos/src/std/range/package.d
@@ -235,7 +235,7 @@
 public import std.typecons : Flag, Yes, No;
 
 import std.internal.attributes : betterC;
-import std.meta : allSatisfy, staticMap;
+import std.meta : allSatisfy, anySatisfy, staticMap;
 import std.traits : CommonType, isCallable, isFloatingPoint, isIntegral,
     isPointer, isSomeFunction, isStaticArray, Unqual, isInstanceOf;
 
@@ -1412,7 +1412,8 @@
 if (isInputRange!(Unqual!R1) && isInputRange!(Unqual!R2) &&
     !is(CommonType!(ElementType!(Unqual!R1), ElementType!(Unqual!R2)) == void))
 {
-    return ChooseResult!(R1, R2)(condition, r1, r2);
+    size_t choice = condition? 0: 1;
+    return ChooseResult!(R1, R2)(choice, r1, r2);
 }
 
 ///
@@ -1447,76 +1448,102 @@
 }
 
 
-private struct ChooseResult(R1, R2)
+private struct ChooseResult(Ranges...)
 {
-    import std.traits : hasElaborateCopyConstructor, hasElaborateDestructor;
+    import std.meta : aliasSeqOf, ApplyLeft;
+    import std.traits : hasElaborateCopyConstructor, hasElaborateDestructor,
+        lvalueOf;
 
     private union
     {
-        R1 r1;
-        R2 r2;
+        Ranges rs;
     }
-    private bool r1Chosen;
+    private size_t chosenI;
 
-    private static auto ref actOnChosen(alias foo, ExtraArgs ...)(ref ChooseResult r,
-            auto ref ExtraArgs extraArgs)
+    private static auto ref actOnChosen(alias foo, ExtraArgs ...)
+        (ref ChooseResult r, auto ref ExtraArgs extraArgs)
     {
-        if (r.r1Chosen)
+        ref getI(size_t i)(return ref ChooseResult r) @trusted { return r.rs[i]; }
+
+        switch (r.chosenI)
         {
-            ref get1(return ref ChooseResult r) @trusted { return r.r1; }
-            return foo(get1(r), extraArgs);
-        }
-        else
-        {
-            ref get2(return ref ChooseResult r) @trusted { return r.r2; }
-            return foo(get2(r), extraArgs);
+            static foreach (candI; 0 .. rs.length)
+            {
+                case candI: return foo(getI!candI(r), extraArgs);
+            }
+
+            default: assert(false);
         }
     }
 
-    this(bool r1Chosen, return scope R1 r1, return scope R2 r2) @trusted
+    // @trusted because of assignment of r which overlap each other
+    this(size_t chosen, return scope Ranges rs) @trusted
     {
-        // @trusted because of assignment of r1 and r2 which overlap each other
         import core.lifetime : emplace;
 
-        // This should be the only place r1Chosen is ever assigned
+        // This should be the only place chosenI is ever assigned
         // independently
-        this.r1Chosen = r1Chosen;
-        if (r1Chosen)
+        this.chosenI = chosen;
+
+        // Otherwise the compiler will complain about skipping these fields
+        static foreach (i; 0 .. rs.length)
         {
-            this.r2 = R2.init;
-            emplace(&this.r1, r1);
+            this.rs[i] = Ranges[i].init;
         }
-        else
+
+        // The relevant field needs to be initialized last so it will overwrite
+        // the other initializations and not the other way around.
+        sw: switch (chosenI)
         {
-            this.r1 = R1.init;
-            emplace(&this.r2, r2);
+            static foreach (i; 0 .. rs.length)
+            {
+                case i:
+                emplace(&this.rs[i], rs[i]);
+                break sw;
+            }
+
+            default: assert(false);
         }
     }
 
+    // Some legacy code may still call this with typeof(choose(/*...*/))(/*...*/)
+    // without this overload the regular constructor would invert the meaning of
+    // the boolean
+    static if (rs.length == 2)
+    pragma(inline, true)
+    deprecated("Call with size_t (0 = first), or use the choose function")
+    this(bool firstChosen, Ranges rs)
+    {
+        import core.lifetime : move;
+        this(cast(size_t)(firstChosen? 0: 1), rs[0].move, rs[1].move);
+    }
+
     void opAssign(ChooseResult r)
     {
-        static if (hasElaborateDestructor!R1 || hasElaborateDestructor!R2)
-            if (r1Chosen != r.r1Chosen)
-            {
-                // destroy the current item
-                actOnChosen!((ref r) => destroy(r))(this);
-            }
-        r1Chosen = r.r1Chosen;
-        if (r1Chosen)
+        ref getI(size_t i)(return ref ChooseResult r) @trusted { return r.rs[i]; }
+
+        static if (anySatisfy!(hasElaborateDestructor, Ranges))
+            if (chosenI != r.chosenI)
         {
-            ref get1(return ref ChooseResult r) @trusted { return r.r1; }
-            get1(this) = get1(r);
+            // destroy the current item
+            actOnChosen!((ref r) => destroy(r))(this);
         }
-        else
+        chosenI = r.chosenI;
+
+        sw: switch (chosenI)
         {
-            ref get2(return ref ChooseResult r) @trusted { return r.r2; }
-            get2(this) = get2(r);
+            static foreach (candI; 0 .. rs.length)
+            {
+                case candI: getI!candI(this) = getI!candI(r);
+                break sw;
+            }
+
+            default: assert(false);
         }
     }
 
     // Carefully defined postblit to postblit the appropriate range
-    static if (hasElaborateCopyConstructor!R1
-        || hasElaborateCopyConstructor!R2)
+    static if (anySatisfy!(hasElaborateCopyConstructor, Ranges))
     this(this)
     {
         actOnChosen!((ref r) {
@@ -1524,20 +1551,18 @@
             })(this);
     }
 
-    static if (hasElaborateDestructor!R1 || hasElaborateDestructor!R2)
+    static if (anySatisfy!(hasElaborateDestructor, Ranges))
     ~this()
     {
         actOnChosen!((ref r) => destroy(r))(this);
     }
 
-    static if (isInfinite!R1 && isInfinite!R2)
-        // Propagate infiniteness.
-        enum bool empty = false;
-    else
-        @property bool empty()
-        {
-            return actOnChosen!(r => r.empty)(this);
-        }
+    // Propagate infiniteness.
+    static if (allSatisfy!(isInfinite, Ranges)) enum bool empty = false;
+    else @property bool empty()
+    {
+        return actOnChosen!(r => r.empty)(this);
+    }
 
     @property auto ref front()
     {
@@ -1550,34 +1575,38 @@
         return actOnChosen!((ref r) { r.popFront; })(this);
     }
 
-    static if (isForwardRange!R1 && isForwardRange!R2)
-    @property auto save() return scope
+    static if (allSatisfy!(isForwardRange, Ranges))
+    @property auto save() // return scope inferred
     {
-        if (r1Chosen)
+        auto saveOrInit(size_t i)()
         {
-            ref R1 getR1() @trusted { return r1; }
-            return ChooseResult(r1Chosen, getR1.save, R2.init);
+            ref getI() @trusted { return rs[i]; }
+            if (i == chosenI) return getI().save;
+            else return Ranges[i].init;
         }
-        else
+
+        return typeof(this)(chosenI, staticMap!(saveOrInit,
+            aliasSeqOf!(rs.length.iota)));
+    }
+
+    template front(T)
+    {
+        private enum overloadValidFor(alias r) = is(typeof(r.front = T.init));
+
+        static if (allSatisfy!(overloadValidFor, rs))
+        void front(T v)
         {
-            ref R2 getR2() @trusted { return r2; }
-            return ChooseResult(r1Chosen, R1.init, getR2.save);
+            actOnChosen!((ref r, T v) { r.front = v; })(this, v);
         }
     }
 
-    @property void front(T)(T v)
-    if (is(typeof({ r1.front = v; r2.front = v; })))
+    static if (allSatisfy!(hasMobileElements, Ranges))
+    auto moveFront()
     {
-        actOnChosen!((ref r, T v) { r.front = v; })(this, v);
+        return actOnChosen!((ref r) => r.moveFront)(this);
     }
 
-    static if (hasMobileElements!R1 && hasMobileElements!R2)
-        auto moveFront()
-        {
-            return actOnChosen!((ref r) => r.moveFront)(this);
-        }
-
-    static if (isBidirectionalRange!R1 && isBidirectionalRange!R2)
+    static if (allSatisfy!(isBidirectionalRange, Ranges))
     {
         @property auto ref back()
         {
@@ -1590,20 +1619,25 @@
             actOnChosen!((ref r) { r.popBack; })(this);
         }
 
-        static if (hasMobileElements!R1 && hasMobileElements!R2)
-            auto moveBack()
-            {
-                return actOnChosen!((ref r) => r.moveBack)(this);
-            }
-
-        @property void back(T)(T v)
-        if (is(typeof({ r1.back = v; r2.back = v; })))
+        static if (allSatisfy!(hasMobileElements, Ranges))
+        auto moveBack()
         {
-            actOnChosen!((ref r, T v) { r.back = v; })(this, v);
+            return actOnChosen!((ref r) => r.moveBack)(this);
+        }
+
+        template back(T)
+        {
+            private enum overloadValidFor(alias r) = is(typeof(r.back = T.init));
+
+            static if (allSatisfy!(overloadValidFor, rs))
+            void back(T v)
+            {
+                actOnChosen!((ref r, T v) { r.back = v; })(this, v);
+            }
         }
     }
 
-    static if (hasLength!R1 && hasLength!R2)
+    static if (allSatisfy!(hasLength, Ranges))
     {
         @property size_t length()
         {
@@ -1612,7 +1646,7 @@
         alias opDollar = length;
     }
 
-    static if (isRandomAccessRange!R1 && isRandomAccessRange!R2)
+    static if (allSatisfy!(isRandomAccessRange, Ranges))
     {
         auto ref opIndex(size_t index)
         {
@@ -1620,33 +1654,41 @@
             return actOnChosen!get(this, index);
         }
 
-        static if (hasMobileElements!R1 && hasMobileElements!R2)
+        static if (allSatisfy!(hasMobileElements, Ranges))
             auto moveAt(size_t index)
             {
                 return actOnChosen!((ref r, size_t index) => r.moveAt(index))
                     (this, index);
             }
 
-        void opIndexAssign(T)(T v, size_t index)
-        if (is(typeof({ r1[1] = v; r2[1] = v; })))
+        private enum indexAssignable(T, R) = is(typeof(lvalueOf!R[1] = T.init));
+
+        template opIndexAssign(T)
+        if (allSatisfy!(ApplyLeft!(indexAssignable, T), Ranges))
         {
-            return actOnChosen!((ref r, size_t index, T v) { r[index] = v; })
-                (this, index, v);
+            void opIndexAssign(T v, size_t index)
+            {
+                return actOnChosen!((ref r, size_t index, T v) { r[index] = v; })
+                    (this, index, v);
+            }
         }
     }
 
-    static if (hasSlicing!R1 && hasSlicing!R2)
-        auto opSlice(size_t begin, size_t end)
+    static if (allSatisfy!(hasSlicing, Ranges))
+    auto opSlice(size_t begin, size_t end)
+    {
+        alias Slice(R) = typeof(R.init[0 .. 1]);
+        alias Slices = staticMap!(Slice, Ranges);
+
+        auto sliceOrInit(size_t i)()
         {
-            alias Slice1 = typeof(R1.init[0 .. 1]);
-            alias Slice2 = typeof(R2.init[0 .. 1]);
-            return actOnChosen!((r, size_t begin, size_t end) {
-                    static if (is(typeof(r) == Slice1))
-                        return choose(true, r[begin .. end], Slice2.init);
-                    else
-                        return choose(false, Slice1.init, r[begin .. end]);
-                })(this, begin, end);
+            ref getI() @trusted { return rs[i]; }
+            return i == chosenI? getI()[begin .. end]: Slices[i].init;
         }
+
+        return chooseAmong(chosenI, staticMap!(sliceOrInit,
+            aliasSeqOf!(rs.length.iota)));
+    }
 }
 
 // https://issues.dlang.org/show_bug.cgi?id=18657
@@ -1668,8 +1710,9 @@
         int front;
         bool empty;
         void popFront() {}
-        @property R save() { p = q; return this; }
-            // `p = q;` is only there to prevent inference of `scope return`.
+        // `p = q;` is only there to prevent inference of `scope return`.
+        @property @safe R save() { p = q; return this; }
+
     }
     R r;
     choose(true, r, r).save;
@@ -1801,10 +1844,7 @@
         && allSatisfy!(isInputRange, staticMap!(Unqual, Ranges))
         && !is(CommonType!(staticMap!(ElementType, Ranges)) == void))
 {
-    static if (Ranges.length == 2)
-        return choose(index == 0, rs[0], rs[1]);
-    else
-        return choose(index == 0, rs[0], chooseAmong(index - 1, rs[1 .. $]));
+        return ChooseResult!Ranges(index, rs);
 }
 
 ///
@@ -13521,3 +13561,49 @@
 
     assert([1, 2, 3, 4].padRight(0, 10)[7 .. 9].equal([0, 0]));
 }
+
+/**
+This simplifies a commonly used idiom in phobos for accepting any kind of string
+parameter. The type `R` can for example be a simple string, chained string using
+$(REF chain, std,range), $(REF chainPath, std,path) or any other input range of
+characters.
+
+Only finite length character ranges are allowed with this constraint.
+
+This template is equivalent to:
+---
+isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R)
+---
+
+See_Also:
+$(REF isInputRange, std,range,primitives),
+$(REF isInfinite, std,range,primitives),
+$(LREF isSomeChar),
+$(REF ElementEncodingType, std,range,primitives)
+*/
+template isSomeFiniteCharInputRange(R)
+{
+    import std.traits : isSomeChar;
+
+    enum isSomeFiniteCharInputRange = isInputRange!R && !isInfinite!R
+        && isSomeChar!(ElementEncodingType!R);
+}
+
+///
+@safe unittest
+{
+    import std.path : chainPath;
+    import std.range : chain;
+
+    void someLibraryMethod(R)(R argument)
+    if (isSomeFiniteCharInputRange!R)
+    {
+        // implementation detail, would iterate over each character of argument
+    }
+
+    someLibraryMethod("simple strings work");
+    someLibraryMethod(chain("chained", " ", "strings", " ", "work"));
+    someLibraryMethod(chainPath("chained", "paths", "work"));
+    // you can also use custom structs implementing a char range
+}
+
diff --git a/libphobos/src/std/regex/package.d b/libphobos/src/std/regex/package.d
index 8db0b1e..e24abc5 100644
--- a/libphobos/src/std/regex/package.d
+++ b/libphobos/src/std/regex/package.d
@@ -170,6 +170,10 @@
       Greedy version - tries as many times as possible.)
     $(REG_ROW +?, Matches previous character/subexpression 1 or more times.
       Lazy version  - stops as early as possible.)
+    $(REG_ROW ?, Matches previous character/subexpression 0 or 1 time.
+      Greedy version - tries as many times as possible.)
+    $(REG_ROW ??, Matches previous character/subexpression 0 or 1 time.
+      Lazy version  - stops as early as possible.)
     $(REG_ROW {n}, Matches previous character/subexpression exactly n times. )
     $(REG_ROW {n$(COMMA)}, Matches previous character/subexpression n times or more.
       Greedy version - tries as many times as possible. )
@@ -1745,3 +1749,9 @@
       assert(s2.escaper.equal(""));
     }}
 }
+
+@system unittest
+{
+    assert("ab".matchFirst(regex(`a?b?`)).hit == "ab");
+    assert("ab".matchFirst(regex(`a??b?`)).hit == "");
+}
diff --git a/libphobos/src/std/stdio.d b/libphobos/src/std/stdio.d
index f30ea80..bc2d3fe 100644
--- a/libphobos/src/std/stdio.d
+++ b/libphobos/src/std/stdio.d
@@ -50,8 +50,8 @@
 public import core.stdc.stdio;
 import std.algorithm.mutation : copy;
 import std.meta : allSatisfy;
-import std.range.primitives : ElementEncodingType, empty, front,
-    isBidirectionalRange, isInputRange, put;
+import std.range : ElementEncodingType, empty, front, isBidirectionalRange,
+    isInputRange, isSomeFiniteCharInputRange, put;
 import std.traits : isSomeChar, isSomeString, Unqual, isPointer;
 import std.typecons : Flag, No, Yes;
 
@@ -555,7 +555,7 @@
 
     /// ditto
     this(R1, R2)(R1 name)
-        if (isInputRange!R1 && isSomeChar!(ElementEncodingType!R1))
+        if (isSomeFiniteCharInputRange!R1)
     {
         import std.conv : to;
         this(name.to!string, "rb");
@@ -563,8 +563,8 @@
 
     /// ditto
     this(R1, R2)(R1 name, R2 mode)
-        if (isInputRange!R1 && isSomeChar!(ElementEncodingType!R1) &&
-            isInputRange!R2 && isSomeChar!(ElementEncodingType!R2))
+        if (isSomeFiniteCharInputRange!R1 &&
+            isSomeFiniteCharInputRange!R2)
     {
         import std.conv : to;
         this(name.to!string, mode.to!string);
@@ -957,7 +957,7 @@
     }
 
 /**
-If the file is not opened, returns `true`. Otherwise, returns
+If the file is closed or not yet opened, returns `true`. Otherwise, returns
 $(HTTP cplusplus.com/reference/clibrary/cstdio/ferror.html, ferror) for
 the file handle.
  */
@@ -1013,8 +1013,8 @@
     }
 
 /**
-If the file was unopened, succeeds vacuously. Otherwise closes the
-file (by calling $(HTTP
+If the file was closed or not yet opened, succeeds vacuously. Otherwise
+closes the file (by calling $(HTTP
 cplusplus.com/reference/clibrary/cstdio/fclose.html, fclose)),
 throwing on error. Even if an exception is thrown, afterwards the $(D
 File) object is empty. This is different from `detach` in that it
@@ -1042,7 +1042,7 @@
     }
 
 /**
-If the file is not opened, succeeds vacuously. Otherwise, returns
+If the file is closed or not yet opened, succeeds vacuously. Otherwise, returns
 $(HTTP cplusplus.com/reference/clibrary/cstdio/_clearerr.html,
 _clearerr) for the file handle.
  */
@@ -4642,8 +4642,8 @@
  * with appropriately-constructed C-style strings.
  */
 private FILE* _fopen(R1, R2)(R1 name, R2 mode = "r")
-if ((isInputRange!R1 && isSomeChar!(ElementEncodingType!R1) || isSomeString!R1) &&
-    (isInputRange!R2 && isSomeChar!(ElementEncodingType!R2) || isSomeString!R2))
+if ((isSomeFiniteCharInputRange!R1 || isSomeString!R1) &&
+    (isSomeFiniteCharInputRange!R2 || isSomeString!R2))
 {
     import std.internal.cstring : tempCString;
 
@@ -4684,8 +4684,8 @@
      * with appropriately-constructed C-style strings.
      */
     FILE* _popen(R1, R2)(R1 name, R2 mode = "r") @trusted nothrow @nogc
-    if ((isInputRange!R1 && isSomeChar!(ElementEncodingType!R1) || isSomeString!R1) &&
-        (isInputRange!R2 && isSomeChar!(ElementEncodingType!R2) || isSomeString!R2))
+    if ((isSomeFiniteCharInputRange!R1 || isSomeString!R1) &&
+        (isSomeFiniteCharInputRange!R2 || isSomeString!R2))
     {
         import std.internal.cstring : tempCString;
 
diff --git a/libphobos/src/std/traits.d b/libphobos/src/std/traits.d
index c1d6bc9..596c11c 100644
--- a/libphobos/src/std/traits.d
+++ b/libphobos/src/std/traits.d
@@ -5195,16 +5195,54 @@
 
 /**
 Returns `true` iff an rvalue of type `Rhs` can be assigned to a variable of
-type `Lhs`
+type `Lhs`.
 */
 enum isRvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, { lvalueOf!Lhs = rvalueOf!Rhs; });
 
+///
+@safe unittest
+{
+    struct S1
+    {
+        void opAssign(S1);
+    }
+
+    struct S2
+    {
+        void opAssign(ref S2);
+    }
+
+    static assert( isRvalueAssignable!(long, int));
+    static assert(!isRvalueAssignable!(int, long));
+    static assert( isRvalueAssignable!S1);
+    static assert(!isRvalueAssignable!S2);
+}
+
 /**
 Returns `true` iff an lvalue of type `Rhs` can be assigned to a variable of
-type `Lhs`
+type `Lhs`.
 */
 enum isLvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, { lvalueOf!Lhs = lvalueOf!Rhs; });
 
+///
+@safe unittest
+{
+    struct S1
+    {
+        void opAssign(S1);
+    }
+
+    struct S2
+    {
+        void opAssign(ref S2);
+    }
+
+    static assert( isLvalueAssignable!(long, int));
+    static assert(!isLvalueAssignable!(int, long));
+    static assert( isLvalueAssignable!S1);
+    static assert( isLvalueAssignable!S2);
+}
+
 @safe unittest
 {
     static assert(!isAssignable!(immutable int, int));
@@ -6095,7 +6133,7 @@
             alias X = OriginalType!T;
         static if (__traits(isArithmetic, X) && !is(X == __vector) ||
                 __traits(isStaticArray, X) || is(X == E[], E) ||
-                __traits(isAssociativeArray, X))
+                __traits(isAssociativeArray, X) || is(X == typeof(null)))
             alias BuiltinTypeOf = X;
         else
             static assert(0);
@@ -6117,7 +6155,13 @@
     static assert( isBoolean!bool);
     enum EB : bool { a = true }
     static assert( isBoolean!EB);
-    static assert(!isBoolean!(SubTypeOf!bool));
+
+    struct SubTypeOfBool
+    {
+        bool val;
+        alias val this;
+    }
+    static assert(!isBoolean!(SubTypeOfBool));
 }
 
 @safe unittest
@@ -6994,6 +7038,18 @@
  */
 enum bool isAssociativeArray(T) = __traits(isAssociativeArray, T);
 
+///
+@safe unittest
+{
+    struct S;
+
+    static assert( isAssociativeArray!(int[string]));
+    static assert( isAssociativeArray!(S[S]));
+    static assert(!isAssociativeArray!(string[]));
+    static assert(!isAssociativeArray!S);
+    static assert(!isAssociativeArray!(int[4]));
+}
+
 @safe unittest
 {
     struct Foo
@@ -7037,6 +7093,7 @@
     static assert( isBuiltinType!string);
     static assert( isBuiltinType!(int[]));
     static assert( isBuiltinType!(C[string]));
+    static assert( isBuiltinType!(typeof(null)));
     static assert(!isBuiltinType!C);
     static assert(!isBuiltinType!U);
     static assert(!isBuiltinType!S);
@@ -7049,6 +7106,7 @@
  */
 enum bool isSIMDVector(T) = is(T : __vector(V[N]), V, size_t N);
 
+///
 @safe unittest
 {
     static if (is(__vector(float[4])))
@@ -7066,6 +7124,20 @@
  */
 enum bool isPointer(T) = is(T == U*, U) && __traits(isScalar, T);
 
+///
+@safe unittest
+{
+    void fun();
+
+    static assert( isPointer!(int*));
+    static assert( isPointer!(int function()));
+    static assert(!isPointer!int);
+    static assert(!isPointer!string);
+    static assert(!isPointer!(typeof(null)));
+    static assert(!isPointer!(typeof(fun)));
+    static assert(!isPointer!(int delegate()));
+}
+
 @safe unittest
 {
     static foreach (T; AliasSeq!(int*, void*, char[]*))
@@ -8835,6 +8907,27 @@
 */
 enum ifTestable(T, alias pred = a => a) = __traits(compiles, { if (pred(T.init)) {} });
 
+///
+@safe unittest
+{
+    class C;
+    struct S1;
+    struct S2
+    {
+        T opCast(T)() const;
+    }
+
+    static assert( ifTestable!bool);
+    static assert( ifTestable!int);
+    static assert( ifTestable!(S1*));
+    static assert( ifTestable!(typeof(null)));
+    static assert( ifTestable!(int[]));
+    static assert( ifTestable!(int[string]));
+    static assert( ifTestable!S2);
+    static assert( ifTestable!C);
+    static assert(!ifTestable!S1);
+}
+
 @safe unittest
 {
     import std.meta : AliasSeq, allSatisfy;
diff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d
index cde2b9d..28edb9b 100644
--- a/libphobos/src/std/typecons.d
+++ b/libphobos/src/std/typecons.d
@@ -76,36 +76,42 @@
 import std.traits;
 import std.internal.attributes : betterC;
 
-///
+/// Value tuples
 @safe unittest
 {
-    // value tuples
     alias Coord = Tuple!(int, "x", int, "y", int, "z");
     Coord c;
     c[1] = 1;       // access by index
     c.z = 1;        // access by given name
     assert(c == Coord(0, 1, 1));
 
-    // names can be omitted
-    alias DicEntry = Tuple!(string, string);
+    // names can be omitted, types can be mixed
+    alias DictEntry = Tuple!(string, int);
+    auto dict = DictEntry("seven", 7);
 
-    // tuples can also be constructed on instantiation
+    // element types can be inferred
     assert(tuple(2, 3, 4)[1] == 3);
-    // construction on instantiation works with names too
-    assert(tuple!("x", "y", "z")(2, 3, 4).y == 3);
+    // type inference works with names too
+    auto tup = tuple!("x", "y", "z")(2, 3, 4);
+    assert(tup.y == 3);
+}
 
-    // Rebindable references to const and immutable objects
+/// Rebindable references to const and immutable objects
+@safe unittest
+{
+    class Widget
     {
-        class Widget { void foo() const @safe {} }
-        const w1 = new Widget, w2 = new Widget;
-        w1.foo();
-        // w1 = w2 would not work; can't rebind const object
-        auto r = Rebindable!(const Widget)(w1);
-        // invoke method as if r were a Widget object
-        r.foo();
-        // rebind r to refer to another object
-        r = w2;
+        void foo() const @safe {}
     }
+    const w1 = new Widget, w2 = new Widget;
+    w1.foo();
+    // w1 = w2 would not work; can't rebind const object
+
+    auto r = Rebindable!(const Widget)(w1);
+    // invoke method as if r were a Widget object
+    r.foo();
+    // rebind r to refer to another object
+    r = w2;
 }
 
 /**
@@ -4036,7 +4042,7 @@
     import std.functional : unaryFun;
 
     auto apply(T)(auto ref T t)
-    if (isInstanceOf!(Nullable, T) && is(typeof(unaryFun!fun(T.init.get))))
+    if (isInstanceOf!(Nullable, T))
     {
         alias FunType = typeof(unaryFun!fun(T.init.get));
 
@@ -5107,6 +5113,46 @@
         static abstract class C_9 : K {}
         auto o = new BlackHole!C_9;
     }+/
+    // test `parent` alias
+    {
+        interface I_11
+        {
+            void simple(int) @safe;
+            int anotherSimple(string);
+            int overloaded(int);
+            /+ XXX [BUG 19715]
+            void overloaded(string) @safe;
+            +/
+        }
+
+        static class C_11
+        {
+            import std.traits : Parameters, ReturnType;
+            import std.meta : Alias;
+
+            protected ReturnType!fn _impl(alias fn)(Parameters!fn)
+            if (is(Alias!(__traits(parent, fn)) == interface))
+            {
+                static if (!is(typeof(return) == void))
+                    return typeof(return).init;
+            }
+        }
+
+        template tpl(I, alias fn)
+        if (is(I == interface) && __traits(isSame, __traits(parent, fn), I))
+        {
+            enum string tpl = q{
+                enum bool haveReturn = !is(typeof(return) == void);
+
+                static if (is(typeof(return) == void))
+                    _impl!parent(args);
+                else
+                    return _impl!parent(args);
+            };
+        }
+
+        auto o = new AutoImplement!(I_11, C_11, tpl);
+    }
 }
 
 // https://issues.dlang.org/show_bug.cgi?id=17177
@@ -5188,6 +5234,7 @@
         void bar(int a) { }
     }
 }
+
 @system unittest
 {
     auto foo = new issue10647_DoNothing!issue10647_Foo();
@@ -5424,8 +5471,8 @@
             if (!isCtor)
             {
                 preamble ~= "alias self = " ~ name ~ ";\n";
-                if (WITH_BASE_CLASS && !__traits(isAbstractFunction, func))
-                    preamble ~= `alias parent = __traits(getMember, super, "` ~ name ~ `");`;
+                static if (WITH_BASE_CLASS)
+                    preamble ~= `alias parent = __traits(getMember, ` ~ Policy.BASE_CLASS_ID ~ `, "` ~ name ~ `");`;
             }
 
             // Function body
diff --git a/libphobos/src/std/utf.d b/libphobos/src/std/utf.d
index a29025a..5c23684 100644
--- a/libphobos/src/std/utf.d
+++ b/libphobos/src/std/utf.d
@@ -65,9 +65,9 @@
 import std.exception : basicExceptionCtors;
 import core.exception : UnicodeException;
 import std.meta : AliasSeq;
-import std.range.primitives;
-import std.traits : isAutodecodableString, isPointer, isSomeChar,
-    isSomeString, isStaticArray, Unqual, isConvertibleToString;
+import std.range;
+import std.traits : isAutodecodableString, isConvertibleToString, isPointer,
+    isSomeChar, isSomeString, isStaticArray, Unqual;
 import std.typecons : Flag, Yes, No;
 
 
@@ -2809,7 +2809,7 @@
         The number of code units in `input` when encoded to `C`
   +/
 size_t codeLength(C, InputRange)(InputRange input)
-if (isInputRange!InputRange && !isInfinite!InputRange && isSomeChar!(ElementType!InputRange))
+if (isSomeFiniteCharInputRange!InputRange)
 {
     alias EncType = Unqual!(ElementEncodingType!InputRange);
     static if (isSomeString!InputRange && is(EncType == C) && is(typeof(input.length)))
@@ -2961,7 +2961,7 @@
  *     For a lazy, non-allocating version of these functions, see $(LREF byUTF).
  */
 string toUTF8(S)(S s)
-if (isInputRange!S && !isInfinite!S && isSomeChar!(ElementEncodingType!S))
+if (isSomeFiniteCharInputRange!S)
 {
     return toUTFImpl!string(s);
 }
@@ -3003,7 +3003,7 @@
  *     For a lazy, non-allocating version of these functions, see $(LREF byUTF).
  */
 wstring toUTF16(S)(S s)
-if (isInputRange!S && !isInfinite!S && isSomeChar!(ElementEncodingType!S))
+if (isSomeFiniteCharInputRange!S)
 {
     return toUTFImpl!wstring(s);
 }
@@ -3047,7 +3047,7 @@
  *     For a lazy, non-allocating version of these functions, see $(LREF byUTF).
  */
 dstring toUTF32(S)(scope S s)
-if (isInputRange!S && !isInfinite!S && isSomeChar!(ElementEncodingType!S))
+if (isSomeFiniteCharInputRange!S)
 {
     return toUTFImpl!dstring(s);
 }
diff --git a/libphobos/src/std/variant.d b/libphobos/src/std/variant.d
index ce635fb..41cd484 100644
--- a/libphobos/src/std/variant.d
+++ b/libphobos/src/std/variant.d
@@ -472,6 +472,20 @@
                 auto rhsPA = getPtr(&temp.store);
                 return compare(rhsPA, zis, selector);
             }
+            // Generate the function below only if the Variant's type is
+            // comparable with 'null'
+            static if (__traits(compiles, () => A.init == null))
+            {
+                if (rhsType == typeid(null))
+                {
+                    // if rhsType is typeof(null), then we're comparing with 'null'
+                    // this takes into account 'opEquals' and 'opCmp'
+                    // all types that can compare with null have to following properties:
+                    // if it's 'null' then it's equal to null, otherwise it's always greater
+                    // than 'null'
+                    return *zis == null ? 0 : 1;
+                }
+            }
             return ptrdiff_t.min; // dunno
         case OpID.toString:
             auto target = cast(string*) parm;
@@ -1608,6 +1622,42 @@
     assert(v != b);
 }
 
+// https://issues.dlang.org/show_bug.cgi?id=22647
+// Can compare with 'null'
+@system unittest
+{
+    static struct Bar
+    {
+        int* ptr;
+        alias ptr this;
+    }
+
+    static class Foo {}
+    int* iptr;
+    int[] arr;
+
+    Variant v = Foo.init; // 'null'
+    assert(v != null); // can only compare objects with 'null' by using 'is'
+
+    v = iptr;
+    assert(v == null); // pointers can be compared with 'null'
+
+    v = arr;
+    assert(v == null); // arrays can be compared with 'null'
+
+    v = "";
+    assert(v == null); // strings are arrays, an empty string is considered 'null'
+
+    v = Bar.init;
+    assert(v == null); // works with alias this
+
+    v = [3];
+    assert(v != null);
+    assert(v > null);
+    assert(v >= null);
+    assert(!(v < null));
+}
+
 /**
 _Algebraic data type restricted to a closed set of possible
 types. It's an alias for $(LREF VariantN) with an
@@ -2052,10 +2102,10 @@
 
     assert(v == 2);
     assert(v < 3);
-    static assert(!__traits(compiles, {v == long.max;}));
-    static assert(!__traits(compiles, {v == null;}));
-    static assert(!__traits(compiles, {v < long.max;}));
-    static assert(!__traits(compiles, {v > null;}));
+    static assert(!__traits(compiles, () => v == long.max));
+    static assert(!__traits(compiles, () => v == null));
+    static assert(!__traits(compiles, () => v < long.max));
+    static assert(!__traits(compiles, () => v > null));
 }
 
 // https://issues.dlang.org/show_bug.cgi?id=1558
diff --git a/libphobos/testsuite/testsuite_flags.in b/libphobos/testsuite/testsuite_flags.in
index 42053b2..528cff4 100755
--- a/libphobos/testsuite/testsuite_flags.in
+++ b/libphobos/testsuite/testsuite_flags.in
@@ -29,7 +29,9 @@
     --gdcflags)
       GDCFLAGS_default="-fmessage-length=0 -fno-show-column"
       GDCFLAGS_config="@WARN_DFLAGS@ @GDCFLAGS@ @CET_DFLAGS@
-		       @phobos_compiler_shared_flag@ -fpreview=dip1000 -fno-release -funittest"
+		       @phobos_compiler_shared_flag@
+		       -fall-instantiations -fpreview=dip1000
+		       -fno-release -funittest"
       echo ${GDCFLAGS_default} ${GDCFLAGS_config}
       ;;
     --gdcpaths)
diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog
index 92714c8..ef98eaf 100644
--- a/libsanitizer/ChangeLog
+++ b/libsanitizer/ChangeLog
@@ -1,3 +1,8 @@
+2022-02-15  Jakub Jelinek  <jakub@redhat.com>
+
+	* sanitizer_common/sanitizer_linux_libcdep.cpp: Cherry-pick
+	llvm-project revision ef14b78d9a144ba81ba02083fe21eb286a88732b.
+
 2022-02-03  David Seifert  <soap@gentoo.org>
 	    Jakub Jelinek  <jakub@redhat.com>
 
diff --git a/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp b/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp
index fc5619e..0c260b6 100644
--- a/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp
@@ -220,10 +220,8 @@
 // sizeof(struct pthread) from glibc.
 static atomic_uintptr_t thread_descriptor_size;
 
-uptr ThreadDescriptorSize() {
-  uptr val = atomic_load_relaxed(&thread_descriptor_size);
-  if (val)
-    return val;
+static uptr ThreadDescriptorSizeFallback() {
+  uptr val = 0;
 #if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
   int major;
   int minor;
@@ -285,8 +283,21 @@
 #elif defined(__powerpc64__)
   val = 1776; // from glibc.ppc64le 2.20-8.fc21
 #endif
+  return val;
+}
+
+uptr ThreadDescriptorSize() {
+  uptr val = atomic_load_relaxed(&thread_descriptor_size);
   if (val)
-    atomic_store_relaxed(&thread_descriptor_size, val);
+    return val;
+  // _thread_db_sizeof_pthread is a GLIBC_PRIVATE symbol that is exported in
+  // glibc 2.34 and later.
+  if (unsigned *psizeof = static_cast<unsigned *>(
+          dlsym(RTLD_DEFAULT, "_thread_db_sizeof_pthread")))
+    val = *psizeof;
+  if (!val)
+    val = ThreadDescriptorSizeFallback();
+  atomic_store_relaxed(&thread_descriptor_size, val);
   return val;
 }
 
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 5ed0e0f..9c159c8 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,41 @@
+2022-02-15  Jonathan Wakely  <jwakely@redhat.com>
+
+	PR libstdc++/104542
+	* include/bits/uses_allocator_args.h (make_obj_using_allocator)
+	(uninitialized_construct_using_allocator): Add constexpr.
+	* testsuite/20_util/uses_allocator/make_obj.cc: Check constexpr.
+	* testsuite/20_util/uses_allocator/uninitialized_construct.cc: New test.
+
+2022-02-14  Jonathan Wakely  <jwakely@redhat.com>
+
+	PR libstdc++/100912
+	* config/locale/gnu/c_locale.h (__convert_from_v): Use inline
+	namespace for IEEE128 long double mode.
+	* config/os/gnu-linux/ldbl-ieee128-extra.ver: Add new symbol
+	version and export __gnu_cxx_ieee128::__convert_from_v.
+	* include/bits/locale_facets_nonio.tcc (money_put::__do_put):
+	Make __ibm128 overload use snprintf directly
+	* testsuite/util/testsuite_abi.cc: Add new symbol version.
+	Remove stable IEEE128/LDBL versions.
+
+2022-02-14  Jonathan Wakely  <jwakely@redhat.com>
+
+	PR libstdc++/103891
+	* include/bits/c++config (_GLIBCXX_HAVE_COND_TRIVIAL_SPECIAL_MEMBERS):
+	Remove.
+	* include/std/variant: Check feature test macros instead.
+	* include/std/version: Likewise.
+
+2022-02-14  Jonathan Wakely  <jwakely@redhat.com>
+
+	* testsuite/20_util/unsynchronized_pool_resource/allocate.cc:
+	Fix typo.
+
+2022-02-14  Jonathan Wakely  <jwakely@redhat.com>
+
+	* src/c++17/floating_to_chars.cc (FLOAT128_TO_CHARS): Depend on
+	LONG_DOUBLE_ALT128_COMPAT instead of USE_FLOAT128.
+
 2022-02-11  Jonathan Wakely  <jwakely@redhat.com>
 
 	* testsuite/20_util/temporary_buffer.cc: Fix dg-warning target
diff --git a/libstdc++-v3/config/locale/gnu/c_locale.h b/libstdc++-v3/config/locale/gnu/c_locale.h
index 176e022..526b622 100644
--- a/libstdc++-v3/config/locale/gnu/c_locale.h
+++ b/libstdc++-v3/config/locale/gnu/c_locale.h
@@ -61,6 +61,11 @@
 
   typedef __locale_t		__c_locale;
 
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
+  && defined __LONG_DOUBLE_IEEE128__
+namespace __gnu_cxx_ieee128 {
+#endif
+
   // Convert numeric value of type double and long double to string and
   // return length of string.  If vsnprintf is available use it, otherwise
   // fall back to the unsafe vsprintf which, in general, can be dangerous
@@ -108,6 +113,11 @@
     return __ret;
   }
 
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
+  && defined __LONG_DOUBLE_IEEE128__
+} // namespace __gnu_cxx_ieee128
+#endif
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
diff --git a/libstdc++-v3/config/os/gnu-linux/ldbl-ieee128-extra.ver b/libstdc++-v3/config/os/gnu-linux/ldbl-ieee128-extra.ver
index 9b421b6..830cb8c 100644
--- a/libstdc++-v3/config/os/gnu-linux/ldbl-ieee128-extra.ver
+++ b/libstdc++-v3/config/os/gnu-linux/ldbl-ieee128-extra.ver
@@ -2,7 +2,8 @@
 
 GLIBCXX_IEEE128_3.4.29 {
 
-  *__gnu_cxx_ieee128*;
+  _Z*St17__gnu_cxx_ieee1287num_get*;
+  _Z*St17__gnu_cxx_ieee1287num_put*;
 
   _ZNSt14numeric_limitsIu9__ieee128E*;
   _ZNSirsERu9__ieee128;
@@ -45,6 +46,10 @@
 
 } GLIBCXX_3.4.29;
 
+GLIBCXX_IEEE128_3.4.30 {
+  _ZNSt17__gnu_cxx_ieee12816__convert_from_vERKP15__locale_structPciPKcz;
+} GLIBCXX_3.4.30;
+
 CXXABI_IEEE128_1.3.13 {
 
   _ZT[IS]u9__ieee128;
diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config
index b197349..c64b61b 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -810,11 +810,6 @@
 
 #undef _GLIBCXX_HAS_BUILTIN
 
-#if __cplusplus >= 202002L && __cpp_concepts && __GNUC__ >= 12
-// XXX workaround for missing feature test macro for P0848R3 (see P2493R0).
-# define _GLIBCXX_HAVE_COND_TRIVIAL_SPECIAL_MEMBERS 1
-#endif
-
 // PSTL configuration
 
 #if __cplusplus >= 201703L
diff --git a/libstdc++-v3/include/bits/locale_facets_nonio.tcc b/libstdc++-v3/include/bits/locale_facets_nonio.tcc
index 6473782..9844241 100644
--- a/libstdc++-v3/include/bits/locale_facets_nonio.tcc
+++ b/libstdc++-v3/include/bits/locale_facets_nonio.tcc
@@ -635,6 +635,9 @@
 
 #if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
       && defined __LONG_DOUBLE_IEEE128__
+extern "C"
+__typeof__(__builtin_snprintf) __glibcxx_snprintfibm128 __asm__("snprintf");
+
   template<typename _CharT, typename _OutIter>
     _OutIter
     money_put<_CharT, _OutIter>::
@@ -643,30 +646,24 @@
     {
       const locale __loc = __io.getloc();
       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
-#if _GLIBCXX_USE_C99_STDIO
       // First try a buffer perhaps big enough.
       int __cs_size = 64;
       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
+      const __c_locale __old = __gnu_cxx::__uselocale(_S_get_c_locale());
+
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // 328. Bad sprintf format modifier in money_put<>::do_put()
-      int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
-					"%.*Lf", 0, __units);
+      int __len = __glibcxx_snprintfibm128(__cs, __cs_size, "%.*Lf", 0,
+					     __units);
       // If the buffer was not large enough, try again with the correct size.
       if (__len >= __cs_size)
 	{
 	  __cs_size = __len + 1;
 	  __cs = static_cast<char*>(__builtin_alloca(__cs_size));
-	  __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
-					"%.*Lf", 0, __units);
+	  __len = __glibcxx_snprintfibm128(__cs, __cs_size, "%.*Lf", 0,
+					     __units);
 	}
-#else
-      // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
-      const int __cs_size =
-	__gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3;
-      char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
-      int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf", 
-					0, __units);
-#endif
+      __gnu_cxx::__uselocale(__old);
       string_type __digits(__len, char_type());
       __ctype.widen(__cs, __cs + __len, &__digits[0]);
       return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
diff --git a/libstdc++-v3/include/bits/uses_allocator_args.h b/libstdc++-v3/include/bits/uses_allocator_args.h
index a3aa37d..d92dd1f 100644
--- a/libstdc++-v3/include/bits/uses_allocator_args.h
+++ b/libstdc++-v3/include/bits/uses_allocator_args.h
@@ -196,7 +196,7 @@
     }
 
   template<typename _Tp, typename _Alloc, typename... _Args>
-    inline _Tp
+    constexpr _Tp
     make_obj_using_allocator(const _Alloc& __a, _Args&&... __args)
     {
       return std::make_from_tuple<_Tp>(
@@ -205,7 +205,7 @@
     }
 
   template<typename _Tp, typename _Alloc, typename... _Args>
-    inline _Tp*
+    constexpr _Tp*
     uninitialized_construct_using_allocator(_Tp* __p, const _Alloc& __a,
 					    _Args&&... __args)
     {
diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant
index c41f9f2..beed396 100644
--- a/libstdc++-v3/include/std/variant
+++ b/libstdc++-v3/include/std/variant
@@ -44,24 +44,22 @@
 #include <bits/stl_iterator_base_funcs.h>
 #include <bits/stl_construct.h>
 #include <bits/utility.h> // in_place_index_t
-#ifndef _GLIBCXX_HAVE_COND_TRIVIAL_SPECIAL_MEMBERS
-# include <ext/aligned_buffer.h>
-#endif
 #if __cplusplus >= 202002L
 # include <compare>
 #endif
 
+#if __cpp_concepts >= 202002L && __cpp_constexpr >= 201811L
+// P2231R1 constexpr needs constexpr unions and constrained destructors.
+# define __cpp_lib_variant 202106L
+#else
+# include <ext/aligned_buffer.h> // Use __aligned_membuf instead of union.
+# define __cpp_lib_variant 202102L
+#endif
+
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
-#ifdef _GLIBCXX_HAVE_COND_TRIVIAL_SPECIAL_MEMBERS
-// P2231R1 constexpr needs constexpr unions and constrained destructors.
-# define __cpp_lib_variant 202106L
-#else
-# define __cpp_lib_variant 202102L
-#endif
-
   template<typename... _Types> class tuple;
   template<typename... _Types> class variant;
   template <typename> struct hash;
diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version
index 30e04b5..24311ee 100644
--- a/libstdc++-v3/include/std/version
+++ b/libstdc++-v3/include/std/version
@@ -175,7 +175,7 @@
 # define __cpp_lib_to_chars 201611L
 #endif
 #define __cpp_lib_unordered_map_try_emplace 201411L
-#ifndef _GLIBCXX_HAVE_COND_TRIVIAL_SPECIAL_MEMBERS
+#if !(__cplusplus >= 202002L && __cpp_concepts >= 202002L)
 // N.B. updated value in C++20
 # define __cpp_lib_variant 202102L
 #endif
@@ -292,7 +292,7 @@
 # endif
 #define __cpp_lib_to_address 201711L
 #define __cpp_lib_to_array 201907L
-#ifdef _GLIBCXX_HAVE_COND_TRIVIAL_SPECIAL_MEMBERS
+#if __cplusplus >= 202002L && __cpp_concepts >= 202002L
 # define __cpp_lib_variant 202106L
 #endif
 #endif
diff --git a/libstdc++-v3/src/c++17/floating_to_chars.cc b/libstdc++-v3/src/c++17/floating_to_chars.cc
index 8da2f23..5825e66 100644
--- a/libstdc++-v3/src/c++17/floating_to_chars.cc
+++ b/libstdc++-v3/src/c++17/floating_to_chars.cc
@@ -76,16 +76,12 @@
 # define LONG_DOUBLE_KIND LDK_UNSUPPORTED
 #endif
 
-#if defined _GLIBCXX_USE_FLOAT128 && __FLT128_MANT_DIG__ == 113
+// For now we only support __float128 when it's the powerpc64 __ieee128 type.
+#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT && __FLT128_MANT_DIG__ == 113
 // Define overloads of std::to_chars for __float128.
 # define FLOAT128_TO_CHARS 1
 #endif
 
-// For now we only support __float128 when it's the powerpc64 __ieee128 type.
-#ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
-# undef FLOAT128_TO_CHARS
-#endif
-
 #ifdef FLOAT128_TO_CHARS
 using F128_type = __float128;
 #else
diff --git a/libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/allocate.cc b/libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/allocate.cc
index 25e5ce6..1c228ea 100644
--- a/libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/allocate.cc
+++ b/libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/allocate.cc
@@ -287,7 +287,7 @@
     // so that careful_resource::do_allocate can distinguish this allocation
     // from any required for the pool resource's internal data structures):
     void* p = upr.allocate(std::size_t(-2), 1024);
-#pragma GCC distinguish pop
+#pragma GCC diagnostic pop
     // Should not reach here!
     VERIFY( !"attempt to allocate SIZE_MAX-1 should not have succeeded" );
     throw p;
diff --git a/libstdc++-v3/testsuite/20_util/uses_allocator/make_obj.cc b/libstdc++-v3/testsuite/20_util/uses_allocator/make_obj.cc
index cd4497e..2dd0f81 100644
--- a/libstdc++-v3/testsuite/20_util/uses_allocator/make_obj.cc
+++ b/libstdc++-v3/testsuite/20_util/uses_allocator/make_obj.cc
@@ -142,7 +142,7 @@
   VERIFY( c2.alloc_id == 1 );
 }
 
-void 
+void
 test02()
 {
   decltype(auto) b
@@ -389,6 +389,34 @@
   std::make_obj_using_allocator<X>(a);
 }
 
+constexpr bool
+test_pr104542()
+{
+  // PR libstdc++/104542 - missing constexpr
+  std::allocator<void> a;
+  int i = std::make_obj_using_allocator<int>(a, 1);
+
+  struct X {
+    using allocator_type = std::allocator<long>;
+    constexpr X(std::allocator_arg_t, std::allocator<int>, int i) : i(i+1) { }
+    int i;
+  };
+
+  X x = std::make_obj_using_allocator<X>(a, i);
+
+  struct Y {
+    using allocator_type = std::allocator<char>;
+    constexpr Y(X x, std::allocator<int>) : i(x.i+1) { }
+    int i;
+  };
+
+  Y y = std::make_obj_using_allocator<Y>(a, x);
+
+  return y.i == 3;
+}
+
+static_assert( test_pr104542() );
+
 int
 main()
 {
diff --git a/libstdc++-v3/testsuite/20_util/uses_allocator/uninitialized_construct.cc b/libstdc++-v3/testsuite/20_util/uses_allocator/uninitialized_construct.cc
new file mode 100644
index 0000000..f403cbe
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/uses_allocator/uninitialized_construct.cc
@@ -0,0 +1,17 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+
+#include <memory>
+
+constexpr bool
+test_pr104542()
+{
+  // PR libstdc++/104542 - missing constexpr
+  std::allocator<int> a;
+  int* p = a.allocate(1);
+  int i = *std::uninitialized_construct_using_allocator<int>(p, a, 999);
+  a.deallocate(p, 1);
+  return i == 999;
+}
+
+static_assert( test_pr104542() );
diff --git a/libstdc++-v3/testsuite/util/testsuite_abi.cc b/libstdc++-v3/testsuite/util/testsuite_abi.cc
index 0ac0ea3..3dee737 100644
--- a/libstdc++-v3/testsuite/util/testsuite_abi.cc
+++ b/libstdc++-v3/testsuite/util/testsuite_abi.cc
@@ -213,6 +213,7 @@
       known_versions.push_back("GLIBCXX_3.4.30");
       known_versions.push_back("GLIBCXX_LDBL_3.4.29");
       known_versions.push_back("GLIBCXX_IEEE128_3.4.29");
+      known_versions.push_back("GLIBCXX_IEEE128_3.4.30");
       known_versions.push_back("CXXABI_1.3");
       known_versions.push_back("CXXABI_LDBL_1.3");
       known_versions.push_back("CXXABI_1.3.1");
@@ -247,11 +248,8 @@
 
       // Check that added symbols are added in the latest pre-release version.
       bool latestp = (test.version_name == "GLIBCXX_3.4.30"
-	  // XXX remove next 3 lines when baselines have been regenerated
-	  // to include {IEEE128,LDBL} symbols:
-		     || test.version_name == "GLIBCXX_LDBL_3.4.29"
-		     || test.version_name == "GLIBCXX_IEEE128_3.4.29"
-		     || test.version_name == "CXXABI_IEEE128_1.3.13"
+	  // XXX remove next line when baselines have been regenerated.
+		     || test.version_name == "GLIBCXX_IEEE128_3.4.30"
 		     || test.version_name == "CXXABI_1.3.13"
 		     || test.version_name == "CXXABI_FLOAT128"
 		     || test.version_name == "CXXABI_TM_1");