]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/cp/constexpr.c
Update copyright years.
[thirdparty/gcc.git] / gcc / cp / constexpr.c
index 67a8f04310cbb381a1e6a62d4a9f6a09d00a590d..c8852bd93090e3f6e8cb725d46b9364ab392b04e 100644 (file)
@@ -2,7 +2,7 @@
    constexpr functions.  These routines are used both during actual parsing
    and during the instantiation of template functions.
 
-   Copyright (C) 1998-2019 Free Software Foundation, Inc.
+   Copyright (C) 1998-2020 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-fold.h"
 #include "timevar.h"
 #include "fold-const-call.h"
+#include "stor-layout.h"
 
 static bool verify_constant (tree, bool, bool *, bool *);
 #define VERIFY_CONSTANT(X)                                             \
@@ -766,6 +767,10 @@ massage_constexpr_body (tree fun, tree body)
 static bool
 cx_check_missing_mem_inits (tree ctype, tree body, bool complain)
 {
+  /* We allow uninitialized bases/fields in C++20.  */
+  if (cxx_dialect >= cxx2a)
+    return false;
+
   unsigned nelts = 0;
   
   if (body)
@@ -814,7 +819,7 @@ cx_check_missing_mem_inits (tree ctype, tree body, bool complain)
            continue;
          if (ANON_AGGR_TYPE_P (TREE_TYPE (field)))
            {
-             /* Recurse to check the anonummous aggregate member.  */
+             /* Recurse to check the anonymous aggregate member.  */
              bad |= cx_check_missing_mem_inits
                (TREE_TYPE (field), NULL_TREE, complain);
              if (bad && !complain)
@@ -880,16 +885,16 @@ register_constexpr_fundef (tree fun, tree body)
       return NULL;
     }
 
-  if (!potential_rvalue_constant_expression (massaged))
-    {
-      if (!DECL_GENERATED_P (fun))
-       require_potential_rvalue_constant_expression (massaged);
-      return NULL;
-    }
+  bool potential = potential_rvalue_constant_expression (massaged);
+  if (!potential && !DECL_GENERATED_P (fun))
+    require_potential_rvalue_constant_expression (massaged);
 
   if (DECL_CONSTRUCTOR_P (fun)
       && cx_check_missing_mem_inits (DECL_CONTEXT (fun),
                                     massaged, !DECL_GENERATED_P (fun)))
+    potential = false;
+
+  if (!potential && !DECL_GENERATED_P (fun))
     return NULL;
 
   /* Create the constexpr function table if necessary.  */
@@ -912,6 +917,12 @@ register_constexpr_fundef (tree fun, tree body)
   if (clear_ctx)
     DECL_CONTEXT (DECL_RESULT (fun)) = NULL_TREE;
 
+  if (!potential)
+    /* For a template instantiation, we want to remember the pre-generic body
+       for explain_invalid_constexpr_fn, but do tell cxx_eval_call_expression
+       that it doesn't need to bother trying to expand the function.  */
+    entry.result = error_mark_node;
+
   gcc_assert (*slot == NULL);
   *slot = ggc_alloc<constexpr_fundef> ();
   **slot = entry;
@@ -933,7 +944,10 @@ explain_invalid_constexpr_fn (tree fun)
   if (!DECL_DEFAULTED_FN (fun)
       && !LAMBDA_TYPE_P (CP_DECL_CONTEXT (fun))
       && !is_instantiation_of_constexpr (fun))
-    return;
+    {
+      inform (DECL_SOURCE_LOCATION (fun), "%qD declared here", fun);
+      return;
+    }
   if (diagnosed == NULL)
     diagnosed = new hash_set<tree>;
   if (diagnosed->add (fun))
@@ -954,11 +968,15 @@ explain_invalid_constexpr_fn (tree fun)
     {
       /* Then if it's OK, the body.  */
       if (!DECL_DECLARED_CONSTEXPR_P (fun)
-         && !LAMBDA_TYPE_P (CP_DECL_CONTEXT (fun)))
+         && DECL_DEFAULTED_FN (fun))
        explain_implicit_non_constexpr (fun);
       else
        {
-         body = massage_constexpr_body (fun, DECL_SAVED_TREE (fun));
+         if (constexpr_fundef *fd = retrieve_constexpr_fundef (fun))
+           body = fd->body;
+         else
+           body = DECL_SAVED_TREE (fun);
+         body = massage_constexpr_body (fun, body);
          require_potential_rvalue_constant_expression (body);
          if (DECL_CONSTRUCTOR_P (fun))
            cx_check_missing_mem_inits (DECL_CONTEXT (fun), body, true);
@@ -974,12 +992,7 @@ explain_invalid_constexpr_fn (tree fun)
 struct GTY((for_user)) constexpr_call {
   /* Description of the constexpr function definition.  */
   constexpr_fundef *fundef;
-  /* Parameter bindings environment.  A TREE_LIST where each TREE_PURPOSE
-     is a parameter _DECL and the TREE_VALUE is the value of the parameter.
-     Note: This arrangement is made to accommodate the use of
-     iterative_hash_template_arg (see pt.c).  If you change this
-     representation, also change the hash calculation in
-     cxx_eval_call_expression.  */
+  /* Parameter bindings environment.  A TREE_VEC of arguments.  */
   tree bindings;
   /* Result of the call.
        NULL means the call is being evaluated.
@@ -1011,19 +1024,39 @@ enum constexpr_switch_state {
   css_default_processing
 };
 
+/* The constexpr expansion context part which needs one instance per
+   cxx_eval_outermost_constant_expr invocation.  VALUES is a map of values of
+   variables initialized within the expression.  */
+
+struct constexpr_global_ctx {
+  /* Values for any temporaries or local variables within the
+     constant-expression. */
+  hash_map<tree,tree> values;
+  /* Number of cxx_eval_constant_expression calls (except skipped ones,
+     on simple constants or location wrappers) encountered during current
+     cxx_eval_outermost_constant_expr call.  */
+  HOST_WIDE_INT constexpr_ops_count;
+  /* Heap VAR_DECLs created during the evaluation of the outermost constant
+     expression.  */
+  auto_vec<tree, 16> heap_vars;
+  /* Cleanups that need to be evaluated at the end of CLEANUP_POINT_EXPR.  */
+  vec<tree> *cleanups;
+  /* Constructor.  */
+  constexpr_global_ctx () : constexpr_ops_count (0), cleanups (NULL) {}
+};
+
 /* The constexpr expansion context.  CALL is the current function
    expansion, CTOR is the current aggregate initializer, OBJECT is the
-   object being initialized by CTOR, either a VAR_DECL or a _REF.  VALUES
-   is a map of values of variables initialized within the expression.  */
+   object being initialized by CTOR, either a VAR_DECL or a _REF.    */
 
 struct constexpr_ctx {
+  /* The part of the context that needs to be unique to the whole
+     cxx_eval_outermost_constant_expr invocation.  */
+  constexpr_global_ctx *global;
   /* The innermost call we're evaluating.  */
   constexpr_call *call;
-  /* Values for any temporaries or local variables within the
-     constant-expression. */
-  hash_map<tree,tree> *values;
-  /* SAVE_EXPRs that we've seen within the current LOOP_EXPR.  NULL if we
-     aren't inside a loop.  */
+  /* SAVE_EXPRs and TARGET_EXPR_SLOT vars of TARGET_EXPRs that we've seen
+     within the current LOOP_EXPR.  NULL if we aren't inside a loop.  */
   vec<tree> *save_exprs;
   /* The CONSTRUCTOR we're currently building up for an aggregate
      initializer.  */
@@ -1032,10 +1065,6 @@ struct constexpr_ctx {
   tree object;
   /* If inside SWITCH_EXPR.  */
   constexpr_switch_state *css_state;
-  /* Number of cxx_eval_constant_expression calls (except skipped ones,
-     on simple constants or location wrappers) encountered during current
-     cxx_eval_outermost_constant_expr call.  */
-  HOST_WIDE_INT *constexpr_ops_count;
 
   /* Whether we should error on a non-constant expression or fail quietly.  */
   bool quiet;
@@ -1069,8 +1098,6 @@ constexpr_call_hasher::hash (constexpr_call *info)
 bool
 constexpr_call_hasher::equal (constexpr_call *lhs, constexpr_call *rhs)
 {
-  tree lhs_bindings;
-  tree rhs_bindings;
   if (lhs == rhs)
     return true;
   if (lhs->hash != rhs->hash)
@@ -1079,19 +1106,7 @@ constexpr_call_hasher::equal (constexpr_call *lhs, constexpr_call *rhs)
     return false;
   if (!constexpr_fundef_hasher::equal (lhs->fundef, rhs->fundef))
     return false;
-  lhs_bindings = lhs->bindings;
-  rhs_bindings = rhs->bindings;
-  while (lhs_bindings != NULL && rhs_bindings != NULL)
-    {
-      tree lhs_arg = TREE_VALUE (lhs_bindings);
-      tree rhs_arg = TREE_VALUE (rhs_bindings);
-      gcc_assert (same_type_p (TREE_TYPE (lhs_arg), TREE_TYPE (rhs_arg)));
-      if (!cp_tree_equal (lhs_arg, rhs_arg))
-        return false;
-      lhs_bindings = TREE_CHAIN (lhs_bindings);
-      rhs_bindings = TREE_CHAIN (rhs_bindings);
-    }
-  return lhs_bindings == rhs_bindings;
+  return cp_tree_equal (lhs->bindings, rhs->bindings);
 }
 
 /* Initialize the constexpr call table, if needed.  */
@@ -1117,15 +1132,6 @@ maybe_initialize_constexpr_call_table (void)
 
 static GTY(()) hash_map<tree, tree> *fundef_copies_table;
 
-/* Initialize FUNDEF_COPIES_TABLE if it's not initialized.  */
-
-static void
-maybe_initialize_fundef_copies_table ()
-{
-  if (fundef_copies_table == NULL)
-    fundef_copies_table = hash_map<tree,tree>::create_ggc (101);
-}
-
 /* Reuse a copy or create a new unshared copy of the function FUN.
    Return this copy.  We use a TREE_LIST whose PURPOSE is body, VALUE
    is parms, TYPE is result.  */
@@ -1133,11 +1139,10 @@ maybe_initialize_fundef_copies_table ()
 static tree
 get_fundef_copy (constexpr_fundef *fundef)
 {
-  maybe_initialize_fundef_copies_table ();
-
   tree copy;
   bool existed;
-  tree *slot = &fundef_copies_table->get_or_insert (fundef->decl, &existed);
+  tree *slot = &(hash_map_safe_get_or_insert<hm_ggc>
+                (fundef_copies_table, fundef->decl, &existed, 127));
 
   if (!existed)
     {
@@ -1249,6 +1254,9 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
       return boolean_true_node;
     }
 
+  if (fndecl_built_in_p (fun, CP_BUILT_IN_SOURCE_LOCATION, BUILT_IN_FRONTEND))
+    return fold_builtin_source_location (EXPR_LOCATION (t));
+
   /* Be permissive for arguments to built-ins; __builtin_constant_p should
      return constant false for a non-constant argument.  */
   constexpr_ctx new_ctx = *ctx;
@@ -1274,7 +1282,7 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
     }
 
   bool save_ffbcp = force_folding_builtin_constant_p;
-  force_folding_builtin_constant_p = true;
+  force_folding_builtin_constant_p |= ctx->manifestly_const_eval;
   tree save_cur_fn = current_function_decl;
   /* Return name of ctx->call->fundef->decl for __builtin_FUNCTION ().  */
   if (fndecl_built_in_p (fun, BUILT_IN_FUNCTION)
@@ -1337,31 +1345,62 @@ adjust_temp_type (tree type, tree temp)
   if (TREE_CODE (temp) == EMPTY_CLASS_EXPR)
     return build0 (EMPTY_CLASS_EXPR, type);
   gcc_assert (scalarish_type_p (type));
-  return cp_fold_convert (type, temp);
+  /* Now we know we're dealing with a scalar, and a prvalue of non-class
+     type is cv-unqualified.  */
+  return cp_fold_convert (cv_unqualified (type), temp);
 }
 
-/* Callback for walk_tree used by unshare_constructor.  */
+/* If T is a CONSTRUCTOR, return an unshared copy of T and any
+   sub-CONSTRUCTORs.  Otherwise return T.
 
-static tree
-find_constructor (tree *tp, int *walk_subtrees, void *)
+   We use this whenever we initialize an object as a whole, whether it's a
+   parameter, a local variable, or a subobject, so that subsequent
+   modifications don't affect other places where it was used.  */
+
+tree
+unshare_constructor (tree t MEM_STAT_DECL)
 {
-  if (TYPE_P (*tp))
-    *walk_subtrees = 0;
-  if (TREE_CODE (*tp) == CONSTRUCTOR)
-    return *tp;
-  return NULL_TREE;
+  if (!t || TREE_CODE (t) != CONSTRUCTOR)
+    return t;
+  auto_vec <tree*, 4> ptrs;
+  ptrs.safe_push (&t);
+  while (!ptrs.is_empty ())
+    {
+      tree *p = ptrs.pop ();
+      tree n = copy_node (*p PASS_MEM_STAT);
+      CONSTRUCTOR_ELTS (n) = vec_safe_copy (CONSTRUCTOR_ELTS (*p) PASS_MEM_STAT);
+      *p = n;
+      vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (n);
+      constructor_elt *ce;
+      for (HOST_WIDE_INT i = 0; vec_safe_iterate (v, i, &ce); ++i)
+       if (TREE_CODE (ce->value) == CONSTRUCTOR)
+         ptrs.safe_push (&ce->value);
+    }
+  return t;
 }
 
-/* If T is a CONSTRUCTOR or an expression that has a CONSTRUCTOR node as a
-   subexpression, return an unshared copy of T.  Otherwise return T.  */
+/* If T is a CONSTRUCTOR, ggc_free T and any sub-CONSTRUCTORs.  */
 
-tree
-unshare_constructor (tree t)
+static void
+free_constructor (tree t)
 {
-  tree ctor = walk_tree (&t, find_constructor, NULL, NULL);
-  if (ctor != NULL_TREE)
-    return unshare_expr (t);
-  return t;
+  if (!t || TREE_CODE (t) != CONSTRUCTOR)
+    return;
+  releasing_vec ctors;
+  vec_safe_push (ctors, t);
+  while (!ctors->is_empty ())
+    {
+      tree c = ctors->pop ();
+      if (vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (c))
+       {
+         constructor_elt *ce;
+         for (HOST_WIDE_INT i = 0; vec_safe_iterate (elts, i, &ce); ++i)
+           if (TREE_CODE (ce->value) == CONSTRUCTOR)
+             vec_safe_push (ctors, ce->value);
+         ggc_free (elts);
+       }
+      ggc_free (c);
+    }
 }
 
 /* Subroutine of cxx_eval_call_expression.
@@ -1380,7 +1419,10 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t,
   tree fun = new_call->fundef->decl;
   tree parms = new_call->fundef->parms;
   int i;
-  tree *p = &new_call->bindings;
+  /* We don't record ellipsis args below.  */
+  int nparms = list_length (parms);
+  int nbinds = nargs < nparms ? nargs : nparms;
+  tree binds = new_call->bindings = make_tree_vec (nbinds);
   for (i = 0; i < nargs; ++i)
     {
       tree x, arg;
@@ -1409,16 +1451,33 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t,
 
       if (!*non_constant_p)
        {
-         /* Don't share a CONSTRUCTOR that might be changed.  */
-         arg = unshare_constructor (arg);
          /* Make sure the binding has the same type as the parm.  But
             only for constant args.  */
          if (!TYPE_REF_P (type))
            arg = adjust_temp_type (type, arg);
          if (!TREE_CONSTANT (arg))
            *non_constant_args = true;
-         *p = build_tree_list (parms, arg);
-         p = &TREE_CHAIN (*p);
+         /* For virtual calls, adjust the this argument, so that it is
+            the object on which the method is called, rather than
+            one of its bases.  */
+         if (i == 0 && DECL_VIRTUAL_P (fun))
+           {
+             tree addr = arg;
+             STRIP_NOPS (addr);
+             if (TREE_CODE (addr) == ADDR_EXPR)
+               {
+                 tree obj = TREE_OPERAND (addr, 0);
+                 while (TREE_CODE (obj) == COMPONENT_REF
+                        && DECL_FIELD_IS_BASE (TREE_OPERAND (obj, 1))
+                        && !same_type_ignoring_top_level_qualifiers_p
+                                       (TREE_TYPE (obj), DECL_CONTEXT (fun)))
+                   obj = TREE_OPERAND (obj, 0);
+                 if (obj != TREE_OPERAND (addr, 0))
+                   arg = build_fold_addr_expr_with_type (obj,
+                                                         TREE_TYPE (arg));
+               }
+           }
+         TREE_VEC_ELT (binds, i) = arg;
        }
       parms = TREE_CHAIN (parms);
     }
@@ -1432,16 +1491,17 @@ static vec<tree> call_stack;
 static int call_stack_tick;
 static int last_cx_error_tick;
 
-static bool
+static int
 push_cx_call_context (tree call)
 {
   ++call_stack_tick;
   if (!EXPR_HAS_LOCATION (call))
     SET_EXPR_LOCATION (call, input_location);
   call_stack.safe_push (call);
-  if (call_stack.length () > (unsigned) max_constexpr_depth)
+  int len = call_stack.length ();
+  if (len > max_constexpr_depth)
     return false;
-  return true;
+  return len;
 }
 
 static void
@@ -1511,7 +1571,7 @@ cxx_eval_internal_function (const constexpr_ctx *ctx, tree t,
 
     default:
       if (!ctx->quiet)
-       error_at (cp_expr_loc_or_loc (t, input_location),
+       error_at (cp_expr_loc_or_input_loc (t),
                  "call to internal function %qE", t);
       *non_constant_p = true;
       return t;
@@ -1526,7 +1586,7 @@ cxx_eval_internal_function (const constexpr_ctx *ctx, tree t,
 
   if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
     {
-      location_t loc = cp_expr_loc_or_loc (t, input_location);
+      location_t loc = cp_expr_loc_or_input_loc (t);
       tree type = TREE_TYPE (TREE_TYPE (t));
       tree result = fold_binary_loc (loc, opcode, type,
                                     fold_convert_loc (loc, type, arg0),
@@ -1559,6 +1619,318 @@ clear_no_implicit_zero (tree ctor)
     }
 }
 
+/* Complain about a const object OBJ being modified in a constant expression.
+   EXPR is the MODIFY_EXPR expression performing the modification.  */
+
+static void
+modifying_const_object_error (tree expr, tree obj)
+{
+  location_t loc = cp_expr_loc_or_input_loc (expr);
+  auto_diagnostic_group d;
+  error_at (loc, "modifying a const object %qE is not allowed in "
+           "a constant expression", TREE_OPERAND (expr, 0));
+  inform (location_of (obj), "originally declared %<const%> here");
+}
+
+/* Return true if FNDECL is a replaceable global allocation function that
+   should be useable during constant expression evaluation.  */
+
+static inline bool
+cxx_replaceable_global_alloc_fn (tree fndecl)
+{
+  return (cxx_dialect >= cxx2a
+         && IDENTIFIER_NEWDEL_OP_P (DECL_NAME (fndecl))
+         && CP_DECL_CONTEXT (fndecl) == global_namespace
+         && (DECL_IS_REPLACEABLE_OPERATOR_NEW_P (fndecl)
+             || DECL_IS_OPERATOR_DELETE_P (fndecl)));
+}
+
+/* Return true if FNDECL is a placement new function that should be
+   useable during constant expression evaluation of std::construct_at.  */
+
+static inline bool
+cxx_placement_new_fn (tree fndecl)
+{
+  if (cxx_dialect >= cxx2a
+      && IDENTIFIER_NEW_OP_P (DECL_NAME (fndecl))
+      && CP_DECL_CONTEXT (fndecl) == global_namespace
+      && !DECL_IS_REPLACEABLE_OPERATOR_NEW_P (fndecl)
+      && TREE_CODE (TREE_TYPE (fndecl)) == FUNCTION_TYPE)
+    {
+      tree first_arg = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
+      if (TREE_VALUE (first_arg) == ptr_type_node
+         && TREE_CHAIN (first_arg) == void_list_node)
+       return true;
+    }
+  return false;
+}
+
+/* Return true if FNDECL is std::construct_at.  */
+
+static inline bool
+is_std_construct_at (tree fndecl)
+{
+  if (!decl_in_std_namespace_p (fndecl))
+    return false;
+
+  tree name = DECL_NAME (fndecl);
+  return name && id_equal (name, "construct_at");
+}
+
+/* Return true if FNDECL is std::allocator<T>::{,de}allocate.  */
+
+static inline bool
+is_std_allocator_allocate (tree fndecl)
+{
+  tree name = DECL_NAME (fndecl);
+  if (name == NULL_TREE
+      || !(id_equal (name, "allocate") || id_equal (name, "deallocate")))
+    return false;
+
+  tree ctx = DECL_CONTEXT (fndecl);
+  if (ctx == NULL_TREE || !CLASS_TYPE_P (ctx) || !TYPE_MAIN_DECL (ctx))
+    return false;
+
+  tree decl = TYPE_MAIN_DECL (ctx);
+  name = DECL_NAME (decl);
+  if (name == NULL_TREE || !id_equal (name, "allocator"))
+    return false;
+
+  return decl_in_std_namespace_p (decl);
+}
+
+/* Return true if FNDECL is __dynamic_cast.  */
+
+static inline bool
+cxx_dynamic_cast_fn_p (tree fndecl)
+{
+  return (cxx_dialect >= cxx2a
+         && id_equal (DECL_NAME (fndecl), "__dynamic_cast")
+         && CP_DECL_CONTEXT (fndecl) == global_namespace);
+}
+
+/* Often, we have an expression in the form of address + offset, e.g.
+   "&_ZTV1A + 16".  Extract the object from it, i.e. "_ZTV1A".  */
+
+static tree
+extract_obj_from_addr_offset (tree expr)
+{
+  if (TREE_CODE (expr) == POINTER_PLUS_EXPR)
+    expr = TREE_OPERAND (expr, 0);
+  STRIP_NOPS (expr);
+  if (TREE_CODE (expr) == ADDR_EXPR)
+    expr = TREE_OPERAND (expr, 0);
+  return expr;
+}
+
+/* Given a PATH like
+
+     g.D.2181.D.2154.D.2102.D.2093
+
+   find a component with type TYPE.  Return NULL_TREE if not found, and
+   error_mark_node if the component is not accessible.  If STOP is non-null,
+   this function will return NULL_TREE if STOP is found before TYPE.  */
+
+static tree
+get_component_with_type (tree path, tree type, tree stop)
+{
+  while (true)
+    {
+      if (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (path), type))
+       /* Found it.  */
+       return path;
+      else if (stop
+              && (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (path),
+                                                             stop)))
+       return NULL_TREE;
+      else if (TREE_CODE (path) == COMPONENT_REF
+              && DECL_FIELD_IS_BASE (TREE_OPERAND (path, 1)))
+       {
+         /* We need to check that the component we're accessing is in fact
+            accessible.  */
+         if (TREE_PRIVATE (TREE_OPERAND (path, 1))
+             || TREE_PROTECTED (TREE_OPERAND (path, 1)))
+           return error_mark_node;
+         path = TREE_OPERAND (path, 0);
+       }
+      else
+       return NULL_TREE;
+    }
+}
+
+/* Evaluate a call to __dynamic_cast (permitted by P1327R1).
+
+   The declaration of __dynamic_cast is:
+
+   void* __dynamic_cast (const void* __src_ptr,
+                        const __class_type_info* __src_type,
+                        const __class_type_info* __dst_type,
+                        ptrdiff_t __src2dst);
+
+   where src2dst has the following possible values
+
+   >-1: src_type is a unique public non-virtual base of dst_type
+       dst_ptr + src2dst == src_ptr
+   -1: unspecified relationship
+   -2: src_type is not a public base of dst_type
+   -3: src_type is a multiple public non-virtual base of dst_type
+
+  Since literal types can't have virtual bases, we only expect hint >=0,
+  -2, or -3.  */
+
+static tree
+cxx_eval_dynamic_cast_fn (const constexpr_ctx *ctx, tree call,
+                         bool *non_constant_p, bool *overflow_p)
+{
+  /* T will be something like
+      __dynamic_cast ((B*) b, &_ZTI1B, &_ZTI1D, 8)
+     dismantle it.  */
+  gcc_assert (call_expr_nargs (call) == 4);
+  tsubst_flags_t complain = ctx->quiet ? tf_none : tf_warning_or_error;
+  tree obj = CALL_EXPR_ARG (call, 0);
+  tree type = CALL_EXPR_ARG (call, 2);
+  HOST_WIDE_INT hint = int_cst_value (CALL_EXPR_ARG (call, 3));
+  location_t loc = cp_expr_loc_or_input_loc (call);
+
+  /* Get the target type of the dynamic_cast.  */
+  gcc_assert (TREE_CODE (type) == ADDR_EXPR);
+  type = TREE_OPERAND (type, 0);
+  type = TREE_TYPE (DECL_NAME (type));
+
+  /* TYPE can only be either T* or T&.  We can't know which of these it
+     is by looking at TYPE, but OBJ will be "(T*) x" in the first case,
+     and something like "(T*)(T&)(T*) x" in the second case.  */
+  bool reference_p = false;
+  while (CONVERT_EXPR_P (obj) || TREE_CODE (obj) == SAVE_EXPR)
+    {
+      reference_p |= TYPE_REF_P (TREE_TYPE (obj));
+      obj = TREE_OPERAND (obj, 0);
+    }
+
+  /* Evaluate the object so that we know its dynamic type.  */
+  obj = cxx_eval_constant_expression (ctx, obj, /*lval*/false, non_constant_p,
+                                     overflow_p);
+  if (*non_constant_p)
+    return call;
+
+  /* We expect OBJ to be in form of &d.D.2102 when HINT == 0,
+     but when HINT is > 0, it can also be something like
+     &d.D.2102 + 18446744073709551608, which includes the BINFO_OFFSET.  */
+  obj = extract_obj_from_addr_offset (obj);
+  const tree objtype = TREE_TYPE (obj);
+  /* If OBJ doesn't refer to a base field, we're done.  */
+  if (tree t = (TREE_CODE (obj) == COMPONENT_REF
+               ? TREE_OPERAND (obj, 1) : obj))
+    if (TREE_CODE (t) != FIELD_DECL || !DECL_FIELD_IS_BASE (t))
+      return integer_zero_node;
+
+  /* [class.cdtor] When a dynamic_cast is used in a constructor ...
+     or in a destructor ... if the operand of the dynamic_cast refers
+     to the object under construction or destruction, this object is
+     considered to be a most derived object that has the type of the
+     constructor or destructor's class.  */
+  tree vtable = build_vfield_ref (obj, TREE_TYPE (obj));
+  vtable = cxx_eval_constant_expression (ctx, vtable, /*lval*/false,
+                                        non_constant_p, overflow_p);
+  if (*non_constant_p)
+    return call;
+  /* VTABLE will be &_ZTV1A + 16 or similar, get _ZTV1A.  */
+  vtable = extract_obj_from_addr_offset (vtable);
+  const tree mdtype = DECL_CONTEXT (vtable);
+
+  /* Given dynamic_cast<T>(v),
+
+     [expr.dynamic.cast] If C is the class type to which T points or refers,
+     the runtime check logically executes as follows:
+
+     If, in the most derived object pointed (referred) to by v, v points
+     (refers) to a public base class subobject of a C object, and if only
+     one object of type C is derived from the subobject pointed (referred)
+     to by v the result points (refers) to that C object.
+
+     In this case, HINT >= 0 or -3.  */
+  if (hint >= 0 || hint == -3)
+    {
+      /* Look for a component with type TYPE.  */
+      tree t = get_component_with_type (obj, type, mdtype);
+      /* If not accessible, give an error.  */
+      if (t == error_mark_node)
+       {
+         if (reference_p)
+           {
+             if (!ctx->quiet)
+               {
+                 error_at (loc, "reference %<dynamic_cast%> failed");
+                 inform (loc, "static type %qT of its operand is a "
+                         "non-public base class of dynamic type %qT",
+                         objtype, type);
+
+               }
+             *non_constant_p = true;
+           }
+         return integer_zero_node;
+       }
+      else if (t)
+       /* The result points to the TYPE object.  */
+       return cp_build_addr_expr (t, complain);
+      /* Else, TYPE was not found, because the HINT turned out to be wrong.
+        Fall through to the normal processing.  */
+    }
+
+  /* Otherwise, if v points (refers) to a public base class subobject of the
+     most derived object, and the type of the most derived object has a base
+     class, of type C, that is unambiguous and public, the result points
+     (refers) to the C subobject of the most derived object.
+
+     But it can also be an invalid case.  */
+      
+  /* Get the most derived object.  */
+  obj = get_component_with_type (obj, mdtype, NULL_TREE);
+  if (obj == error_mark_node)
+    {
+      if (reference_p)
+       {
+         if (!ctx->quiet)
+           {
+             error_at (loc, "reference %<dynamic_cast%> failed");
+             inform (loc, "static type %qT of its operand is a non-public"
+                     " base class of dynamic type %qT", objtype, mdtype);
+           }
+         *non_constant_p = true;
+       }
+      return integer_zero_node;
+    }
+  else
+    gcc_assert (obj);
+
+  /* Check that the type of the most derived object has a base class
+     of type TYPE that is unambiguous and public.  */
+  base_kind b_kind;
+  tree binfo = lookup_base (mdtype, type, ba_check, &b_kind, tf_none);
+  if (!binfo || binfo == error_mark_node)
+    {
+      if (reference_p)
+       {
+         if (!ctx->quiet)
+           {
+             error_at (loc, "reference %<dynamic_cast%> failed");
+             if (b_kind == bk_ambig)
+               inform (loc, "%qT is an ambiguous base class of dynamic "
+                       "type %qT of its operand", type, mdtype);
+             else
+               inform (loc, "dynamic type %qT of its operand does not "
+                       "have an unambiguous public base class %qT",
+                       mdtype, type);
+           }
+         *non_constant_p = true;
+       }
+      return integer_zero_node;
+    }
+  /* If so, return the TYPE subobject of the most derived object.  */
+  obj = convert_to_base_statically (obj, binfo);
+  return cp_build_addr_expr (obj, complain);
+}
+
 /* Subroutine of cxx_eval_constant_expression.
    Evaluate the call expression tree T in the context of OLD_CALL expression
    evaluation.  */
@@ -1568,11 +1940,15 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
                          bool lval,
                          bool *non_constant_p, bool *overflow_p)
 {
-  location_t loc = cp_expr_loc_or_loc (t, input_location);
+  /* Handle concept checks separately.  */
+  if (concept_check_p (t))
+    return evaluate_concept_check (t, tf_warning_or_error);
+
+  location_t loc = cp_expr_loc_or_input_loc (t);
   tree fun = get_function_named_in_call (t);
   constexpr_call new_call
     = { NULL, NULL, NULL, 0, ctx->manifestly_const_eval };
-  bool depth_ok;
+  int depth_ok;
 
   if (fun == NULL_TREE)
     return cxx_eval_internal_function (ctx, t, lval,
@@ -1637,6 +2013,92 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
                                           lval, non_constant_p, overflow_p);
   if (!DECL_DECLARED_CONSTEXPR_P (fun))
     {
+      if (TREE_CODE (t) == CALL_EXPR
+         && cxx_replaceable_global_alloc_fn (fun)
+         && (CALL_FROM_NEW_OR_DELETE_P (t)
+             || (ctx->call
+                 && ctx->call->fundef
+                 && is_std_allocator_allocate (ctx->call->fundef->decl))))
+       {
+         const int nargs = call_expr_nargs (t);
+         tree arg0 = NULL_TREE;
+         for (int i = 0; i < nargs; ++i)
+           {
+             tree arg = CALL_EXPR_ARG (t, i);
+             arg = cxx_eval_constant_expression (ctx, arg, false,
+                                                 non_constant_p, overflow_p);
+             VERIFY_CONSTANT (arg);
+             if (i == 0)
+               arg0 = arg;
+           }
+         gcc_assert (arg0);
+         if (IDENTIFIER_NEW_OP_P (DECL_NAME (fun)))
+           {
+             tree type = build_array_type_nelts (char_type_node,
+                                                 tree_to_uhwi (arg0));
+             tree var = build_decl (loc, VAR_DECL, heap_uninit_identifier,
+                                    type);
+             DECL_ARTIFICIAL (var) = 1;
+             TREE_STATIC (var) = 1;
+             ctx->global->heap_vars.safe_push (var);
+             ctx->global->values.put (var, NULL_TREE);
+             return fold_convert (ptr_type_node, build_address (var));
+           }
+         else
+           {
+             STRIP_NOPS (arg0);
+             if (TREE_CODE (arg0) == ADDR_EXPR
+                 && VAR_P (TREE_OPERAND (arg0, 0)))
+               {
+                 tree var = TREE_OPERAND (arg0, 0);
+                 if (DECL_NAME (var) == heap_uninit_identifier
+                     || DECL_NAME (var) == heap_identifier)
+                   {
+                     DECL_NAME (var) = heap_deleted_identifier;
+                     ctx->global->values.remove (var);
+                     return void_node;
+                   }
+                 else if (DECL_NAME (var) == heap_deleted_identifier)
+                   {
+                     if (!ctx->quiet)
+                       error_at (loc, "deallocation of already deallocated "
+                                      "storage");
+                     *non_constant_p = true;
+                     return t;
+                   }
+               }
+             if (!ctx->quiet)
+               error_at (loc, "deallocation of storage that was "
+                              "not previously allocated");
+             *non_constant_p = true;
+             return t;
+           }
+       }
+      /* Allow placement new in std::construct_at, just return the second
+        argument.  */
+      if (TREE_CODE (t) == CALL_EXPR
+         && cxx_placement_new_fn (fun)
+         && ctx->call
+         && ctx->call->fundef
+         && is_std_construct_at (ctx->call->fundef->decl))
+       {
+         const int nargs = call_expr_nargs (t);
+         tree arg1 = NULL_TREE;
+         for (int i = 0; i < nargs; ++i)
+           {
+             tree arg = CALL_EXPR_ARG (t, i);
+             arg = cxx_eval_constant_expression (ctx, arg, false,
+                                                 non_constant_p, overflow_p);
+             VERIFY_CONSTANT (arg);
+             if (i == 1)
+               arg1 = arg;
+           }
+         gcc_assert (arg1);
+         return arg1;
+       }
+      else if (cxx_dynamic_cast_fn_p (fun))
+       return cxx_eval_dynamic_cast_fn (ctx, t, non_constant_p, overflow_p);
+
       if (!ctx->quiet)
        {
          if (!lambda_static_thunk_p (fun))
@@ -1656,7 +2118,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
       new_ctx.object = AGGR_INIT_EXPR_SLOT (t);
       tree ctor = new_ctx.ctor = build_constructor (DECL_CONTEXT (fun), NULL);
       CONSTRUCTOR_NO_CLEARING (ctor) = true;
-      ctx->values->put (new_ctx.object, ctor);
+      ctx->global->values.put (new_ctx.object, ctor);
       ctx = &new_ctx;
     }
 
@@ -1702,6 +2164,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
     {
       new_call.fundef = retrieve_constexpr_fundef (fun);
       if (new_call.fundef == NULL || new_call.fundef->body == NULL
+         || new_call.fundef->result == error_mark_node
          || fun == current_function_decl)
         {
          if (!ctx->quiet)
@@ -1733,11 +2196,37 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
   bool non_constant_args = false;
   cxx_bind_parameters_in_call (ctx, t, &new_call,
                               non_constant_p, overflow_p, &non_constant_args);
+
+  /* We build up the bindings list before we know whether we already have this
+     call cached.  If we don't end up saving these bindings, ggc_free them when
+     this function exits.  */
+  class free_bindings
+  {
+    tree *bindings;
+  public:
+    free_bindings (tree &b): bindings (&b) { }
+    ~free_bindings () { if (bindings) ggc_free (*bindings); }
+    void preserve () { bindings = NULL; }
+  } fb (new_call.bindings);
+
   if (*non_constant_p)
     return t;
 
   depth_ok = push_cx_call_context (t);
 
+  /* Remember the object we are constructing.  */
+  tree new_obj = NULL_TREE;
+  if (DECL_CONSTRUCTOR_P (fun))
+    {
+      /* In a constructor, it should be the first `this' argument.
+        At this point it has already been evaluated in the call
+        to cxx_bind_parameters_in_call.  */
+      new_obj = TREE_VEC_ELT (new_call.bindings, 0);
+      STRIP_NOPS (new_obj);
+      if (TREE_CODE (new_obj) == ADDR_EXPR)
+       new_obj = TREE_OPERAND (new_obj, 0);
+    }
+
   tree result = NULL_TREE;
 
   constexpr_call *entry = NULL;
@@ -1756,13 +2245,20 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
       entry = *slot;
       if (entry == NULL)
        {
-         /* We need to keep a pointer to the entry, not just the slot, as the
-            slot can move in the call to cxx_eval_builtin_function_call.  */
-         *slot = entry = ggc_alloc<constexpr_call> ();
-         *entry = new_call;
+         /* Only cache up to constexpr_cache_depth to limit memory use.  */
+         if (depth_ok < constexpr_cache_depth)
+           {
+             /* We need to keep a pointer to the entry, not just the slot, as
+                the slot can move during evaluation of the body.  */
+             *slot = entry = ggc_alloc<constexpr_call> ();
+             *entry = new_call;
+             fb.preserve ();
+           }
        }
-      /* Calls that are in progress have their result set to NULL,
-        so that we can detect circular dependencies.  */
+      /* Calls that are in progress have their result set to NULL, so that we
+        can detect circular dependencies.  Now that we only cache up to
+        constexpr_cache_depth this won't catch circular dependencies that
+        start deeper, but they'll hit the recursion or ops limit.  */
       else if (entry->result == NULL)
        {
          if (!ctx->quiet)
@@ -1799,6 +2295,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
       else
        {
          tree body, parms, res;
+         releasing_vec ctors;
 
          /* Reuse or create a new unshared copy of this function's body.  */
          tree copy = get_fundef_copy (new_call.fundef);
@@ -1809,15 +2306,25 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
          /* Associate the bindings with the remapped parms.  */
          tree bound = new_call.bindings;
          tree remapped = parms;
-         while (bound)
+         for (int i = 0; i < TREE_VEC_LENGTH (bound); ++i)
            {
-             tree oparm = TREE_PURPOSE (bound);
-             tree arg = TREE_VALUE (bound);
-             gcc_assert (DECL_NAME (remapped) == DECL_NAME (oparm));
-             /* Don't share a CONSTRUCTOR that might be changed.  */
+             tree arg = TREE_VEC_ELT (bound, i);
+             if (entry)
+               {
+                 /* Unshare args going into the hash table to separate them
+                    from the caller's context, for better GC and to avoid
+                    problems with verify_gimple.  */
+                 arg = unshare_expr_without_location (arg);
+                 TREE_VEC_ELT (bound, i) = arg;
+               }
+             /* Don't share a CONSTRUCTOR that might be changed.  This is not
+                redundant with the unshare just above; we also don't want to
+                change the argument values in the hash table.  XXX Could we
+                unshare lazily in cxx_eval_store_expression?  */
              arg = unshare_constructor (arg);
-             ctx->values->put (remapped, arg);
-             bound = TREE_CHAIN (bound);
+             if (TREE_CODE (arg) == CONSTRUCTOR)
+               vec_safe_push (ctors, arg);
+             ctx->global->values.put (remapped, arg);
              remapped = DECL_CHAIN (remapped);
            }
          /* Add the RESULT_DECL to the values map, too.  */
@@ -1827,14 +2334,14 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
              slot = AGGR_INIT_EXPR_SLOT (t);
              tree addr = build_address (slot);
              addr = build_nop (TREE_TYPE (res), addr);
-             ctx->values->put (res, addr);
-             ctx->values->put (slot, NULL_TREE);
+             ctx->global->values.put (res, addr);
+             ctx->global->values.put (slot, NULL_TREE);
            }
          else
-           ctx->values->put (res, NULL_TREE);
+           ctx->global->values.put (res, NULL_TREE);
 
-         /* Track the callee's evaluated SAVE_EXPRs so that we can forget
-            their values after the call.  */
+         /* Track the callee's evaluated SAVE_EXPRs and TARGET_EXPRs so that
+            we can forget their values after the call.  */
          constexpr_ctx ctx_with_save_exprs = *ctx;
          auto_vec<tree, 10> save_exprs;
          ctx_with_save_exprs.save_exprs = &save_exprs;
@@ -1856,7 +2363,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
            result = void_node;
          else
            {
-             result = *ctx->values->get (slot ? slot : res);
+             result = *ctx->global->values.get (slot ? slot : res);
              if (result == NULL_TREE && !*non_constant_p)
                {
                  if (!ctx->quiet)
@@ -1866,21 +2373,47 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
                }
            }
 
-         /* Forget the saved values of the callee's SAVE_EXPRs.  */
+         /* At this point, the object's constructor will have run, so
+            the object is no longer under construction, and its possible
+            'const' semantics now apply.  Make a note of this fact by
+            marking the CONSTRUCTOR TREE_READONLY.  */
+         if (new_obj
+             && CLASS_TYPE_P (TREE_TYPE (new_obj))
+             && CP_TYPE_CONST_P (TREE_TYPE (new_obj)))
+           {
+             /* Subobjects might not be stored in ctx->global->values but we
+                can get its CONSTRUCTOR by evaluating *this.  */
+             tree e = cxx_eval_constant_expression (ctx, new_obj,
+                                                    /*lval*/false,
+                                                    non_constant_p,
+                                                    overflow_p);
+             TREE_READONLY (e) = true;
+           }
+
+         /* Forget the saved values of the callee's SAVE_EXPRs and
+            TARGET_EXPRs.  */
          unsigned int i;
          tree save_expr;
          FOR_EACH_VEC_ELT (save_exprs, i, save_expr)
-           ctx_with_save_exprs.values->remove (save_expr);
+           ctx->global->values.remove (save_expr);
 
          /* Remove the parms/result from the values map.  Is it worth
             bothering to do this when the map itself is only live for
             one constexpr evaluation?  If so, maybe also clear out
             other vars from call, maybe in BIND_EXPR handling?  */
-         ctx->values->remove (res);
+         ctx->global->values.remove (res);
          if (slot)
-           ctx->values->remove (slot);
+           ctx->global->values.remove (slot);
          for (tree parm = parms; parm; parm = TREE_CHAIN (parm))
-           ctx->values->remove (parm);
+           ctx->global->values.remove (parm);
+
+         /* Free any parameter CONSTRUCTORs we aren't returning directly.  */
+         while (!ctors->is_empty ())
+           {
+             tree c = ctors->pop ();
+             if (c != result)
+               free_constructor (c);
+           }
 
          /* Make the unshared function copy we used available for re-use.  */
          save_fundef_copy (fun, copy);
@@ -1896,15 +2429,26 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
        entry->result = result;
     }
 
-  /* The result of a constexpr function must be completely initialized.  */
-  if (TREE_CODE (result) == CONSTRUCTOR)
+  /* The result of a constexpr function must be completely initialized.
+
+     However, in C++20, a constexpr constructor doesn't necessarily have
+     to initialize all the fields, so we don't clear CONSTRUCTOR_NO_CLEARING
+     in order to detect reading an unitialized object in constexpr instead
+     of value-initializing it.  (reduced_constant_expression_p is expected to
+     take care of clearing the flag.)  */
+  if (TREE_CODE (result) == CONSTRUCTOR
+      && (cxx_dialect < cxx2a
+         || !DECL_CONSTRUCTOR_P (fun)))
     clear_no_implicit_zero (result);
 
   pop_cx_call_context ();
-  return unshare_constructor (result);
+  return result;
 }
 
-/* FIXME speed this up, it's taking 16% of compile time on sieve testcase.  */
+/* Return true if T is a valid constant initializer.  If a CONSTRUCTOR
+   initializes all the members, the CONSTRUCTOR_NO_CLEARING flag will be
+   cleared.
+   FIXME speed this up, it's taking 16% of compile time on sieve testcase.  */
 
 bool
 reduced_constant_expression_p (tree t)
@@ -1926,6 +2470,12 @@ reduced_constant_expression_p (tree t)
          if (TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
            /* An initialized vector would have a VECTOR_CST.  */
            return false;
+         else if (cxx_dialect >= cxx2a
+                  /* An ARRAY_TYPE doesn't have any TYPE_FIELDS.  */
+                  && (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE
+                      /* A union only initializes one member.  */
+                      || TREE_CODE (TREE_TYPE (t)) == UNION_TYPE))
+           field = NULL_TREE;
          else
            field = next_initializable_field (TYPE_FIELDS (TREE_TYPE (t)));
        }
@@ -1939,14 +2489,20 @@ reduced_constant_expression_p (tree t)
            return false;
          if (field)
            {
-             if (idx != field)
-               return false;
+             /* Empty class field may or may not have an initializer.  */
+             for (; idx != field;
+                  field = next_initializable_field (DECL_CHAIN (field)))
+               if (!is_really_empty_class (TREE_TYPE (field),
+                                           /*ignore_vptr*/false))
+                 return false;
              field = next_initializable_field (DECL_CHAIN (field));
            }
        }
-      if (field)
-       return false;
-      else if (CONSTRUCTOR_NO_CLEARING (t))
+      /* There could be a non-empty field at the end.  */
+      for (; field; field = next_initializable_field (DECL_CHAIN (field)))
+       if (!is_really_empty_class (TREE_TYPE (field), /*ignore_vptr*/false))
+         return false;
+      if (CONSTRUCTOR_NO_CLEARING (t))
        /* All the fields are initialized.  */
        CONSTRUCTOR_NO_CLEARING (t) = false;
       return true;
@@ -2227,6 +2783,12 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t,
   else if (code == POINTER_PLUS_EXPR)
     r = cxx_fold_pointer_plus_expression (ctx, t, lhs, rhs, non_constant_p,
                                          overflow_p);
+  else if (code == SPACESHIP_EXPR)
+    {
+      r = genericize_spaceship (type, lhs, rhs);
+      r = cxx_eval_constant_expression (ctx, r, false, non_constant_p,
+                                       overflow_p);
+    }
 
   if (r == NULL_TREE)
     r = fold_binary_loc (loc, code, type, lhs, rhs);
@@ -2444,7 +3006,7 @@ find_array_ctor_elt (tree ary, tree dindex, bool insert)
    an out-of-bounds subscript INDEX into the expression ARRAY.  */
 
 static void
-diag_array_subscript (const constexpr_ctx *ctx, tree array, tree index)
+diag_array_subscript (location_t loc, const constexpr_ctx *ctx, tree array, tree index)
 {
   if (!ctx->quiet)
     {
@@ -2453,22 +3015,23 @@ diag_array_subscript (const constexpr_ctx *ctx, tree array, tree index)
       /* Convert the unsigned array subscript to a signed integer to avoid
         printing huge numbers for small negative values.  */
       tree sidx = fold_convert (ssizetype, index);
+      STRIP_ANY_LOCATION_WRAPPER (array);
       if (DECL_P (array))
        {
          if (TYPE_DOMAIN (arraytype))
-           error ("array subscript value %qE is outside the bounds "
-                  "of array %qD of type %qT", sidx, array, arraytype);
+           error_at (loc, "array subscript value %qE is outside the bounds "
+                     "of array %qD of type %qT", sidx, array, arraytype);
          else
-           error ("non-zero array subscript %qE is used with array %qD of "
-                  "type %qT with unknown bounds", sidx, array, arraytype);
+           error_at (loc, "nonzero array subscript %qE is used with array %qD of "
+                     "type %qT with unknown bounds", sidx, array, arraytype);
          inform (DECL_SOURCE_LOCATION (array), "declared here");
        }
       else if (TYPE_DOMAIN (arraytype))
-       error ("array subscript value %qE is outside the bounds "
-              "of array type %qT", sidx, arraytype);
+       error_at (loc, "array subscript value %qE is outside the bounds "
+                 "of array type %qT", sidx, arraytype);
       else
-       error ("non-zero array subscript %qE is used with array of type %qT "
-              "with unknown bounds", sidx, arraytype);
+       error_at (loc, "nonzero array subscript %qE is used with array of type %qT "
+                 "with unknown bounds", sidx, arraytype);
     }
 }
 
@@ -2519,83 +3082,98 @@ extract_string_elt (tree string, unsigned chars_per_elt, unsigned index)
   return r;
 }
 
-/* Subroutine of cxx_eval_constant_expression.
-   Attempt to reduce a reference to an array slot.  */
+/* Subroutine of cxx_eval_array_reference.  T is an ARRAY_REF; evaluate the
+   subscript, diagnose any problems with it, and return the result.  */
 
 static tree
-cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
-                         bool lval,
-                         bool *non_constant_p, bool *overflow_p)
+eval_and_check_array_index (const constexpr_ctx *ctx,
+                           tree t, bool allow_one_past,
+                           bool *non_constant_p, bool *overflow_p)
 {
-  tree oldary = TREE_OPERAND (t, 0);
-  tree ary = cxx_eval_constant_expression (ctx, oldary,
-                                          lval,
-                                          non_constant_p, overflow_p);
-  tree index, oldidx;
-  HOST_WIDE_INT i = 0;
-  tree elem_type = NULL_TREE;
-  unsigned len = 0, elem_nchars = 1;
-  if (*non_constant_p)
-    return t;
-  oldidx = TREE_OPERAND (t, 1);
-  index = cxx_eval_constant_expression (ctx, oldidx,
-                                       false,
-                                       non_constant_p, overflow_p);
+  location_t loc = cp_expr_loc_or_input_loc (t);
+  tree ary = TREE_OPERAND (t, 0);
+  t = TREE_OPERAND (t, 1);
+  tree index = cxx_eval_constant_expression (ctx, t, false,
+                                            non_constant_p, overflow_p);
   VERIFY_CONSTANT (index);
-  if (!lval)
-    {
-      elem_type = TREE_TYPE (TREE_TYPE (ary));
-      if (TREE_CODE (ary) == VIEW_CONVERT_EXPR
-         && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (ary, 0)))
-         && TREE_TYPE (t) == TREE_TYPE (TREE_TYPE (TREE_OPERAND (ary, 0))))
-       ary = TREE_OPERAND (ary, 0);
-      if (TREE_CODE (ary) == CONSTRUCTOR)
-       len = CONSTRUCTOR_NELTS (ary);
-      else if (TREE_CODE (ary) == STRING_CST)
-       {
-         elem_nchars = (TYPE_PRECISION (elem_type)
-                        / TYPE_PRECISION (char_type_node));
-         len = (unsigned) TREE_STRING_LENGTH (ary) / elem_nchars;
-       }
-      else if (TREE_CODE (ary) == VECTOR_CST)
-       /* We don't create variable-length VECTOR_CSTs.  */
-       len = VECTOR_CST_NELTS (ary).to_constant ();
-      else
-       {
-         /* We can't do anything with other tree codes, so use
-            VERIFY_CONSTANT to complain and fail.  */
-         VERIFY_CONSTANT (ary);
-         gcc_unreachable ();
-       }
 
-      if (!tree_fits_shwi_p (index)
-         || (i = tree_to_shwi (index)) < 0)
-       {
-         diag_array_subscript (ctx, ary, index);
-         *non_constant_p = true;
-         return t;
-       }
+  if (!tree_fits_shwi_p (index)
+      || tree_int_cst_sgn (index) < 0)
+    {
+      diag_array_subscript (loc, ctx, ary, index);
+      *non_constant_p = true;
+      return t;
     }
 
   tree nelts = get_array_or_vector_nelts (ctx, TREE_TYPE (ary), non_constant_p,
                                          overflow_p);
   VERIFY_CONSTANT (nelts);
-  if ((lval
-       ? !tree_int_cst_le (index, nelts)
-       : !tree_int_cst_lt (index, nelts))
-      || tree_int_cst_sgn (index) < 0)
+  if (allow_one_past
+      ? !tree_int_cst_le (index, nelts)
+      : !tree_int_cst_lt (index, nelts))
     {
-      diag_array_subscript (ctx, ary, index);
+      diag_array_subscript (loc, ctx, ary, index);
       *non_constant_p = true;
       return t;
     }
 
+  return index;
+}
+
+/* Subroutine of cxx_eval_constant_expression.
+   Attempt to reduce a reference to an array slot.  */
+
+static tree
+cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
+                         bool lval,
+                         bool *non_constant_p, bool *overflow_p)
+{
+  tree oldary = TREE_OPERAND (t, 0);
+  tree ary = cxx_eval_constant_expression (ctx, oldary,
+                                          lval,
+                                          non_constant_p, overflow_p);
+  if (*non_constant_p)
+    return t;
+  if (!lval
+      && TREE_CODE (ary) == VIEW_CONVERT_EXPR
+      && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (ary, 0)))
+      && TREE_TYPE (t) == TREE_TYPE (TREE_TYPE (TREE_OPERAND (ary, 0))))
+    ary = TREE_OPERAND (ary, 0);
+
+  tree oldidx = TREE_OPERAND (t, 1);
+  tree index = eval_and_check_array_index (ctx, t, lval,
+                                          non_constant_p, overflow_p);
+  if (*non_constant_p)
+    return t;
+
   if (lval && ary == oldary && index == oldidx)
     return t;
   else if (lval)
     return build4 (ARRAY_REF, TREE_TYPE (t), ary, index, NULL, NULL);
 
+  unsigned len = 0, elem_nchars = 1;
+  tree elem_type = TREE_TYPE (TREE_TYPE (ary));
+  if (TREE_CODE (ary) == CONSTRUCTOR)
+    len = CONSTRUCTOR_NELTS (ary);
+  else if (TREE_CODE (ary) == STRING_CST)
+    {
+      elem_nchars = (TYPE_PRECISION (elem_type)
+                    / TYPE_PRECISION (char_type_node));
+      len = (unsigned) TREE_STRING_LENGTH (ary) / elem_nchars;
+    }
+  else if (TREE_CODE (ary) == VECTOR_CST)
+    /* We don't create variable-length VECTOR_CSTs.  */
+    len = VECTOR_CST_NELTS (ary).to_constant ();
+  else
+    {
+      /* We can't do anything with other tree codes, so use
+        VERIFY_CONSTANT to complain and fail.  */
+      VERIFY_CONSTANT (ary);
+      gcc_unreachable ();
+    }
+
   bool found;
+  HOST_WIDE_INT i = 0;
   if (TREE_CODE (ary) == CONSTRUCTOR)
     {
       HOST_WIDE_INT ix = find_array_ctor_elt (ary, index);
@@ -2604,7 +3182,10 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
        i = ix;
     }
   else
-    found = (i < len);
+    {
+      i = tree_to_shwi (index);
+      found = (i < len);
+    }
 
   if (found)
     {
@@ -2701,7 +3282,10 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t,
          : field == part)
        {
          if (value)
-           return value;
+           {
+             STRIP_ANY_LOCATION_WRAPPER (value);
+             return value;
+           }
          else
            /* We're in the middle of initializing it.  */
            break;
@@ -2791,6 +3375,7 @@ cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t,
   FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (whole), i, field, value)
     {
       tree bitpos = bit_position (field);
+      STRIP_ANY_LOCATION_WRAPPER (value);
       if (bitpos == start && DECL_SIZE (field) == TREE_OPERAND (t, 1))
        return value;
       if (TREE_CODE (TREE_TYPE (field)) == INTEGER_TYPE
@@ -2973,7 +3558,7 @@ verify_ctor_sanity (const constexpr_ctx *ctx, tree type)
                          (TREE_TYPE (type), TREE_TYPE (otype)))));
     }
   gcc_assert (!ctx->object || !DECL_P (ctx->object)
-             || *(ctx->values->get (ctx->object)) == ctx->ctor);
+             || *(ctx->global->values.get (ctx->object)) == ctx->ctor);
 }
 
 /* Subroutine of cxx_eval_constant_expression.
@@ -3242,6 +3827,103 @@ same_type_ignoring_tlq_and_bounds_p (tree type1, tree type2)
   return same_type_ignoring_top_level_qualifiers_p (type1, type2);
 }
 
+/* Helper function for cxx_fold_indirect_ref_1, called recursively.  */
+
+static tree
+cxx_fold_indirect_ref_1 (location_t loc, tree type, tree op,
+                        unsigned HOST_WIDE_INT off, bool *empty_base)
+{
+  tree optype = TREE_TYPE (op);
+  unsigned HOST_WIDE_INT const_nunits;
+  if (off == 0)
+    {
+      if (similar_type_p (optype, type))
+       return op;
+      /* Also handle conversion to an empty base class, which
+        is represented with a NOP_EXPR.  */
+      /* *(foo *)&complexfoo => __real__ complexfoo */
+      else if (TREE_CODE (optype) == COMPLEX_TYPE
+              && similar_type_p (type, TREE_TYPE (optype)))
+       return build1_loc (loc, REALPART_EXPR, type, op);
+    }
+  /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
+  else if (TREE_CODE (optype) == COMPLEX_TYPE
+          && similar_type_p (type, TREE_TYPE (optype))
+          && tree_to_uhwi (TYPE_SIZE_UNIT (type)) == off)
+    return build1_loc (loc, IMAGPART_EXPR, type, op);
+  if (is_empty_class (type)
+      && CLASS_TYPE_P (optype)
+      && DERIVED_FROM_P (type, optype))
+    {
+      *empty_base = true;
+      return op;
+    }
+  /* ((foo*)&vectorfoo)[x] => BIT_FIELD_REF<vectorfoo,...> */
+  else if (VECTOR_TYPE_P (optype)
+          && similar_type_p (type, TREE_TYPE (optype))
+          && TYPE_VECTOR_SUBPARTS (optype).is_constant (&const_nunits))
+    {
+      unsigned HOST_WIDE_INT part_width = tree_to_uhwi (TYPE_SIZE_UNIT (type));
+      unsigned HOST_WIDE_INT max_offset = part_width * const_nunits;
+      if (off < max_offset && off % part_width == 0)
+       {
+         tree index = bitsize_int (off * BITS_PER_UNIT);
+         return build3_loc (loc, BIT_FIELD_REF, type, op,
+                            TYPE_SIZE (type), index);
+       }
+    }
+  /* ((foo *)&fooarray)[x] => fooarray[x] */
+  else if (TREE_CODE (optype) == ARRAY_TYPE
+          && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (optype)))
+          && !integer_zerop (TYPE_SIZE_UNIT (TREE_TYPE (optype))))
+    {
+      tree type_domain = TYPE_DOMAIN (optype);
+      tree min_val = size_zero_node;
+      if (type_domain && TYPE_MIN_VALUE (type_domain))
+       min_val = TYPE_MIN_VALUE (type_domain);
+      unsigned HOST_WIDE_INT el_sz
+       = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (optype)));
+      unsigned HOST_WIDE_INT idx = off / el_sz;
+      unsigned HOST_WIDE_INT rem = off % el_sz;
+      if (tree_fits_uhwi_p (min_val))
+       {
+         tree index = size_int (idx + tree_to_uhwi (min_val));
+         op = build4_loc (loc, ARRAY_REF, TREE_TYPE (optype), op, index,
+                          NULL_TREE, NULL_TREE);
+         return cxx_fold_indirect_ref_1 (loc, type, op, rem,
+                                         empty_base);
+       }
+    }
+  /* ((foo *)&struct_with_foo_field)[x] => COMPONENT_REF */
+  else if (TREE_CODE (optype) == RECORD_TYPE)
+    {
+      for (tree field = TYPE_FIELDS (optype);
+          field; field = DECL_CHAIN (field))
+       if (TREE_CODE (field) == FIELD_DECL
+           && TREE_TYPE (field) != error_mark_node
+           && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (field))))
+         {
+           tree pos = byte_position (field);
+           if (!tree_fits_uhwi_p (pos))
+             continue;
+           unsigned HOST_WIDE_INT upos = tree_to_uhwi (pos);
+           unsigned el_sz
+             = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (field)));
+           if (upos <= off && off < upos + el_sz)
+             {
+               tree cop = build3 (COMPONENT_REF, TREE_TYPE (field),
+                                  op, field, NULL_TREE);
+               if (tree ret = cxx_fold_indirect_ref_1 (loc, type, cop,
+                                                       off - upos,
+                                                       empty_base))
+                 return ret;
+             }
+         }
+    }
+
+  return NULL_TREE;
+}
+
 /* A less strict version of fold_indirect_ref_1, which requires cv-quals to
    match.  We want to be less strict for simple *& folding; if we have a
    non-const temporary that we access through a const pointer, that should
@@ -3249,9 +3931,7 @@ same_type_ignoring_tlq_and_bounds_p (tree type1, tree type2)
    because we're dealing with things like ADDR_EXPR of INTEGER_CST which
    don't really make sense outside of constant expression evaluation.  Also
    we want to allow folding to COMPONENT_REF, which could cause trouble
-   with TBAA in fold_indirect_ref_1.
-
-   Try to keep this function synced with fold_indirect_ref_1.  */
+   with TBAA in fold_indirect_ref_1.  */
 
 static tree
 cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
