[2/2] c++: remove i_c_e_p parm from tsubst_copy_and_build

Message ID 20221110195602.2434376-2-ppalka@redhat.com
State Accepted
Headers
Series [1/2] c++: remove function_p parm from tsubst_copy_and_build |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

Patrick Palka Nov. 10, 2022, 7:56 p.m. UTC
  AFAICT the only purpose of tsubst_copy_and_build's
integral_constant_expression_p boolean parameter is to diagnose certain
constructs that aren't allowed to appear in a C++98 integral constant
expression context, specifically casts to a non-integral type (diagnosed
from the *_CAST_EXPR case of tsubst_copy_and_build) or dependent names
that resolve to a non-constant decl (diagnosed from the IDENTIFIER_NODE
case of tsubst_copy_and_build).  The parameter has no effect outside of
C++98 AFAICT.

But diagnosing such constructs should arguably be done by
is_constant_expression after substitution, and doing it during
substitution by way of an additional parameter complicates the API of
this workhouse function for functionality that's specific to C++98.
And it seems is_constant_expression already does a good job of diagnosing
the aforementioned two constructs in C++98 mode, at least as far as our
testsuite is concerned.

So this patch gets rid of this parameter from tsubst_copy_and_build,
tsubst_expr and tsubst_copy_and_build_call_args.  The only interesting
changes are those to potential_constant_expression_1 and the
IDENTIFIER_NODE and *_CAST_EXPR cases of tsubst_copy_and_build; the rest
are mechanical adjustments to these functions and their call sites.

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?

gcc/cp/ChangeLog:

	* constexpr.cc (potential_constant_expression_1)
	<case *_CAST_EXPR>: Use
	cast_valid_in_integral_constant_expression_p instead of
	open coding it.
	* constraint.cc (tsubst_valid_expression_requirement): Adjust
	calls to tsubst_copy_and_build and tsubst_expr.
	(tsubst_constraint): Likewise.
	(satisfy_atom): Likewise.
	(diagnose_trait_expr): Likewise.
	* cp-tree.h (tsubst_copy_and_build): Remove i_c_e_p parameter.
	(tsubst_expr): Likewise.
	* init.cc (get_nsdmi): Adjust calls to tsubst_copy_and_build
	and tsubst_expr.
	* pt.cc (expand_integer_pack): Likewise.
	(instantiate_non_dependent_expr_internal): Likewise.
	(tsubst_friend_function): Likewise.
	(tsubst_attribute): Likewise.
	(instantiate_class_template): Likewise.
	(tsubst_template_arg): Likewise.
	(gen_elem_of_pack_expansion_instantiation): Likewise.
	(tsubst_fold_expr_init): Likewise.
	(tsubst_pack_expansion): Likewise.
	(tsubst_default_argument): Likewise.
	(tsubst_function_decl): Likewise.
	(tsubst_decl): Likewise.
	(tsubst_arg_types): Likewise.
	(tsubst_exception_specification): Likewise.
	(tsubst): Likewise.
	(tsubst_init): Likewise.
	(tsubst_copy): Likewise.
	(tsubst_omp_clause_decl): Likewise.
	(tsubst_omp_clauses): Likewise.
	(tsubst_copy_asm_operands): Likewise.
	(tsubst_omp_for_iterator): Likewise.
	(tsubst_expr): Likewise.  Remove i_c_e_p parameter.
	(tsubst_omp_udr): Likewise.
	(tsubst_non_call_postfix_expression): Likewise.  Remove i_c_e_p parameter.
	(tsubst_lambda_expr): Likewise.
	(tsubst_copy_and_build_call_args): Likewise.
	(tsubst_copy_and_build): Likewise.  Remove i_c_e_p parameter.
	<case IDENTIFIER_NODE>: Adjust call to finish_id_expression
	following removal of i_c_e_p.
	<case *_CAST_EXPR>: Remove C++98-specific cast validity check
	guarded by i_c_e_p.
	(maybe_instantiate_noexcept): Adjust calls to
	tsubst_copy_and_build and tsubst_expr.
	(instantiate_body): Likewise.
	(instantiate_decl): Likewise.
	(tsubst_initializer_list): Likewise.
	(tsubst_enum): Likewise.

gcc/objcp/ChangeLog:

	* objcp-lang.cc (objcp_tsubst_copy_and_build): Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/template/crash55.C: Don't expect additional
	C++98-specific diagnostics.
	* g++.dg/template/ref3.C: Remove C++98-specific xfail.
---
 gcc/cp/constexpr.cc                     |   4 +-
 gcc/cp/constraint.cc                    |  14 +-
 gcc/cp/cp-tree.h                        |   6 +-
 gcc/cp/init.cc                          |   6 +-
 gcc/cp/pt.cc                            | 240 ++++++++----------------
 gcc/objcp/objcp-lang.cc                 |   3 +-
 gcc/testsuite/g++.dg/template/crash55.C |   3 +-
 gcc/testsuite/g++.dg/template/ref3.C    |   3 +-
 8 files changed, 93 insertions(+), 186 deletions(-)
  

Comments

Patrick Palka Nov. 10, 2022, 8:24 p.m. UTC | #1
On Thu, 10 Nov 2022, Patrick Palka wrote:

> AFAICT the only purpose of tsubst_copy_and_build's
> integral_constant_expression_p boolean parameter is to diagnose certain
> constructs that aren't allowed to appear in a C++98 integral constant
> expression context, specifically casts to a non-integral type (diagnosed
> from the *_CAST_EXPR case of tsubst_copy_and_build) or dependent names
> that resolve to a non-constant decl (diagnosed from the IDENTIFIER_NODE
> case of tsubst_copy_and_build).  The parameter has no effect outside of
> C++98 AFAICT.

I should add that the parameter was added to tsubst_copy_and_build
by r116276 which predates the constexpr machinery.

