Patchwork [C++] Introduce context struct for cxx_eval_constant_expression

login
register
mail settings
Submitter Florian Weimer
Date July 31, 2012, 9:58 a.m.
Message ID <5017AC4D.80306@redhat.com>
Download mbox | patch
Permalink /patch/174190/
State New
Headers show

Comments

Florian Weimer - July 31, 2012, 9:58 a.m.
The attached patch adds a context parameter to 
cxx_eval_constant_expression and its subprograms.  This way, we do not 
have to thread all context parameters manually.  This will simplify the 
introduction of additional location information, as suggested by Jason 
in <http://gcc.gnu.org/ml/gcc-patches/2012-06/msg01596.html>.

Bootstrapped and tested on x86_64-redhat-linux-gnu.
Florian Weimer - Aug. 10, 2012, 2:45 p.m.
On 07/31/2012 11:58 AM, Florian Weimer wrote:
> The attached patch adds a context parameter to
> cxx_eval_constant_expression and its subprograms.  This way, we do not
> have to thread all context parameters manually.  This will simplify the
> introduction of additional location information, as suggested by Jason
> in <http://gcc.gnu.org/ml/gcc-patches/2012-06/msg01596.html>.
>
> Bootstrapped and tested on x86_64-redhat-linux-gnu.

Ping?

Should I submit an alternative approach (keep the context in a class, 
make the internal implementation functions private members) to the 
cxx-conversion branch?

Patch

2012-07-31  Florian Weimer  <fweimer@redhat.com>

	* semantics.c (cxx_eval_builtin_function_call): Introduce
	const cxx_eval_constant_ctx * parameter.
	(cxx_bind_parameters_in_call): Likewise.
	(cxx_eval_call_expression): Likewise.
	(VERIFY_CONSTANT): Likewise.
	(cxx_eval_unary_expression): Likewise.
	(cxx_eval_binary_expression): Likewise.
	(cxx_eval_conditional_expression): Likewise.
	(cxx_eval_array_reference): Likewise.
	(cxx_eval_component_reference): Likewise.
	(cxx_eval_bit_field_ref): Likewise.
	(cxx_eval_logical_expression): Likewise.
	(cxx_eval_bare_aggregate): Likewise.
	(cxx_eval_vec_init_1): Likewise.
	(cxx_eval_vec_init): Likewise.
	(cxx_eval_indirect_ref): Likewise.
	(cxx_eval_vec_perm_expr): Likewise.
	(cxx_eval_constant_expression): Likewise.
	(cxx_eval_outermost_constant_expr): Pass cxx_eval_constant_ctx
	object as parameter.
	(is_sub_constant_expr): Pass cxx_eval_constant_ctx object as
	parameter.

diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index b27e8ab..94a0633 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -6222,10 +6222,19 @@  typedef struct GTY(()) constexpr_call {
 
 static GTY ((param_is (constexpr_call))) htab_t constexpr_call_table;
 
+/* Context passsed down from cxx_eval_constant_expression.
+   Called functions can copy this data structure, so if changes need
+   to be passed upwards, pointers must be used. */
+typedef struct {
+  bool allow_non_constant;
+  bool addr;
+  bool *non_constant_p;
+} cxx_eval_constant_ctx;
+
 static tree cxx_eval_constant_expression (const constexpr_call *, tree,
-					  bool, bool, bool *);
-static tree cxx_eval_vec_perm_expr (const constexpr_call *, tree, bool, bool,
-				    bool *);
+					  const cxx_eval_constant_ctx *);
+static tree cxx_eval_vec_perm_expr (const constexpr_call *, tree,
+				    const cxx_eval_constant_ctx *ctx);
 
 
 /* Compute a hash value for a constexpr call representation.  */