@@ -3274,7 +3954,7 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
       if (TREE_CODE (op) == CONST_DECL)
        return DECL_INITIAL (op);
       /* *&p => p;  make sure to handle *&"str"[cst] here.  */
-      if (same_type_ignoring_tlq_and_bounds_p (optype, type))
+      if (similar_type_p (optype, type))
        {
          tree fop = fold_read_from_constant_string (op);
          if (fop)
@@ -3282,152 +3962,23 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
          else
            return op;
        }
-      /* *(foo *)&fooarray => fooarray[0] */
-      else if (TREE_CODE (optype) == ARRAY_TYPE
-              && (same_type_ignoring_top_level_qualifiers_p
-                  (type, TREE_TYPE (optype))))
-       {
-         tree type_domain = TYPE_DOMAIN (optype);
-         tree min_val = size_zero_node;
-         if (type_domain && TYPE_MIN_VALUE (type_domain))
-           min_val = TYPE_MIN_VALUE (type_domain);
-         return build4_loc (loc, ARRAY_REF, type, op, min_val,
-                            NULL_TREE, NULL_TREE);
-       }
-      /* *(foo *)&complexfoo => __real__ complexfoo */
-      else if (TREE_CODE (optype) == COMPLEX_TYPE
-              && (same_type_ignoring_top_level_qualifiers_p
-                  (type, TREE_TYPE (optype))))
-       return fold_build1_loc (loc, REALPART_EXPR, type, op);
-      /* *(foo *)&vectorfoo => BIT_FIELD_REF<vectorfoo,...> */
-      else if (VECTOR_TYPE_P (optype)
-              && (same_type_ignoring_top_level_qualifiers_p
-                  (type, TREE_TYPE (optype))))
-       {
-         tree part_width = TYPE_SIZE (type);
-         tree index = bitsize_int (0);
-         return fold_build3_loc (loc, BIT_FIELD_REF, type, op, part_width,
-                                 index);
-       }
-      /* Also handle conversion to an empty base class, which
-        is represented with a NOP_EXPR.  */
-      else if (is_empty_class (type)
-              && CLASS_TYPE_P (optype)
-              && DERIVED_FROM_P (type, optype))
-       {
-         *empty_base = true;
-         return op;
-       }
-      /* *(foo *)&struct_with_foo_field => COMPONENT_REF */
-      else if (RECORD_OR_UNION_TYPE_P (optype))
-       {
-         tree field = TYPE_FIELDS (optype);
-         for (; field; field = DECL_CHAIN (field))
-           if (TREE_CODE (field) == FIELD_DECL
-               && TREE_TYPE (field) != error_mark_node
-               && integer_zerop (byte_position (field))
-               && (same_type_ignoring_top_level_qualifiers_p
-                   (TREE_TYPE (field), type)))
-             return fold_build3 (COMPONENT_REF, type, op, field, NULL_TREE);
-       }
+      else
+       return cxx_fold_indirect_ref_1 (loc, type, op, 0, empty_base);
     }
   else if (TREE_CODE (sub) == POINTER_PLUS_EXPR
-          && poly_int_tree_p (TREE_OPERAND (sub, 1), &const_op01))
+          && tree_fits_uhwi_p (TREE_OPERAND (sub, 1)))
     {
       tree op00 = TREE_OPERAND (sub, 0);
       tree op01 = TREE_OPERAND (sub, 1);
 
       STRIP_NOPS (op00);
       if (TREE_CODE (op00) == ADDR_EXPR)
-       {
-         tree op00type;
-         op00 = TREE_OPERAND (op00, 0);
-         op00type = TREE_TYPE (op00);
-
-         /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
-         if (VECTOR_TYPE_P (op00type)
-             && same_type_ignoring_top_level_qualifiers_p
-                                               (type, TREE_TYPE (op00type))
-             /* POINTER_PLUS_EXPR second operand is sizetype, unsigned,
-                but we want to treat offsets with MSB set as negative.
-                For the code below negative offsets are invalid and
-                TYPE_SIZE of the element is something unsigned, so
-                check whether op01 fits into poly_int64, which implies
-                it is from 0 to INTTYPE_MAXIMUM (HOST_WIDE_INT), and
-                then just use poly_uint64 because we want to treat the
-                value as unsigned.  */
-             && tree_fits_poly_int64_p (op01))
-           {
-             tree part_width = TYPE_SIZE (type);
-             poly_uint64 max_offset
-               = (tree_to_uhwi (part_width) / BITS_PER_UNIT
-                  * TYPE_VECTOR_SUBPARTS (op00type));
-             if (known_lt (const_op01, max_offset))
-               {
-                 tree index = bitsize_int (const_op01 * BITS_PER_UNIT);
-                 return fold_build3_loc (loc,
-                                         BIT_FIELD_REF, type, op00,
-                                         part_width, index);
-               }
-           }
-         /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
-         else if (TREE_CODE (op00type) == COMPLEX_TYPE
-                  && (same_type_ignoring_top_level_qualifiers_p
-                      (type, TREE_TYPE (op00type))))
-           {
-             if (known_eq (wi::to_poly_offset (TYPE_SIZE_UNIT (type)),
-                           const_op01))
-               return fold_build1_loc (loc, IMAGPART_EXPR, type, op00);
-           }
-         /* ((foo *)&fooarray)[1] => fooarray[1] */
-         else if (TREE_CODE (op00type) == ARRAY_TYPE
-                  && (same_type_ignoring_top_level_qualifiers_p
-                      (type, TREE_TYPE (op00type))))
-           {
-             tree type_domain = TYPE_DOMAIN (op00type);
-             tree min_val = size_zero_node;
-             if (type_domain && TYPE_MIN_VALUE (type_domain))
-               min_val = TYPE_MIN_VALUE (type_domain);
-             offset_int off = wi::to_offset (op01);
-             offset_int el_sz = wi::to_offset (TYPE_SIZE_UNIT (type));
-             offset_int remainder;
-             off = wi::divmod_trunc (off, el_sz, SIGNED, &remainder);
-             if (remainder == 0 && TREE_CODE (min_val) == INTEGER_CST)
-               {
-                 off = off + wi::to_offset (min_val);
-                 op01 = wide_int_to_tree (sizetype, off);
-                 return build4_loc (loc, ARRAY_REF, type, op00, op01,
-                                    NULL_TREE, NULL_TREE);
-               }
-           }
-         /* Also handle conversion to an empty base class, which
-            is represented with a NOP_EXPR.  */
-         else if (is_empty_class (type)
-                  && CLASS_TYPE_P (op00type)
-                  && DERIVED_FROM_P (type, op00type))
-           {
-             *empty_base = true;
-             return op00;
-           }
-         /* ((foo *)&struct_with_foo_field)[1] => COMPONENT_REF */
-         else if (RECORD_OR_UNION_TYPE_P (op00type))
-           {
-             tree field = TYPE_FIELDS (op00type);
-             for (; field; field = DECL_CHAIN (field))
-               if (TREE_CODE (field) == FIELD_DECL
-                   && TREE_TYPE (field) != error_mark_node
-                   && tree_int_cst_equal (byte_position (field), op01)
-                   && (same_type_ignoring_top_level_qualifiers_p
-                       (TREE_TYPE (field), type)))
-                 return fold_build3 (COMPONENT_REF, type, op00,
-                                     field, NULL_TREE);
-           }
-       }
+       return cxx_fold_indirect_ref_1 (loc, type, TREE_OPERAND (op00, 0),
+                                       tree_to_uhwi (op01), empty_base);
     }
   /* *(foo *)fooarrptr => (*fooarrptr)[0] */
   else if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