> 
> But diagnosing such constructs should arguably be done by
> is_constant_expression after substitution, and doing it during
> substitution by way of an additional parameter complicates the API of
> this workhouse function for functionality that's specific to C++98.
> And it seems is_constant_expression already does a good job of diagnosing
> the aforementioned two constructs in C++98 mode, at least as far as our
> testsuite is concerned.
> 
> So this patch gets rid of this parameter from tsubst_copy_and_build,
> tsubst_expr and tsubst_copy_and_build_call_args.  The only interesting
> changes are those to potential_constant_expression_1 and the
> IDENTIFIER_NODE and *_CAST_EXPR cases of tsubst_copy_and_build; the rest
> are mechanical adjustments to these functions and their call sites.
> 
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk?
> 
> gcc/cp/ChangeLog:
> 
> 	* constexpr.cc (potential_constant_expression_1)
> 	<case *_CAST_EXPR>: Use
> 	cast_valid_in_integral_constant_expression_p instead of
> 	open coding it.
> 	* constraint.cc (tsubst_valid_expression_requirement): Adjust
> 	calls to tsubst_copy_and_build and tsubst_expr.
> 	(tsubst_constraint): Likewise.
> 	(satisfy_atom): Likewise.
> 	(diagnose_trait_expr): Likewise.
> 	* cp-tree.h (tsubst_copy_and_build): Remove i_c_e_p parameter.
> 	(tsubst_expr): Likewise.
> 	* init.cc (get_nsdmi): Adjust calls to tsubst_copy_and_build
> 	and tsubst_expr.
> 	* pt.cc (expand_integer_pack): Likewise.
> 	(instantiate_non_dependent_expr_internal): Likewise.
> 	(tsubst_friend_function): Likewise.
> 	(tsubst_attribute): Likewise.
> 	(instantiate_class_template): Likewise.
> 	(tsubst_template_arg): Likewise.
> 	(gen_elem_of_pack_expansion_instantiation): Likewise.
> 	(tsubst_fold_expr_init): Likewise.
> 	(tsubst_pack_expansion): Likewise.
> 	(tsubst_default_argument): Likewise.
> 	(tsubst_function_decl): Likewise.
> 	(tsubst_decl): Likewise.
> 	(tsubst_arg_types): Likewise.
> 	(tsubst_exception_specification): Likewise.
> 	(tsubst): Likewise.
> 	(tsubst_init): Likewise.
> 	(tsubst_copy): Likewise.
> 	(tsubst_omp_clause_decl): Likewise.
> 	(tsubst_omp_clauses): Likewise.
> 	(tsubst_copy_asm_operands): Likewise.
> 	(tsubst_omp_for_iterator): Likewise.
> 	(tsubst_expr): Likewise.  Remove i_c_e_p parameter.
> 	(tsubst_omp_udr): Likewise.
> 	(tsubst_non_call_postfix_expression): Likewise.  Remove i_c_e_p parameter.
> 	(tsubst_lambda_expr): Likewise.
> 	(tsubst_copy_and_build_call_args): Likewise.
> 	(tsubst_copy_and_build): Likewise.  Remove i_c_e_p parameter.
> 	<case IDENTIFIER_NODE>: Adjust call to finish_id_expression
> 	following removal of i_c_e_p.
> 	<case *_CAST_EXPR>: Remove C++98-specific cast validity check
> 	guarded by i_c_e_p.
> 	(maybe_instantiate_noexcept): Adjust calls to
> 	tsubst_copy_and_build and tsubst_expr.
> 	(instantiate_body): Likewise.
> 	(instantiate_decl): Likewise.
> 	(tsubst_initializer_list): Likewise.
> 	(tsubst_enum): Likewise.
> 
> gcc/objcp/ChangeLog:
> 
> 	* objcp-lang.cc (objcp_tsubst_copy_and_build): Likewise.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/template/crash55.C: Don't expect additional
> 	C++98-specific diagnostics.
> 	* g++.dg/template/ref3.C: Remove C++98-specific xfail.
> ---
>  gcc/cp/constexpr.cc                     |   4 +-
>  gcc/cp/constraint.cc                    |  14 +-
>  gcc/cp/cp-tree.h                        |   6 +-
>  gcc/cp/init.cc                          |   6 +-
>  gcc/cp/pt.cc                            | 240 ++++++++----------------
>  gcc/objcp/objcp-lang.cc                 |   3 +-
>  gcc/testsuite/g++.dg/template/crash55.C |   3 +-
>  gcc/testsuite/g++.dg/template/ref3.C    |   3 +-
>  8 files changed, 93 insertions(+), 186 deletions(-)
> 
> diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> index 15b4f2c4a08..e665839f5b1 100644
> --- a/gcc/cp/constexpr.cc
> +++ b/gcc/cp/constexpr.cc
> @@ -9460,9 +9460,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
>      case STATIC_CAST_EXPR:
>      case REINTERPRET_CAST_EXPR:
>      case IMPLICIT_CONV_EXPR:
> -      if (cxx_dialect < cxx11
> -	  && !dependent_type_p (TREE_TYPE (t))
> -	  && !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t)))
> +      if (!cast_valid_in_integral_constant_expression_p (TREE_TYPE (t)))
>  	/* In C++98, a conversion to non-integral type can't be part of a
>  	   constant expression.  */
>  	{
> diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> index f6ef078171a..3ddbd535330 100644
> --- a/gcc/cp/constraint.cc
> +++ b/gcc/cp/constraint.cc
> @@ -1921,7 +1921,7 @@ hash_placeholder_constraint (tree c)
>  static tree
>  tsubst_valid_expression_requirement (tree t, tree args, sat_info info)
>  {
> -  tree r = tsubst_expr (t, args, tf_none, info.in_decl, false);
> +  tree r = tsubst_expr (t, args, tf_none, info.in_decl);
>    if (convert_to_void (r, ICV_STATEMENT, tf_none) != error_mark_node)
>      return r;
>  
> @@ -1932,7 +1932,7 @@ tsubst_valid_expression_requirement (tree t, tree args, sat_info info)
>  	{
>  	  inform (loc, "the required expression %qE is invalid, because", t);
>  	  if (r == error_mark_node)
> -	    tsubst_expr (t, args, info.complain, info.in_decl, false);
> +	    tsubst_expr (t, args, info.complain, info.in_decl);
>  	  else
>  	    convert_to_void (r, ICV_STATEMENT, info.complain);
>  	}
> @@ -1941,7 +1941,7 @@ tsubst_valid_expression_requirement (tree t, tree args, sat_info info)
>      }
>    else if (info.noisy ())
>      {
> -      r = tsubst_expr (t, args, info.complain, info.in_decl, false);
> +      r = tsubst_expr (t, args, info.complain, info.in_decl);
>        convert_to_void (r, ICV_STATEMENT, info.complain);
>      }
>  
> @@ -2706,7 +2706,7 @@ tsubst_constraint (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>       constraint-expressions of a declaration.  */
>    processing_constraint_expression_sentinel s;
>    cp_unevaluated u;
> -  tree expr = tsubst_expr (t, args, complain, in_decl, false);
> +  tree expr = tsubst_expr (t, args, complain, in_decl);
>    return expr;
>  }
>  
> @@ -2954,13 +2954,13 @@ satisfy_atom (tree t, tree args, sat_info info)
>  
>    /* Apply the parameter mapping (i.e., just substitute).  */
>    tree expr = ATOMIC_CONSTR_EXPR (t);
> -  tree result = tsubst_expr (expr, args, quiet.complain, quiet.in_decl, false);
> +  tree result = tsubst_expr (expr, args, quiet.complain, quiet.in_decl);
>    if (result == error_mark_node)
>      {
>        /* If substitution results in an invalid type or expression, the constraint
>  	 is not satisfied. Replay the substitution.  */
>        if (info.diagnose_unsatisfaction_p ())
> -	tsubst_expr (expr, args, info.complain, info.in_decl, false);
> +	tsubst_expr (expr, args, info.complain, info.in_decl);
>        return cache.save (inst_cache.save (boolean_false_node));
>      }
>  
> @@ -3587,7 +3587,7 @@ diagnose_trait_expr (tree expr, tree args)
>    /* Build a "fake" version of the instantiated trait, so we can
>       get the instantiated types from result.  */
>    ++processing_template_decl;
> -  expr = tsubst_expr (expr, args, tf_none, NULL_TREE, false);
> +  expr = tsubst_expr (expr, args, tf_none, NULL_TREE);
>    --processing_template_decl;
>  
>    tree t1 = TRAIT_EXPR_TYPE1 (expr);
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index 40fd2e1ebb9..7ff3206e245 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -7382,10 +7382,8 @@ extern void instantiate_pending_templates	(int);
>  extern tree tsubst_default_argument		(tree, int, tree, tree,
>  						 tsubst_flags_t);
>  extern tree tsubst (tree, tree, tsubst_flags_t, tree);
> -extern tree tsubst_copy_and_build		(tree, tree, tsubst_flags_t,
> -						 tree, bool = false);
> -extern tree tsubst_expr                         (tree, tree, tsubst_flags_t,
> -                                                 tree, bool);
> +extern tree tsubst_copy_and_build		(tree, tree, tsubst_flags_t, tree);
> +extern tree tsubst_expr                         (tree, tree, tsubst_flags_t, tree);
>  extern tree tsubst_pack_expansion		(tree, tree, tsubst_flags_t, tree);
>  extern tree tsubst_argument_pack		(tree, tree, tsubst_flags_t, tree);
>  extern tree tsubst_template_args		(tree, tree, tsubst_flags_t, tree);
> diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
> index fee49090de7..2fff4ad2dc7 100644
> --- a/gcc/cp/init.cc
> +++ b/gcc/cp/init.cc
> @@ -620,10 +620,8 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)
>  	  start_lambda_scope (member);
>  
>  	  /* Do deferred instantiation of the NSDMI.  */
> -	  init = (tsubst_copy_and_build
> -		  (init, DECL_TI_ARGS (member),
> -		   complain, member,
> -		   /*integral_constant_expression_p=*/false));
> +	  init = tsubst_copy_and_build (init, DECL_TI_ARGS (member),
> +					complain, member);
>  	  init = digest_nsdmi_init (member, init, complain);
>  
>  	  finish_lambda_scope ();
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index bcc275f8b6e..e3d311b0a8b 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -3772,8 +3772,7 @@ expand_integer_pack (tree call, tree args, tsubst_flags_t complain,
>  		     tree in_decl)
>  {
>    tree ohi = CALL_EXPR_ARG (call, 0);
> -  tree hi = tsubst_copy_and_build (ohi, args, complain, in_decl,
> -				   true/*int_cst*/);
> +  tree hi = tsubst_copy_and_build (ohi, args, complain, in_decl);
>  
>    if (instantiation_dependent_expression_p (hi))
>      {
> @@ -6360,8 +6359,7 @@ instantiate_non_dependent_expr_internal (tree expr, tsubst_flags_t complain)
>    return tsubst_copy_and_build (expr,
>  				/*args=*/NULL_TREE,
>  				complain,
> -				/*in_decl=*/NULL_TREE,
> -				/*integral_constant_expression_p=*/true);
> +				/*in_decl=*/NULL_TREE);
>  }
>  
>  /* Instantiate the non-dependent expression EXPR.  */
> @@ -11195,8 +11193,7 @@ tsubst_friend_function (tree decl, tree args)
>  	 current class with same name.  */
>        push_nested_namespace (ns);
>        fns = tsubst_expr (DECL_TI_TEMPLATE (decl), args,
> -			 tf_warning_or_error, NULL_TREE,
> -			 /*integral_constant_expression_p=*/false);
> +			 tf_warning_or_error, NULL_TREE);
>        pop_nested_namespace (ns);
>        arglist = tsubst (DECL_TI_ARGS (decl), args,
>  			tf_warning_or_error, NULL_TREE);
> @@ -11609,9 +11606,7 @@ tsubst_attribute (tree t, tree *decl_p, tree args,
>  			      get_attribute_name (t)))
>      {
>        ++cp_unevaluated_operand;
> -      tree varid
> -	= tsubst_expr (TREE_PURPOSE (val), args, complain,
> -		       in_decl, /*integral_constant_expression_p=*/false);
> +      tree varid = tsubst_expr (TREE_PURPOSE (val), args, complain, in_decl);
>        --cp_unevaluated_operand;
>        tree chain = TREE_CHAIN (val);
>        location_t match_loc = cp_expr_loc_or_input_loc (TREE_PURPOSE (chain));
> @@ -11647,7 +11642,7 @@ tsubst_attribute (tree t, tree *decl_p, tree args,
>  			tree v = TREE_VALUE (t3);
>  			if (TREE_CODE (v) == STRING_CST && allow_string)
>  			  continue;
> -			v = tsubst_expr (v, args, complain, in_decl, true);
> +			v = tsubst_expr (v, args, complain, in_decl);
>  			v = fold_non_dependent_expr (v);
>  			if (!INTEGRAL_TYPE_P (TREE_TYPE (v))
>  			    || (TREE_PURPOSE (t3) == score
> @@ -11693,8 +11688,7 @@ tsubst_attribute (tree t, tree *decl_p, tree args,
>    else if (attribute_takes_identifier_p (get_attribute_name (t)))
>      {
>        tree chain
> -	= tsubst_expr (TREE_CHAIN (val), args, complain, in_decl,
> -		       /*integral_constant_expression_p=*/false);
> +	= tsubst_expr (TREE_CHAIN (val), args, complain, in_decl);
>        if (chain != TREE_CHAIN (val))
>  	val = tree_cons (NULL_TREE, TREE_VALUE (val), chain);
>      }
> @@ -11717,8 +11711,7 @@ tsubst_attribute (tree t, tree *decl_p, tree args,
>        return list;
>      }
>    else
> -    val = tsubst_expr (val, args, complain, in_decl,
> -		       /*integral_constant_expression_p=*/false);
> +    val = tsubst_expr (val, args, complain, in_decl);
>  
>    if (val == error_mark_node)
>      return error_mark_node;
> @@ -12160,8 +12153,7 @@ instantiate_class_template (tree type)
>  	    {
>  	      /* Build new TYPE_FIELDS.  */
>                if (TREE_CODE (t) == STATIC_ASSERT)
> -		tsubst_expr (t, args, tf_warning_or_error, NULL_TREE,
> -			     /*integral_constant_expression_p=*/true);
> +		tsubst_expr (t, args, tf_warning_or_error, NULL_TREE);
>  	      else if (TREE_CODE (t) != CONST_DECL)
>  		{
>  		  tree r;
> @@ -12418,8 +12410,7 @@ tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>      {
>        if (!(complain & tf_warning))
>  	++c_inhibit_evaluation_warnings;
> -      r = tsubst_expr (t, args, complain, in_decl,
> -		       /*integral_constant_expression_p=*/true);
> +      r = tsubst_expr (t, args, complain, in_decl);
>        if (!(complain & tf_warning))
>  	--c_inhibit_evaluation_warnings;
>      }
> @@ -12683,8 +12674,7 @@ gen_elem_of_pack_expansion_instantiation (tree pattern,
>    else if (pattern == error_mark_node)
>      t = error_mark_node;
>    else if (!TYPE_P (pattern))
> -    t = tsubst_expr (pattern, args, complain, in_decl,
> -		     /*integral_constant_expression_p=*/false);
> +    t = tsubst_expr (pattern, args, complain, in_decl);
>    else
>      {
>        t = tsubst (pattern, args, complain, in_decl);
> @@ -12778,7 +12768,7 @@ tsubst_fold_expr_pack (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>  static inline tree
>  tsubst_fold_expr_init (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>  {
> -  return tsubst_expr (FOLD_EXPR_INIT (t), args, complain, in_decl, false);
> +  return tsubst_expr (FOLD_EXPR_INIT (t), args, complain, in_decl);
>  }
>  
>  /* Expand a PACK of arguments into a grouped as left fold.
> @@ -13147,12 +13137,12 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
>  	  if (BASES_DIRECT (parm_pack))
>  	    return calculate_direct_bases (tsubst_expr (BASES_TYPE (parm_pack),
>  							args, complain,
> -							in_decl, false),
> +							in_decl),
>  					   complain);
>  	  else
>  	    return calculate_bases (tsubst_expr (BASES_TYPE (parm_pack),
> -						 args, complain, in_decl,
> -						 false), complain);
> +						 args, complain, in_decl),
> +				    complain);
>  	}
>        else if (builtin_pack_call_p (parm_pack))
>  	{
> @@ -13326,8 +13316,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
>  	 pattern and return a PACK_EXPANSION_*. The caller will need to
>  	 deal with that.  */
>        if (TREE_CODE (t) == EXPR_PACK_EXPANSION)
> -	result = tsubst_expr (pattern, args, complain, in_decl,
> -			 /*integral_constant_expression_p=*/false);
> +	result = tsubst_expr (pattern, args, complain, in_decl);
>        else
>  	result = tsubst (pattern, args, complain, in_decl);
>        result = make_pack_expansion (result, complain);
> @@ -13901,9 +13890,7 @@ tsubst_default_argument (tree fn, int parmnum, tree type, tree arg,
>       the body of function so as to avoid collecting live data on the
>       stack.  */
>    ++function_depth;
> -  arg = tsubst_expr (arg, DECL_TI_ARGS (fn),
> -		     complain, NULL_TREE,
> -		     /*integral_constant_expression_p=*/false);
> +  arg = tsubst_expr (arg, DECL_TI_ARGS (fn), complain, NULL_TREE);
>    --function_depth;
>  
>    finish_lambda_scope ();
> @@ -14208,8 +14195,7 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain,
>    if (DECL_HAS_DEPENDENT_EXPLICIT_SPEC_P (t))
>      {
>        tree spec = lookup_explicit_specifier (t);
> -      spec = tsubst_copy_and_build (spec, args, complain, in_decl,
> -				    /*i_c_e_p=*/true);
> +      spec = tsubst_copy_and_build (spec, args, complain, in_decl);
>        spec = build_explicit_specifier (spec, complain);
>        if (spec == error_mark_node)
>  	return error_mark_node;
> @@ -14821,8 +14807,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
>  		 number of bits.  */
>  	      DECL_BIT_FIELD_REPRESENTATIVE (r)
>  		= tsubst_expr (DECL_BIT_FIELD_REPRESENTATIVE (t), args,
> -			       complain, in_decl,
> -			       /*integral_constant_expression_p=*/true);
> +			       complain, in_decl);
>  	    if (DECL_INITIAL (t))
>  	      {
>  		/* Set up DECL_TEMPLATE_INFO so that we can get at the
> @@ -15074,8 +15059,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
>  		bool nop = (TREE_CODE (ve) == NOP_EXPR);
>  		if (nop)
>  		  ve = TREE_OPERAND (ve, 0);
> -		ve = tsubst_expr (ve, args, complain, in_decl,
> -				  /*constant_expression_p=*/false);
> +		ve = tsubst_expr (ve, args, complain, in_decl);
>  		if (REFERENCE_REF_P (ve))
>  		  {
>  		    gcc_assert (TYPE_REF_P (type));
> @@ -15273,8 +15257,7 @@ tsubst_arg_types (tree arg_types,
>    if (lambda_fn_in_template_p (in_decl)
>        || (in_decl && TREE_CODE (in_decl) == FUNCTION_DECL
>  	  && DECL_LOCAL_DECL_P (in_decl)))
> -    default_arg = tsubst_copy_and_build (default_arg, args, complain, in_decl,
> -					 false/*constexpr*/);
> +    default_arg = tsubst_copy_and_build (default_arg, args, complain, in_decl);
>  
>    tree remaining_arg_types = tsubst_arg_types (TREE_CHAIN (arg_types),
>  					       args, end, complain, in_decl);
> @@ -15455,9 +15438,7 @@ tsubst_exception_specification (tree fntype,
>  					   args);
>  	      expr = DEFERRED_NOEXCEPT_PATTERN (expr);
>  	    }
> -	  new_specs = tsubst_copy_and_build
> -	    (expr, args, complain, in_decl,
> -	     /*integral_constant_expression_p=*/true);
> +	  new_specs = tsubst_copy_and_build (expr, args, complain, in_decl);
>  	}
>        new_specs = build_noexcept_spec (new_specs, complain);
>        /* We've instantiated a template before a noexcept-specifier
> @@ -15764,8 +15745,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>        {
>  	tree max, omax = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);
>  
> -	max = tsubst_expr (omax, args, complain, in_decl,
> -			   /*integral_constant_expression_p=*/false);
> +	max = tsubst_expr (omax, args, complain, in_decl);
>  
>  	/* Fix up type of the magic NOP_EXPR with TREE_SIDE_EFFECTS if
>  	   needed.  */
> @@ -16358,9 +16338,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>  	++cp_unevaluated_operand;
>  	++c_inhibit_evaluation_warnings;
>  
> -	type = tsubst_expr (TYPEOF_TYPE_EXPR (t), args,
> -			    complain, in_decl,
> -			    /*integral_constant_expression_p=*/false);
> +	type = tsubst_expr (TYPEOF_TYPE_EXPR (t), args, complain, in_decl);
>  
>  	--cp_unevaluated_operand;
>  	--c_inhibit_evaluation_warnings;
> @@ -16380,8 +16358,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>  	++c_inhibit_evaluation_warnings;
>  
>  	type = tsubst_copy_and_build (DECLTYPE_TYPE_EXPR (t), args,
> -				      complain|tf_decltype, in_decl,
> -				      /*integral_constant_expression*/false);
> +				      complain|tf_decltype, in_decl);
>  
>  	--cp_unevaluated_operand;
>  	--c_inhibit_evaluation_warnings;
> @@ -16840,7 +16817,7 @@ tsubst_init (tree init, tree decl, tree args,
>    if (!init)
>      return NULL_TREE;
>  
> -  init = tsubst_expr (init, args, complain, in_decl, false);
> +  init = tsubst_expr (init, args, complain, in_decl);
>  
>    tree type = TREE_TYPE (decl);
>  
> @@ -17677,9 +17654,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>        return t;
>  
>      case CO_AWAIT_EXPR:
> -      return tsubst_expr (t, args, complain, in_decl,
> -			  /*integral_constant_expression_p=*/false);
> -      break;
> +      return tsubst_expr (t, args, complain, in_decl);
>  
>      default:
>        /* We shouldn't get here, but keep going if !flag_checking.  */
> @@ -17719,14 +17694,11 @@ tsubst_omp_clause_decl (tree decl, tree args, tsubst_flags_t complain,
>  	      DECL_CONTEXT (TREE_VEC_ELT (*tp, 0)) = current_function_decl;
>  	      pushdecl (TREE_VEC_ELT (*tp, 0));
>  	      TREE_VEC_ELT (*tp, 1)
> -		= tsubst_expr (TREE_VEC_ELT (it, 1), args, complain, in_decl,
> -			       /*integral_constant_expression_p=*/false);
> +		= tsubst_expr (TREE_VEC_ELT (it, 1), args, complain, in_decl);
>  	      TREE_VEC_ELT (*tp, 2)
> -		= tsubst_expr (TREE_VEC_ELT (it, 2), args, complain, in_decl,
> -			       /*integral_constant_expression_p=*/false);
> +		= tsubst_expr (TREE_VEC_ELT (it, 2), args, complain, in_decl);
>  	      TREE_VEC_ELT (*tp, 3)
> -		= tsubst_expr (TREE_VEC_ELT (it, 3), args, complain, in_decl,
> -			       /*integral_constant_expression_p=*/false);
> +		= tsubst_expr (TREE_VEC_ELT (it, 3), args, complain, in_decl);
>  	      TREE_CHAIN (*tp) = NULL_TREE;
>  	      tp = &TREE_CHAIN (*tp);
>  	    }
> @@ -17748,10 +17720,8 @@ tsubst_omp_clause_decl (tree decl, tree args, tsubst_flags_t complain,
>    if (TREE_CODE (decl) == TREE_LIST)
>      {
>        tree low_bound
> -	= tsubst_expr (TREE_PURPOSE (decl), args, complain, in_decl,
> -		       /*integral_constant_expression_p=*/false);
> -      tree length = tsubst_expr (TREE_VALUE (decl), args, complain, in_decl,
> -				 /*integral_constant_expression_p=*/false);
> +	= tsubst_expr (TREE_PURPOSE (decl), args, complain, in_decl);
> +      tree length = tsubst_expr (TREE_VALUE (decl), args, complain, in_decl);
>        tree chain = tsubst_omp_clause_decl (TREE_CHAIN (decl), args, complain,
>  					   in_decl, NULL);
>        if (TREE_PURPOSE (decl) == low_bound
> @@ -17763,8 +17733,7 @@ tsubst_omp_clause_decl (tree decl, tree args, tsubst_flags_t complain,
>  	= OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (decl);
>        return ret;
>      }
> -  tree ret = tsubst_expr (decl, args, complain, in_decl,
> -			  /*integral_constant_expression_p=*/false);
> +  tree ret = tsubst_expr (decl, args, complain, in_decl);
>    /* Undo convert_from_reference tsubst_expr could have called.  */
>    if (decl
>        && REFERENCE_REF_P (ret)
> @@ -17795,8 +17764,8 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
>  	  if (OMP_CLAUSE_LASTPRIVATE_STMT (oc))
>  	    {
>  	      OMP_CLAUSE_LASTPRIVATE_STMT (nc) = push_stmt_list ();
> -	      tsubst_expr (OMP_CLAUSE_LASTPRIVATE_STMT (oc), args, complain,
> -			   in_decl, /*integral_constant_expression_p=*/false);
> +	      tsubst_expr (OMP_CLAUSE_LASTPRIVATE_STMT (oc), args,
> +			   complain, in_decl);
>  	      OMP_CLAUSE_LASTPRIVATE_STMT (nc)
>  		= pop_stmt_list (OMP_CLAUSE_LASTPRIVATE_STMT (nc));
>  	    }
> @@ -17829,8 +17798,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
>  	  if (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (oc))
>  	    OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (nc)
>  	      = tsubst_expr (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (oc), args,
> -			     complain, in_decl,
> -			     /*integral_constant_expression_p=*/false);
> +			     complain, in_decl);
>  	  /* FALLTHRU */
>  	case OMP_CLAUSE_TILE:
>  	case OMP_CLAUSE_IF:
> @@ -17858,8 +17826,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
>  	case OMP_CLAUSE_WAIT:
>  	case OMP_CLAUSE_DETACH:
>  	  OMP_CLAUSE_OPERAND (nc, 0)
> -	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
> -			   in_decl, /*integral_constant_expression_p=*/false);
> +	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain, in_decl);
>  	  break;
>  	case OMP_CLAUSE_REDUCTION:
>  	case OMP_CLAUSE_IN_REDUCTION:
> @@ -17889,19 +17856,16 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
>  	    = tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
>  				      in_decl, NULL);
>  	  OMP_CLAUSE_OPERAND (nc, 1)
> -	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain,
> -			   in_decl, /*integral_constant_expression_p=*/false);
> +	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain, in_decl);
>  	  break;
>  	case OMP_CLAUSE_ALLOCATE:
>  	  OMP_CLAUSE_DECL (nc)
>  	    = tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
>  				      in_decl, NULL);
>  	  OMP_CLAUSE_OPERAND (nc, 1)
> -	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain,
> -			   in_decl, /*integral_constant_expression_p=*/false);
> +	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain, in_decl);
>  	  OMP_CLAUSE_OPERAND (nc, 2)
> -	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 2), args, complain,
> -			   in_decl, /*integral_constant_expression_p=*/false);
> +	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 2), args, complain, in_decl);
>  	  break;
>  	case OMP_CLAUSE_LINEAR:
>  	  OMP_CLAUSE_DECL (nc)
> @@ -17918,9 +17882,8 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
>  					complain, in_decl, NULL);
>  	  else
>  	    OMP_CLAUSE_LINEAR_STEP (nc)
> -	      = tsubst_expr (OMP_CLAUSE_LINEAR_STEP (oc), args, complain,
> -			     in_decl,
> -			     /*integral_constant_expression_p=*/false);
> +	      = tsubst_expr (OMP_CLAUSE_LINEAR_STEP (oc), args,
> +			     complain, in_decl);
>  	  break;
>  	case OMP_CLAUSE_NOWAIT:
>  	case OMP_CLAUSE_DEFAULT:
> @@ -18045,8 +18008,7 @@ tsubst_copy_asm_operands (tree t, tree args, tsubst_flags_t complain,
>      return t;
>  
>    if (TREE_CODE (t) != TREE_LIST)
> -    return tsubst_copy_and_build (t, args, complain, in_decl,
> -				  /*integral_constant_expression_p=*/false);
> +    return tsubst_copy_and_build (t, args, complain, in_decl);
>  
>    if (t == void_list_node)
>      return t;
> @@ -18087,12 +18049,10 @@ static tree tsubst_decomp_names (tree, tree, tree, tsubst_flags_t, tree,
>  static bool
>  tsubst_omp_for_iterator (tree t, int i, tree declv, tree &orig_declv,
>  			 tree initv, tree condv, tree incrv, tree *clauses,
> -			 tree args, tsubst_flags_t complain, tree in_decl,
> -			 bool integral_constant_expression_p)
> +			 tree args, tsubst_flags_t complain, tree in_decl)
>  {
>  #define RECUR(NODE)				\
> -  tsubst_expr ((NODE), args, complain, in_decl,	\
> -	       integral_constant_expression_p)
> +  tsubst_expr ((NODE), args, complain, in_decl)
>    tree decl, init, cond = NULL_TREE, incr = NULL_TREE;
>    bool ret = false;
>  
> @@ -18580,13 +18540,11 @@ dependent_operand_p (tree t)
>     processing.  */
>  
>  tree
> -tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
> -	     bool integral_constant_expression_p)
> +tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>  {
>  #define RETURN(EXP) do { r = (EXP); goto out; } while(0)
>  #define RECUR(NODE)				\
> -  tsubst_expr ((NODE), args, complain, in_decl,	\
> -	       integral_constant_expression_p)
> +  tsubst_expr ((NODE), args, complain, in_decl)
>  
>    tree stmt, tmp;
>    tree r;
> @@ -19132,11 +19090,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
>  	tree condition;
>  
>  	++c_inhibit_evaluation_warnings;
> -	condition =
> -	  tsubst_expr (STATIC_ASSERT_CONDITION (t),
> -                       args,
> -                       complain, in_decl,
> -                       /*integral_constant_expression_p=*/true);
> +	condition = tsubst_expr (STATIC_ASSERT_CONDITION (t), args,
> +				 complain, in_decl);
>  	--c_inhibit_evaluation_warnings;
>  
>          finish_static_assert (condition,
> @@ -19232,8 +19187,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
>  	    any_range_for
>  	      |= tsubst_omp_for_iterator (t, i, declv, orig_declv, initv,
>  					  condv, incrv, &clauses, args,
> -					  complain, in_decl,
> -					  integral_constant_expression_p);
> +					  complain, in_decl);
>  	omp_parallel_combined_clauses = NULL;
>  
>  	if (any_range_for)
> @@ -19631,8 +19585,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
>      default:
>        gcc_assert (!STATEMENT_CODE_P (TREE_CODE (t)));
>  
> -      RETURN (tsubst_copy_and_build (t, args, complain, in_decl,
> -				    integral_constant_expression_p));
> +      RETURN (tsubst_copy_and_build (t, args, complain, in_decl));
>      }
>  
>    RETURN (NULL_TREE);
> @@ -19679,7 +19632,7 @@ tsubst_omp_udr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>        DECL_CONTEXT (omp_in) = current_function_decl;
>        keep_next_level (true);
>        tree block = begin_omp_structured_block ();
> -      tsubst_expr (stmts[2], args, complain, in_decl, false);
> +      tsubst_expr (stmts[2], args, complain, in_decl);
>        block = finish_omp_structured_block (block);
>        block = maybe_cleanup_point_expr_void (block);
>        add_decl_expr (omp_out);
> @@ -19699,7 +19652,7 @@ tsubst_omp_udr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>        DECL_CONTEXT (omp_orig) = current_function_decl;
>        keep_next_level (true);
>        tree block = begin_omp_structured_block ();
> -      tsubst_expr (stmts[5], args, complain, in_decl, false);
> +      tsubst_expr (stmts[5], args, complain, in_decl);
>        block = finish_omp_structured_block (block);
>        block = maybe_cleanup_point_expr_void (block);
>        cp_walk_tree (&block, cp_remove_omp_priv_cleanup_stmt, omp_priv, NULL);
> @@ -19723,8 +19676,7 @@ tsubst_non_call_postfix_expression (tree t, tree args,
>      t = tsubst_qualified_id (t, args, complain, in_decl,
>  			     /*done=*/false, /*address_p=*/false);
>    else
> -    t = tsubst_copy_and_build (t, args, complain, in_decl,
> -			       /*integral_constant_expression_p=*/false);
> +    t = tsubst_copy_and_build (t, args, complain, in_decl);
>  
>    return t;
>  }
> @@ -19795,8 +19747,7 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>        if (PACK_EXPANSION_P (init))
>  	init = tsubst_pack_expansion (init, args, complain, in_decl);
>        else
> -	init = tsubst_copy_and_build (init, args, complain, in_decl,
> -				      /*constexpr*/false);
> +	init = tsubst_copy_and_build (init, args, complain, in_decl);
>  
>        if (init == error_mark_node)
>  	return error_mark_node;
> @@ -19962,7 +19913,7 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>  	   need another to confuse NRV (91217).  */
>  	saved = BIND_EXPR_BODY (saved);
>  
> -      tsubst_expr (saved, args, complain, r, /*constexpr*/false);
> +      tsubst_expr (saved, args, complain, r);
>  
>        finish_lambda_function (body);
>  
> @@ -20053,7 +20004,6 @@ maybe_fold_fn_template_args (tree fn, tsubst_flags_t complain)
>  static void
>  tsubst_copy_and_build_call_args (tree t, tree args, tsubst_flags_t complain,
>  				 tree in_decl,
> -				 bool integral_constant_expression_p,
>  				 releasing_vec &call_args)
>  {
>    unsigned int nargs = call_expr_nargs (t);
> @@ -20063,8 +20013,7 @@ tsubst_copy_and_build_call_args (tree t, tree args, tsubst_flags_t complain,
>  
>        if (!PACK_EXPANSION_P (arg))
>  	vec_safe_push (call_args,
> -		       tsubst_copy_and_build (arg, args, complain, in_decl,
> -					      integral_constant_expression_p));
> +		       tsubst_copy_and_build (arg, args, complain, in_decl));
>        else
>  	{
>  	  /* Expand the pack expansion and push each entry onto CALL_ARGS.  */
> @@ -20093,16 +20042,11 @@ tsubst_copy_and_build_call_args (tree t, tree args, tsubst_flags_t complain,
>     analysis.  */
>  
>  tree
> -tsubst_copy_and_build (tree t,
> -		       tree args,
> -		       tsubst_flags_t complain,
> -		       tree in_decl,
> -		       bool integral_constant_expression_p)
> +tsubst_copy_and_build (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>  {
>  #define RETURN(EXP) do { retval = (EXP); goto out; } while(0)
>  #define RECUR(NODE)						\
> -  tsubst_copy_and_build (NODE, args, complain, in_decl, 	\
> -			 integral_constant_expression_p)
> +  tsubst_copy_and_build (NODE, args, complain, in_decl)
>  
>    tree retval, op1;
>    location_t save_loc;
> @@ -20128,7 +20072,6 @@ tsubst_copy_and_build (tree t,
>        {
>  	tree decl;
>  	cp_id_kind idk;
> -	bool non_integral_constant_expression_p;
>  	const char *error_msg;
>  
>  	if (IDENTIFIER_CONV_OP_P (t))
> @@ -20147,9 +20090,9 @@ tsubst_copy_and_build (tree t,
>  
>  	decl = finish_id_expression (t, decl, NULL_TREE,
>  				     &idk,
> -				     integral_constant_expression_p,
> -          /*allow_non_integral_constant_expression_p=*/(cxx_dialect >= cxx11),
> -				     &non_integral_constant_expression_p,
> +				     /*i_c_e_p=*/false,
> +				     /*allow_i_c_e_p=*/true,
> +				     /*non_i_c_e_p=*/nullptr,
>  				     /*template_p=*/false,
>  				     /*done=*/true,
>  				     /*address_p=*/false,
> @@ -20171,8 +20114,7 @@ tsubst_copy_and_build (tree t,
>        {
>  	tree object;
>  	tree templ = tsubst_copy_and_build (TREE_OPERAND (t, 0), args,
> -					    complain, in_decl,
> -					    integral_constant_expression_p);
> +					    complain, in_decl);
>  	tree targs = TREE_OPERAND (t, 1);
>  
>  	if (targs)
> @@ -20312,14 +20254,6 @@ tsubst_copy_and_build (tree t,
>  	if (TREE_CODE (t) == CAST_EXPR)
>  	  tcomplain |= tf_tst_ok;
>  	type = tsubst (TREE_TYPE (t), args, tcomplain, in_decl);
> -	if (integral_constant_expression_p
> -	    && !cast_valid_in_integral_constant_expression_p (type))
> -	  {
> -            if (complain & tf_error)
> -              error ("a cast to a type other than an integral or "
> -                     "enumeration type cannot appear in a constant-expression");
> -	    RETURN (error_mark_node);
> -	  }
>  
>  	op = RECUR (TREE_OPERAND (t, 0));
>  
> @@ -20504,7 +20438,6 @@ tsubst_copy_and_build (tree t,
>  	  tree c = TREE_OPERAND (t, 1);
>  	  releasing_vec index_exp_list;
>  	  tsubst_copy_and_build_call_args (c, args, complain, in_decl,
> -					   integral_constant_expression_p,
>  					   index_exp_list);
>  
>  	  tree r;
> @@ -20553,9 +20486,7 @@ tsubst_copy_and_build (tree t,
>  	    if (TYPE_P (op1))
>  	      op1 = tsubst (op1, args, complain, in_decl);
>  	    else
> -	      op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
> -					   /*integral_constant_expression_p=*/
> -					   false);
> +	      op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
>  	    --cp_unevaluated_operand;
>  	    --c_inhibit_evaluation_warnings;
>  	  }
> @@ -20592,8 +20523,7 @@ tsubst_copy_and_build (tree t,
>  	op1 = TREE_OPERAND (t, 0);
>  	++cp_unevaluated_operand;
>  	++c_inhibit_evaluation_warnings;
> -	op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
> -				     /*integral_constant_expression_p=*/false);
> +	op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
>  	--cp_unevaluated_operand;
>  	--c_inhibit_evaluation_warnings;
>  	RETURN (objc_build_encode_expr (op1));
> @@ -20604,8 +20534,7 @@ tsubst_copy_and_build (tree t,
>        ++cp_unevaluated_operand;
>        ++c_inhibit_evaluation_warnings;
>        ++cp_noexcept_operand;
> -      op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
> -				   /*integral_constant_expression_p=*/false);
> +      op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
>        --cp_unevaluated_operand;
>        --c_inhibit_evaluation_warnings;
>        --cp_noexcept_operand;
> @@ -20714,8 +20643,7 @@ tsubst_copy_and_build (tree t,
>      case COMPOUND_EXPR:
>        {
>  	tree op0 = tsubst_copy_and_build (TREE_OPERAND (t, 0), args,
> -					  complain & ~tf_decltype, in_decl,
> -					  integral_constant_expression_p);
> +					  complain & ~tf_decltype, in_decl);
>  	RETURN (build_x_compound_expr (EXPR_LOCATION (t),
>  				       op0,
>  				       RECUR (TREE_OPERAND (t, 1)),
> @@ -20796,9 +20724,7 @@ tsubst_copy_and_build (tree t,
>  		 augmenting the overload set via ADL, so during this initial
>  		 substitution we disable mark_used by setting tf_conv (68942).  */
>  	      subcomplain |= tf_conv;
> -	    function = tsubst_copy_and_build (function, args, subcomplain,
> -					      in_decl,
> -					      integral_constant_expression_p);
> +	    function = tsubst_copy_and_build (function, args, subcomplain, in_decl);
>  
>  	    if (BASELINK_P (function))
>  	      qualified_p = true;
> @@ -20807,7 +20733,6 @@ tsubst_copy_and_build (tree t,
>  	nargs = call_expr_nargs (t);
>  	releasing_vec call_args;
>  	tsubst_copy_and_build_call_args (t, args, complain, in_decl,
> -					 integral_constant_expression_p,
>  					 call_args);
>  
>  	/* Stripped-down processing for a call in a thunk.  Specifically, in
> @@ -20900,9 +20825,8 @@ tsubst_copy_and_build (tree t,
>  		/* For backwards compatibility and good diagnostics, try
>  		   the unqualified lookup again if we aren't in SFINAE
>  		   context.  */
> -		tree unq = (tsubst_copy_and_build
> -			    (function, args, complain, in_decl,
> -			     integral_constant_expression_p));
> +		tree unq = tsubst_copy_and_build (function, args,
> +						  complain, in_decl);
>  		if (unq == error_mark_node)
>  		  RETURN (error_mark_node);
>  
> @@ -21450,9 +21374,8 @@ tsubst_copy_and_build (tree t,
>      case OFFSETOF_EXPR:
>        {
>  	tree object_ptr
> -	  = tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
> -				   in_decl,
> -				   /*integral_constant_expression_p=*/false);
> +	  = tsubst_copy_and_build (TREE_OPERAND (t, 1), args,
> +				   complain, in_decl);
>  	RETURN (finish_offsetof (object_ptr,
>  				 RECUR (TREE_OPERAND (t, 0)),
>  				 EXPR_LOCATION (t)));
> @@ -21478,8 +21401,7 @@ tsubst_copy_and_build (tree t,
>  	tree stmt_expr = begin_stmt_expr ();
>  
>  	cur_stmt_expr = stmt_expr;
> -	tsubst_expr (STMT_EXPR_STMT (t), args, complain, in_decl,
> -		     integral_constant_expression_p);
> +	tsubst_expr (STMT_EXPR_STMT (t), args, complain, in_decl);
>  	stmt_expr = finish_stmt_expr (stmt_expr, false);
>  	cur_stmt_expr = old_stmt_expr;
>  
> @@ -21506,8 +21428,7 @@ tsubst_copy_and_build (tree t,
>        }
>  
>      case TRANSACTION_EXPR:
> -      RETURN (tsubst_expr(t, args, complain, in_decl,
> -	     integral_constant_expression_p));
> +      RETURN (tsubst_expr (t, args, complain, in_decl));
>  
>      case PAREN_EXPR:
>        if (REF_PARENTHESIZED_P (t))
> @@ -26369,8 +26290,7 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
>  	  /* Do deferred instantiation of the noexcept-specifier.  */
>  	  noex = tsubst_copy_and_build (DEFERRED_NOEXCEPT_PATTERN (noex),
>  					DEFERRED_NOEXCEPT_ARGS (noex),
> -					tf_warning_or_error, fn,
> -					/*i_c_e_p=*/true);
> +					tf_warning_or_error, fn);
>  
>  	  /* Build up the noexcept-specification.  */
>  	  spec = build_noexcept_spec (noex, tf_warning_or_error);
> @@ -26556,8 +26476,7 @@ instantiate_body (tree pattern, tree args, tree d, bool nested_p)
>        else
>  	{
>  	  tsubst_expr (DECL_SAVED_TREE (code_pattern), args,
> -		       tf_warning_or_error, DECL_TI_TEMPLATE (d),
> -		       /*integral_constant_expression_p=*/false);
> +		       tf_warning_or_error, DECL_TI_TEMPLATE (d));
>  
>  	  /* Set the current input_location to the end of the function
>  	     so that finish_function knows where we are.  */
> @@ -26798,8 +26717,7 @@ instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p)
>  	    push_nested_class (DECL_CONTEXT (d));
>  	  init = tsubst_expr (DECL_INITIAL (code_pattern),
>  			      args,
> -			      tf_warning_or_error, NULL_TREE,
> -			      /*integral_constant_expression_p=*/false);
> +			      tf_warning_or_error, NULL_TREE);
>  	  /* If instantiating the initializer involved instantiating this
>  	     again, don't call cp_finish_decl twice.  */
>  	  if (!DECL_INITIAL (d))
> @@ -27087,8 +27005,7 @@ tsubst_initializer_list (tree t, tree argvec)
>  	      tmp = init;
>  	      if (init != void_type_node)
>  		init = tsubst_expr (init, argvec,
> -				    tf_warning_or_error, NULL_TREE,
> -				    /*integral_constant_expression_p=*/false);
> +				    tf_warning_or_error, NULL_TREE);
>  	      if (init == NULL_TREE && tmp != NULL_TREE)
>  		/* If we had an initializer but it instantiated to nothing,
>  		   value-initialize the object.  This will only occur when
> @@ -27154,8 +27071,7 @@ tsubst_enum (tree tag, tree newtag, tree args)
>        /* Note that in a template enum, the TREE_VALUE is the
>  	 CONST_DECL, not the corresponding INTEGER_CST.  */
>        value = tsubst_expr (DECL_INITIAL (decl),
> -			   args, tf_warning_or_error, NULL_TREE,
> -			   /*integral_constant_expression_p=*/true);
> +			   args, tf_warning_or_error, NULL_TREE);
>  
>        /* Give this enumeration constant the correct access.  */
>        set_current_access_from_decl (decl);
> diff --git a/gcc/objcp/objcp-lang.cc b/gcc/objcp/objcp-lang.cc
> index 5f0e22942b8..fa754028773 100644
> --- a/gcc/objcp/objcp-lang.cc
> +++ b/gcc/objcp/objcp-lang.cc
> @@ -54,8 +54,7 @@ objcp_tsubst_copy_and_build (tree t, tree args, tsubst_flags_t complain,
>  			     tree in_decl)
>  {
>  #define RECURSE(NODE)							\
> -  tsubst_copy_and_build (NODE, args, complain, in_decl, 		\
> -			 /*integral_constant_expression_p=*/false)
> +  tsubst_copy_and_build (NODE, args, complain, in_decl)
>  
>    /* The following two can only occur in Objective-C++.  */
>  
> diff --git a/gcc/testsuite/g++.dg/template/crash55.C b/gcc/testsuite/g++.dg/template/crash55.C
> index 5416e32cacb..8a7fc112c19 100644
> --- a/gcc/testsuite/g++.dg/template/crash55.C
> +++ b/gcc/testsuite/g++.dg/template/crash55.C
> @@ -1,7 +1,6 @@
>  //PR c++/27668
>  
>  template<typename class T, T = T()> // { dg-error "nested-name-specifier|two or more|class type|incomplete" }
> -// { dg-error "cast" "" { target c++98_only } .-1 }
>  struct A {};
>  
> -template<int> void foo(A<int>);	// { dg-error "template argument 2" "" { target c++98_only } }
> +template<int> void foo(A<int>);
> diff --git a/gcc/testsuite/g++.dg/template/ref3.C b/gcc/testsuite/g++.dg/template/ref3.C
> index 91e3c93a35d..976c093a15b 100644
> --- a/gcc/testsuite/g++.dg/template/ref3.C
> +++ b/gcc/testsuite/g++.dg/template/ref3.C
> @@ -5,8 +5,7 @@ template<const int&> struct A {};
>  template<typename T> struct B
>  {
>    A<(T)0> b; // { dg-error "constant|not a valid" }
> -  A<T(0)> a; // { dg-error "constant|not a valid" "" { xfail c++98_only } }
> -                                                       // PR c++/68699
> +  A<T(0)> a; // { dg-error "constant|not a valid" }
>  };
>  
>  B<const int&> b;
> -- 
> 2.38.1.420.g319605f8f0
> 
>
  
Jason Merrill Nov. 14, 2022, 11:33 p.m. UTC | #2
On 11/10/22 09:56, Patrick Palka wrote:
> AFAICT the only purpose of tsubst_copy_and_build's
> integral_constant_expression_p boolean parameter is to diagnose certain
> constructs that aren't allowed to appear in a C++98 integral constant
> expression context, specifically casts to a non-integral type (diagnosed
> from the *_CAST_EXPR case of tsubst_copy_and_build) or dependent names
> that resolve to a non-constant decl (diagnosed from the IDENTIFIER_NODE
> case of tsubst_copy_and_build).  The parameter has no effect outside of
> C++98 AFAICT.
> 
> But diagnosing such constructs should arguably be done by
> is_constant_expression after substitution, and doing it during
> substitution by way of an additional parameter complicates the API of
> this workhouse function for functionality that's specific to C++98.
> And it seems is_constant_expression already does a good job of diagnosing
> the aforementioned two constructs in C++98 mode, at least as far as our
> testsuite is concerned.
> 
> So this patch gets rid of this parameter from tsubst_copy_and_build,
> tsubst_expr and tsubst_copy_and_build_call_args.  The only interesting
> changes are those to potential_constant_expression_1 and the
> IDENTIFIER_NODE and *_CAST_EXPR cases of tsubst_copy_and_build; the rest
> are mechanical adjustments to these functions and their call sites.
> 
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk?

OK.

> gcc/cp/ChangeLog:
> 
> 	* constexpr.cc (potential_constant_expression_1)
> 	<case *_CAST_EXPR>: Use
> 	cast_valid_in_integral_constant_expression_p instead of
> 	open coding it.
> 	* constraint.cc (tsubst_valid_expression_requirement): Adjust
> 	calls to tsubst_copy_and_build and tsubst_expr.
> 	(tsubst_constraint): Likewise.
> 	(satisfy_atom): Likewise.
> 	(diagnose_trait_expr): Likewise.
> 	* cp-tree.h (tsubst_copy_and_build): Remove i_c_e_p parameter.
> 	(tsubst_expr): Likewise.
> 	* init.cc (get_nsdmi): Adjust calls to tsubst_copy_and_build
> 	and tsubst_expr.
> 	* pt.cc (expand_integer_pack): Likewise.
> 	(instantiate_non_dependent_expr_internal): Likewise.
> 	(tsubst_friend_function): Likewise.
> 	(tsubst_attribute): Likewise.
> 	(instantiate_class_template): Likewise.
> 	(tsubst_template_arg): Likewise.
> 	(gen_elem_of_pack_expansion_instantiation): Likewise.
> 	(tsubst_fold_expr_init): Likewise.
> 	(tsubst_pack_expansion): Likewise.
> 	(tsubst_default_argument): Likewise.
> 	(tsubst_function_decl): Likewise.
> 	(tsubst_decl): Likewise.
> 	(tsubst_arg_types): Likewise.
> 	(tsubst_exception_specification): Likewise.
> 	(tsubst): Likewise.
> 	(tsubst_init): Likewise.
> 	(tsubst_copy): Likewise.
> 	(tsubst_omp_clause_decl): Likewise.
> 	(tsubst_omp_clauses): Likewise.
> 	(tsubst_copy_asm_operands): Likewise.
> 	(tsubst_omp_for_iterator): Likewise.
> 	(tsubst_expr): Likewise.  Remove i_c_e_p parameter.
> 	(tsubst_omp_udr): Likewise.
> 	(tsubst_non_call_postfix_expression): Likewise.  Remove i_c_e_p parameter.
> 	(tsubst_lambda_expr): Likewise.
> 	(tsubst_copy_and_build_call_args): Likewise.
> 	(tsubst_copy_and_build): Likewise.  Remove i_c_e_p parameter.
> 	<case IDENTIFIER_NODE>: Adjust call to finish_id_expression
> 	following removal of i_c_e_p.
> 	<case *_CAST_EXPR>: Remove C++98-specific cast validity check
> 	guarded by i_c_e_p.
> 	(maybe_instantiate_noexcept): Adjust calls to
> 	tsubst_copy_and_build and tsubst_expr.
> 	(instantiate_body): Likewise.
> 	(instantiate_decl): Likewise.
> 	(tsubst_initializer_list): Likewise.
> 	(tsubst_enum): Likewise.
> 
> gcc/objcp/ChangeLog:
> 
> 	* objcp-lang.cc (objcp_tsubst_copy_and_build): Likewise.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/template/crash55.C: Don't expect additional
> 	C++98-specific diagnostics.
> 	* g++.dg/template/ref3.C: Remove C++98-specific xfail.
> ---
>   gcc/cp/constexpr.cc                     |   4 +-
>   gcc/cp/constraint.cc                    |  14 +-
>   gcc/cp/cp-tree.h                        |   6 +-
>   gcc/cp/init.cc                          |   6 +-
>   gcc/cp/pt.cc                            | 240 ++++++++----------------
>   gcc/objcp/objcp-lang.cc                 |   3 +-
>   gcc/testsuite/g++.dg/template/crash55.C |   3 +-
>   gcc/testsuite/g++.dg/template/ref3.C    |   3 +-
>   8 files changed, 93 insertions(+), 186 deletions(-)
> 
> diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> index 15b4f2c4a08..e665839f5b1 100644
> --- a/gcc/cp/constexpr.cc
> +++ b/gcc/cp/constexpr.cc
> @@ -9460,9 +9460,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
>       case STATIC_CAST_EXPR:
>       case REINTERPRET_CAST_EXPR:
>       case IMPLICIT_CONV_EXPR:
> -      if (cxx_dialect < cxx11
> -	  && !dependent_type_p (TREE_TYPE (t))
> -	  && !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t)))
> +      if (!cast_valid_in_integral_constant_expression_p (TREE_TYPE (t)))
>   	/* In C++98, a conversion to non-integral type can't be part of a
>   	   constant expression.  */
>   	{
> diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> index f6ef078171a..3ddbd535330 100644
> --- a/gcc/cp/constraint.cc
> +++ b/gcc/cp/constraint.cc
> @@ -1921,7 +1921,7 @@ hash_placeholder_constraint (tree c)
>   static tree
>   tsubst_valid_expression_requirement (tree t, tree args, sat_info info)
>   {
> -  tree r = tsubst_expr (t, args, tf_none, info.in_decl, false);
> +  tree r = tsubst_expr (t, args, tf_none, info.in_decl);
>     if (convert_to_void (r, ICV_STATEMENT, tf_none) != error_mark_node)
>       return r;
>   
> @@ -1932,7 +1932,7 @@ tsubst_valid_expression_requirement (tree t, tree args, sat_info info)
>   	{
>   	  inform (loc, "the required expression %qE is invalid, because", t);
>   	  if (r == error_mark_node)
> -	    tsubst_expr (t, args, info.complain, info.in_decl, false);
> +	    tsubst_expr (t, args, info.complain, info.in_decl);
>   	  else
>   	    convert_to_void (r, ICV_STATEMENT, info.complain);
>   	}
> @@ -1941,7 +1941,7 @@ tsubst_valid_expression_requirement (tree t, tree args, sat_info info)
>       }
>     else if (info.noisy ())
>       {
> -      r = tsubst_expr (t, args, info.complain, info.in_decl, false);
> +      r = tsubst_expr (t, args, info.complain, info.in_decl);
>         convert_to_void (r, ICV_STATEMENT, info.complain);
>       }
>   
> @@ -2706,7 +2706,7 @@ tsubst_constraint (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>        constraint-expressions of a declaration.  */
>     processing_constraint_expression_sentinel s;
>     cp_unevaluated u;
> -  tree expr = tsubst_expr (t, args, complain, in_decl, false);
> +  tree expr = tsubst_expr (t, args, complain, in_decl);
>     return expr;
>   }
>   
> @@ -2954,13 +2954,13 @@ satisfy_atom (tree t, tree args, sat_info info)
>   
>     /* Apply the parameter mapping (i.e., just substitute).  */
>     tree expr = ATOMIC_CONSTR_EXPR (t);
> -  tree result = tsubst_expr (expr, args, quiet.complain, quiet.in_decl, false);
> +  tree result = tsubst_expr (expr, args, quiet.complain, quiet.in_decl);
>     if (result == error_mark_node)
>       {
>         /* If substitution results in an invalid type or expression, the constraint
>   	 is not satisfied. Replay the substitution.  */
>         if (info.diagnose_unsatisfaction_p ())
> -	tsubst_expr (expr, args, info.complain, info.in_decl, false);
> +	tsubst_expr (expr, args, info.complain, info.in_decl);
>         return cache.save (inst_cache.save (boolean_false_node));
>       }
>   
> @@ -3587,7 +3587,7 @@ diagnose_trait_expr (tree expr, tree args)
>     /* Build a "fake" version of the instantiated trait, so we can
>        get the instantiated types from result.  */
>     ++processing_template_decl;
> -  expr = tsubst_expr (expr, args, tf_none, NULL_TREE, false);
> +  expr = tsubst_expr (expr, args, tf_none, NULL_TREE);
>     --processing_template_decl;
>   
>     tree t1 = TRAIT_EXPR_TYPE1 (expr);
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index 40fd2e1ebb9..7ff3206e245 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -7382,10 +7382,8 @@ extern void instantiate_pending_templates	(int);
>   extern tree tsubst_default_argument		(tree, int, tree, tree,
>   						 tsubst_flags_t);
>   extern tree tsubst (tree, tree, tsubst_flags_t, tree);
> -extern tree tsubst_copy_and_build		(tree, tree, tsubst_flags_t,
> -						 tree, bool = false);
> -extern tree tsubst_expr                         (tree, tree, tsubst_flags_t,
> -                                                 tree, bool);
> +extern tree tsubst_copy_and_build		(tree, tree, tsubst_flags_t, tree);
> +extern tree tsubst_expr                         (tree, tree, tsubst_flags_t, tree);
>   extern tree tsubst_pack_expansion		(tree, tree, tsubst_flags_t, tree);
>   extern tree tsubst_argument_pack		(tree, tree, tsubst_flags_t, tree);
>   extern tree tsubst_template_args		(tree, tree, tsubst_flags_t, tree);
> diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
> index fee49090de7..2fff4ad2dc7 100644
> --- a/gcc/cp/init.cc
> +++ b/gcc/cp/init.cc
> @@ -620,10 +620,8 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)
>   	  start_lambda_scope (member);
>   
>   	  /* Do deferred instantiation of the NSDMI.  */
> -	  init = (tsubst_copy_and_build
> -		  (init, DECL_TI_ARGS (member),
> -		   complain, member,
> -		   /*integral_constant_expression_p=*/false));
> +	  init = tsubst_copy_and_build (init, DECL_TI_ARGS (member),
> +					complain, member);
>   	  init = digest_nsdmi_init (member, init, complain);
>   
>   	  finish_lambda_scope ();
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index bcc275f8b6e..e3d311b0a8b 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -3772,8 +3772,7 @@ expand_integer_pack (tree call, tree args, tsubst_flags_t complain,
>   		     tree in_decl)
>   {
>     tree ohi = CALL_EXPR_ARG (call, 0);
> -  tree hi = tsubst_copy_and_build (ohi, args, complain, in_decl,
> -				   true/*int_cst*/);
> +  tree hi = tsubst_copy_and_build (ohi, args, complain, in_decl);
>   
>     if (instantiation_dependent_expression_p (hi))
>       {
> @@ -6360,8 +6359,7 @@ instantiate_non_dependent_expr_internal (tree expr, tsubst_flags_t complain)
>     return tsubst_copy_and_build (expr,
>   				/*args=*/NULL_TREE,
>   				complain,
> -				/*in_decl=*/NULL_TREE,
> -				/*integral_constant_expression_p=*/true);
> +				/*in_decl=*/NULL_TREE);
>   }
>   
>   /* Instantiate the non-dependent expression EXPR.  */
> @@ -11195,8 +11193,7 @@ tsubst_friend_function (tree decl, tree args)
>   	 current class with same name.  */
>         push_nested_namespace (ns);
>         fns = tsubst_expr (DECL_TI_TEMPLATE (decl), args,
> -			 tf_warning_or_error, NULL_TREE,
> -			 /*integral_constant_expression_p=*/false);
> +			 tf_warning_or_error, NULL_TREE);
>         pop_nested_namespace (ns);
>         arglist = tsubst (DECL_TI_ARGS (decl), args,
>   			tf_warning_or_error, NULL_TREE);
> @@ -11609,9 +11606,7 @@ tsubst_attribute (tree t, tree *decl_p, tree args,
>   			      get_attribute_name (t)))
>       {
>         ++cp_unevaluated_operand;
> -      tree varid
> -	= tsubst_expr (TREE_PURPOSE (val), args, complain,
> -		       in_decl, /*integral_constant_expression_p=*/false);
> +      tree varid = tsubst_expr (TREE_PURPOSE (val), args, complain, in_decl);
>         --cp_unevaluated_operand;
>         tree chain = TREE_CHAIN (val);
>         location_t match_loc = cp_expr_loc_or_input_loc (TREE_PURPOSE (chain));
> @@ -11647,7 +11642,7 @@ tsubst_attribute (tree t, tree *decl_p, tree args,
>   			tree v = TREE_VALUE (t3);
>   			if (TREE_CODE (v) == STRING_CST && allow_string)
>   			  continue;
> -			v = tsubst_expr (v, args, complain, in_decl, true);
> +			v = tsubst_expr (v, args, complain, in_decl);
>   			v = fold_non_dependent_expr (v);
>   			if (!INTEGRAL_TYPE_P (TREE_TYPE (v))
>   			    || (TREE_PURPOSE (t3) == score
> @@ -11693,8 +11688,7 @@ tsubst_attribute (tree t, tree *decl_p, tree args,
>     else if (attribute_takes_identifier_p (get_attribute_name (t)))
>       {
>         tree chain
> -	= tsubst_expr (TREE_CHAIN (val), args, complain, in_decl,
> -		       /*integral_constant_expression_p=*/false);
> +	= tsubst_expr (TREE_CHAIN (val), args, complain, in_decl);
>         if (chain != TREE_CHAIN (val))
>   	val = tree_cons (NULL_TREE, TREE_VALUE (val), chain);
>       }
> @@ -11717,8 +11711,7 @@ tsubst_attribute (tree t, tree *decl_p, tree args,
>         return list;
>       }
>     else
> -    val = tsubst_expr (val, args, complain, in_decl,
> -		       /*integral_constant_expression_p=*/false);
> +    val = tsubst_expr (val, args, complain, in_decl);
>   
>     if (val == error_mark_node)
>       return error_mark_node;
> @@ -12160,8 +12153,7 @@ instantiate_class_template (tree type)
>   	    {
>   	      /* Build new TYPE_FIELDS.  */
>                 if (TREE_CODE (t) == STATIC_ASSERT)
> -		tsubst_expr (t, args, tf_warning_or_error, NULL_TREE,
> -			     /*integral_constant_expression_p=*/true);
> +		tsubst_expr (t, args, tf_warning_or_error, NULL_TREE);
>   	      else if (TREE_CODE (t) != CONST_DECL)
>   		{
>   		  tree r;
> @@ -12418,8 +12410,7 @@ tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>       {
>         if (!(complain & tf_warning))
>   	++c_inhibit_evaluation_warnings;
> -      r = tsubst_expr (t, args, complain, in_decl,
> -		       /*integral_constant_expression_p=*/true);
> +      r = tsubst_expr (t, args, complain, in_decl);
>         if (!(complain & tf_warning))
>   	--c_inhibit_evaluation_warnings;
>       }
> @@ -12683,8 +12674,7 @@ gen_elem_of_pack_expansion_instantiation (tree pattern,
>     else if (pattern == error_mark_node)
>       t = error_mark_node;
>     else if (!TYPE_P (pattern))
> -    t = tsubst_expr (pattern, args, complain, in_decl,
> -		     /*integral_constant_expression_p=*/false);
> +    t = tsubst_expr (pattern, args, complain, in_decl);
>     else
>       {
>         t = tsubst (pattern, args, complain, in_decl);
> @@ -12778,7 +12768,7 @@ tsubst_fold_expr_pack (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>   static inline tree
>   tsubst_fold_expr_init (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>   {
> -  return tsubst_expr (FOLD_EXPR_INIT (t), args, complain, in_decl, false);
> +  return tsubst_expr (FOLD_EXPR_INIT (t), args, complain, in_decl);
>   }
>   
>   /* Expand a PACK of arguments into a grouped as left fold.
> @@ -13147,12 +13137,12 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
>   	  if (BASES_DIRECT (parm_pack))
>   	    return calculate_direct_bases (tsubst_expr (BASES_TYPE (parm_pack),
>   							args, complain,
> -							in_decl, false),
> +							in_decl),
>   					   complain);
>   	  else
>   	    return calculate_bases (tsubst_expr (BASES_TYPE (parm_pack),
> -						 args, complain, in_decl,
> -						 false), complain);
> +						 args, complain, in_decl),
> +				    complain);
>   	}
>         else if (builtin_pack_call_p (parm_pack))
>   	{
> @@ -13326,8 +13316,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
>   	 pattern and return a PACK_EXPANSION_*. The caller will need to
>   	 deal with that.  */
>         if (TREE_CODE (t) == EXPR_PACK_EXPANSION)
> -	result = tsubst_expr (pattern, args, complain, in_decl,
> -			 /*integral_constant_expression_p=*/false);
> +	result = tsubst_expr (pattern, args, complain, in_decl);
>         else
>   	result = tsubst (pattern, args, complain, in_decl);
>         result = make_pack_expansion (result, complain);
> @@ -13901,9 +13890,7 @@ tsubst_default_argument (tree fn, int parmnum, tree type, tree arg,
>        the body of function so as to avoid collecting live data on the
>        stack.  */
>     ++function_depth;
> -  arg = tsubst_expr (arg, DECL_TI_ARGS (fn),
> -		     complain, NULL_TREE,
> -		     /*integral_constant_expression_p=*/false);
> +  arg = tsubst_expr (arg, DECL_TI_ARGS (fn), complain, NULL_TREE);
>     --function_depth;
>   
>     finish_lambda_scope ();
> @@ -14208,8 +14195,7 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain,
>     if (DECL_HAS_DEPENDENT_EXPLICIT_SPEC_P (t))
>       {
>         tree spec = lookup_explicit_specifier (t);
> -      spec = tsubst_copy_and_build (spec, args, complain, in_decl,
> -				    /*i_c_e_p=*/true);
> +      spec = tsubst_copy_and_build (spec, args, complain, in_decl);
>         spec = build_explicit_specifier (spec, complain);
>         if (spec == error_mark_node)
>   	return error_mark_node;
> @@ -14821,8 +14807,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
>   		 number of bits.  */
>   	      DECL_BIT_FIELD_REPRESENTATIVE (r)
>   		= tsubst_expr (DECL_BIT_FIELD_REPRESENTATIVE (t), args,
> -			       complain, in_decl,
> -			       /*integral_constant_expression_p=*/true);
> +			       complain, in_decl);
>   	    if (DECL_INITIAL (t))
>   	      {
>   		/* Set up DECL_TEMPLATE_INFO so that we can get at the
> @@ -15074,8 +15059,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
>   		bool nop = (TREE_CODE (ve) == NOP_EXPR);
>   		if (nop)
>   		  ve = TREE_OPERAND (ve, 0);
> -		ve = tsubst_expr (ve, args, complain, in_decl,
> -				  /*constant_expression_p=*/false);
> +		ve = tsubst_expr (ve, args, complain, in_decl);
>   		if (REFERENCE_REF_P (ve))
>   		  {
>   		    gcc_assert (TYPE_REF_P (type));
> @@ -15273,8 +15257,7 @@ tsubst_arg_types (tree arg_types,
>     if (lambda_fn_in_template_p (in_decl)
>         || (in_decl && TREE_CODE (in_decl) == FUNCTION_DECL
>   	  && DECL_LOCAL_DECL_P (in_decl)))
> -    default_arg = tsubst_copy_and_build (default_arg, args, complain, in_decl,
> -					 false/*constexpr*/);
> +    default_arg = tsubst_copy_and_build (default_arg, args, complain, in_decl);
>   
>     tree remaining_arg_types = tsubst_arg_types (TREE_CHAIN (arg_types),
>   					       args, end, complain, in_decl);
> @@ -15455,9 +15438,7 @@ tsubst_exception_specification (tree fntype,
>   					   args);
>   	      expr = DEFERRED_NOEXCEPT_PATTERN (expr);
>   	    }
> -	  new_specs = tsubst_copy_and_build
> -	    (expr, args, complain, in_decl,
> -	     /*integral_constant_expression_p=*/true);
> +	  new_specs = tsubst_copy_and_build (expr, args, complain, in_decl);
>   	}
>         new_specs = build_noexcept_spec (new_specs, complain);
>         /* We've instantiated a template before a noexcept-specifier
> @@ -15764,8 +15745,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>         {
>   	tree max, omax = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);
>   
> -	max = tsubst_expr (omax, args, complain, in_decl,
> -			   /*integral_constant_expression_p=*/false);
> +	max = tsubst_expr (omax, args, complain, in_decl);
>   
>   	/* Fix up type of the magic NOP_EXPR with TREE_SIDE_EFFECTS if
>   	   needed.  */
> @@ -16358,9 +16338,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>   	++cp_unevaluated_operand;
>   	++c_inhibit_evaluation_warnings;
>   
> -	type = tsubst_expr (TYPEOF_TYPE_EXPR (t), args,
> -			    complain, in_decl,
> -			    /*integral_constant_expression_p=*/false);
> +	type = tsubst_expr (TYPEOF_TYPE_EXPR (t), args, complain, in_decl);
>   
>   	--cp_unevaluated_operand;
>   	--c_inhibit_evaluation_warnings;
> @@ -16380,8 +16358,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>   	++c_inhibit_evaluation_warnings;
>   
>   	type = tsubst_copy_and_build (DECLTYPE_TYPE_EXPR (t), args,
> -				      complain|tf_decltype, in_decl,
> -				      /*integral_constant_expression*/false);
> +				      complain|tf_decltype, in_decl);
>   
>   	--cp_unevaluated_operand;
>   	--c_inhibit_evaluation_warnings;
> @@ -16840,7 +16817,7 @@ tsubst_init (tree init, tree decl, tree args,
>     if (!init)
>       return NULL_TREE;
>   
> -  init = tsubst_expr (init, args, complain, in_decl, false);
> +  init = tsubst_expr (init, args, complain, in_decl);
>   
>     tree type = TREE_TYPE (decl);
>   
> @@ -17677,9 +17654,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>         return t;
>   
>       case CO_AWAIT_EXPR:
> -      return tsubst_expr (t, args, complain, in_decl,
> -			  /*integral_constant_expression_p=*/false);
> -      break;
> +      return tsubst_expr (t, args, complain, in_decl);
>   
>       default:
>         /* We shouldn't get here, but keep going if !flag_checking.  */
> @@ -17719,14 +17694,11 @@ tsubst_omp_clause_decl (tree decl, tree args, tsubst_flags_t complain,
>   	      DECL_CONTEXT (TREE_VEC_ELT (*tp, 0)) = current_function_decl;
>   	      pushdecl (TREE_VEC_ELT (*tp, 0));
>   	      TREE_VEC_ELT (*tp, 1)
> -		= tsubst_expr (TREE_VEC_ELT (it, 1), args, complain, in_decl,
> -			       /*integral_constant_expression_p=*/false);
> +		= tsubst_expr (TREE_VEC_ELT (it, 1), args, complain, in_decl);
>   	      TREE_VEC_ELT (*tp, 2)
> -		= tsubst_expr (TREE_VEC_ELT (it, 2), args, complain, in_decl,
> -			       /*integral_constant_expression_p=*/false);
> +		= tsubst_expr (TREE_VEC_ELT (it, 2), args, complain, in_decl);
>   	      TREE_VEC_ELT (*tp, 3)
> -		= tsubst_expr (TREE_VEC_ELT (it, 3), args, complain, in_decl,
> -			       /*integral_constant_expression_p=*/false);
> +		= tsubst_expr (TREE_VEC_ELT (it, 3), args, complain, in_decl);
>   	      TREE_CHAIN (*tp) = NULL_TREE;
>   	      tp = &TREE_CHAIN (*tp);
>   	    }
> @@ -17748,10 +17720,8 @@ tsubst_omp_clause_decl (tree decl, tree args, tsubst_flags_t complain,
>     if (TREE_CODE (decl) == TREE_LIST)
>       {
>         tree low_bound
> -	= tsubst_expr (TREE_PURPOSE (decl), args, complain, in_decl,
> -		       /*integral_constant_expression_p=*/false);
> -      tree length = tsubst_expr (TREE_VALUE (decl), args, complain, in_decl,
> -				 /*integral_constant_expression_p=*/false);
> +	= tsubst_expr (TREE_PURPOSE (decl), args, complain, in_decl);
> +      tree length = tsubst_expr (TREE_VALUE (decl), args, complain, in_decl);
>         tree chain = tsubst_omp_clause_decl (TREE_CHAIN (decl), args, complain,
>   					   in_decl, NULL);
>         if (TREE_PURPOSE (decl) == low_bound
> @@ -17763,8 +17733,7 @@ tsubst_omp_clause_decl (tree decl, tree args, tsubst_flags_t complain,
>   	= OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (decl);
>         return ret;
>       }
> -  tree ret = tsubst_expr (decl, args, complain, in_decl,
> -			  /*integral_constant_expression_p=*/false);
> +  tree ret = tsubst_expr (decl, args, complain, in_decl);
>     /* Undo convert_from_reference tsubst_expr could have called.  */
>     if (decl
>         && REFERENCE_REF_P (ret)
> @@ -17795,8 +17764,8 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
>   	  if (OMP_CLAUSE_LASTPRIVATE_STMT (oc))
>   	    {
>   	      OMP_CLAUSE_LASTPRIVATE_STMT (nc) = push_stmt_list ();
> -	      tsubst_expr (OMP_CLAUSE_LASTPRIVATE_STMT (oc), args, complain,
> -			   in_decl, /*integral_constant_expression_p=*/false);
> +	      tsubst_expr (OMP_CLAUSE_LASTPRIVATE_STMT (oc), args,
> +			   complain, in_decl);
>   	      OMP_CLAUSE_LASTPRIVATE_STMT (nc)
>   		= pop_stmt_list (OMP_CLAUSE_LASTPRIVATE_STMT (nc));
>   	    }
> @@ -17829,8 +17798,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
>   	  if (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (oc))
>   	    OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (nc)
>   	      = tsubst_expr (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (oc), args,
> -			     complain, in_decl,
> -			     /*integral_constant_expression_p=*/false);
> +			     complain, in_decl);
>   	  /* FALLTHRU */
>   	case OMP_CLAUSE_TILE:
>   	case OMP_CLAUSE_IF:
> @@ -17858,8 +17826,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
>   	case OMP_CLAUSE_WAIT:
>   	case OMP_CLAUSE_DETACH:
>   	  OMP_CLAUSE_OPERAND (nc, 0)
> -	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
> -			   in_decl, /*integral_constant_expression_p=*/false);
> +	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain, in_decl);
>   	  break;
>   	case OMP_CLAUSE_REDUCTION:
>   	case OMP_CLAUSE_IN_REDUCTION:
> @@ -17889,19 +17856,16 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
>   	    = tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
>   				      in_decl, NULL);
>   	  OMP_CLAUSE_OPERAND (nc, 1)
> -	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain,
> -			   in_decl, /*integral_constant_expression_p=*/false);
> +	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain, in_decl);
>   	  break;
>   	case OMP_CLAUSE_ALLOCATE:
>   	  OMP_CLAUSE_DECL (nc)
>   	    = tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
>   				      in_decl, NULL);
>   	  OMP_CLAUSE_OPERAND (nc, 1)
> -	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain,
> -			   in_decl, /*integral_constant_expression_p=*/false);
> +	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain, in_decl);
>   	  OMP_CLAUSE_OPERAND (nc, 2)
> -	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 2), args, complain,
> -			   in_decl, /*integral_constant_expression_p=*/false);
> +	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 2), args, complain, in_decl);
>   	  break;
>   	case OMP_CLAUSE_LINEAR:
>   	  OMP_CLAUSE_DECL (nc)
> @@ -17918,9 +17882,8 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
>   					complain, in_decl, NULL);
>   	  else
>   	    OMP_CLAUSE_LINEAR_STEP (nc)
> -	      = tsubst_expr (OMP_CLAUSE_LINEAR_STEP (oc), args, complain,
> -			     in_decl,
> -			     /*integral_constant_expression_p=*/false);
> +	      = tsubst_expr (OMP_CLAUSE_LINEAR_STEP (oc), args,
> +			     complain, in_decl);
>   	  break;
>   	case OMP_CLAUSE_NOWAIT:
>   	case OMP_CLAUSE_DEFAULT:
> @@ -18045,8 +18008,7 @@ tsubst_copy_asm_operands (tree t, tree args, tsubst_flags_t complain,
>       return t;
>   
>     if (TREE_CODE (t) != TREE_LIST)
> -    return tsubst_copy_and_build (t, args, complain, in_decl,
> -				  /*integral_constant_expression_p=*/false);
> +    return tsubst_copy_and_build (t, args, complain, in_decl);
>   
>     if (t == void_list_node)
>       return t;
> @@ -18087,12 +18049,10 @@ static tree tsubst_decomp_names (tree, tree, tree, tsubst_flags_t, tree,
>   static bool
>   tsubst_omp_for_iterator (tree t, int i, tree declv, tree &orig_declv,
>   			 tree initv, tree condv, tree incrv, tree *clauses,
> -			 tree args, tsubst_flags_t complain, tree in_decl,
> -			 bool integral_constant_expression_p)
> +			 tree args, tsubst_flags_t complain, tree in_decl)
>   {
>   #define RECUR(NODE)				\
> -  tsubst_expr ((NODE), args, complain, in_decl,	\
> -	       integral_constant_expression_p)
> +  tsubst_expr ((NODE), args, complain, in_decl)
>     tree decl, init, cond = NULL_TREE, incr = NULL_TREE;
>     bool ret = false;
>   
> @@ -18580,13 +18540,11 @@ dependent_operand_p (tree t)
>      processing.  */
>   
>   tree
> -tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
> -	     bool integral_constant_expression_p)
> +tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>   {
>   #define RETURN(EXP) do { r = (EXP); goto out; } while(0)
>   #define RECUR(NODE)				\
> -  tsubst_expr ((NODE), args, complain, in_decl,	\
> -	       integral_constant_expression_p)
> +  tsubst_expr ((NODE), args, complain, in_decl)
>   
>     tree stmt, tmp;
>     tree r;
> @@ -19132,11 +19090,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
>   	tree condition;
>   
>   	++c_inhibit_evaluation_warnings;
> -	condition =
> -	  tsubst_expr (STATIC_ASSERT_CONDITION (t),
> -                       args,
> -                       complain, in_decl,
> -                       /*integral_constant_expression_p=*/true);
> +	condition = tsubst_expr (STATIC_ASSERT_CONDITION (t), args,
> +				 complain, in_decl);
>   	--c_inhibit_evaluation_warnings;
>   
>           finish_static_assert (condition,
> @@ -19232,8 +19187,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
>   	    any_range_for
>   	      |= tsubst_omp_for_iterator (t, i, declv, orig_declv, initv,
>   					  condv, incrv, &clauses, args,
> -					  complain, in_decl,
> -					  integral_constant_expression_p);
> +					  complain, in_decl);
>   	omp_parallel_combined_clauses = NULL;
>   
>   	if (any_range_for)
> @@ -19631,8 +19585,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
>       default:
>         gcc_assert (!STATEMENT_CODE_P (TREE_CODE (t)));
>   
> -      RETURN (tsubst_copy_and_build (t, args, complain, in_decl,
> -				    integral_constant_expression_p));
> +      RETURN (tsubst_copy_and_build (t, args, complain, in_decl));
>       }
>   
>     RETURN (NULL_TREE);
> @@ -19679,7 +19632,7 @@ tsubst_omp_udr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>         DECL_CONTEXT (omp_in) = current_function_decl;
>         keep_next_level (true);
>         tree block = begin_omp_structured_block ();
> -      tsubst_expr (stmts[2], args, complain, in_decl, false);
> +      tsubst_expr (stmts[2], args, complain, in_decl);
>         block = finish_omp_structured_block (block);
>         block = maybe_cleanup_point_expr_void (block);
>         add_decl_expr (omp_out);
> @@ -19699,7 +19652,7 @@ tsubst_omp_udr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>         DECL_CONTEXT (omp_orig) = current_function_decl;
>         keep_next_level (true);
>         tree block = begin_omp_structured_block ();
> -      tsubst_expr (stmts[5], args, complain, in_decl, false);
> +      tsubst_expr (stmts[5], args, complain, in_decl);
>         block = finish_omp_structured_block (block);
>         block = maybe_cleanup_point_expr_void (block);
>         cp_walk_tree (&block, cp_remove_omp_priv_cleanup_stmt, omp_priv, NULL);
> @@ -19723,8 +19676,7 @@ tsubst_non_call_postfix_expression (tree t, tree args,
>       t = tsubst_qualified_id (t, args, complain, in_decl,
>   			     /*done=*/false, /*address_p=*/false);
>     else
> -    t = tsubst_copy_and_build (t, args, complain, in_decl,
> -			       /*integral_constant_expression_p=*/false);
> +    t = tsubst_copy_and_build (t, args, complain, in_decl);
>   
>     return t;
>   }
> @@ -19795,8 +19747,7 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>         if (PACK_EXPANSION_P (init))
>   	init = tsubst_pack_expansion (init, args, complain, in_decl);
>         else
> -	init = tsubst_copy_and_build (init, args, complain, in_decl,
> -				      /*constexpr*/false);
> +	init = tsubst_copy_and_build (init, args, complain, in_decl);
>   
>         if (init == error_mark_node)
>   	return error_mark_node;
> @@ -19962,7 +19913,7 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>   	   need another to confuse NRV (91217).  */
>   	saved = BIND_EXPR_BODY (saved);
>   
> -      tsubst_expr (saved, args, complain, r, /*constexpr*/false);
> +      tsubst_expr (saved, args, complain, r);
>   
>         finish_lambda_function (body);
>   
> @@ -20053,7 +20004,6 @@ maybe_fold_fn_template_args (tree fn, tsubst_flags_t complain)
>   static void
>   tsubst_copy_and_build_call_args (tree t, tree args, tsubst_flags_t complain,
>   				 tree in_decl,
> -				 bool integral_constant_expression_p,
>   				 releasing_vec &call_args)
>   {
>     unsigned int nargs = call_expr_nargs (t);
> @@ -20063,8 +20013,7 @@ tsubst_copy_and_build_call_args (tree t, tree args, tsubst_flags_t complain,
>   
>         if (!PACK_EXPANSION_P (arg))
>   	vec_safe_push (call_args,
> -		       tsubst_copy_and_build (arg, args, complain, in_decl,
> -					      integral_constant_expression_p));
> +		       tsubst_copy_and_build (arg, args, complain, in_decl));
>         else
>   	{
>   	  /* Expand the pack expansion and push each entry onto CALL_ARGS.  */
> @@ -20093,16 +20042,11 @@ tsubst_copy_and_build_call_args (tree t, tree args, tsubst_flags_t complain,
>      analysis.  */
>   
>   tree
> -tsubst_copy_and_build (tree t,
> -		       tree args,
> -		       tsubst_flags_t complain,
> -		       tree in_decl,
> -		       bool integral_constant_expression_p)
> +tsubst_copy_and_build (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>   {
>   #define RETURN(EXP) do { retval = (EXP); goto out; } while(0)
>   #define RECUR(NODE)						\
> -  tsubst_copy_and_build (NODE, args, complain, in_decl, 	\
> -			 integral_constant_expression_p)
> +  tsubst_copy_and_build (NODE, args, complain, in_decl)
>   
>     tree retval, op1;
>     location_t save_loc;
> @@ -20128,7 +20072,6 @@ tsubst_copy_and_build (tree t,
>         {
>   	tree decl;
>   	cp_id_kind idk;
> -	bool non_integral_constant_expression_p;
>   	const char *error_msg;
>   
>   	if (IDENTIFIER_CONV_OP_P (t))
> @@ -20147,9 +20090,9 @@ tsubst_copy_and_build (tree t,
>   
>   	decl = finish_id_expression (t, decl, NULL_TREE,
>   				     &idk,
> -				     integral_constant_expression_p,
> -          /*allow_non_integral_constant_expression_p=*/(cxx_dialect >= cxx11),
> -				     &non_integral_constant_expression_p,
> +				     /*i_c_e_p=*/false,
> +				     /*allow_i_c_e_p=*/true,
> +				     /*non_i_c_e_p=*/nullptr,
>   				     /*template_p=*/false,
>   				     /*done=*/true,
>   				     /*address_p=*/false,
> @@ -20171,8 +20114,7 @@ tsubst_copy_and_build (tree t,
>         {
>   	tree object;
>   	tree templ = tsubst_copy_and_build (TREE_OPERAND (t, 0), args,
> -					    complain, in_decl,
> -					    integral_constant_expression_p);
> +					    complain, in_decl);
>   	tree targs = TREE_OPERAND (t, 1);
>   
>   	if (targs)
> @@ -20312,14 +20254,6 @@ tsubst_copy_and_build (tree t,
>   	if (TREE_CODE (t) == CAST_EXPR)
>   	  tcomplain |= tf_tst_ok;
>   	type = tsubst (TREE_TYPE (t), args, tcomplain, in_decl);
> -	if (integral_constant_expression_p
> -	    && !cast_valid_in_integral_constant_expression_p (type))
> -	  {
> -            if (complain & tf_error)
> -              error ("a cast to a type other than an integral or "
> -                     "enumeration type cannot appear in a constant-expression");
> -	    RETURN (error_mark_node);
> -	  }
>   
>   	op = RECUR (TREE_OPERAND (t, 0));
>   
> @@ -20504,7 +20438,6 @@ tsubst_copy_and_build (tree t,
>   	  tree c = TREE_OPERAND (t, 1);
>   	  releasing_vec index_exp_list;
>   	  tsubst_copy_and_build_call_args (c, args, complain, in_decl,
> -					   integral_constant_expression_p,
>   					   index_exp_list);
>   
>   	  tree r;
> @@ -20553,9 +20486,7 @@ tsubst_copy_and_build (tree t,
>   	    if (TYPE_P (op1))
>   	      op1 = tsubst (op1, args, complain, in_decl);
>   	    else
> -	      op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
> -					   /*integral_constant_expression_p=*/
> -					   false);
> +	      op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
>   	    --cp_unevaluated_operand;
>   	    --c_inhibit_evaluation_warnings;
>   	  }
> @@ -20592,8 +20523,7 @@ tsubst_copy_and_build (tree t,
>   	op1 = TREE_OPERAND (t, 0);
>   	++cp_unevaluated_operand;
>   	++c_inhibit_evaluation_warnings;
> -	op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
> -				     /*integral_constant_expression_p=*/false);
> +	op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
>   	--cp_unevaluated_operand;
>   	--c_inhibit_evaluation_warnings;
>   	RETURN (objc_build_encode_expr (op1));
> @@ -20604,8 +20534,7 @@ tsubst_copy_and_build (tree t,
>         ++cp_unevaluated_operand;
>         ++c_inhibit_evaluation_warnings;
>         ++cp_noexcept_operand;
> -      op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
> -				   /*integral_constant_expression_p=*/false);
> +      op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
>         --cp_unevaluated_operand;
>         --c_inhibit_evaluation_warnings;
>         --cp_noexcept_operand;
> @@ -20714,8 +20643,7 @@ tsubst_copy_and_build (tree t,
>       case COMPOUND_EXPR:
>         {
>   	tree op0 = tsubst_copy_and_build (TREE_OPERAND (t, 0), args,
> -					  complain & ~tf_decltype, in_decl,
> -					  integral_constant_expression_p);
> +					  complain & ~tf_decltype, in_decl);
>   	RETURN (build_x_compound_expr (EXPR_LOCATION (t),
>   				       op0,
>   				       RECUR (TREE_OPERAND (t, 1)),
> @@ -20796,9 +20724,7 @@ tsubst_copy_and_build (tree t,
>   		 augmenting the overload set via ADL, so during this initial
>   		 substitution we disable mark_used by setting tf_conv (68942).  */
>   	      subcomplain |= tf_conv;
> -	    function = tsubst_copy_and_build (function, args, subcomplain,
> -					      in_decl,
> -					      integral_constant_expression_p);
> +	    function = tsubst_copy_and_build (function, args, subcomplain, in_decl);
>   
>   	    if (BASELINK_P (function))
>   	      qualified_p = true;
> @@ -20807,7 +20733,6 @@ tsubst_copy_and_build (tree t,
>   	nargs = call_expr_nargs (t);
>   	releasing_vec call_args;
>   	tsubst_copy_and_build_call_args (t, args, complain, in_decl,
> -					 integral_constant_expression_p,
>   					 call_args);
>   
>   	/* Stripped-down processing for a call in a thunk.  Specifically, in
> @@ -20900,9 +20825,8 @@ tsubst_copy_and_build (tree t,
>   		/* For backwards compatibility and good diagnostics, try
>   		   the unqualified lookup again if we aren't in SFINAE
>   		   context.  */
> -		tree unq = (tsubst_copy_and_build
> -			    (function, args, complain, in_decl,
> -			     integral_constant_expression_p));
> +		tree unq = tsubst_copy_and_build (function, args,
> +						  complain, in_decl);
>   		if (unq == error_mark_node)
>   		  RETURN (error_mark_node);
>   
> @@ -21450,9 +21374,8 @@ tsubst_copy_and_build (tree t,
>       case OFFSETOF_EXPR:
>         {
>   	tree object_ptr
> -	  = tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
> -				   in_decl,
> -				   /*integral_constant_expression_p=*/false);
> +	  = tsubst_copy_and_build (TREE_OPERAND (t, 1), args,
> +				   complain, in_decl);
>   	RETURN (finish_offsetof (object_ptr,
>   				 RECUR (TREE_OPERAND (t, 0)),
>   				 EXPR_LOCATION (t)));
> @@ -21478,8 +21401,7 @@ tsubst_copy_and_build (tree t,
>   	tree stmt_expr = begin_stmt_expr ();
>   
>   	cur_stmt_expr = stmt_expr;
> -	tsubst_expr (STMT_EXPR_STMT (t), args, complain, in_decl,
> -		     integral_constant_expression_p);
> +	tsubst_expr (STMT_EXPR_STMT (t), args, complain, in_decl);
>   	stmt_expr = finish_stmt_expr (stmt_expr, false);
>   	cur_stmt_expr = old_stmt_expr;
>   
> @@ -21506,8 +21428,7 @@ tsubst_copy_and_build (tree t,
>         }
>   
>       case TRANSACTION_EXPR:
> -      RETURN (tsubst_expr(t, args, complain, in_decl,
> -	     integral_constant_expression_p));
> +      RETURN (tsubst_expr (t, args, complain, in_decl));
>   
>       case PAREN_EXPR:
>         if (REF_PARENTHESIZED_P (t))
> @@ -26369,8 +26290,7 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
>   	  /* Do deferred instantiation of the noexcept-specifier.  */
>   	  noex = tsubst_copy_and_build (DEFERRED_NOEXCEPT_PATTERN (noex),
>   					DEFERRED_NOEXCEPT_ARGS (noex),
> -					tf_warning_or_error, fn,
> -					/*i_c_e_p=*/true);
> +					tf_warning_or_error, fn);
>   
>   	  /* Build up the noexcept-specification.  */
>   	  spec = build_noexcept_spec (noex, tf_warning_or_error);
> @@ -26556,8 +26476,7 @@ instantiate_body (tree pattern, tree args, tree d, bool nested_p)
>         else
>   	{
>   	  tsubst_expr (DECL_SAVED_TREE (code_pattern), args,
> -		       tf_warning_or_error, DECL_TI_TEMPLATE (d),
> -		       /*integral_constant_expression_p=*/false);
> +		       tf_warning_or_error, DECL_TI_TEMPLATE (d));
>   
>   	  /* Set the current input_location to the end of the function
>   	     so that finish_function knows where we are.  */
> @@ -26798,8 +26717,7 @@ instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p)
>   	    push_nested_class (DECL_CONTEXT (d));
>   	  init = tsubst_expr (DECL_INITIAL (code_pattern),
>   			      args,
> -			      tf_warning_or_error, NULL_TREE,
> -			      /*integral_constant_expression_p=*/false);
> +			      tf_warning_or_error, NULL_TREE);
>   	  /* If instantiating the initializer involved instantiating this
>   	     again, don't call cp_finish_decl twice.  */
>   	  if (!DECL_INITIAL (d))
> @@ -27087,8 +27005,7 @@ tsubst_initializer_list (tree t, tree argvec)
>   	      tmp = init;
>   	      if (init != void_type_node)
>   		init = tsubst_expr (init, argvec,
> -				    tf_warning_or_error, NULL_TREE,
> -				    /*integral_constant_expression_p=*/false);
> +				    tf_warning_or_error, NULL_TREE);
>   	      if (init == NULL_TREE && tmp != NULL_TREE)
>   		/* If we had an initializer but it instantiated to nothing,
>   		   value-initialize the object.  This will only occur when
> @@ -27154,8 +27071,7 @@ tsubst_enum (tree tag, tree newtag, tree args)
>         /* Note that in a template enum, the TREE_VALUE is the
>   	 CONST_DECL, not the corresponding INTEGER_CST.  */
>         value = tsubst_expr (DECL_INITIAL (decl),
> -			   args, tf_warning_or_error, NULL_TREE,
> -			   /*integral_constant_expression_p=*/true);
> +			   args, tf_warning_or_error, NULL_TREE);
>   
>         /* Give this enumeration constant the correct access.  */
>         set_current_access_from_decl (decl);
> diff --git a/gcc/objcp/objcp-lang.cc b/gcc/objcp/objcp-lang.cc
> index 5f0e22942b8..fa754028773 100644
> --- a/gcc/objcp/objcp-lang.cc
> +++ b/gcc/objcp/objcp-lang.cc
> @@ -54,8 +54,7 @@ objcp_tsubst_copy_and_build (tree t, tree args, tsubst_flags_t complain,
>   			     tree in_decl)
>   {
>   #define RECURSE(NODE)							\
> -  tsubst_copy_and_build (NODE, args, complain, in_decl, 		\
> -			 /*integral_constant_expression_p=*/false)
> +  tsubst_copy_and_build (NODE, args, complain, in_decl)
>   
>     /* The following two can only occur in Objective-C++.  */
>   
> diff --git a/gcc/testsuite/g++.dg/template/crash55.C b/gcc/testsuite/g++.dg/template/crash55.C
> index 5416e32cacb..8a7fc112c19 100644
> --- a/gcc/testsuite/g++.dg/template/crash55.C
> +++ b/gcc/testsuite/g++.dg/template/crash55.C
> @@ -1,7 +1,6 @@
>   //PR c++/27668
>   
>   template<typename class T, T = T()> // { dg-error "nested-name-specifier|two or more|class type|incomplete" }
> -// { dg-error "cast" "" { target c++98_only } .-1 }
>   struct A {};
>   
> -template<int> void foo(A<int>);	// { dg-error "template argument 2" "" { target c++98_only } }
> +template<int> void foo(A<int>);
> diff --git a/gcc/testsuite/g++.dg/template/ref3.C b/gcc/testsuite/g++.dg/template/ref3.C
> index 91e3c93a35d..976c093a15b 100644
> --- a/gcc/testsuite/g++.dg/template/ref3.C
> +++ b/gcc/testsuite/g++.dg/template/ref3.C
> @@ -5,8 +5,7 @@ template<const int&> struct A {};
>   template<typename T> struct B
>   {
>     A<(T)0> b; // { dg-error "constant|not a valid" }
> -  A<T(0)> a; // { dg-error "constant|not a valid" "" { xfail c++98_only } }
> -                                                       // PR c++/68699
> +  A<T(0)> a; // { dg-error "constant|not a valid" }
>   };
>   
>   B<const int&> b;
  

Patch

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 15b4f2c4a08..e665839f5b1 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -9460,9 +9460,7 @@  potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
     case STATIC_CAST_EXPR:
     case REINTERPRET_CAST_EXPR:
     case IMPLICIT_CONV_EXPR:
-      if (cxx_dialect < cxx11
-	  && !dependent_type_p (TREE_TYPE (t))
-	  && !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t)))
+      if (!cast_valid_in_integral_constant_expression_p (TREE_TYPE (t)))
 	/* In C++98, a conversion to non-integral type can't be part of a
 	   constant expression.  */
 	{
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index f6ef078171a..3ddbd535330 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -1921,7 +1921,7 @@  hash_placeholder_constraint (tree c)
 static tree
 tsubst_valid_expression_requirement (tree t, tree args, sat_info info)
 {
-  tree r = tsubst_expr (t, args, tf_none, info.in_decl, false);
+  tree r = tsubst_expr (t, args, tf_none, info.in_decl);
   if (convert_to_void (r, ICV_STATEMENT, tf_none) != error_mark_node)
     return r;
 
@@ -1932,7 +1932,7 @@  tsubst_valid_expression_requirement (tree t, tree args, sat_info info)
 	{
 	  inform (loc, "the required expression %qE is invalid, because", t);
 	  if (r == error_mark_node)
-	    tsubst_expr (t, args, info.complain, info.in_decl, false);
+	    tsubst_expr (t, args, info.complain, info.in_decl);
 	  else
 	    convert_to_void (r, ICV_STATEMENT, info.complain);
 	}
@@ -1941,7 +1941,7 @@  tsubst_valid_expression_requirement (tree t, tree args, sat_info info)
     }
   else if (info.noisy ())
     {
-      r = tsubst_expr (t, args, info.complain, info.in_decl, false);
+      r = tsubst_expr (t, args, info.complain, info.in_decl);
       convert_to_void (r, ICV_STATEMENT, info.complain);
     }
 
@@ -2706,7 +2706,7 @@  tsubst_constraint (tree t, tree args, tsubst_flags_t complain, tree in_decl)
      constraint-expressions of a declaration.  */
   processing_constraint_expression_sentinel s;
   cp_unevaluated u;
-  tree expr = tsubst_expr (t, args, complain, in_decl, false);
+  tree expr = tsubst_expr (t, args, complain, in_decl);
   return expr;
 }
 
@@ -2954,13 +2954,13 @@  satisfy_atom (tree t, tree args, sat_info info)
 
   /* Apply the parameter mapping (i.e., just substitute).  */
   tree expr = ATOMIC_CONSTR_EXPR (t);
-  tree result = tsubst_expr (expr, args, quiet.complain, quiet.in_decl, false);
+  tree result = tsubst_expr (expr, args, quiet.complain, quiet.in_decl);
   if (result == error_mark_node)
     {
       /* If substitution results in an invalid type or expression, the constraint
 	 is not satisfied. Replay the substitution.  */
       if (info.diagnose_unsatisfaction_p ())
-	tsubst_expr (expr, args, info.complain, info.in_decl, false);
+	tsubst_expr (expr, args, info.complain, info.in_decl);
       return cache.save (inst_cache.save (boolean_false_node));
     }
 
@@ -3587,7 +3587,7 @@  diagnose_trait_expr (tree expr, tree args)
   /* Build a "fake" version of the instantiated trait, so we can
      get the instantiated types from result.  */
   ++processing_template_decl;
-  expr = tsubst_expr (expr, args, tf_none, NULL_TREE, false);
+  expr = tsubst_expr (expr, args, tf_none, NULL_TREE);
   --processing_template_decl;
 
   tree t1 = TRAIT_EXPR_TYPE1 (expr);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 40fd2e1ebb9..7ff3206e245 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7382,10 +7382,8 @@  extern void instantiate_pending_templates	(int);
 extern tree tsubst_default_argument		(tree, int, tree, tree,
 						 tsubst_flags_t);
 extern tree tsubst (tree, tree, tsubst_flags_t, tree);
-extern tree tsubst_copy_and_build		(tree, tree, tsubst_flags_t,
-						 tree, bool = false);
-extern tree tsubst_expr                         (tree, tree, tsubst_flags_t,
-                                                 tree, bool);
+extern tree tsubst_copy_and_build		(tree, tree, tsubst_flags_t, tree);
+extern tree tsubst_expr                         (tree, tree, tsubst_flags_t, tree);
 extern tree tsubst_pack_expansion		(tree, tree, tsubst_flags_t, tree);
 extern tree tsubst_argument_pack		(tree, tree, tsubst_flags_t, tree);
 extern tree tsubst_template_args		(tree, tree, tsubst_flags_t, tree);
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index fee49090de7..2fff4ad2dc7 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -620,10 +620,8 @@  get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)
 	  start_lambda_scope (member);
 
 	  /* Do deferred instantiation of the NSDMI.  */
-	  init = (tsubst_copy_and_build
-		  (init, DECL_TI_ARGS (member),
-		   complain, member,
-		   /*integral_constant_expression_p=*/false));
+	  init = tsubst_copy_and_build (init, DECL_TI_ARGS (member),
+					complain, member);
 	  init = digest_nsdmi_init (member, init, complain);
 
 	  finish_lambda_scope ();
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index bcc275f8b6e..e3d311b0a8b 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -3772,8 +3772,7 @@  expand_integer_pack (tree call, tree args, tsubst_flags_t complain,
 		     tree in_decl)
 {
   tree ohi = CALL_EXPR_ARG (call, 0);
-  tree hi = tsubst_copy_and_build (ohi, args, complain, in_decl,
-				   true/*int_cst*/);
+  tree hi = tsubst_copy_and_build (ohi, args, complain, in_decl);
 
   if (instantiation_dependent_expression_p (hi))
     {
@@ -6360,8 +6359,7 @@  instantiate_non_dependent_expr_internal (tree expr, tsubst_flags_t complain)
   return tsubst_copy_and_build (expr,
 				/*args=*/NULL_TREE,
 				complain,
-				/*in_decl=*/NULL_TREE,
-				/*integral_constant_expression_p=*/true);
+				/*in_decl=*/NULL_TREE);
 }
 
 /* Instantiate the non-dependent expression EXPR.  */
@@ -11195,8 +11193,7 @@  tsubst_friend_function (tree decl, tree args)
 	 current class with same name.  */
       push_nested_namespace (ns);
       fns = tsubst_expr (DECL_TI_TEMPLATE (decl), args,
-			 tf_warning_or_error, NULL_TREE,
-			 /*integral_constant_expression_p=*/false);
+			 tf_warning_or_error, NULL_TREE);
       pop_nested_namespace (ns);
       arglist = tsubst (DECL_TI_ARGS (decl), args,
 			tf_warning_or_error, NULL_TREE);
@@ -11609,9 +11606,7 @@  tsubst_attribute (tree t, tree *decl_p, tree args,
 			      get_attribute_name (t)))
     {
       ++cp_unevaluated_operand;
-      tree varid
-	= tsubst_expr (TREE_PURPOSE (val), args, complain,
-		       in_decl, /*integral_constant_expression_p=*/false);
+      tree varid = tsubst_expr (TREE_PURPOSE (val), args, complain, in_decl);
       --cp_unevaluated_operand;
       tree chain = TREE_CHAIN (val);
       location_t match_loc = cp_expr_loc_or_input_loc (TREE_PURPOSE (chain));
@@ -11647,7 +11642,7 @@  tsubst_attribute (tree t, tree *decl_p, tree args,
 			tree v = TREE_VALUE (t3);
 			if (TREE_CODE (v) == STRING_CST && allow_string)
 			  continue;
-			v = tsubst_expr (v, args, complain, in_decl, true);
+			v = tsubst_expr (v, args, complain, in_decl);
 			v = fold_non_dependent_expr (v);
 			if (!INTEGRAL_TYPE_P (TREE_TYPE (v))
 			    || (TREE_PURPOSE (t3) == score
@@ -11693,8 +11688,7 @@  tsubst_attribute (tree t, tree *decl_p, tree args,
   else if (attribute_takes_identifier_p (get_attribute_name (t)))
     {
       tree chain
-	= tsubst_expr (TREE_CHAIN (val), args, complain, in_decl,
-		       /*integral_constant_expression_p=*/false);
+	= tsubst_expr (TREE_CHAIN (val), args, complain, in_decl);
       if (chain != TREE_CHAIN (val))
 	val = tree_cons (NULL_TREE, TREE_VALUE (val), chain);
     }
@@ -11717,8 +11711,7 @@  tsubst_attribute (tree t, tree *decl_p, tree args,
       return list;
     }
   else
-    val = tsubst_expr (val, args, complain, in_decl,
-		       /*integral_constant_expression_p=*/false);
+    val = tsubst_expr (val, args, complain, in_decl);
 
   if (val == error_mark_node)
     return error_mark_node;
@@ -12160,8 +12153,7 @@  instantiate_class_template (tree type)
 	    {
 	      /* Build new TYPE_FIELDS.  */
               if (TREE_CODE (t) == STATIC_ASSERT)
-		tsubst_expr (t, args, tf_warning_or_error, NULL_TREE,
-			     /*integral_constant_expression_p=*/true);
+		tsubst_expr (t, args, tf_warning_or_error, NULL_TREE);
 	      else if (TREE_CODE (t) != CONST_DECL)
 		{
 		  tree r;
@@ -12418,8 +12410,7 @@  tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     {
       if (!(complain & tf_warning))
 	++c_inhibit_evaluation_warnings;
-      r = tsubst_expr (t, args, complain, in_decl,
-		       /*integral_constant_expression_p=*/true);
+      r = tsubst_expr (t, args, complain, in_decl);
       if (!(complain & tf_warning))
 	--c_inhibit_evaluation_warnings;
     }
@@ -12683,8 +12674,7 @@  gen_elem_of_pack_expansion_instantiation (tree pattern,
   else if (pattern == error_mark_node)
     t = error_mark_node;
   else if (!TYPE_P (pattern))
-    t = tsubst_expr (pattern, args, complain, in_decl,
-		     /*integral_constant_expression_p=*/false);
+    t = tsubst_expr (pattern, args, complain, in_decl);
   else
     {
       t = tsubst (pattern, args, complain, in_decl);
@@ -12778,7 +12768,7 @@  tsubst_fold_expr_pack (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 static inline tree
 tsubst_fold_expr_init (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 {
-  return tsubst_expr (FOLD_EXPR_INIT (t), args, complain, in_decl, false);
+  return tsubst_expr (FOLD_EXPR_INIT (t), args, complain, in_decl);
 }
 
 /* Expand a PACK of arguments into a grouped as left fold.
@@ -13147,12 +13137,12 @@  tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
 	  if (BASES_DIRECT (parm_pack))
 	    return calculate_direct_bases (tsubst_expr (BASES_TYPE (parm_pack),
 							args, complain,
-							in_decl, false),
+							in_decl),
 					   complain);
 	  else
 	    return calculate_bases (tsubst_expr (BASES_TYPE (parm_pack),
-						 args, complain, in_decl,
-						 false), complain);
+						 args, complain, in_decl),
+				    complain);
 	}
       else if (builtin_pack_call_p (parm_pack))
 	{
@@ -13326,8 +13316,7 @@  tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
 	 pattern and return a PACK_EXPANSION_*. The caller will need to
 	 deal with that.  */
       if (TREE_CODE (t) == EXPR_PACK_EXPANSION)
-	result = tsubst_expr (pattern, args, complain, in_decl,
-			 /*integral_constant_expression_p=*/false);
+	result = tsubst_expr (pattern, args, complain, in_decl);
       else
 	result = tsubst (pattern, args, complain, in_decl);
       result = make_pack_expansion (result, complain);
@@ -13901,9 +13890,7 @@  tsubst_default_argument (tree fn, int parmnum, tree type, tree arg,
      the body of function so as to avoid collecting live data on the
      stack.  */
   ++function_depth;
-  arg = tsubst_expr (arg, DECL_TI_ARGS (fn),
-		     complain, NULL_TREE,
-		     /*integral_constant_expression_p=*/false);
+  arg = tsubst_expr (arg, DECL_TI_ARGS (fn), complain, NULL_TREE);
   --function_depth;
 
   finish_lambda_scope ();
@@ -14208,8 +14195,7 @@  tsubst_function_decl (tree t, tree args, tsubst_flags_t complain,
   if (DECL_HAS_DEPENDENT_EXPLICIT_SPEC_P (t))
     {
       tree spec = lookup_explicit_specifier (t);
-      spec = tsubst_copy_and_build (spec, args, complain, in_decl,
-				    /*i_c_e_p=*/true);
+      spec = tsubst_copy_and_build (spec, args, complain, in_decl);
       spec = build_explicit_specifier (spec, complain);
       if (spec == error_mark_node)
 	return error_mark_node;
@@ -14821,8 +14807,7 @@  tsubst_decl (tree t, tree args, tsubst_flags_t complain)
 		 number of bits.  */
 	      DECL_BIT_FIELD_REPRESENTATIVE (r)
 		= tsubst_expr (DECL_BIT_FIELD_REPRESENTATIVE (t), args,
-			       complain, in_decl,
-			       /*integral_constant_expression_p=*/true);
+			       complain, in_decl);
 	    if (DECL_INITIAL (t))
 	      {
 		/* Set up DECL_TEMPLATE_INFO so that we can get at the
@@ -15074,8 +15059,7 @@  tsubst_decl (tree t, tree args, tsubst_flags_t complain)
 		bool nop = (TREE_CODE (ve) == NOP_EXPR);
 		if (nop)
 		  ve = TREE_OPERAND (ve, 0);
-		ve = tsubst_expr (ve, args, complain, in_decl,
-				  /*constant_expression_p=*/false);
+		ve = tsubst_expr (ve, args, complain, in_decl);
 		if (REFERENCE_REF_P (ve))
 		  {
 		    gcc_assert (TYPE_REF_P (type));
@@ -15273,8 +15257,7 @@  tsubst_arg_types (tree arg_types,
   if (lambda_fn_in_template_p (in_decl)
       || (in_decl && TREE_CODE (in_decl) == FUNCTION_DECL
 	  && DECL_LOCAL_DECL_P (in_decl)))
-    default_arg = tsubst_copy_and_build (default_arg, args, complain, in_decl,
-					 false/*constexpr*/);
+    default_arg = tsubst_copy_and_build (default_arg, args, complain, in_decl);
 
   tree remaining_arg_types = tsubst_arg_types (TREE_CHAIN (arg_types),
 					       args, end, complain, in_decl);
@@ -15455,9 +15438,7 @@  tsubst_exception_specification (tree fntype,
 					   args);
 	      expr = DEFERRED_NOEXCEPT_PATTERN (expr);
 	    }
-	  new_specs = tsubst_copy_and_build
-	    (expr, args, complain, in_decl,
-	     /*integral_constant_expression_p=*/true);
+	  new_specs = tsubst_copy_and_build (expr, args, complain, in_decl);
 	}
       new_specs = build_noexcept_spec (new_specs, complain);
       /* We've instantiated a template before a noexcept-specifier
@@ -15764,8 +15745,7 @@  tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       {
 	tree max, omax = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);
 
-	max = tsubst_expr (omax, args, complain, in_decl,
-			   /*integral_constant_expression_p=*/false);
+	max = tsubst_expr (omax, args, complain, in_decl);
 
 	/* Fix up type of the magic NOP_EXPR with TREE_SIDE_EFFECTS if
 	   needed.  */
@@ -16358,9 +16338,7 @@  tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	++cp_unevaluated_operand;
 	++c_inhibit_evaluation_warnings;
 
-	type = tsubst_expr (TYPEOF_TYPE_EXPR (t), args,
-			    complain, in_decl,
-			    /*integral_constant_expression_p=*/false);
+	type = tsubst_expr (TYPEOF_TYPE_EXPR (t), args, complain, in_decl);
 
 	--cp_unevaluated_operand;
 	--c_inhibit_evaluation_warnings;
@@ -16380,8 +16358,7 @@  tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	++c_inhibit_evaluation_warnings;
 
 	type = tsubst_copy_and_build (DECLTYPE_TYPE_EXPR (t), args,
-				      complain|tf_decltype, in_decl,
-				      /*integral_constant_expression*/false);
+				      complain|tf_decltype, in_decl);
 
 	--cp_unevaluated_operand;
 	--c_inhibit_evaluation_warnings;
@@ -16840,7 +16817,7 @@  tsubst_init (tree init, tree decl, tree args,
   if (!init)
     return NULL_TREE;
 
-  init = tsubst_expr (init, args, complain, in_decl, false);
+  init = tsubst_expr (init, args, complain, in_decl);
 
   tree type = TREE_TYPE (decl);
 
@@ -17677,9 +17654,7 @@  tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       return t;
 
     case CO_AWAIT_EXPR:
-      return tsubst_expr (t, args, complain, in_decl,
-			  /*integral_constant_expression_p=*/false);
-      break;
+      return tsubst_expr (t, args, complain, in_decl);
 
     default:
       /* We shouldn't get here, but keep going if !flag_checking.  */
@@ -17719,14 +17694,11 @@  tsubst_omp_clause_decl (tree decl, tree args, tsubst_flags_t complain,
 	      DECL_CONTEXT (TREE_VEC_ELT (*tp, 0)) = current_function_decl;
 	      pushdecl (TREE_VEC_ELT (*tp, 0));
 	      TREE_VEC_ELT (*tp, 1)
-		= tsubst_expr (TREE_VEC_ELT (it, 1), args, complain, in_decl,
-			       /*integral_constant_expression_p=*/false);
+		= tsubst_expr (TREE_VEC_ELT (it, 1), args, complain, in_decl);
 	      TREE_VEC_ELT (*tp, 2)
-		= tsubst_expr (TREE_VEC_ELT (it, 2), args, complain, in_decl,
-			       /*integral_constant_expression_p=*/false);
+		= tsubst_expr (TREE_VEC_ELT (it, 2), args, complain, in_decl);
 	      TREE_VEC_ELT (*tp, 3)
-		= tsubst_expr (TREE_VEC_ELT (it, 3), args, complain, in_decl,
-			       /*integral_constant_expression_p=*/false);
+		= tsubst_expr (TREE_VEC_ELT (it, 3), args, complain, in_decl);
 	      TREE_CHAIN (*tp) = NULL_TREE;
 	      tp = &TREE_CHAIN (*tp);
 	    }
@@ -17748,10 +17720,8 @@  tsubst_omp_clause_decl (tree decl, tree args, tsubst_flags_t complain,
   if (TREE_CODE (decl) == TREE_LIST)
     {
       tree low_bound
-	= tsubst_expr (TREE_PURPOSE (decl), args, complain, in_decl,
-		       /*integral_constant_expression_p=*/false);
-      tree length = tsubst_expr (TREE_VALUE (decl), args, complain, in_decl,
-				 /*integral_constant_expression_p=*/false);
+	= tsubst_expr (TREE_PURPOSE (decl), args, complain, in_decl);
+      tree length = tsubst_expr (TREE_VALUE (decl), args, complain, in_decl);
       tree chain = tsubst_omp_clause_decl (TREE_CHAIN (decl), args, complain,
 					   in_decl, NULL);
       if (TREE_PURPOSE (decl) == low_bound
@@ -17763,8 +17733,7 @@  tsubst_omp_clause_decl (tree decl, tree args, tsubst_flags_t complain,
 	= OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (decl);
       return ret;
     }
-  tree ret = tsubst_expr (decl, args, complain, in_decl,
-			  /*integral_constant_expression_p=*/false);
+  tree ret = tsubst_expr (decl, args, complain, in_decl);
   /* Undo convert_from_reference tsubst_expr could have called.  */
   if (decl
       && REFERENCE_REF_P (ret)
@@ -17795,8 +17764,8 @@  tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
 	  if (OMP_CLAUSE_LASTPRIVATE_STMT (oc))
 	    {
 	      OMP_CLAUSE_LASTPRIVATE_STMT (nc) = push_stmt_list ();
-	      tsubst_expr (OMP_CLAUSE_LASTPRIVATE_STMT (oc), args, complain,
-			   in_decl, /*integral_constant_expression_p=*/false);
+	      tsubst_expr (OMP_CLAUSE_LASTPRIVATE_STMT (oc), args,
+			   complain, in_decl);
 	      OMP_CLAUSE_LASTPRIVATE_STMT (nc)
 		= pop_stmt_list (OMP_CLAUSE_LASTPRIVATE_STMT (nc));
 	    }
@@ -17829,8 +17798,7 @@  tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
 	  if (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (oc))
 	    OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (nc)
 	      = tsubst_expr (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (oc), args,
-			     complain, in_decl,
-			     /*integral_constant_expression_p=*/false);
+			     complain, in_decl);
 	  /* FALLTHRU */
 	case OMP_CLAUSE_TILE:
 	case OMP_CLAUSE_IF:
@@ -17858,8 +17826,7 @@  tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
 	case OMP_CLAUSE_WAIT:
 	case OMP_CLAUSE_DETACH:
 	  OMP_CLAUSE_OPERAND (nc, 0)
-	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
-			   in_decl, /*integral_constant_expression_p=*/false);
+	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain, in_decl);
 	  break;
 	case OMP_CLAUSE_REDUCTION:
 	case OMP_CLAUSE_IN_REDUCTION:
@@ -17889,19 +17856,16 @@  tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
 	    = tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
 				      in_decl, NULL);
 	  OMP_CLAUSE_OPERAND (nc, 1)
-	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain,
-			   in_decl, /*integral_constant_expression_p=*/false);
+	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain, in_decl);
 	  break;
 	case OMP_CLAUSE_ALLOCATE:
 	  OMP_CLAUSE_DECL (nc)
 	    = tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
 				      in_decl, NULL);
 	  OMP_CLAUSE_OPERAND (nc, 1)
-	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain,
-			   in_decl, /*integral_constant_expression_p=*/false);
+	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain, in_decl);
 	  OMP_CLAUSE_OPERAND (nc, 2)
-	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 2), args, complain,
-			   in_decl, /*integral_constant_expression_p=*/false);
+	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 2), args, complain, in_decl);
 	  break;
 	case OMP_CLAUSE_LINEAR:
 	  OMP_CLAUSE_DECL (nc)
@@ -17918,9 +17882,8 @@  tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
 					complain, in_decl, NULL);
 	  else
 	    OMP_CLAUSE_LINEAR_STEP (nc)
-	      = tsubst_expr (OMP_CLAUSE_LINEAR_STEP (oc), args, complain,
-			     in_decl,
-			     /*integral_constant_expression_p=*/false);
+	      = tsubst_expr (OMP_CLAUSE_LINEAR_STEP (oc), args,
+			     complain, in_decl);
 	  break;
 	case OMP_CLAUSE_NOWAIT:
 	case OMP_CLAUSE_DEFAULT:
@@ -18045,8 +18008,7 @@  tsubst_copy_asm_operands (tree t, tree args, tsubst_flags_t complain,
     return t;
 
   if (TREE_CODE (t) != TREE_LIST)
-    return tsubst_copy_and_build (t, args, complain, in_decl,
-				  /*integral_constant_expression_p=*/false);
+    return tsubst_copy_and_build (t, args, complain, in_decl);
 
   if (t == void_list_node)
     return t;
@@ -18087,12 +18049,10 @@  static tree tsubst_decomp_names (tree, tree, tree, tsubst_flags_t, tree,
 static bool
 tsubst_omp_for_iterator (tree t, int i, tree declv, tree &orig_declv,
 			 tree initv, tree condv, tree incrv, tree *clauses,
-			 tree args, tsubst_flags_t complain, tree in_decl,
-			 bool integral_constant_expression_p)
+			 tree args, tsubst_flags_t complain, tree in_decl)
 {
 #define RECUR(NODE)				\
-  tsubst_expr ((NODE), args, complain, in_decl,	\
-	       integral_constant_expression_p)
+  tsubst_expr ((NODE), args, complain, in_decl)
   tree decl, init, cond = NULL_TREE, incr = NULL_TREE;
   bool ret = false;
 
@@ -18580,13 +18540,11 @@  dependent_operand_p (tree t)
    processing.  */
 
 tree
-tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
-	     bool integral_constant_expression_p)
+tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 {
 #define RETURN(EXP) do { r = (EXP); goto out; } while(0)
 #define RECUR(NODE)				\
-  tsubst_expr ((NODE), args, complain, in_decl,	\
-	       integral_constant_expression_p)
+  tsubst_expr ((NODE), args, complain, in_decl)
 
   tree stmt, tmp;
   tree r;
@@ -19132,11 +19090,8 @@  tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
 	tree condition;
 
 	++c_inhibit_evaluation_warnings;
-	condition =
-	  tsubst_expr (STATIC_ASSERT_CONDITION (t),
-                       args,
-                       complain, in_decl,
-                       /*integral_constant_expression_p=*/true);
+	condition = tsubst_expr (STATIC_ASSERT_CONDITION (t), args,
+				 complain, in_decl);
 	--c_inhibit_evaluation_warnings;
 
         finish_static_assert (condition,
@@ -19232,8 +19187,7 @@  tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
 	    any_range_for
 	      |= tsubst_omp_for_iterator (t, i, declv, orig_declv, initv,
 					  condv, incrv, &clauses, args,
-					  complain, in_decl,
-					  integral_constant_expression_p);
+					  complain, in_decl);
 	omp_parallel_combined_clauses = NULL;
 
 	if (any_range_for)
@@ -19631,8 +19585,7 @@  tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
     default:
       gcc_assert (!STATEMENT_CODE_P (TREE_CODE (t)));
 
-      RETURN (tsubst_copy_and_build (t, args, complain, in_decl,
-				    integral_constant_expression_p));
+      RETURN (tsubst_copy_and_build (t, args, complain, in_decl));
     }
 
   RETURN (NULL_TREE);
@@ -19679,7 +19632,7 @@  tsubst_omp_udr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       DECL_CONTEXT (omp_in) = current_function_decl;
       keep_next_level (true);
       tree block = begin_omp_structured_block ();
-      tsubst_expr (stmts[2], args, complain, in_decl, false);
+      tsubst_expr (stmts[2], args, complain, in_decl);
       block = finish_omp_structured_block (block);
       block = maybe_cleanup_point_expr_void (block);
       add_decl_expr (omp_out);
@@ -19699,7 +19652,7 @@  tsubst_omp_udr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       DECL_CONTEXT (omp_orig) = current_function_decl;
       keep_next_level (true);
       tree block = begin_omp_structured_block ();
-      tsubst_expr (stmts[5], args, complain, in_decl, false);
+      tsubst_expr (stmts[5], args, complain, in_decl);
       block = finish_omp_structured_block (block);
       block = maybe_cleanup_point_expr_void (block);
       cp_walk_tree (&block, cp_remove_omp_priv_cleanup_stmt, omp_priv, NULL);
@@ -19723,8 +19676,7 @@  tsubst_non_call_postfix_expression (tree t, tree args,
     t = tsubst_qualified_id (t, args, complain, in_decl,
 			     /*done=*/false, /*address_p=*/false);
   else
-    t = tsubst_copy_and_build (t, args, complain, in_decl,
-			       /*integral_constant_expression_p=*/false);
+    t = tsubst_copy_and_build (t, args, complain, in_decl);
 
   return t;
 }
@@ -19795,8 +19747,7 @@  tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       if (PACK_EXPANSION_P (init))
 	init = tsubst_pack_expansion (init, args, complain, in_decl);
       else
-	init = tsubst_copy_and_build (init, args, complain, in_decl,
-				      /*constexpr*/false);
+	init = tsubst_copy_and_build (init, args, complain, in_decl);
 
       if (init == error_mark_node)
 	return error_mark_node;
@@ -19962,7 +19913,7 @@  tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	   need another to confuse NRV (91217).  */
 	saved = BIND_EXPR_BODY (saved);
 
-      tsubst_expr (saved, args, complain, r, /*constexpr*/false);
+      tsubst_expr (saved, args, complain, r);
 
       finish_lambda_function (body);
 
@@ -20053,7 +20004,6 @@  maybe_fold_fn_template_args (tree fn, tsubst_flags_t complain)
 static void
 tsubst_copy_and_build_call_args (tree t, tree args, tsubst_flags_t complain,
 				 tree in_decl,
-				 bool integral_constant_expression_p,
 				 releasing_vec &call_args)
 {
   unsigned int nargs = call_expr_nargs (t);
@@ -20063,8 +20013,7 @@  tsubst_copy_and_build_call_args (tree t, tree args, tsubst_flags_t complain,
 
       if (!PACK_EXPANSION_P (arg))
 	vec_safe_push (call_args,
-		       tsubst_copy_and_build (arg, args, complain, in_decl,
-					      integral_constant_expression_p));
+		       tsubst_copy_and_build (arg, args, complain, in_decl));
       else
 	{
 	  /* Expand the pack expansion and push each entry onto CALL_ARGS.  */
@@ -20093,16 +20042,11 @@  tsubst_copy_and_build_call_args (tree t, tree args, tsubst_flags_t complain,
    analysis.  */
 
 tree
-tsubst_copy_and_build (tree t,
-		       tree args,
-		       tsubst_flags_t complain,
-		       tree in_decl,
-		       bool integral_constant_expression_p)
+tsubst_copy_and_build (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 {
 #define RETURN(EXP) do { retval = (EXP); goto out; } while(0)
 #define RECUR(NODE)						\
-  tsubst_copy_and_build (NODE, args, complain, in_decl, 	\
-			 integral_constant_expression_p)
+  tsubst_copy_and_build (NODE, args, complain, in_decl)
 
   tree retval, op1;
   location_t save_loc;
@@ -20128,7 +20072,6 @@  tsubst_copy_and_build (tree t,
       {
 	tree decl;
 	cp_id_kind idk;
-	bool non_integral_constant_expression_p;
 	const char *error_msg;
 
 	if (IDENTIFIER_CONV_OP_P (t))
@@ -20147,9 +20090,9 @@  tsubst_copy_and_build (tree t,
 
 	decl = finish_id_expression (t, decl, NULL_TREE,
 				     &idk,
-				     integral_constant_expression_p,
-          /*allow_non_integral_constant_expression_p=*/(cxx_dialect >= cxx11),
-				     &non_integral_constant_expression_p,
+				     /*i_c_e_p=*/false,
+				     /*allow_i_c_e_p=*/true,
+				     /*non_i_c_e_p=*/nullptr,
 				     /*template_p=*/false,
 				     /*done=*/true,
 				     /*address_p=*/false,
@@ -20171,8 +20114,7 @@  tsubst_copy_and_build (tree t,
       {
 	tree object;
 	tree templ = tsubst_copy_and_build (TREE_OPERAND (t, 0), args,
-					    complain, in_decl,
-					    integral_constant_expression_p);
+					    complain, in_decl);
 	tree targs = TREE_OPERAND (t, 1);
 
 	if (targs)
@@ -20312,14 +20254,6 @@  tsubst_copy_and_build (tree t,
 	if (TREE_CODE (t) == CAST_EXPR)
 	  tcomplain |= tf_tst_ok;
 	type = tsubst (TREE_TYPE (t), args, tcomplain, in_decl);
-	if (integral_constant_expression_p
-	    && !cast_valid_in_integral_constant_expression_p (type))
-	  {
-            if (complain & tf_error)
-              error ("a cast to a type other than an integral or "
-                     "enumeration type cannot appear in a constant-expression");
-	    RETURN (error_mark_node);
-	  }
 
 	op = RECUR (TREE_OPERAND (t, 0));
 
@@ -20504,7 +20438,6 @@  tsubst_copy_and_build (tree t,
 	  tree c = TREE_OPERAND (t, 1);
 	  releasing_vec index_exp_list;
 	  tsubst_copy_and_build_call_args (c, args, complain, in_decl,
-					   integral_constant_expression_p,
 					   index_exp_list);
 
 	  tree r;
@@ -20553,9 +20486,7 @@  tsubst_copy_and_build (tree t,
 	    if (TYPE_P (op1))
 	      op1 = tsubst (op1, args, complain, in_decl);
 	    else
-	      op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
-					   /*integral_constant_expression_p=*/
-					   false);
+	      op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
 	    --cp_unevaluated_operand;
 	    --c_inhibit_evaluation_warnings;
 	  }
@@ -20592,8 +20523,7 @@  tsubst_copy_and_build (tree t,
 	op1 = TREE_OPERAND (t, 0);
 	++cp_unevaluated_operand;
 	++c_inhibit_evaluation_warnings;
-	op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
-				     /*integral_constant_expression_p=*/false);
+	op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
 	--cp_unevaluated_operand;
 	--c_inhibit_evaluation_warnings;
 	RETURN (objc_build_encode_expr (op1));
@@ -20604,8 +20534,7 @@  tsubst_copy_and_build (tree t,
       ++cp_unevaluated_operand;
       ++c_inhibit_evaluation_warnings;
       ++cp_noexcept_operand;
-      op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
-				   /*integral_constant_expression_p=*/false);
+      op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
       --cp_unevaluated_operand;
       --c_inhibit_evaluation_warnings;
       --cp_noexcept_operand;
@@ -20714,8 +20643,7 @@  tsubst_copy_and_build (tree t,
     case COMPOUND_EXPR:
       {
 	tree op0 = tsubst_copy_and_build (TREE_OPERAND (t, 0), args,
-					  complain & ~tf_decltype, in_decl,
-					  integral_constant_expression_p);
+					  complain & ~tf_decltype, in_decl);
 	RETURN (build_x_compound_expr (EXPR_LOCATION (t),
 				       op0,
 				       RECUR (TREE_OPERAND (t, 1)),
@@ -20796,9 +20724,7 @@  tsubst_copy_and_build (tree t,
 		 augmenting the overload set via ADL, so during this initial
 		 substitution we disable mark_used by setting tf_conv (68942).  */
 	      subcomplain |= tf_conv;
-	    function = tsubst_copy_and_build (function, args, subcomplain,
-					      in_decl,
-					      integral_constant_expression_p);
+	    function = tsubst_copy_and_build (function, args, subcomplain, in_decl);
 
 	    if (BASELINK_P (function))
 	      qualified_p = true;
@@ -20807,7 +20733,6 @@  tsubst_copy_and_build (tree t,
 	nargs = call_expr_nargs (t);
 	releasing_vec call_args;
 	tsubst_copy_and_build_call_args (t, args, complain, in_decl,
-					 integral_constant_expression_p,
 					 call_args);
 
 	/* Stripped-down processing for a call in a thunk.  Specifically, in
@@ -20900,9 +20825,8 @@  tsubst_copy_and_build (tree t,
 		/* For backwards compatibility and good diagnostics, try
 		   the unqualified lookup again if we aren't in SFINAE
 		   context.  */
-		tree unq = (tsubst_copy_and_build
-			    (function, args, complain, in_decl,
-			     integral_constant_expression_p));
+		tree unq = tsubst_copy_and_build (function, args,
+						  complain, in_decl);
 		if (unq == error_mark_node)
 		  RETURN (error_mark_node);
 
@@ -21450,9 +21374,8 @@  tsubst_copy_and_build (tree t,
     case OFFSETOF_EXPR:
       {
 	tree object_ptr
-	  = tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
-				   in_decl,
-				   /*integral_constant_expression_p=*/false);
+	  = tsubst_copy_and_build (TREE_OPERAND (t, 1), args,
+				   complain, in_decl);
 	RETURN (finish_offsetof (object_ptr,
 				 RECUR (TREE_OPERAND (t, 0)),
 				 EXPR_LOCATION (t)));
@@ -21478,8 +21401,7 @@  tsubst_copy_and_build (tree t,
 	tree stmt_expr = begin_stmt_expr ();
 
 	cur_stmt_expr = stmt_expr;
-	tsubst_expr (STMT_EXPR_STMT (t), args, complain, in_decl,
-		     integral_constant_expression_p);
+	tsubst_expr (STMT_EXPR_STMT (t), args, complain, in_decl);
 	stmt_expr = finish_stmt_expr (stmt_expr, false);
 	cur_stmt_expr = old_stmt_expr;
 
@@ -21506,8 +21428,7 @@  tsubst_copy_and_build (tree t,
       }
 
     case TRANSACTION_EXPR:
-      RETURN (tsubst_expr(t, args, complain, in_decl,
-	     integral_constant_expression_p));
+      RETURN (tsubst_expr (t, args, complain, in_decl));
 
     case PAREN_EXPR:
       if (REF_PARENTHESIZED_P (t))
@@ -26369,8 +26290,7 @@  maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
 	  /* Do deferred instantiation of the noexcept-specifier.  */
 	  noex = tsubst_copy_and_build (DEFERRED_NOEXCEPT_PATTERN (noex),
 					DEFERRED_NOEXCEPT_ARGS (noex),
-					tf_warning_or_error, fn,
-					/*i_c_e_p=*/true);
+					tf_warning_or_error, fn);
 
 	  /* Build up the noexcept-specification.  */
 	  spec = build_noexcept_spec (noex, tf_warning_or_error);
@@ -26556,8 +26476,7 @@  instantiate_body (tree pattern, tree args, tree d, bool nested_p)
       else
 	{
 	  tsubst_expr (DECL_SAVED_TREE (code_pattern), args,
-		       tf_warning_or_error, DECL_TI_TEMPLATE (d),
-		       /*integral_constant_expression_p=*/false);
+		       tf_warning_or_error, DECL_TI_TEMPLATE (d));
 
 	  /* Set the current input_location to the end of the function
 	     so that finish_function knows where we are.  */
@@ -26798,8 +26717,7 @@  instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p)
 	    push_nested_class (DECL_CONTEXT (d));
 	  init = tsubst_expr (DECL_INITIAL (code_pattern),
 			      args,
-			      tf_warning_or_error, NULL_TREE,
-			      /*integral_constant_expression_p=*/false);
+			      tf_warning_or_error, NULL_TREE);
 	  /* If instantiating the initializer involved instantiating this
 	     again, don't call cp_finish_decl twice.  */
 	  if (!DECL_INITIAL (d))
@@ -27087,8 +27005,7 @@  tsubst_initializer_list (tree t, tree argvec)
 	      tmp = init;
 	      if (init != void_type_node)
 		init = tsubst_expr (init, argvec,
-				    tf_warning_or_error, NULL_TREE,
-				    /*integral_constant_expression_p=*/false);
+				    tf_warning_or_error, NULL_TREE);
 	      if (init == NULL_TREE && tmp != NULL_TREE)
 		/* If we had an initializer but it instantiated to nothing,
 		   value-initialize the object.  This will only occur when
@@ -27154,8 +27071,7 @@  tsubst_enum (tree tag, tree newtag, tree args)
       /* Note that in a template enum, the TREE_VALUE is the
 	 CONST_DECL, not the corresponding INTEGER_CST.  */
       value = tsubst_expr (DECL_INITIAL (decl),
-			   args, tf_warning_or_error, NULL_TREE,
-			   /*integral_constant_expression_p=*/true);
+			   args, tf_warning_or_error, NULL_TREE);
 
       /* Give this enumeration constant the correct access.  */
       set_current_access_from_decl (decl);
diff --git a/gcc/objcp/objcp-lang.cc b/gcc/objcp/objcp-lang.cc
index 5f0e22942b8..fa754028773 100644
--- a/gcc/objcp/objcp-lang.cc
+++ b/gcc/objcp/objcp-lang.cc
@@ -54,8 +54,7 @@  objcp_tsubst_copy_and_build (tree t, tree args, tsubst_flags_t complain,
 			     tree in_decl)
 {
 #define RECURSE(NODE)							\
-  tsubst_copy_and_build (NODE, args, complain, in_decl, 		\
-			 /*integral_constant_expression_p=*/false)
+  tsubst_copy_and_build (NODE, args, complain, in_decl)
 
   /* The following two can only occur in Objective-C++.  */
 
diff --git a/gcc/testsuite/g++.dg/template/crash55.C b/gcc/testsuite/g++.dg/template/crash55.C
index 5416e32cacb..8a7fc112c19 100644
--- a/gcc/testsuite/g++.dg/template/crash55.C
+++ b/gcc/testsuite/g++.dg/template/crash55.C
@@ -1,7 +1,6 @@ 
 //PR c++/27668
 
 template<typename class T, T = T()> // { dg-error "nested-name-specifier|two or more|class type|incomplete" }
-// { dg-error "cast" "" { target c++98_only } .-1 }
 struct A {};
 
-template<int> void foo(A<int>);	// { dg-error "template argument 2" "" { target c++98_only } }
+template<int> void foo(A<int>);
diff --git a/gcc/testsuite/g++.dg/template/ref3.C b/gcc/testsuite/g++.dg/template/ref3.C
index 91e3c93a35d..976c093a15b 100644
--- a/gcc/testsuite/g++.dg/template/ref3.C
+++ b/gcc/testsuite/g++.dg/template/ref3.C
@@ -5,8 +5,7 @@  template<const int&> struct A {};
 template<typename T> struct B
 {
   A<(T)0> b; // { dg-error "constant|not a valid" }
-  A<T(0)> a; // { dg-error "constant|not a valid" "" { xfail c++98_only } }
-                                                       // PR c++/68699
+  A<T(0)> a; // { dg-error "constant|not a valid" }
 };
 
 B<const int&> b;