]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/cp/constexpr.c
Update copyright years.
[thirdparty/gcc.git] / gcc / cp / constexpr.c
index ee3ccb9691cafe20dc61e7ec9c3364a8dc71ab80..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.
 
@@ -767,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)
@@ -815,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)
@@ -881,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.  */
@@ -913,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;
@@ -958,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);
@@ -1025,8 +1039,10 @@ struct constexpr_global_ctx {
   /* 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) {}
+  constexpr_global_ctx () : constexpr_ops_count (0), cleanups (NULL) {}
 };
 
 /* The constexpr expansion context.  CALL is the current function
@@ -1039,8 +1055,8 @@ struct constexpr_ctx {
   constexpr_global_ctx *global;
   /* The innermost call we're evaluating.  */
   constexpr_call *call;
-  /* 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.  */
@@ -1238,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;
@@ -1432,15 +1451,32 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t,
 
       if (!*non_constant_p)
        {
-         /* Unsharing here isn't necessary for correctness, but it
-            significantly improves memory performance for some reason.  */
-         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;
+         /* 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);
@@ -1663,6 +1699,238 @@ is_std_allocator_allocate (tree fndecl)
   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.  */
@@ -1828,6 +2096,9 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
          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))
@@ -1893,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)
@@ -1930,19 +2202,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
      this function exits.  */
   class free_bindings
   {
+    tree *bindings;
   public:
-    tree &bindings;
-    bool do_free;
-    free_bindings (tree &b): bindings (b), do_free(true) { }
-    void preserve () { do_free = false; }
-    ~free_bindings () {
-      if (do_free)
-       {
-         for (int i = 0; i < TREE_VEC_LENGTH (bindings); ++i)
-           free_constructor (TREE_VEC_ELT (bindings, i));
-         ggc_free (bindings);
-       }
-    }
+    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)
@@ -2045,7 +2309,18 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
          for (int i = 0; i < TREE_VEC_LENGTH (bound); ++i)
            {
              tree arg = TREE_VEC_ELT (bound, i);
-             /* Don't share a CONSTRUCTOR that might be changed.  */
+             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);
              if (TREE_CODE (arg) == CONSTRUCTOR)
                vec_safe_push (ctors, arg);
@@ -2065,8 +2340,8 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
          else
            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;
@@ -2115,7 +2390,8 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
              TREE_READONLY (e) = true;
            }
 
-         /* Forget the saved values of the callee's SAVE_EXPRs.  */
+         /* 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)
@@ -2153,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 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)
@@ -2183,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)));
        }
@@ -2196,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;
@@ -4615,7 +4914,7 @@ 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)
@@ -4639,7 +4938,7 @@ 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)
@@ -4984,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
@@ -5004,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->global->values.put (slot, r);
-         return slot;
-       }
+       return TARGET_EXPR_SLOT (t);
       break;
 
     case INIT_EXPR:
@@ -5060,10 +5368,15 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree 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:
@@ -5073,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,
@@ -5548,6 +5881,7 @@ 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))))
@@ -5882,6 +6216,9 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
        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);
@@ -5891,6 +6228,13 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
   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.  */
@@ -6631,7 +6975,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
                    && (!cxx_placement_new_fn (fun)
                        || TREE_CODE (t) != CALL_EXPR
                        || current_function_decl == NULL_TREE
-                       || !is_std_construct_at (current_function_decl)))
+                       || !is_std_construct_at (current_function_decl))
+                   && !cxx_dynamic_cast_fn_p (fun))
                  {
                    if (flags & tf_error)
                      {