-          && (same_type_ignoring_top_level_qualifiers_p
-              (type, TREE_TYPE (TREE_TYPE (subtype)))))
+          && similar_type_p (type, TREE_TYPE (TREE_TYPE (subtype))))
     {
       tree type_domain;
       tree min_val = size_zero_node;
@@ -3497,13 +4048,14 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t,
          STRIP_NOPS (sub);
          if (TREE_CODE (sub) == ADDR_EXPR)
            {
-             gcc_assert (!same_type_ignoring_top_level_qualifiers_p
+             gcc_assert (!similar_type_p
                          (TREE_TYPE (TREE_TYPE (sub)), TREE_TYPE (t)));
              /* DR 1188 says we don't have to deal with this.  */
              if (!ctx->quiet)
-               error ("accessing value of %qE through a %qT glvalue in a "
-                      "constant expression", build_fold_indirect_ref (sub),
-                      TREE_TYPE (t));
+               error_at (cp_expr_loc_or_input_loc (t),
+                         "accessing value of %qE through a %qT glvalue in a "
+                         "constant expression", build_fold_indirect_ref (sub),
+                         TREE_TYPE (t));
              *non_constant_p = true;
              return t;
            }
@@ -3537,11 +4089,27 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t,
    cxx_eval_constant_expression.  */
 
 static void
-non_const_var_error (tree r)
+non_const_var_error (location_t loc, tree r)
 {
+  auto_diagnostic_group d;
   tree type = TREE_TYPE (r);
-  error ("the value of %qD is not usable in a constant "
-        "expression", r);
+  if (DECL_NAME (r) == heap_uninit_identifier
+      || DECL_NAME (r) == heap_identifier)
+    {
+      error_at (loc, "the content of uninitialized storage is not usable "
+               "in a constant expression");
+      inform (DECL_SOURCE_LOCATION (r), "allocated here");
+      return;
+    }
+  if (DECL_NAME (r) == heap_deleted_identifier)
+    {
+      error_at (loc, "use of allocated storage after deallocation in a "
+               "constant expression");
+      inform (DECL_SOURCE_LOCATION (r), "allocated here");
+      return;
+    }
+  error_at (loc, "the value of %qD is not usable in a constant "
+           "expression", r);
   /* Avoid error cascade.  */
   if (DECL_INITIAL (r) == error_mark_node)
     return;
@@ -3653,6 +4221,26 @@ maybe_simplify_trivial_copy (tree &target, tree &init)
     }
 }
 
+/* Return true if we are modifying something that is const during constant
+   expression evaluation.  CODE is the code of the statement, OBJ is the
+   object in question, MUTABLE_P is true if one of the subobjects were
+   declared mutable.  */
+
+static bool
+modifying_const_object_p (tree_code code, tree obj, bool mutable_p)
+{
+  /* If this is initialization, there's no problem.  */
+  if (code != MODIFY_EXPR)
+    return false;
+
+  /* [basic.type.qualifier] "A const object is an object of type
+     const T or a non-mutable subobject of a const object."  */
+  if (mutable_p)
+    return false;
+
+  return (TREE_READONLY (obj) || CP_TYPE_CONST_P (TREE_TYPE (obj)));
+}
+
 /* Evaluate an INIT_EXPR or MODIFY_EXPR.  */
 
 static tree
@@ -3685,62 +4273,26 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
       if (*non_constant_p)
        return t;
     }