@@ -6351,8 +6360,7 @@  lookup_parameter_binding (const constexpr_call *call, tree t)
 
 static tree
 cxx_eval_builtin_function_call (const constexpr_call *call, tree t,
-				bool allow_non_constant, bool addr,
-				bool *non_constant_p)
+				const cxx_eval_constant_ctx *ctx)
 {
   const int nargs = call_expr_nargs (t);
   tree *args = (tree *) alloca (nargs * sizeof (tree));
@@ -6360,13 +6368,11 @@  cxx_eval_builtin_function_call (const constexpr_call *call, tree t,
   int i;
   for (i = 0; i < nargs; ++i)
     {
-      args[i] = cxx_eval_constant_expression (call, CALL_EXPR_ARG (t, i),
-					      allow_non_constant, addr,
-					      non_constant_p);
-      if (allow_non_constant && *non_constant_p)
+      args[i] = cxx_eval_constant_expression (call, CALL_EXPR_ARG (t, i), ctx);
+      if (ctx->allow_non_constant && *ctx->non_constant_p)
 	return t;
     }
-  if (*non_constant_p)
+  if (*ctx->non_constant_p)
     return t;
   new_call = build_call_array_loc (EXPR_LOCATION (t), TREE_TYPE (t),
                                    CALL_EXPR_FN (t), nargs, args);
@@ -6397,8 +6403,7 @@  adjust_temp_type (tree type, tree temp)
 static void
 cxx_bind_parameters_in_call (const constexpr_call *old_call, tree t,
                              constexpr_call *new_call,
-			     bool allow_non_constant,
-			     bool *non_constant_p)
+			     const cxx_eval_constant_ctx *ctx)
 {
   const int nargs = call_expr_nargs (t);
   tree fun = new_call->fundef->decl;
@@ -6408,22 +6413,23 @@  cxx_bind_parameters_in_call (const constexpr_call *old_call, tree t,
     {
       tree x, arg;
       tree type = parms ? TREE_TYPE (parms) : void_type_node;
+      cxx_eval_constant_ctx ctx1;
       /* For member function, the first argument is a pointer to the implied
          object.  And for an object contruction, don't bind `this' before
          it is fully constructed.  */
       if (i == 0 && DECL_CONSTRUCTOR_P (fun))
         goto next;
       x = get_nth_callarg (t, i);
-      arg = cxx_eval_constant_expression (old_call, x, allow_non_constant,
-					  TREE_CODE (type) == REFERENCE_TYPE,
-					  non_constant_p);
+      ctx1 = *ctx;
+      ctx1.addr = TREE_CODE (type) == REFERENCE_TYPE;
+      arg = cxx_eval_constant_expression (old_call, x, &ctx1);
       /* Don't VERIFY_CONSTANT here.  */
-      if (*non_constant_p && allow_non_constant)
+      if (*ctx->non_constant_p && ctx->allow_non_constant)
 	return;
       /* Just discard ellipsis args after checking their constantitude.  */
       if (!parms)
 	continue;
-      if (*non_constant_p)
+      if (*ctx->non_constant_p)
 	/* Don't try to adjust the type of non-constant args.  */
 	goto next;
 
@@ -6480,8 +6486,7 @@  cx_error_context (void)
 
 static tree
 cxx_eval_call_expression (const constexpr_call *old_call, tree t,
-			  bool allow_non_constant, bool addr,
-			  bool *non_constant_p)
+			  const cxx_eval_constant_ctx *ctx)
 {
   location_t loc = EXPR_LOC_OR_HERE (t);
   tree fun = get_function_named_in_call (t);
@@ -6490,36 +6495,37 @@  cxx_eval_call_expression (const constexpr_call *old_call, tree t,
   constexpr_call **slot;
   constexpr_call *entry;
   bool depth_ok;
+  cxx_eval_constant_ctx ctx1;
 
   if (TREE_CODE (fun) != FUNCTION_DECL)
     {
       /* Might be a constexpr function pointer.  */
-      fun = cxx_eval_constant_expression (old_call, fun, allow_non_constant,
-					  /*addr*/false, non_constant_p);
+      ctx1 = *ctx;
+      ctx1.addr = false;
+      fun = cxx_eval_constant_expression (old_call, fun, &ctx1);
       if (TREE_CODE (fun) == ADDR_EXPR)
 	fun = TREE_OPERAND (fun, 0);
     }
   if (TREE_CODE (fun) != FUNCTION_DECL)
     {
-      if (!allow_non_constant && !*non_constant_p)
+      if (!ctx->allow_non_constant && !*ctx->non_constant_p)
 	error_at (loc, "expression %qE does not designate a constexpr "
 		  "function", fun);
-      *non_constant_p = true;
+      *ctx->non_constant_p = true;
       return t;
     }
   if (DECL_CLONED_FUNCTION_P (fun))
     fun = DECL_CLONED_FUNCTION (fun);
   if (is_builtin_fn (fun))
-    return cxx_eval_builtin_function_call (old_call, t, allow_non_constant,
-					   addr, non_constant_p);
+    return cxx_eval_builtin_function_call (old_call, t, ctx);
   if (!DECL_DECLARED_CONSTEXPR_P (fun))
     {
-      if (!allow_non_constant)
+      if (!ctx->allow_non_constant)
 	{
 	  error_at (loc, "call to non-constexpr function %qD", fun);
 	  explain_invalid_constexpr_fn (fun);
 	}
-      *non_constant_p = true;
+      *ctx->non_constant_p = true;
       return t;
     }
 
@@ -6527,8 +6533,7 @@  cxx_eval_call_expression (const constexpr_call *old_call, tree t,
   if (call_expr_nargs (t) == 2 && trivial_fn_p (fun))
     {
       tree arg = convert_from_reference (get_nth_callarg (t, 1));
-      return cxx_eval_constant_expression (old_call, arg, allow_non_constant,
-					   addr, non_constant_p);
+      return cxx_eval_constant_expression (old_call, arg, ctx);
     }
 
   /* If in direct recursive call, optimize definition search.  */
@@ -6539,7 +6544,7 @@  cxx_eval_call_expression (const constexpr_call *old_call, tree t,
       new_call.fundef = retrieve_constexpr_fundef (fun);
       if (new_call.fundef == NULL || new_call.fundef->body == NULL)
         {
-	  if (!allow_non_constant)
+	  if (!ctx->allow_non_constant)
 	    {
 	      if (DECL_INITIAL (fun))
 		{
@@ -6550,13 +6555,12 @@  cxx_eval_call_expression (const constexpr_call *old_call, tree t,
 	      else
 		error_at (loc, "%qD used before its definition", fun);
 	    }
-	  *non_constant_p = true;
+	  *ctx->non_constant_p = true;
           return t;
         }
     }
-  cxx_bind_parameters_in_call (old_call, t, &new_call,
-			       allow_non_constant, non_constant_p);
-  if (*non_constant_p)
+  cxx_bind_parameters_in_call (old_call, t, &new_call, ctx);
+  if (*ctx->non_constant_p)
     return t;
 
   depth_ok = push_cx_call_context (t);
@@ -6581,19 +6585,19 @@  cxx_eval_call_expression (const constexpr_call *old_call, tree t,
      so that we can detect circular dependencies.  */
   else if (entry->result == NULL)
     {
-      if (!allow_non_constant)
+      if (!ctx->allow_non_constant)
 	error ("call has circular dependency");
-      *non_constant_p = true;
+      *ctx->non_constant_p = true;
       entry->result = result = error_mark_node;
     }
 
   if (!depth_ok)
     {
-      if (!allow_non_constant)
+      if (!ctx->allow_non_constant)
 	error ("constexpr evaluation depth exceeds maximum of %d (use "
 	       "-fconstexpr-depth= to increase the maximum)",
 	       max_constexpr_depth);
-      *non_constant_p = true;
+      *ctx->non_constant_p = true;
       entry->result = result = error_mark_node;
     }
   else
@@ -6601,12 +6605,10 @@  cxx_eval_call_expression (const constexpr_call *old_call, tree t,
       result = entry->result;
       if (!result || result == error_mark_node)
 	result = (cxx_eval_constant_expression
-		  (&new_call, new_call.fundef->body,
-		   allow_non_constant, addr,
-		   non_constant_p));
+		  (&new_call, new_call.fundef->body, ctx));
       if (result == error_mark_node)
-	*non_constant_p = true;
-      if (*non_constant_p)
+	*ctx->non_constant_p = true;
+      if (*ctx->non_constant_p)
 	entry->result = result = error_mark_node;
       else
 	{
@@ -6676,7 +6678,8 @@  verify_constant (tree t, bool allow_non_constant, bool *non_constant_p)
 }
 #define VERIFY_CONSTANT(X)						\
 do {									\
-  if (verify_constant ((X), allow_non_constant, non_constant_p))	\
+  if (verify_constant ((X), (ctx)->allow_non_constant,			\
+		       (ctx)->non_constant_p))				\
     return t;								\
  } while (0)
 
@@ -6687,13 +6690,11 @@  do {									\
 
 static tree
 cxx_eval_unary_expression (const constexpr_call *call, tree t,
-			   bool allow_non_constant, bool addr,
-			   bool *non_constant_p)
+			   const cxx_eval_constant_ctx *ctx)
 {
   tree r;
   tree orig_arg = TREE_OPERAND (t, 0);
-  tree arg = cxx_eval_constant_expression (call, orig_arg, allow_non_constant,
-					   addr, non_constant_p);
+  tree arg = cxx_eval_constant_expression (call, orig_arg, ctx);
   VERIFY_CONSTANT (arg);
   if (arg == orig_arg)
     return t;
@@ -6707,20 +6708,15 @@  cxx_eval_unary_expression (const constexpr_call *call, tree t,
 
 static tree
 cxx_eval_binary_expression (const constexpr_call *call, tree t,
-			    bool allow_non_constant, bool addr,
-			    bool *non_constant_p)
+			    const cxx_eval_constant_ctx *ctx)
 {
   tree r;
   tree orig_lhs = TREE_OPERAND (t, 0);
   tree orig_rhs = TREE_OPERAND (t, 1);
   tree lhs, rhs;
-  lhs = cxx_eval_constant_expression (call, orig_lhs,
-				      allow_non_constant, addr,
-				      non_constant_p);
+  lhs = cxx_eval_constant_expression (call, orig_lhs, ctx);
   VERIFY_CONSTANT (lhs);
-  rhs = cxx_eval_constant_expression (call, orig_rhs,
-				      allow_non_constant, addr,
-				      non_constant_p);
+  rhs = cxx_eval_constant_expression (call, orig_rhs, ctx);
   VERIFY_CONSTANT (rhs);
   if (lhs == orig_lhs && rhs == orig_rhs)
     return t;
@@ -6735,21 +6731,14 @@  cxx_eval_binary_expression (const constexpr_call *call, tree t,
 
 static tree
 cxx_eval_conditional_expression (const constexpr_call *call, tree t,
-				 bool allow_non_constant, bool addr,
-				 bool *non_constant_p)
+				 const cxx_eval_constant_ctx *ctx)
 {
-  tree val = cxx_eval_constant_expression (call, TREE_OPERAND (t, 0),
-					   allow_non_constant, addr,
-					   non_constant_p);
+  tree val = cxx_eval_constant_expression (call, TREE_OPERAND (t, 0), ctx);
   VERIFY_CONSTANT (val);
   /* Don't VERIFY_CONSTANT the other operands.  */
   if (integer_zerop (val))
-    return cxx_eval_constant_expression (call, TREE_OPERAND (t, 2),
-					 allow_non_constant, addr,
-					 non_constant_p);
-  return cxx_eval_constant_expression (call, TREE_OPERAND (t, 1),
-				       allow_non_constant, addr,
-				       non_constant_p);
+    return cxx_eval_constant_expression (call, TREE_OPERAND (t, 2), ctx);
+  return cxx_eval_constant_expression (call, TREE_OPERAND (t, 1), ctx);
 }
 
 /* Subroutine of cxx_eval_constant_expression.
@@ -6757,27 +6746,24 @@  cxx_eval_conditional_expression (const constexpr_call *call, tree t,
 
 static tree
 cxx_eval_array_reference (const constexpr_call *call, tree t,
-			  bool allow_non_constant, bool addr,
-			  bool *non_constant_p)
+			  const cxx_eval_constant_ctx *ctx)
 {
   tree oldary = TREE_OPERAND (t, 0);
-  tree ary = cxx_eval_constant_expression (call, oldary,
-					   allow_non_constant, addr,
-					   non_constant_p);
+  tree ary = cxx_eval_constant_expression (call, oldary, ctx);
   tree index, oldidx;
   HOST_WIDE_INT i;
   tree elem_type;
   unsigned len, elem_nchars = 1;
-  if (*non_constant_p)
+  cxx_eval_constant_ctx ctx1 = *ctx;
+  if (*ctx->non_constant_p)
     return t;
   oldidx = TREE_OPERAND (t, 1);
-  index = cxx_eval_constant_expression (call, oldidx,
-					allow_non_constant, false,
-					non_constant_p);
+  ctx1.addr = false;
+  index = cxx_eval_constant_expression (call, oldidx, &ctx1);
   VERIFY_CONSTANT (index);
-  if (addr && ary == oldary && index == oldidx)
+  if (ctx->addr && ary == oldary && index == oldidx)
     return t;
-  else if (addr)
+  else if (ctx->addr)
     return build4 (ARRAY_REF, TREE_TYPE (t), ary, index, NULL, NULL);
   elem_type = TREE_TYPE (TREE_TYPE (ary));
   if (TREE_CODE (ary) == CONSTRUCTOR)
@@ -6802,14 +6788,12 @@  cxx_eval_array_reference (const constexpr_call *call, tree t,
 	  /* If it's within the array bounds but doesn't have an explicit
 	     initializer, it's value-initialized.  */
 	  tree val = build_value_init (elem_type, tf_warning_or_error);
-	  return cxx_eval_constant_expression (call, val,
-					       allow_non_constant, addr,
-					       non_constant_p);
+	  return cxx_eval_constant_expression (call, val, ctx);
 	}
 
-      if (!allow_non_constant)
+      if (!ctx->allow_non_constant)
 	error ("array subscript out of bound");
-      *non_constant_p = true;
+      *ctx->non_constant_p = true;
       return t;
     }
   i = tree_low_cst (index, 0);
@@ -6833,37 +6817,34 @@  cxx_eval_array_reference (const constexpr_call *call, tree t,
 
 static tree
 cxx_eval_component_reference (const constexpr_call *call, tree t,
-			      bool allow_non_constant, bool addr,
-			      bool *non_constant_p)
+			      const cxx_eval_constant_ctx *ctx)
 {
   unsigned HOST_WIDE_INT i;
   tree field;
   tree value;
   tree part = TREE_OPERAND (t, 1);
   tree orig_whole = TREE_OPERAND (t, 0);
-  tree whole = cxx_eval_constant_expression (call, orig_whole,
-					     allow_non_constant, addr,
-					     non_constant_p);
+  tree whole = cxx_eval_constant_expression (call, orig_whole, ctx);
   if (whole == orig_whole)
     return t;
-  if (addr)
+  if (ctx->addr)
     return fold_build3 (COMPONENT_REF, TREE_TYPE (t),
 			whole, part, NULL_TREE);
   /* Don't VERIFY_CONSTANT here; we only want to check that we got a
      CONSTRUCTOR.  */
-  if (!*non_constant_p && TREE_CODE (whole) != CONSTRUCTOR)
+  if (!*ctx->non_constant_p && TREE_CODE (whole) != CONSTRUCTOR)
     {
-      if (!allow_non_constant)
+      if (!ctx->allow_non_constant)
 	error ("%qE is not a constant expression", orig_whole);
-      *non_constant_p = true;
+      *ctx->non_constant_p = true;
     }
   if (DECL_MUTABLE_P (part))
     {
-      if (!allow_non_constant)
+      if (!ctx->allow_non_constant)
 	error ("mutable %qD is not usable in a constant expression", part);
-      *non_constant_p = true;
+      *ctx->non_constant_p = true;
     }
-  if (*non_constant_p)
+  if (*ctx->non_constant_p)
     return t;
   FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (whole), i, field, value)
     {
@@ -6874,18 +6855,16 @@  cxx_eval_component_reference (const constexpr_call *call, tree t,
       && CONSTRUCTOR_NELTS (whole) > 0)
     {
       /* DR 1188 says we don't have to deal with this.  */
-      if (!allow_non_constant)
+      if (!ctx->allow_non_constant)
 	error ("accessing %qD member instead of initialized %qD member in "
 	       "constant expression", part, CONSTRUCTOR_ELT (whole, 0)->index);
-      *non_constant_p = true;
+      *ctx->non_constant_p = true;
       return t;
     }
 
   /* If there's no explicit init for this field, it's value-initialized.  */
   value = build_value_init (TREE_TYPE (t), tf_warning_or_error);
-  return cxx_eval_constant_expression (call, value,
-				       allow_non_constant, addr,
-				       non_constant_p);
+  return cxx_eval_constant_expression (call, value, ctx);
 }
 
 /* Subroutine of cxx_eval_constant_expression.
@@ -6894,16 +6873,13 @@  cxx_eval_component_reference (const constexpr_call *call, tree t,
 
 static tree
 cxx_eval_bit_field_ref (const constexpr_call *call, tree t,
-			bool allow_non_constant, bool addr,
-			bool *non_constant_p)
+			const cxx_eval_constant_ctx *ctx)
 {
   tree orig_whole = TREE_OPERAND (t, 0);
   tree retval, fldval, utype, mask;
   bool fld_seen = false;
   HOST_WIDE_INT istart, isize;
-  tree whole = cxx_eval_constant_expression (call, orig_whole,
-					     allow_non_constant, addr,
-					     non_constant_p);
+  tree whole = cxx_eval_constant_expression (call, orig_whole, ctx);
   tree start, field, value;
   unsigned HOST_WIDE_INT i;
 
@@ -6911,13 +6887,13 @@  cxx_eval_bit_field_ref (const constexpr_call *call, tree t,
     return t;
   /* Don't VERIFY_CONSTANT here; we only want to check that we got a
      CONSTRUCTOR.  */
-  if (!*non_constant_p && TREE_CODE (whole) != CONSTRUCTOR)
+  if (!*ctx->non_constant_p && TREE_CODE (whole) != CONSTRUCTOR)
     {
-      if (!allow_non_constant)
+      if (!ctx->allow_non_constant)
 	error ("%qE is not a constant expression", orig_whole);
-      *non_constant_p = true;
+      *ctx->non_constant_p = true;
     }
-  if (*non_constant_p)
+  if (*ctx->non_constant_p)
     return t;
 
   start = TREE_OPERAND (t, 2);
@@ -6974,19 +6950,15 @@  cxx_eval_bit_field_ref (const constexpr_call *call, tree t,
 static tree
 cxx_eval_logical_expression (const constexpr_call *call, tree t,
                              tree bailout_value, tree continue_value,
-			     bool allow_non_constant, bool addr,
-			     bool *non_constant_p)
+			     const cxx_eval_constant_ctx *ctx)
 {
   tree r;
-  tree lhs = cxx_eval_constant_expression (call, TREE_OPERAND (t, 0),
-					   allow_non_constant, addr,
-					   non_constant_p);
+  tree lhs = cxx_eval_constant_expression (call, TREE_OPERAND (t, 0), ctx);
   VERIFY_CONSTANT (lhs);
   if (tree_int_cst_equal (lhs, bailout_value))
     return lhs;
   gcc_assert (tree_int_cst_equal (lhs, continue_value));
-  r = cxx_eval_constant_expression (call, TREE_OPERAND (t, 1),
-				    allow_non_constant, addr, non_constant_p);
+  r = cxx_eval_constant_expression (call, TREE_OPERAND (t, 1), ctx);
   VERIFY_CONSTANT (r);
   return r;
 }
@@ -7027,8 +6999,7 @@  base_field_constructor_elt (VEC(constructor_elt,gc) *v, tree ref)
 
 static tree
 cxx_eval_bare_aggregate (const constexpr_call *call, tree t,
-			 bool allow_non_constant, bool addr,
-			 bool *non_constant_p)
+			 const cxx_eval_constant_ctx *ctx)
 {
   VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (t);
   VEC(constructor_elt,gc) *n = VEC_alloc (constructor_elt, gc,
@@ -7039,11 +7010,9 @@  cxx_eval_bare_aggregate (const constexpr_call *call, tree t,
   gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (t));
   for (i = 0; VEC_iterate (constructor_elt, v, i, ce); ++i)
     {
-      tree elt = cxx_eval_constant_expression (call, ce->value,
-					       allow_non_constant, addr,
-					       non_constant_p);
+      tree elt = cxx_eval_constant_expression (call, ce->value, ctx);
       /* Don't VERIFY_CONSTANT here.  */
-      if (allow_non_constant && *non_constant_p)
+      if (ctx->allow_non_constant && *ctx->non_constant_p)
 	goto fail;
       if (elt != ce->value)
 	changed = true;
@@ -7064,7 +7033,7 @@  cxx_eval_bare_aggregate (const constexpr_call *call, tree t,
       else
 	CONSTRUCTOR_APPEND_ELT (n, ce->index, elt);
     }
-  if (*non_constant_p || !changed)
+  if (*ctx->non_constant_p || !changed)
     {
     fail:
       VEC_free (constructor_elt, gc, n);
@@ -7089,8 +7058,7 @@  cxx_eval_bare_aggregate (const constexpr_call *call, tree t,
 
 static tree
 cxx_eval_vec_init_1 (const constexpr_call *call, tree atype, tree init,
-		     bool value_init, bool allow_non_constant, bool addr,
-		     bool *non_constant_p)
+		     bool value_init, const cxx_eval_constant_ctx *ctx)
 {
   tree elttype = TREE_TYPE (atype);
   int max = tree_low_cst (array_type_nelts (atype), 0);
@@ -7108,8 +7076,7 @@  cxx_eval_vec_init_1 (const constexpr_call *call, tree atype, tree init,
   else if (value_init)
     {
       init = build_value_init (elttype, tf_warning_or_error);
-      init = cxx_eval_constant_expression
-	    (call, init, allow_non_constant, addr, non_constant_p);
+      init = cxx_eval_constant_expression (call, init, ctx);
       pre_init = true;
     }
   else if (!init)
@@ -7119,12 +7086,11 @@  cxx_eval_vec_init_1 (const constexpr_call *call, tree atype, tree init,
 					&argvec, elttype, LOOKUP_NORMAL,
 					tf_warning_or_error);
       release_tree_vector (argvec);
-      init = cxx_eval_constant_expression (call, init, allow_non_constant,
-					   addr, non_constant_p);
+      init = cxx_eval_constant_expression (call, init, ctx);
       pre_init = true;
     }
 
-  if (*non_constant_p && !allow_non_constant)
+  if (*ctx->non_constant_p && !ctx->allow_non_constant)
     goto fail;
 
   for (i = 0; i <= max; ++i)
@@ -7140,8 +7106,7 @@  cxx_eval_vec_init_1 (const constexpr_call *call, tree atype, tree init,
 	    eltinit = cp_build_array_ref (input_location, init, idx,
 					  tf_warning_or_error);
 	  eltinit = cxx_eval_vec_init_1 (call, elttype, eltinit, value_init,
-					 allow_non_constant, addr,
-					 non_constant_p);
+					 ctx);
 	}
       else if (pre_init)
 	{
@@ -7168,15 +7133,14 @@  cxx_eval_vec_init_1 (const constexpr_call *call, tree atype, tree init,
 		     (NULL_TREE, complete_ctor_identifier, &argvec,
 		      elttype, LOOKUP_NORMAL, tf_warning_or_error));
 	  release_tree_vector (argvec);
-	  eltinit = cxx_eval_constant_expression
-	    (call, eltinit, allow_non_constant, addr, non_constant_p);
+	  eltinit = cxx_eval_constant_expression (call, eltinit, ctx);
 	}
-      if (*non_constant_p && !allow_non_constant)
+      if (*ctx->non_constant_p && !ctx->allow_non_constant)
 	goto fail;
       CONSTRUCTOR_APPEND_ELT (n, idx, eltinit);
     }
 
-  if (!*non_constant_p)
+  if (!*ctx->non_constant_p)
     {
       init = build_constructor (atype, n);
       TREE_CONSTANT (init) = true;
@@ -7190,15 +7154,13 @@  cxx_eval_vec_init_1 (const constexpr_call *call, tree atype, tree init,
 
 static tree
 cxx_eval_vec_init (const constexpr_call *call, tree t,
-		   bool allow_non_constant, bool addr,
-		   bool *non_constant_p)
+		   const cxx_eval_constant_ctx *ctx)
 {
   tree atype = TREE_TYPE (t);
   tree init = VEC_INIT_EXPR_INIT (t);
   tree r = cxx_eval_vec_init_1 (call, atype, init,
-				VEC_INIT_EXPR_VALUE_INIT (t),
-				allow_non_constant, addr, non_constant_p);
-  if (*non_constant_p)
+				VEC_INIT_EXPR_VALUE_INIT (t), ctx);
+  if (*ctx->non_constant_p)
     return t;
   else
     return r;
@@ -7386,25 +7348,26 @@  cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
 
 static tree
 cxx_eval_indirect_ref (const constexpr_call *call, tree t,
-		       bool allow_non_constant, bool addr,
-		       bool *non_constant_p)
+		       const cxx_eval_constant_ctx *ctx)
 {
   tree orig_op0 = TREE_OPERAND (t, 0);
-  tree op0 = cxx_eval_constant_expression (call, orig_op0, allow_non_constant,
-					   /*addr*/false, non_constant_p);
+  tree op0;
   bool empty_base = false;
   tree r;
+  cxx_eval_constant_ctx ctx1 = *ctx;
+
+  ctx1.addr = false;
+  op0 = cxx_eval_constant_expression (call, orig_op0, &ctx1);
 
   /* Don't VERIFY_CONSTANT here.  */
-  if (*non_constant_p)
+  if (*ctx->non_constant_p)
     return t;
 
   r = cxx_fold_indirect_ref (EXPR_LOCATION (t), TREE_TYPE (t), op0,
 			     &empty_base);
 
   if (r)
-    r = cxx_eval_constant_expression (call, r, allow_non_constant,
-				      addr, non_constant_p);
+    r = cxx_eval_constant_expression (call, r, ctx);
   else
     {
       tree sub = op0;
@@ -7421,11 +7384,11 @@  cxx_eval_indirect_ref (const constexpr_call *call, tree t,
 	  gcc_assert (!same_type_ignoring_top_level_qualifiers_p
 		      (TREE_TYPE (TREE_TYPE (sub)), TREE_TYPE (t)));
 	  /* DR 1188 says we don't have to deal with this.  */
-	  if (!allow_non_constant)
+	  if (!ctx->allow_non_constant)
 	    error ("accessing value of %qE through a %qT glvalue in a "
 		   "constant expression", build_fold_indirect_ref (sub),
 		   TREE_TYPE (t));
-	  *non_constant_p = true;
+	  *ctx->non_constant_p = true;
 	  return t;
 	}
     }
@@ -7491,9 +7454,8 @@  non_const_var_error (tree r)
 
 /* Evaluate VEC_PERM_EXPR (v1, v2, mask).  */
 static tree
-cxx_eval_vec_perm_expr (const constexpr_call *call, tree t, 
-			bool allow_non_constant, bool addr,
-			bool * non_constant_p)
+cxx_eval_vec_perm_expr (const constexpr_call *call, tree t,
+			const cxx_eval_constant_ctx *ctx)
 {
   int i;
   tree args[3];
@@ -7502,10 +7464,8 @@  cxx_eval_vec_perm_expr (const constexpr_call *call, tree t,
 
   for (i = 0; i < 3; i++)
     {
-      args[i] = cxx_eval_constant_expression (call, TREE_OPERAND (t, i),
-					      allow_non_constant, addr,
-					      non_constant_p);
-      if (*non_constant_p)
+      args[i] = cxx_eval_constant_expression (call, TREE_OPERAND (t, i), ctx);
+      if (*ctx->non_constant_p)
       	goto fail;
     }
 
@@ -7528,14 +7488,13 @@  cxx_eval_vec_perm_expr (const constexpr_call *call, tree t,
 
 static tree
 cxx_eval_constant_expression (const constexpr_call *call, tree t,
-			      bool allow_non_constant, bool addr,
-			      bool *non_constant_p)
+			      const cxx_eval_constant_ctx *ctx)
 {
   tree r = t;
 
   if (t == error_mark_node)
     {
-      *non_constant_p = true;
+      *ctx->non_constant_p = true;
       return t;
     }
   if (CONSTANT_CLASS_P (t))
@@ -7551,7 +7510,7 @@  cxx_eval_constant_expression (const constexpr_call *call, tree t,
   switch (TREE_CODE (t))
     {
     case VAR_DECL:
-      if (addr)
+      if (ctx->addr)
 	return t;
       /* else fall through. */
     case CONST_DECL:
@@ -7561,9 +7520,9 @@  cxx_eval_constant_expression (const constexpr_call *call, tree t,
 	r = TARGET_EXPR_INITIAL (r);
       if (DECL_P (r))
 	{
-	  if (!allow_non_constant)
+	  if (!ctx->allow_non_constant)
 	    non_const_var_error (r);
-	  *non_constant_p = true;
+	  *ctx->non_constant_p = true;
 	}
       break;
 
@@ -7577,58 +7536,57 @@  cxx_eval_constant_expression (const constexpr_call *call, tree t,
 	{
 	  if (DECL_ARTIFICIAL (t) && DECL_CONSTRUCTOR_P (DECL_CONTEXT (t)))
 	    {
-	      if (!allow_non_constant)
+	      if (!ctx->allow_non_constant)
 		sorry ("use of the value of the object being constructed "
 		       "in a constant expression");
-	      *non_constant_p = true;
+	      *ctx->non_constant_p = true;
 	    }
 	  else
 	    r = lookup_parameter_binding (call, t);
 	}
-      else if (addr)
+      else if (ctx->addr)
 	/* Defer in case this is only used for its type.  */;
       else
 	{
-	  if (!allow_non_constant)
+	  if (!ctx->allow_non_constant)
 	    error ("%qE is not a constant expression", t);
-	  *non_constant_p = true;
+	  *ctx->non_constant_p = true;
 	}
       break;
 
     case CALL_EXPR:
     case AGGR_INIT_EXPR:
-      r = cxx_eval_call_expression (call, t, allow_non_constant, addr,
-				    non_constant_p);
+      r = cxx_eval_call_expression (call, t, ctx);
       break;
 
     case TARGET_EXPR:
       if (!literal_type_p (TREE_TYPE (t)))
 	{
-	  if (!allow_non_constant)
+	  if (!ctx->allow_non_constant)
 	    {
 	      error ("temporary of non-literal type %qT in a "
 		     "constant expression", TREE_TYPE (t));
 	      explain_non_literal_class (TREE_TYPE (t));
 	    }
-	  *non_constant_p = true;
+	  *ctx->non_constant_p = true;
 	  break;
 	}
       /* else fall through.  */
     case INIT_EXPR:
       /* Pass false for 'addr' because these codes indicate
 	 initialization of a temporary.  */
-      r = cxx_eval_constant_expression (call, TREE_OPERAND (t, 1),
-					allow_non_constant, false,
-					non_constant_p);
-      if (!*non_constant_p)
+      {
+	cxx_eval_constant_ctx ctx1 = *ctx;
+	ctx1.addr = false;
+	r = cxx_eval_constant_expression (call, TREE_OPERAND (t, 1), &ctx1);
+      }
+      if (!*ctx->non_constant_p)
 	/* Adjust the type of the result to the type of the temporary.  */
 	r = adjust_temp_type (TREE_TYPE (t), r);
       break;
 
     case SCOPE_REF:
-      r = cxx_eval_constant_expression (call, TREE_OPERAND (t, 1),
-					allow_non_constant, addr,
-					non_constant_p);
+      r = cxx_eval_constant_expression (call, TREE_OPERAND (t, 1), ctx);
       break;
 
     case RETURN_EXPR:
@@ -7637,28 +7595,25 @@  cxx_eval_constant_expression (const constexpr_call *call, tree t,
     case CLEANUP_POINT_EXPR:
     case MUST_NOT_THROW_EXPR:
     case SAVE_EXPR:
-      r = cxx_eval_constant_expression (call, TREE_OPERAND (t, 0),
-					allow_non_constant, addr,
-					non_constant_p);
+      r = cxx_eval_constant_expression (call, TREE_OPERAND (t, 0), ctx);
       break;
 
       /* These differ from cxx_eval_unary_expression in that this doesn't
 	 check for a constant operand or result; an address can be
 	 constant without its operand being, and vice versa.  */
     case INDIRECT_REF:
-      r = cxx_eval_indirect_ref (call, t, allow_non_constant, addr,
-				 non_constant_p);
+      r = cxx_eval_indirect_ref (call, t, ctx);
       break;
 
     case ADDR_EXPR:
       {
 	tree oldop = TREE_OPERAND (t, 0);
-	tree op = cxx_eval_constant_expression (call, oldop,
-						allow_non_constant,
-						/*addr*/true,
-						non_constant_p);
+	tree op;
+	cxx_eval_constant_ctx ctx1 = *ctx;
+	ctx1.addr=  true;
+	op = cxx_eval_constant_expression (call, oldop, &ctx1);
 	/* Don't VERIFY_CONSTANT here.  */
-	if (*non_constant_p)
+	if (*ctx->non_constant_p)
 	  return t;
 	/* This function does more aggressive folding than fold itself.  */
 	r = build_fold_addr_expr_with_type (op, TREE_TYPE (t));
@@ -7677,8 +7632,7 @@  cxx_eval_constant_expression (const constexpr_call *call, tree t,
     case BIT_NOT_EXPR:
     case TRUTH_NOT_EXPR:
     case FIXED_CONVERT_EXPR:
-      r = cxx_eval_unary_expression (call, t, allow_non_constant, addr,
-				     non_constant_p);
+      r = cxx_eval_unary_expression (call, t, ctx);
       break;
 
     case COMPOUND_EXPR:
@@ -7691,15 +7645,14 @@  cxx_eval_constant_expression (const constexpr_call *call, tree t,
 	STRIP_NOPS (op1);
 	if ((TREE_CODE (op0) == TARGET_EXPR && op1 == TARGET_EXPR_SLOT (op0))
 	    || TREE_CODE (op1) == EMPTY_CLASS_EXPR)
-	  r = cxx_eval_constant_expression (call, op0, allow_non_constant,
-					    addr, non_constant_p);
+	  r = cxx_eval_constant_expression (call, op0, ctx);
 	else
 	  {
 	    /* Check that the LHS is constant and then discard it.  */
-	    cxx_eval_constant_expression (call, op0, allow_non_constant,
-					  false, non_constant_p);
-	    r = cxx_eval_constant_expression (call, op1, allow_non_constant,
-					      addr, non_constant_p);
+	    cxx_eval_constant_ctx ctx1 = *ctx;
+	    ctx1.addr = false;
+	    cxx_eval_constant_expression (call, op0, &ctx1);
+	    r = cxx_eval_constant_expression (call, op1, ctx);
 	  }
       }
       break;
@@ -7742,8 +7695,7 @@  cxx_eval_constant_expression (const constexpr_call *call, tree t,
     case UNEQ_EXPR:
     case RANGE_EXPR:
     case COMPLEX_EXPR:
-      r = cxx_eval_binary_expression (call, t, allow_non_constant, addr,
-				      non_constant_p);
+      r = cxx_eval_binary_expression (call, t, ctx);
       break;
 
       /* fold can introduce non-IF versions of these; still treat them as
@@ -7751,43 +7703,34 @@  cxx_eval_constant_expression (const constexpr_call *call, tree t,
     case TRUTH_AND_EXPR:
     case TRUTH_ANDIF_EXPR:
       r = cxx_eval_logical_expression (call, t, boolean_false_node,
-				       boolean_true_node,
-				       allow_non_constant, addr,
-				       non_constant_p);
+				       boolean_true_node, ctx);
       break;
 
     case TRUTH_OR_EXPR:
     case TRUTH_ORIF_EXPR:
       r = cxx_eval_logical_expression (call, t, boolean_true_node,
-				       boolean_false_node,
-				       allow_non_constant, addr,
-				       non_constant_p);
+				       boolean_false_node, ctx);
       break;
 
     case ARRAY_REF:
-      r = cxx_eval_array_reference (call, t, allow_non_constant, addr,
-				    non_constant_p);
+      r = cxx_eval_array_reference (call, t, ctx);
       break;
 
     case COMPONENT_REF:
-      r = cxx_eval_component_reference (call, t, allow_non_constant, addr,
-					non_constant_p);
+      r = cxx_eval_component_reference (call, t, ctx);
       break;
 
     case BIT_FIELD_REF:
-      r = cxx_eval_bit_field_ref (call, t, allow_non_constant, addr,
-				  non_constant_p);
+      r = cxx_eval_bit_field_ref (call, t, ctx);
       break;
 
     case COND_EXPR:
     case VEC_COND_EXPR:
-      r = cxx_eval_conditional_expression (call, t, allow_non_constant, addr,
-					   non_constant_p);
+      r = cxx_eval_conditional_expression (call, t, ctx);
       break;
 
     case CONSTRUCTOR:
-      r = cxx_eval_bare_aggregate (call, t, allow_non_constant, addr,
-				   non_constant_p);
+      r = cxx_eval_bare_aggregate (call, t, ctx);
       break;
 
     case VEC_INIT_EXPR:
@@ -7796,13 +7739,11 @@  cxx_eval_constant_expression (const constexpr_call *call, tree t,
 	 be NULL, meaning default-initialization, or it will be an lvalue
 	 or xvalue of the same type, meaning direct-initialization from the
 	 corresponding member.  */
-      r = cxx_eval_vec_init (call, t, allow_non_constant, addr,
-			     non_constant_p);
+      r = cxx_eval_vec_init (call, t, ctx);
       break;
 
     case VEC_PERM_EXPR:
-      r = cxx_eval_vec_perm_expr (call, t, allow_non_constant, addr,
-				  non_constant_p);
+      r = cxx_eval_vec_perm_expr (call, t, ctx);
       break;
 
     case CONVERT_EXPR:
@@ -7810,10 +7751,8 @@  cxx_eval_constant_expression (const constexpr_call *call, tree t,
     case NOP_EXPR:
       {
 	tree oldop = TREE_OPERAND (t, 0);
-	tree op = cxx_eval_constant_expression (call, oldop,
-						allow_non_constant, addr,
-						non_constant_p);
-	if (*non_constant_p)
+	tree op = cxx_eval_constant_expression (call, oldop, ctx);
+	if (*ctx->non_constant_p)
 	  return t;
 	if (op == oldop)
 	  /* We didn't fold at the top so we could check for ptr-int
@@ -7855,23 +7794,23 @@  cxx_eval_constant_expression (const constexpr_call *call, tree t,
     case BASELINK:
     case EXPR_STMT:
     case OFFSET_REF:
-      if (!allow_non_constant)
+      if (!ctx->allow_non_constant)
         error_at (EXPR_LOC_OR_HERE (t),
 		  "expression %qE is not a constant-expression", t);
-      *non_constant_p = true;
+      *ctx->non_constant_p = true;
       break;
 
     default:
       internal_error ("unexpected expression %qE of kind %s", t,
 		      tree_code_name[TREE_CODE (t)]);
-      *non_constant_p = true;
+      *ctx->non_constant_p = true;
       break;
     }
 
   if (r == error_mark_node)
-    *non_constant_p = true;
+    *ctx->non_constant_p = true;
 
-  if (*non_constant_p)
+  if (*ctx->non_constant_p)
     return t;
   else
     return r;
@@ -7881,8 +7820,12 @@  static tree
 cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant)
 {
   bool non_constant_p = false;
-  tree r = cxx_eval_constant_expression (NULL, t, allow_non_constant,
-					 false, &non_constant_p);
+  tree r;
+  cxx_eval_constant_ctx ctx;
+  ctx.allow_non_constant = allow_non_constant;
+  ctx.addr = false;
+  ctx.non_constant_p = &non_constant_p;
+  r = cxx_eval_constant_expression (NULL, t, &ctx);
 
   verify_constant (r, allow_non_constant, &non_constant_p);
 
@@ -7949,7 +7892,11 @@  bool
 is_sub_constant_expr (tree t)
 {
   bool non_constant_p = false;
-  cxx_eval_constant_expression (NULL, t, true, false, &non_constant_p);
+  cxx_eval_constant_ctx ctx;
+  ctx.allow_non_constant = true;
+  ctx.addr = false;
+  ctx.non_constant_p = &non_constant_p;
+  cxx_eval_constant_expression (NULL, t, &ctx);
   return !non_constant_p;
 }