-  target = cxx_eval_constant_expression (ctx, target,
-                                        true,
-                                        non_constant_p, overflow_p);
-  if (*non_constant_p)
-    return t;
 
-  /* cxx_eval_array_reference for lval = true allows references one past
-     end of array, because it does not know if it is just taking address
-     (which is valid), or actual dereference.  Here we know it is
-     a dereference, so diagnose it here.  */
-  for (tree probe = target; probe; )
+  bool evaluated = false;
+  if (lval)
     {
-      switch (TREE_CODE (probe))
-       {
-       case ARRAY_REF:
-         tree nelts, ary;
-         ary = TREE_OPERAND (probe, 0);
-         nelts = get_array_or_vector_nelts (ctx, TREE_TYPE (ary),
+      /* If we want to return a reference to the target, we need to evaluate it
+        as a whole; otherwise, only evaluate the innermost piece to avoid
+        building up unnecessary *_REFs.  */
+      target = cxx_eval_constant_expression (ctx, target, true,
                                             non_constant_p, overflow_p);
-         VERIFY_CONSTANT (nelts);
-         gcc_assert (TREE_CODE (nelts) == INTEGER_CST
-                     && TREE_CODE (TREE_OPERAND (probe, 1)) == INTEGER_CST);
-         if (wi::to_widest (TREE_OPERAND (probe, 1)) == wi::to_widest (nelts))
-           {
-             diag_array_subscript (ctx, ary, TREE_OPERAND (probe, 1));
-             *non_constant_p = true;
-             return t;
-           }
-         /* FALLTHRU */
-
-       case BIT_FIELD_REF:
-       case COMPONENT_REF:
-         probe = TREE_OPERAND (probe, 0);
-         continue;
-
-       default:
-         probe = NULL_TREE;
-         continue;
-       }
-    }
-
-  if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (target), type))
-    {
-      /* For initialization of an empty base, the original target will be
-         *(base*)this, which the above evaluation resolves to the object
-        argument, which has the derived type rather than the base type.  In
-        this situation, just evaluate the initializer and return, since
-        there's no actual data to store.  */
-      gcc_assert (is_empty_class (type));
-      return cxx_eval_constant_expression (ctx, init, false,
-                                          non_constant_p, overflow_p);
+      evaluated = true;
+      if (*non_constant_p)
+       return t;
     }
 
-  /* And then find the underlying variable.  */
+  /* Find the underlying variable.  */
   releasing_vec refs;
   tree object = NULL_TREE;
+  /* If we're modifying a const object, save it.  */
+  tree const_object_being_modified = NULL_TREE;
+  bool mutable_p = false;
   for (tree probe = target; object == NULL_TREE; )
     {
       switch (TREE_CODE (probe))
@@ -3748,16 +4300,52 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
        case BIT_FIELD_REF:
        case COMPONENT_REF:
        case ARRAY_REF:
-         vec_safe_push (refs, TREE_OPERAND (probe, 1));
-         vec_safe_push (refs, TREE_TYPE (probe));
-         probe = TREE_OPERAND (probe, 0);
+         {
+           tree ob = TREE_OPERAND (probe, 0);
+           tree elt = TREE_OPERAND (probe, 1);
+           if (TREE_CODE (elt) == FIELD_DECL && DECL_MUTABLE_P (elt))
+             mutable_p = true;
+           if (TREE_CODE (probe) == ARRAY_REF)
+             {
+               elt = eval_and_check_array_index (ctx, probe, false,
+                                                 non_constant_p, overflow_p);
+               if (*non_constant_p)
+                 return t;
+             }
+           /* We don't check modifying_const_object_p for ARRAY_REFs.  Given
+              "int a[10]", an ARRAY_REF "a[2]" can be "const int", even though
+              the array isn't const.  Instead, check "a" in the next iteration;
+              that will detect modifying "const int a[10]".  */
+           else if (evaluated
+                    && modifying_const_object_p (TREE_CODE (t), probe,
+                                                 mutable_p)
+                    && const_object_being_modified == NULL_TREE)
+             const_object_being_modified = probe;
+           vec_safe_push (refs, elt);
+           vec_safe_push (refs, TREE_TYPE (probe));
+           probe = ob;
+         }
          break;
 
        default:
-         object = probe;
+         if (evaluated)
+           object = probe;
+         else
+           {
+             probe = cxx_eval_constant_expression (ctx, probe, true,
+                                                   non_constant_p, overflow_p);
+             evaluated = true;
+             if (*non_constant_p)
+               return t;
+           }
+         break;
        }
     }
 
+  if (modifying_const_object_p (TREE_CODE (t), object, mutable_p)
+      && const_object_being_modified == NULL_TREE)
+    const_object_being_modified = object;
+
   /* And then find/build up our initializer for the path to the subobject
      we're initializing.  */
   tree *valp;
@@ -3768,7 +4356,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
        DECL_NAME to handle TARGET_EXPR temporaries, which are fair game.  */
     valp = NULL;
   else if (DECL_P (object))
-    valp = ctx->values->get (object);
+    valp = ctx->global->values.get (object);
   else
     valp = NULL;
   if (!valp)
@@ -3784,7 +4372,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
   bool no_zero_init = true;
 
   releasing_vec ctors;
-  while (!refs->is_empty())
+  while (!refs->is_empty ())
     {
       if (*valp == NULL_TREE)
        {
@@ -3856,7 +4444,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
              if (cxx_dialect < cxx2a)
                {
                  if (!ctx->quiet)
-                   error_at (cp_expr_loc_or_loc (t, input_location),
+                   error_at (cp_expr_loc_or_input_loc (t),
                              "change of the active member of a union "
                              "from %qD to %qD",
                              CONSTRUCTOR_ELT (*valp, 0)->index,
@@ -3897,6 +4485,64 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
       valp = &cep->value;
     }
 
+  /* Detect modifying a constant object in constexpr evaluation.
+     We have found a const object that is being modified.  Figure out
+     if we need to issue an error.  Consider
+
+     struct A {
+       int n;
+       constexpr A() : n(1) { n = 2; } // #1
+     };
+     struct B {
+       const A a;
+       constexpr B() { a.n = 3; } // #2
+     };
+    constexpr B b{};
+
+    #1 is OK, since we're modifying an object under construction, but
+    #2 is wrong, since "a" is const and has been fully constructed.
+    To track it, we use the TREE_READONLY bit in the object's CONSTRUCTOR
+    which means that the object is read-only.  For the example above, the
+    *ctors stack at the point of #2 will look like:
+
+      ctors[0] = {.a={.n=2}}  TREE_READONLY = 0
+      ctors[1] = {.n=2}       TREE_READONLY = 1
+
+    and we're modifying "b.a", so we search the stack and see if the
+    constructor for "b.a" has already run.  */
+  if (const_object_being_modified)
+    {
+      bool fail = false;
+      tree const_objtype
+       = strip_array_types (TREE_TYPE (const_object_being_modified));
+      if (!CLASS_TYPE_P (const_objtype))
+       fail = true;
+      else
+       {
+         /* [class.ctor]p5 "A constructor can be invoked for a const,
+            volatile, or const volatile object.  const and volatile
+            semantics are not applied on an object under construction.
+            They come into effect when the constructor for the most
+            derived object ends."  */
+         tree elt;
+         unsigned int i;
+         FOR_EACH_VEC_ELT (*ctors, i, elt)
+           if (same_type_ignoring_top_level_qualifiers_p
+               (TREE_TYPE (const_object_being_modified), TREE_TYPE (elt)))
+             {
+               fail = TREE_READONLY (elt);
+               break;
+             }
+       }
+      if (fail)
+       {
+         if (!ctx->quiet)
+           modifying_const_object_error (t, const_object_being_modified);
+         *non_constant_p = true;
+         return t;
+       }
+    }
+
   if (!preeval)
     {
       /* Create a new CONSTRUCTOR in case evaluation of the initializer
@@ -3910,9 +4556,9 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
       new_ctx.object = target;
       init = cxx_eval_constant_expression (&new_ctx, init, false,
                                           non_constant_p, overflow_p);
-      if (target == object)
+      if (ctors->is_empty())
        /* The hash table might have moved since the get earlier.  */
-       valp = ctx->values->get (object);
+       valp = ctx->global->values.get (object);
     }
 
   /* Don't share a CONSTRUCTOR that might be changed later.  */
@@ -3923,6 +4569,17 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
     {
       /* An outer ctx->ctor might be pointing to *valp, so replace
         its contents.  */
+      if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (init),
+                                                     TREE_TYPE (*valp)))
+       {
+         /* For initialization of an empty base, the original target will be
+          *(base*)this, evaluation of which resolves to the object
+          argument, which has the derived type rather than the base type.  In
+          this situation, just evaluate the initializer and return, since
+          there's no actual data to store.  */
+         gcc_assert (is_empty_class (TREE_TYPE (init)) && !lval);
+         return init;
+       }
       CONSTRUCTOR_ELTS (*valp) = CONSTRUCTOR_ELTS (init);
       TREE_CONSTANT (*valp) = TREE_CONSTANT (init);
       TREE_SIDE_EFFECTS (*valp) = TREE_SIDE_EFFECTS (init);
@@ -3968,6 +4625,10 @@ cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t,
   tree offset = TREE_OPERAND (t, 1);
   gcc_assert (TREE_CONSTANT (offset));
 
+  /* OFFSET is constant, but perhaps not constant enough.  We need to
+     e.g. bash FLOAT_EXPRs to REAL_CSTs.  */
+  offset = fold_simple (offset);
+
   /* The operand as an lvalue.  */
   op = cxx_eval_constant_expression (ctx, op, true,
                                     non_constant_p, overflow_p);
@@ -3999,9 +4660,11 @@ cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t,
     VERIFY_CONSTANT (mod);
 
   /* Storing the modified value.  */
-  tree store = build2 (MODIFY_EXPR, type, op, mod);
+  tree store = build2_loc (cp_expr_loc_or_loc (t, input_location),
+                          MODIFY_EXPR, type, op, mod);
   cxx_eval_constant_expression (ctx, store,
                                true, non_constant_p, overflow_p);
+  ggc_free (store);
 
   /* And the value of the expression.  */
   if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
@@ -4155,7 +4818,7 @@ cxx_eval_statement_list (const constexpr_ctx *ctx, tree t,
       /* We aren't communicating the jump to our caller, so give up.  We don't
         need to support evaluation of jumps out of statement-exprs.  */
       if (!ctx->quiet)
-       error_at (cp_expr_loc_or_loc (r, input_location),
+       error_at (cp_expr_loc_or_input_loc (r),
                  "statement is not a constant expression");
       *non_constant_p = true;
     }
@@ -4171,6 +4834,12 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t,
                    tree *jump_target)
 {
   constexpr_ctx new_ctx = *ctx;
+  tree local_target;
+  if (!jump_target)
+    {
+      local_target = NULL_TREE;
+      jump_target = &local_target;
+    }
 
   tree body, cond = NULL_TREE, expr = NULL_TREE;
   int count = 0;
@@ -4245,17 +4914,17 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t,
            gcc_assert (*jump_target);
        }
 
-      /* Forget saved values of SAVE_EXPRs.  */
+      /* Forget saved values of SAVE_EXPRs and TARGET_EXPRs.  */
       unsigned int i;
       tree save_expr;
       FOR_EACH_VEC_ELT (save_exprs, i, save_expr)
-       new_ctx.values->remove (save_expr);
+       ctx->global->values.remove (save_expr);
       save_exprs.truncate (0);
 
       if (++count >= constexpr_loop_limit)
        {
          if (!ctx->quiet)
-           error_at (cp_expr_loc_or_loc (t, input_location),
+           error_at (cp_expr_loc_or_input_loc (t),
                      "%<constexpr%> loop iteration count exceeds limit of %d "
                      "(use %<-fconstexpr-loop-limit=%> to increase the limit)",
                      constexpr_loop_limit);
@@ -4269,11 +4938,11 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t,
         && (!switches (jump_target) || count == 0)
         && !*non_constant_p);
 
-  /* Forget saved values of SAVE_EXPRs.  */
+  /* Forget saved values of SAVE_EXPRs and TARGET_EXPRs.  */
   unsigned int i;
   tree save_expr;
   FOR_EACH_VEC_ELT (save_exprs, i, save_expr)
-    new_ctx.values->remove (save_expr);
+    ctx->global->values.remove (save_expr);
 
   return NULL_TREE;
 }
@@ -4346,6 +5015,17 @@ lookup_placeholder (const constexpr_ctx *ctx, bool lval, tree type)
   return ob;
 }
 
+/* Complain about an attempt to evaluate inline assembly.  */
+
+static void
+inline_asm_in_constexpr_error (location_t loc)
+{
+  auto_diagnostic_group d;
+  error_at (loc, "inline assembly is not a constant expression");
+  inform (loc, "only unevaluated inline assembly is allowed in a "
+         "%<constexpr%> function in C++2a");
+}
+
 /* Attempt to reduce the expression T to a constant value.
    On failure, issue diagnostic and return error_mark_node.  */
 /* FIXME unify with c_fully_fold */
@@ -4357,9 +5037,6 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
                              bool *non_constant_p, bool *overflow_p,
                              tree *jump_target /* = NULL */)
 {
-  constexpr_ctx new_ctx;
-  tree r = t;
-
   if (jump_target && *jump_target)
     {
       /* If we are jumping, ignore all statements/expressions except those
@@ -4390,6 +5067,11 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
       *non_constant_p = true;
       return t;
     }
+
+  location_t loc = cp_expr_loc_or_input_loc (t);
+
+  STRIP_ANY_LOCATION_WRAPPER (t);
+
   if (CONSTANT_CLASS_P (t))
     {
       if (TREE_OVERFLOW (t))
@@ -4414,19 +5096,21 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
     }
 
   /* Avoid excessively long constexpr evaluations.  */
-  if (!location_wrapper_p (t)
-      && ++*ctx->constexpr_ops_count >= constexpr_ops_limit)
+  if (++ctx->global->constexpr_ops_count >= constexpr_ops_limit)
     {
       if (!ctx->quiet)
-       error_at (cp_expr_loc_or_loc (t, input_location),
+       error_at (loc,
                  "%<constexpr%> evaluation operation count exceeds limit of "
                  "%wd (use %<-fconstexpr-ops-limit=%> to increase the limit)",
                  constexpr_ops_limit);
-      *ctx->constexpr_ops_count = INTTYPE_MINIMUM (HOST_WIDE_INT);
+      ctx->global->constexpr_ops_count = INTTYPE_MINIMUM (HOST_WIDE_INT);
       *non_constant_p = true;
       return t;
     }
 
+  constexpr_ctx new_ctx;
+  tree r = t;
+
   tree_code tcode = TREE_CODE (t);
   switch (tcode)
     {
@@ -4436,7 +5120,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
       /* We ask for an rvalue for the RESULT_DECL when indirecting
         through an invisible reference, or in named return value
         optimization.  */
-      if (tree *p = ctx->values->get (t))
+      if (tree *p = ctx->global->values.get (t))
        return *p;
       else
        {
@@ -4492,13 +5176,13 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
          && TREE_CODE (TARGET_EXPR_INITIAL (r)) == CONSTRUCTOR)
        r = TARGET_EXPR_INITIAL (r);
       if (VAR_P (r))
-       if (tree *p = ctx->values->get (r))
+       if (tree *p = ctx->global->values.get (r))
          if (*p != NULL_TREE)
            r = *p;
       if (DECL_P (r))
        {
          if (!ctx->quiet)
-           non_const_var_error (r);
+           non_const_var_error (loc, r);
          *non_constant_p = true;
        }
       break;
@@ -4519,7 +5203,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
     case PARM_DECL:
       if (lval && !TYPE_REF_P (TREE_TYPE (t)))
        /* glvalue use.  */;
-      else if (tree *p = ctx->values->get (r))
+      else if (tree *p = ctx->global->values.get (r))
        r = *p;
       else if (lval)
        /* Defer in case this is only used for its type.  */;
@@ -4561,7 +5245,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
            new_ctx.object = r;
            new_ctx.ctor = build_constructor (TREE_TYPE (r), NULL);
            CONSTRUCTOR_NO_CLEARING (new_ctx.ctor) = true;
-           new_ctx.values->put (r, new_ctx.ctor);
+           ctx->global->values.put (r, new_ctx.ctor);
            ctx = &new_ctx;
          }
 
@@ -4572,12 +5256,17 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
                                                 non_constant_p, overflow_p);
            /* Don't share a CONSTRUCTOR that might be changed.  */
            init = unshare_constructor (init);
-           ctx->values->put (r, init);
+           /* Remember that a constant object's constructor has already
+              run.  */
+           if (CLASS_TYPE_P (TREE_TYPE (r))
+               && CP_TYPE_CONST_P (TREE_TYPE (r)))
+             TREE_READONLY (init) = true;
+           ctx->global->values.put (r, init);
          }
        else if (ctx == &new_ctx)
          /* We gave it a CONSTRUCTOR above.  */;
        else
-         ctx->values->put (r, NULL_TREE);
+         ctx->global->values.put (r, NULL_TREE);
       }
       break;
 
@@ -4594,6 +5283,14 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
          *non_constant_p = true;
          break;
        }
+      /* Avoid evaluating a TARGET_EXPR more than once.  */
+      if (tree *p = ctx->global->values.get (TARGET_EXPR_SLOT (t)))
+       {
+         if (lval)
+           return TARGET_EXPR_SLOT (t);
+         r = *p;
+         break;
+       }
       if ((AGGREGATE_TYPE_P (TREE_TYPE (t)) || VECTOR_TYPE_P (TREE_TYPE (t))))
        {
          /* We're being expanded without an explicit target, so start
@@ -4603,7 +5300,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
          new_ctx.ctor = build_constructor (TREE_TYPE (t), NULL);
          CONSTRUCTOR_NO_CLEARING (new_ctx.ctor) = true;
          new_ctx.object = TARGET_EXPR_SLOT (t);
-         ctx->values->put (new_ctx.object, new_ctx.ctor);
+         ctx->global->values.put (new_ctx.object, new_ctx.ctor);
          ctx = &new_ctx;
        }
       /* Pass false for 'lval' because this indicates
@@ -4614,13 +5311,14 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
       if (!*non_constant_p)
        /* Adjust the type of the result to the type of the temporary.  */
        r = adjust_temp_type (TREE_TYPE (t), r);
+      if (TARGET_EXPR_CLEANUP (t) && !CLEANUP_EH_ONLY (t))
+       ctx->global->cleanups->safe_push (TARGET_EXPR_CLEANUP (t));
+      r = unshare_constructor (r);
+      ctx->global->values.put (TARGET_EXPR_SLOT (t), r);
+      if (ctx->save_exprs)
+       ctx->save_exprs->safe_push (TARGET_EXPR_SLOT (t));
       if (lval)
-       {
-         tree slot = TARGET_EXPR_SLOT (t);
-         r = unshare_constructor (r);
-         ctx->values->put (slot, r);
-         return slot;
-       }
+       return TARGET_EXPR_SLOT (t);
       break;
 
     case INIT_EXPR:
@@ -4658,22 +5356,27 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
 
     case SAVE_EXPR:
       /* Avoid evaluating a SAVE_EXPR more than once.  */
-      if (tree *p = ctx->values->get (t))
+      if (tree *p = ctx->global->values.get (t))
        r = *p;
       else
        {
          r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), false,
                                            non_constant_p, overflow_p);
-         ctx->values->put (t, r);
+         ctx->global->values.put (t, r);
          if (ctx->save_exprs)
            ctx->save_exprs->safe_push (t);
        }
       break;
 
-    case NON_LVALUE_EXPR:
     case TRY_CATCH_EXPR:
+      if (TREE_OPERAND (t, 0) == NULL_TREE)
+       {
+         r = void_node;
+         break;
+       }
+      /* FALLTHRU */
+    case NON_LVALUE_EXPR:
     case TRY_BLOCK:
-    case CLEANUP_POINT_EXPR:
     case MUST_NOT_THROW_EXPR:
     case EXPR_STMT:
     case EH_SPEC_BLOCK:
@@ -4683,6 +5386,26 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
                                        jump_target);
       break;
 
+    case CLEANUP_POINT_EXPR:
+      {
+       auto_vec<tree, 2> cleanups;
+       vec<tree> *prev_cleanups = ctx->global->cleanups;
+       ctx->global->cleanups = &cleanups;
+       r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0),
+                                         lval,
+                                         non_constant_p, overflow_p,
+                                         jump_target);
+       ctx->global->cleanups = prev_cleanups;
+       unsigned int i;
+       tree cleanup;
+       /* Evaluate the cleanups.  */
+       FOR_EACH_VEC_ELT_REVERSE (cleanups, i, cleanup)
+         cxx_eval_constant_expression (ctx, cleanup, false,
+                                       non_constant_p, overflow_p,
+                                       jump_target);
+      }
+      break;
+
     case TRY_FINALLY_EXPR:
       r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval,
                                        non_constant_p, overflow_p,
@@ -4695,14 +5418,24 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
       break;
 
     case CLEANUP_STMT:
-      r = cxx_eval_constant_expression (ctx, CLEANUP_BODY (t), lval,
-                                       non_constant_p, overflow_p,
-                                       jump_target);
-      if (!CLEANUP_EH_ONLY (t) && !*non_constant_p)
-       /* Also evaluate the cleanup.  */
-       cxx_eval_constant_expression (ctx, CLEANUP_EXPR (t), true,
-                                     non_constant_p, overflow_p,
-                                     jump_target);
+      {
+       tree initial_jump_target = jump_target ? *jump_target : NULL_TREE;
+       r = cxx_eval_constant_expression (ctx, CLEANUP_BODY (t), lval,
+                                         non_constant_p, overflow_p,
+                                         jump_target);
+       if (!CLEANUP_EH_ONLY (t) && !*non_constant_p)
+         {
+           iloc_sentinel ils (loc);
+           /* Also evaluate the cleanup.  If we weren't skipping at the
+              start of the CLEANUP_BODY, change jump_target temporarily
+              to &initial_jump_target, so that even a return or break or
+              continue in the body doesn't skip the cleanup.  */
+           cxx_eval_constant_expression (ctx, CLEANUP_EXPR (t), true,
+                                         non_constant_p, overflow_p,
+                                         jump_target ? &initial_jump_target
+                                         : NULL);
+         }
+      }
       break;
 
       /* These differ from cxx_eval_unary_expression in that this doesn't
@@ -4727,7 +5460,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
        /* This function does more aggressive folding than fold itself.  */
        r = build_fold_addr_expr_with_type (op, TREE_TYPE (t));
        if (TREE_CODE (r) == ADDR_EXPR && TREE_OPERAND (r, 0) == oldop)
-         return t;
+         {
+           ggc_free (r);
+           return t;
+         }
        break;
       }
 
@@ -4760,9 +5496,19 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
       break;
 
     case SIZEOF_EXPR:
-      r = cxx_eval_constant_expression (ctx, fold_sizeof_expr (t), lval,
-                                       non_constant_p, overflow_p,
-                                       jump_target);
+      r = fold_sizeof_expr (t);
+      /* In a template, fold_sizeof_expr may merely create a new SIZEOF_EXPR,
+        which could lead to an infinite recursion.  */
+      if (TREE_CODE (r) != SIZEOF_EXPR)
+       r = cxx_eval_constant_expression (ctx, r, lval,
+                                         non_constant_p, overflow_p,
+                                         jump_target);
+      else
+       {
+         *non_constant_p = true;
+         gcc_assert (ctx->quiet);
+       }
+
       break;
 
     case COMPOUND_EXPR:
@@ -4812,8 +5558,6 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
     case MAX_EXPR:
     case LSHIFT_EXPR:
     case RSHIFT_EXPR:
-    case LROTATE_EXPR:
-    case RROTATE_EXPR:
     case BIT_IOR_EXPR:
     case BIT_XOR_EXPR:
     case BIT_AND_EXPR:
@@ -4824,6 +5568,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
     case GE_EXPR:
     case EQ_EXPR:
     case NE_EXPR:
+    case SPACESHIP_EXPR:
     case UNORDERED_EXPR:
     case ORDERED_EXPR:
     case UNLT_EXPR:
@@ -4956,7 +5701,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
       if (REINTERPRET_CAST_P (t))
        {
          if (!ctx->quiet)
-           error_at (cp_expr_loc_or_loc (t, input_location),
+           error_at (loc,
                      "%<reinterpret_cast%> is not a constant expression");
          *non_constant_p = true;
          return t;
@@ -4974,8 +5719,11 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
        if (*non_constant_p)
          return t;
        tree type = TREE_TYPE (t);
-       if (TREE_CODE (op) == PTRMEM_CST
-           && !TYPE_PTRMEM_P (type))
+
+       if (VOID_TYPE_P (type))
+         return void_node;
+
+       if (TREE_CODE (op) == PTRMEM_CST && !TYPE_PTRMEM_P (type))
          op = cplus_expand_constant (op);
 
        if (TREE_CODE (op) == PTRMEM_CST && tcode == NOP_EXPR)
@@ -4993,7 +5741,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
                if (TYPE_REF_P (type))
                  {
                    if (!ctx->quiet)
-                     error_at (cp_expr_loc_or_loc (t, input_location),
+                     error_at (loc,
                                "dereferencing a null pointer");
                    *non_constant_p = true;
                    return t;
@@ -5005,7 +5753,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
                    if (!can_convert (type, from, tf_none))
                      {
                        if (!ctx->quiet)
-                         error_at (cp_expr_loc_or_loc (t, input_location),
+                         error_at (loc,
                                    "conversion of %qT null pointer to %qT "
                                    "is not a constant expression",
                                    from, type);
@@ -5020,8 +5768,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
                     reinterpret_cast<void*>(sizeof 0)
                */
                if (!ctx->quiet)
-                 error_at (cp_expr_loc_or_loc (t, input_location),
-                           "%<reinterpret_cast<%T>(%E)%> is not "
+                 error_at (loc, "%<reinterpret_cast<%T>(%E)%> is not "
                            "a constant expression",
                            type, op);
                *non_constant_p = true;
@@ -5029,15 +5776,49 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
              }
          }
 
+       if (INDIRECT_TYPE_P (type)
+           && TREE_CODE (op) == NOP_EXPR
+           && TREE_TYPE (op) == ptr_type_node
+           && TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR
+           && VAR_P (TREE_OPERAND (TREE_OPERAND (op, 0), 0))
+           && DECL_NAME (TREE_OPERAND (TREE_OPERAND (op, 0),
+                                       0)) == heap_uninit_identifier)
+         {
+           tree var = TREE_OPERAND (TREE_OPERAND (op, 0), 0);
+           tree var_size = TYPE_SIZE_UNIT (TREE_TYPE (var));
+           tree elt_type = TREE_TYPE (type);
+           tree cookie_size = NULL_TREE;
+           if (TREE_CODE (elt_type) == RECORD_TYPE
+               && TYPE_NAME (elt_type) == heap_identifier)
+             {
+               tree fld1 = TYPE_FIELDS (elt_type);
+               tree fld2 = DECL_CHAIN (fld1);
+               elt_type = TREE_TYPE (TREE_TYPE (fld2));
+               cookie_size = TYPE_SIZE_UNIT (TREE_TYPE (fld1));
+             }
+           DECL_NAME (var) = heap_identifier;
+           TREE_TYPE (var)
+             = build_new_constexpr_heap_type (elt_type, cookie_size,
+                                              var_size);
+           TREE_TYPE (TREE_OPERAND (op, 0))
+             = build_pointer_type (TREE_TYPE (var));
+         }
+
        if (op == oldop && tcode != UNARY_PLUS_EXPR)
          /* We didn't fold at the top so we could check for ptr-int
             conversion.  */
          return fold (t);
 
+       tree sop;
+
        /* Handle an array's bounds having been deduced after we built
           the wrapping expression.  */
        if (same_type_ignoring_tlq_and_bounds_p (type, TREE_TYPE (op)))
          r = op;
+       else if (sop = tree_strip_nop_conversions (op),
+                sop != op && (same_type_ignoring_tlq_and_bounds_p
+                              (type, TREE_TYPE (sop))))
+         r = sop;
        else if (tcode == UNARY_PLUS_EXPR)
          r = fold_convert (TREE_TYPE (t), op);
        else
@@ -5088,8 +5869,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
     case BASELINK:
     case OFFSET_REF:
       if (!ctx->quiet)
-        error_at (cp_expr_loc_or_loc (t, input_location),
-                 "expression %qE is not a constant expression", t);
+       error_at (loc, "expression %qE is not a constant expression", t);
       *non_constant_p = true;
       break;
 
@@ -5101,13 +5881,13 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
        tree obj = OBJ_TYPE_REF_OBJECT (t);
        obj = cxx_eval_constant_expression (ctx, obj, lval, non_constant_p,
                                            overflow_p);
+       STRIP_NOPS (obj);
        /* We expect something in the form of &x.D.2103.D.2094; get x. */
        if (TREE_CODE (obj) != ADDR_EXPR
            || !DECL_P (get_base_address (TREE_OPERAND (obj, 0))))
          {
            if (!ctx->quiet)
-             error_at (cp_expr_loc_or_loc (t, input_location),
-                       "expression %qE is not a constant expression", t);
+             error_at (loc, "expression %qE is not a constant expression", t);
            *non_constant_p = true;
            return t;
          }
@@ -5183,7 +5963,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
          '!requires (T t) { ... }' which is not transformed into
          a constraint.  */
       if (!processing_template_decl)
-        return evaluate_constraint_expression (t, NULL_TREE);
+        return satisfy_constraint_expression (t);
       else
         *non_constant_p = true;
       return t;
@@ -5199,6 +5979,38 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
       r = void_node;
       break;
 
+    case TEMPLATE_ID_EXPR:
+      {
+        /* We can evaluate template-id that refers to a concept only if
+          the template arguments are non-dependent.  */
+       tree id = unpack_concept_check (t);
+       tree tmpl = TREE_OPERAND (id, 0);
+       if (!concept_definition_p (tmpl))
+         internal_error ("unexpected template-id %qE", t);
+
+       if (function_concept_p (tmpl))
+         {
+           if (!ctx->quiet)
+             error_at (cp_expr_loc_or_input_loc (t),
+                       "function concept must be called");
+           r = error_mark_node;
+           break;
+         }
+
+       if (!processing_template_decl)
+         r = evaluate_concept_check (t, tf_warning_or_error);
+       else
+         *non_constant_p = true;
+
+       break;
+      }
+
+    case ASM_EXPR:
+      if (!ctx->quiet)
+       inline_asm_in_constexpr_error (loc);
+      *non_constant_p = true;
+      return t;
+
     default:
       if (STATEMENT_CODE_P (TREE_CODE (t)))
        {
@@ -5258,6 +6070,7 @@ instantiate_cx_fn_r (tree *tp, int *walk_subtrees, void */*data*/)
 
   return NULL_TREE;
 }
+
 static void
 instantiate_constexpr_fns (tree t)
 {
@@ -5266,34 +6079,97 @@ instantiate_constexpr_fns (tree t)
   input_location = loc;
 }
 
+/* Look for heap variables in the expression *TP.  */
+
+static tree
+find_heap_var_refs (tree *tp, int *walk_subtrees, void */*data*/)
+{
+  if (VAR_P (*tp)
+      && (DECL_NAME (*tp) == heap_uninit_identifier
+         || DECL_NAME (*tp) == heap_identifier
+         || DECL_NAME (*tp) == heap_deleted_identifier))
+    return *tp;
+
+  if (TYPE_P (*tp))
+    *walk_subtrees = 0;
+  return NULL_TREE;
+}
+
+/* Find immediate function decls in *TP if any.  */
+
+static tree
+find_immediate_fndecl (tree *tp, int */*walk_subtrees*/, void */*data*/)
+{
+  if (TREE_CODE (*tp) == FUNCTION_DECL && DECL_IMMEDIATE_FUNCTION_P (*tp))
+    return *tp;
+  return NULL_TREE;
+}
+
 /* ALLOW_NON_CONSTANT is false if T is required to be a constant expression.
    STRICT has the same sense as for constant_value_1: true if we only allow
    conforming C++ constant expressions, or false if we want a constant value
    even if it doesn't conform.
    MANIFESTLY_CONST_EVAL is true if T is manifestly const-evaluated as
-   per P0595 even when ALLOW_NON_CONSTANT is true.  */
+   per P0595 even when ALLOW_NON_CONSTANT is true.
+   CONSTEXPR_DTOR is true when evaluating the dtor of a constexpr variable.
+   OBJECT must be non-NULL in that case.  */
 
 static tree
 cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
                                  bool strict = true,
                                  bool manifestly_const_eval = false,
+                                 bool constexpr_dtor = false,
                                  tree object = NULL_TREE)
 {
   auto_timevar time (TV_CONSTEXPR);
 
   bool non_constant_p = false;
   bool overflow_p = false;
-  hash_map<tree,tree> map;
-  HOST_WIDE_INT constexpr_ctx_count = 0;
 
-  constexpr_ctx ctx = { NULL, &map, NULL, NULL, NULL, NULL,
-                       &constexpr_ctx_count, allow_non_constant, strict,
+  constexpr_global_ctx global_ctx;
+  constexpr_ctx ctx = { &global_ctx, NULL, NULL, NULL, NULL, NULL,
+                       allow_non_constant, strict,
                        manifestly_const_eval || !allow_non_constant };
 
   tree type = initialized_type (t);
   tree r = t;
+  bool is_consteval = false;
   if (VOID_TYPE_P (type))
-    return t;
+    {
+      if (constexpr_dtor)
+       /* Used for destructors of array elements.  */
+       type = TREE_TYPE (object);
+      else
+       {
+         if (cxx_dialect < cxx2a)
+           return t;
+         if (TREE_CODE (t) != CALL_EXPR && TREE_CODE (t) != AGGR_INIT_EXPR)
+           return t;
+         /* Calls to immediate functions returning void need to be
+            evaluated.  */
+         tree fndecl = cp_get_callee_fndecl_nofold (t);
+         if (fndecl == NULL_TREE || !DECL_IMMEDIATE_FUNCTION_P (fndecl))
+           return t;
+         else
+           is_consteval = true;
+       }
+    }
+  else if (cxx_dialect >= cxx2a
+          && (TREE_CODE (t) == CALL_EXPR
+              || TREE_CODE (t) == AGGR_INIT_EXPR
+              || TREE_CODE (t) == TARGET_EXPR))
+    {
+      /* For non-concept checks, determine if it is consteval.  */
+      if (!concept_check_p (t))
+       {
+         tree x = t;
+         if (TREE_CODE (x) == TARGET_EXPR)
+           x = TARGET_EXPR_INITIAL (x);
+         tree fndecl = cp_get_callee_fndecl_nofold (x);
+         if (fndecl && DECL_IMMEDIATE_FUNCTION_P (fndecl))
+           is_consteval = true;
+       }
+    }
   if (AGGREGATE_TYPE_P (type) || VECTOR_TYPE_P (type))
     {
       /* In C++14 an NSDMI can participate in aggregate initialization,
@@ -5303,8 +6179,24 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
         update ctx.values for the VAR_DECL.  We use the same strategy
         for C++11 constexpr constructors that refer to the object being
         initialized.  */
-      ctx.ctor = build_constructor (type, NULL);
-      CONSTRUCTOR_NO_CLEARING (ctx.ctor) = true;
+      if (constexpr_dtor)
+       {
+         gcc_assert (object && VAR_P (object));
+         gcc_assert (DECL_DECLARED_CONSTEXPR_P (object));
+         gcc_assert (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (object));
+         if (error_operand_p (DECL_INITIAL (object)))
+           return t;
+         ctx.ctor = unshare_expr (DECL_INITIAL (object));
+         TREE_READONLY (ctx.ctor) = false;
+         /* Temporarily force decl_really_constant_value to return false
+            for it, we want to use ctx.ctor for the current value instead.  */
+         DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (object) = false;
+       }
+      else
+       {
+         ctx.ctor = build_constructor (type, NULL);
+         CONSTRUCTOR_NO_CLEARING (ctx.ctor) = true;
+       }
       if (!object)
        {
          if (TREE_CODE (t) == TARGET_EXPR)
@@ -5317,24 +6209,36 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
        gcc_assert (same_type_ignoring_top_level_qualifiers_p
                    (type, TREE_TYPE (object)));
       if (object && DECL_P (object))
-       map.put (object, ctx.ctor);
+       global_ctx.values.put (object, ctx.ctor);
       if (TREE_CODE (r) == TARGET_EXPR)
        /* Avoid creating another CONSTRUCTOR when we expand the
           TARGET_EXPR.  */
        r = TARGET_EXPR_INITIAL (r);
     }
 
+  auto_vec<tree, 16> cleanups;
+  global_ctx.cleanups = &cleanups;
+
   instantiate_constexpr_fns (r);
   r = cxx_eval_constant_expression (&ctx, r,
                                    false, &non_constant_p, &overflow_p);
 
-  verify_constant (r, allow_non_constant, &non_constant_p, &overflow_p);
+  if (!constexpr_dtor)
+    verify_constant (r, allow_non_constant, &non_constant_p, &overflow_p);
+  else
+    DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (object) = true;
+
+  unsigned int i;
+  tree cleanup;
+  /* Evaluate the cleanups.  */
+  FOR_EACH_VEC_ELT_REVERSE (cleanups, i, cleanup)
+    cxx_eval_constant_expression (&ctx, cleanup, false,
+                                 &non_constant_p, &overflow_p);
 
   /* Mutable logic is a bit tricky: we want to allow initialization of
      constexpr variables with mutable members, but we can't copy those
      members to another constexpr variable.  */
-  if (TREE_CODE (r) == CONSTRUCTOR
-      && CONSTRUCTOR_MUTABLE_POISON (r))
+  if (TREE_CODE (r) == CONSTRUCTOR && CONSTRUCTOR_MUTABLE_POISON (r))
     {
       if (!allow_non_constant)
        error ("%qE is not a constant expression because it refers to "
@@ -5342,8 +6246,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
       non_constant_p = true;
     }
 
-  if (TREE_CODE (r) == CONSTRUCTOR
-      && CONSTRUCTOR_NO_CLEARING (r))
+  if (TREE_CODE (r) == CONSTRUCTOR && CONSTRUCTOR_NO_CLEARING (r))
     {
       if (!allow_non_constant)
        error ("%qE is not a constant expression because it refers to "
@@ -5352,6 +6255,51 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
       non_constant_p = true;
     }
 
+  if (!global_ctx.heap_vars.is_empty ())
+    {
+      tree heap_var = cp_walk_tree_without_duplicates (&r, find_heap_var_refs,
+                                                      NULL);
+      unsigned int i;
+      if (heap_var)
+       {
+         if (!allow_non_constant && !non_constant_p)
+           error_at (DECL_SOURCE_LOCATION (heap_var),
+                     "%qE is not a constant expression because it refers to "
+                     "a result of %<operator new%>", t);
+         r = t;
+         non_constant_p = true;
+       }
+      FOR_EACH_VEC_ELT (global_ctx.heap_vars, i, heap_var)
+       if (DECL_NAME (heap_var) != heap_deleted_identifier)
+         {
+           if (!allow_non_constant && !non_constant_p)
+             error_at (DECL_SOURCE_LOCATION (heap_var),
+                       "%qE is not a constant expression because allocated "
+                       "storage has not been deallocated", t);
+           r = t;
+           non_constant_p = true;
+         }
+    }
+
+  /* Check that immediate invocation does not return an expression referencing
+     any immediate function decls.  They need to be allowed while parsing
+     immediate functions, but can't leak outside of them.  */
+  if (is_consteval
+      && t != r
+      && (current_function_decl == NULL_TREE
+         || !DECL_IMMEDIATE_FUNCTION_P (current_function_decl)))
+    if (tree immediate_fndecl
+       = cp_walk_tree_without_duplicates (&r, find_immediate_fndecl,
+                                          NULL))
+    {
+      if (!allow_non_constant && !non_constant_p)
+       error_at (cp_expr_loc_or_input_loc (t),
+                 "immediate evaluation returns address of immediate "
+                 "function %qD", immediate_fndecl);
+      r = t;
+      non_constant_p = true;
+    }
+
   /* Technically we should check this for all subexpressions, but that
      runs into problems with our internal representation of pointer
      subtraction and the 5.19 rules are still in flux.  */
@@ -5377,6 +6325,8 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
 
   if (non_constant_p && !allow_non_constant)
     return error_mark_node;
+  else if (constexpr_dtor)
+    return r;
   else if (non_constant_p && TREE_CONSTANT (r))
     {
       /* If __builtin_is_constant_evaluated () was evaluated to true
@@ -5384,7 +6334,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
         punt.  */
       if (manifestly_const_eval)
        return cxx_eval_outermost_constant_expr (t, true, strict,
-                                                false, object);
+                                                false, false, object);
       /* This isn't actually constant, so unset TREE_CONSTANT.
         Don't clear TREE_CONSTANT on ADDR_EXPR, as the middle-end requires
         it to be set if it is invariant address, even when it is not
@@ -5412,7 +6362,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
        return t;
       else if (TREE_CODE (t) != CONSTRUCTOR)
        {
-         r = get_target_expr (r);
+         r = get_target_expr_sfinae (r, tf_warning_or_error | tf_no_cleanup);
          TREE_CONSTANT (r) = true;
        }
     }
@@ -5427,7 +6377,16 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
 tree
 cxx_constant_value (tree t, tree decl)
 {
-  return cxx_eval_outermost_constant_expr (t, false, true, true, decl);
+  return cxx_eval_outermost_constant_expr (t, false, true, true, false, decl);
+}
+
+/* Like cxx_constant_value, but used for evaluation of constexpr destructors
+   of constexpr variables.  The actual initializer of DECL is not modified.  */
+
+void
+cxx_constant_dtor (tree t, tree decl)
+{
+  cxx_eval_outermost_constant_expr (t, false, true, true, true, decl);
 }
 
 /* Helper routine for fold_simple function.  Either return simplified
@@ -5531,14 +6490,14 @@ maybe_constant_value (tree t, tree decl, bool manifestly_const_eval)
     return t;
 
   if (manifestly_const_eval)
-    return cxx_eval_outermost_constant_expr (t, true, true, true, decl);
+    return cxx_eval_outermost_constant_expr (t, true, true, true, false, decl);
 
   if (cv_cache == NULL)
     cv_cache = hash_map<tree, tree>::create_ggc (101);
   if (tree *cached = cv_cache->get (t))
     return *cached;
 
-  r = cxx_eval_outermost_constant_expr (t, true, true, false, decl);
+  r = cxx_eval_outermost_constant_expr (t, true, true, false, false, decl);
   gcc_checking_assert (r == t
                       || CONVERT_EXPR_P (t)
                       || TREE_CODE (t) == VIEW_CONVERT_EXPR
@@ -5557,13 +6516,15 @@ clear_cv_cache (void)
     cv_cache->empty ();
 }
 
-/* Dispose of the whole CV_CACHE and FOLD_CACHE.  */
+/* Dispose of the whole CV_CACHE, FOLD_CACHE, and satisfaction caches.  */
 
 void
-clear_cv_and_fold_caches (void)
+clear_cv_and_fold_caches (bool sat /*= true*/)
 {
   clear_cv_cache ();
   clear_fold_cache ();
+  if (sat)
+    clear_satisfaction_cache ();
 }
 
 /* Internal function handling expressions in templates for
@@ -5579,7 +6540,8 @@ clear_cv_and_fold_caches (void)
 
 static tree
 fold_non_dependent_expr_template (tree t, tsubst_flags_t complain,
-                                 bool manifestly_const_eval)
+                                 bool manifestly_const_eval,
+                                 tree object)
 {
   gcc_assert (processing_template_decl);
 
@@ -5600,7 +6562,7 @@ fold_non_dependent_expr_template (tree t, tsubst_flags_t complain,
 
       tree r = cxx_eval_outermost_constant_expr (t, true, true,
                                                 manifestly_const_eval,
-                                                NULL_TREE);
+                                                false, object);
       /* cp_tree_equal looks through NOPs, so allow them.  */
       gcc_checking_assert (r == t
                           || CONVERT_EXPR_P (t)
@@ -5636,16 +6598,17 @@ fold_non_dependent_expr_template (tree t, tsubst_flags_t complain,
 tree
 fold_non_dependent_expr (tree t,
                         tsubst_flags_t complain /* = tf_warning_or_error */,
-                        bool manifestly_const_eval /* = false */)
+                        bool manifestly_const_eval /* = false */,
+                        tree object /* = NULL_TREE */)
 {
   if (t == NULL_TREE)
     return NULL_TREE;
 
   if (processing_template_decl)
     return fold_non_dependent_expr_template (t, complain,
-                                            manifestly_const_eval);
+                                            manifestly_const_eval, object);
 
-  return maybe_constant_value (t, NULL_TREE, manifestly_const_eval);
+  return maybe_constant_value (t, object, manifestly_const_eval);
 }
 
 
@@ -5662,7 +6625,7 @@ fold_non_dependent_init (tree t,
   if (processing_template_decl)
     {
       t = fold_non_dependent_expr_template (t, complain,
-                                           manifestly_const_eval);
+                                           manifestly_const_eval, NULL_TREE);
       /* maybe_constant_init does this stripping, so do it here too.  */
       if (TREE_CODE (t) == TARGET_EXPR)
        {
@@ -5704,7 +6667,7 @@ maybe_constant_init_1 (tree t, tree decl, bool allow_non_constant,
   else
     t = cxx_eval_outermost_constant_expr (t, allow_non_constant,
                                          /*strict*/false,
-                                         manifestly_const_eval, decl);
+                                         manifestly_const_eval, false, decl);
   if (TREE_CODE (t) == TARGET_EXPR)
     {
       tree init = TARGET_EXPR_INITIAL (t);
@@ -5870,7 +6833,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
     return false;
   if (t == NULL_TREE)
     return true;
-  location_t loc = cp_expr_loc_or_loc (t, input_location);
+  location_t loc = cp_expr_loc_or_input_loc (t);
 
   if (*jump_target)
     /* If we are jumping, ignore everything.  This is simpler than the
@@ -5902,6 +6865,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
     case LABEL_DECL:
     case LABEL_EXPR:
     case CASE_LABEL_EXPR:
+    case PREDICT_EXPR:
     case CONST_DECL:
     case SIZEOF_EXPR:
     case ALIGNOF_EXPR:
@@ -5998,7 +6962,21 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
                if (!DECL_DECLARED_CONSTEXPR_P (fun)
                    /* Allow any built-in function; if the expansion
                       isn't constant, we'll deal with that then.  */
-                   && !fndecl_built_in_p (fun))
+                   && !fndecl_built_in_p (fun)
+                   /* In C++2a, replaceable global allocation functions
+                      are constant expressions.  */
+                   && (!cxx_replaceable_global_alloc_fn (fun)
+                       || TREE_CODE (t) != CALL_EXPR
+                       || (!CALL_FROM_NEW_OR_DELETE_P (t)
+                           && (current_function_decl == NULL_TREE
+                               || !is_std_allocator_allocate
+                                               (current_function_decl))))
+                   /* Allow placement new in std::construct_at.  */
+                   && (!cxx_placement_new_fn (fun)
+                       || TREE_CODE (t) != CALL_EXPR
+                       || current_function_decl == NULL_TREE
+                       || !is_std_construct_at (current_function_decl))
+                   && !cxx_dynamic_cast_fn_p (fun))
                  {
                    if (flags & tf_error)
                      {
@@ -6107,7 +7085,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
          && !is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false))
         {
           if (flags & tf_error)
-            non_const_var_error (t);
+           non_const_var_error (loc, t);
           return false;
         }
       return true;
@@ -6227,6 +7205,9 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
        goto fail;
       if (!RECUR (TREE_OPERAND (t, 0), any))
        return false;
+      /* Just ignore clobbers.  */
+      if (TREE_CLOBBER_P (TREE_OPERAND (t, 1)))
+       return true;
       if (!RECUR (TREE_OPERAND (t, 1), rval))
        return false;
       return true;
@@ -6347,6 +7328,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
     case OMP_SIMD:
     case OMP_DISTRIBUTE:
     case OMP_TASKLOOP:
+    case OMP_LOOP:
     case OMP_TEAMS:
     case OMP_TARGET_DATA:
     case OMP_TARGET:
@@ -6367,6 +7349,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
     case OMP_DEPOBJ:
     case OACC_PARALLEL:
     case OACC_KERNELS:
+    case OACC_SERIAL:
     case OACC_DATA:
     case OACC_HOST_DATA:
     case OACC_LOOP:
@@ -6378,13 +7361,17 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
       /* GCC internal stuff.  */
     case VA_ARG_EXPR:
     case TRANSACTION_EXPR:
-    case ASM_EXPR:
     case AT_ENCODE_EXPR:
     fail:
       if (flags & tf_error)
        error_at (loc, "expression %qE is not a constant expression", t);
       return false;
 
+    case ASM_EXPR:
+      if (flags & tf_error)
+       inline_asm_in_constexpr_error (loc);
+      return false;
+
     case OBJ_TYPE_REF:
       if (cxx_dialect >= cxx2a)
        /* In C++2a virtual calls can be constexpr, don't give up yet.  */
@@ -6395,11 +7382,14 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
       return false;
 
     case TYPEID_EXPR:
-      /* -- a typeid expression whose operand is of polymorphic
-            class type;  */
+      /* In C++20, a typeid expression whose operand is of polymorphic
+        class type can be constexpr.  */
       {
         tree e = TREE_OPERAND (t, 0);
-        if (!TYPE_P (e) && !type_dependent_expression_p (e)
+       if (cxx_dialect < cxx2a
+           && strict
+           && !TYPE_P (e)
+           && !type_dependent_expression_p (e)
            && TYPE_POLYMORPHIC_P (TREE_TYPE (e)))
           {
             if (flags & tf_error)
@@ -6421,6 +7411,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
     case GE_EXPR:
     case EQ_EXPR:
     case NE_EXPR:
+    case SPACESHIP_EXPR:
       want_rval = true;
       goto binary;
 
@@ -6653,8 +7644,6 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
     case MAX_EXPR:
     case LSHIFT_EXPR:
     case RSHIFT_EXPR:
-    case LROTATE_EXPR:
-    case RROTATE_EXPR:
     case BIT_IOR_EXPR:
     case BIT_XOR_EXPR:
     case BIT_AND_EXPR:
@@ -6691,7 +7680,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
      return true;
 
     case COND_EXPR:
-      if (COND_EXPR_IS_VEC_DELETE (t))
+      if (COND_EXPR_IS_VEC_DELETE (t) && cxx_dialect < cxx2a)
        {
          if (flags & tf_error)
            error_at (loc, "%<delete[]%> is not a constant expression");
@@ -6737,8 +7726,13 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
       return true;
 
     case CLEANUP_STMT:
+      if (!RECUR (CLEANUP_BODY (t), any))
+       return false;
+      if (!CLEANUP_EH_ONLY (t) && !RECUR (CLEANUP_EXPR (t), any))
+       return false;
+      return true;
+
     case EMPTY_CLASS_EXPR:
-    case PREDICT_EXPR:
       return false;
 
     case GOTO_EXPR: