===================================================================
@@ -1272,7 +1272,8 @@ finish_shorthand_constraint (tree decl, tree const
/* Get the argument and overload used for the requirement
and adjust it if we're going to expand later. */
- tree arg = template_parm_to_arg (build_tree_list (NULL_TREE, decl));
+ tree arg = template_parm_to_arg (build_tree_list (NULL_TREE, decl),
+ tf_warning_or_error);
if (apply_to_all_p)
arg = PACK_EXPANSION_PATTERN (TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg), 0));
@@ -1420,7 +1421,8 @@ finish_template_introduction (tree tmpl_decl, tree
for (; n < TREE_VEC_LENGTH (parm_list); ++n)
{
tree parm = TREE_VEC_ELT (parm_list, n);
- TREE_VEC_ELT (check_args, n) = template_parm_to_arg (parm);
+ TREE_VEC_ELT (check_args, n)
+ = template_parm_to_arg (parm, tf_warning_or_error);
}
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (check_args, n);
===================================================================
@@ -6435,7 +6435,7 @@ extern bool uses_parameter_packs (t
extern bool template_parameter_pack_p (const_tree);
extern bool function_parameter_pack_p (const_tree);
extern bool function_parameter_expanded_from_pack_p (tree, tree);
-extern tree make_pack_expansion (tree);
+extern tree make_pack_expansion (tree, tsubst_flags_t = tf_warning_or_error);
extern bool check_for_bare_parameter_packs (tree);
extern tree build_template_info (tree, tree);
extern tree get_template_info (const_tree);
@@ -6517,7 +6517,7 @@ extern tree coerce_template_parms (t
extern void register_local_specialization (tree, tree);
extern tree retrieve_local_specialization (tree);
extern tree extract_fnparm_pack (tree, tree *);
-extern tree template_parm_to_arg (tree);
+extern tree template_parm_to_arg (tree, tsubst_flags_t);
extern tree dguide_name (tree);
extern bool dguide_name_p (tree);
extern bool deduction_guide_p (const_tree);
===================================================================
@@ -3435,7 +3435,7 @@ expand_integer_pack (tree call, tree args, tsubst_
call = copy_node (call);
CALL_EXPR_ARG (call, 0) = hi;
}
- tree ex = make_pack_expansion (call);
+ tree ex = make_pack_expansion (call, complain);
tree vec = make_tree_vec (1);
TREE_VEC_ELT (vec, 0) = ex;
return vec;
@@ -3724,7 +3724,7 @@ uses_parameter_packs (tree t)
EXPR_PACK_EXPANSION, TYPE_PACK_EXPANSION, or TREE_LIST,
respectively. */
tree
-make_pack_expansion (tree arg)
+make_pack_expansion (tree arg, tsubst_flags_t complain)
{
tree result;
tree parameter_packs = NULL_TREE;
@@ -3770,7 +3770,9 @@ tree
if (parameter_packs == NULL_TREE)
{
- error ("base initializer expansion %qT contains no parameter packs", arg);
+ if (complain & tf_error)
+ error ("base initializer expansion %qT contains no parameter packs",
+ arg);
delete ppd.visited;
return error_mark_node;
}
@@ -3834,10 +3836,13 @@ tree
/* Make sure we found some parameter packs. */
if (parameter_packs == NULL_TREE)
{
- if (TYPE_P (arg))
- error ("expansion pattern %qT contains no argument packs", arg);
- else
- error ("expansion pattern %qE contains no argument packs", arg);
+ if (complain & tf_error)
+ {
+ if (TYPE_P (arg))
+ error ("expansion pattern %qT contains no argument packs", arg);
+ else
+ error ("expansion pattern %qE contains no argument packs", arg);
+ }
return error_mark_node;
}
PACK_EXPANSION_PARAMETER_PACKS (result) = parameter_packs;
@@ -4330,7 +4335,7 @@ end_template_decl (void)
node, the returned argument is error_mark_node. */
tree
-template_parm_to_arg (tree t)
+template_parm_to_arg (tree t, tsubst_flags_t complain)
{
if (t == NULL_TREE
@@ -4355,7 +4360,7 @@ tree
if (CHECKING_P)
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (vec, TREE_VEC_LENGTH (vec));
- TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
+ TREE_VEC_ELT (vec, 0) = make_pack_expansion (t, complain);
t = cxx_make_type (TYPE_ARGUMENT_PACK);
SET_ARGUMENT_PACK_ARGS (t, vec);
@@ -4374,7 +4379,7 @@ tree
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (vec, TREE_VEC_LENGTH (vec));
t = convert_from_reference (t);
- TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
+ TREE_VEC_ELT (vec, 0) = make_pack_expansion (t, complain);
t = make_node (NONTYPE_ARGUMENT_PACK);
SET_ARGUMENT_PACK_ARGS (t, vec);
@@ -4389,12 +4394,13 @@ tree
as a set of template arguments. */
static tree
-template_parms_level_to_args (tree parms)
+template_parms_level_to_args (tree parms, tsubst_flags_t complain)
{
tree a = copy_node (parms);
TREE_TYPE (a) = NULL_TREE;
for (int i = TREE_VEC_LENGTH (a) - 1; i >= 0; --i)
- TREE_VEC_ELT (a, i) = template_parm_to_arg (TREE_VEC_ELT (a, i));
+ TREE_VEC_ELT (a, i) = template_parm_to_arg (TREE_VEC_ELT (a, i),
+ complain);
if (CHECKING_P)
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (a, TREE_VEC_LENGTH (a));
@@ -4407,7 +4413,7 @@ static tree
the form documented in cp-tree.h for template arguments. */
static tree
-template_parms_to_args (tree parms)
+template_parms_to_args (tree parms, tsubst_flags_t complain)
{
tree header;
tree args = NULL_TREE;
@@ -4422,7 +4428,8 @@ static tree
for (header = parms; header; header = TREE_CHAIN (header))
{
- tree a = template_parms_level_to_args (TREE_VALUE (header));
+ tree a = template_parms_level_to_args (TREE_VALUE (header),
+ complain);
if (length > 1)
TREE_VEC_ELT (args, --l) = a;
@@ -4437,9 +4444,9 @@ static tree
template parameters as an argument TREE_VEC. */
static tree
-current_template_args (void)
+current_template_args (tsubst_flags_t complain = tf_warning_or_error)
{
- return template_parms_to_args (current_template_parms);
+ return template_parms_to_args (current_template_parms, complain);
}
/* Update the declared TYPE by doing any lookups which were thought to be
@@ -5670,7 +5677,7 @@ add_inherited_template_parms (tree fn, tree inheri
= tree_cons (size_int (processing_template_decl + 1),
inner_parms, current_template_parms);
tree tmpl = build_template_decl (fn, parms, /*member*/true);
- tree args = template_parms_to_args (parms);
+ tree args = template_parms_to_args (parms, tf_warning_or_error);
DECL_TEMPLATE_INFO (fn) = build_template_info (tmpl, args);
TREE_TYPE (tmpl) = TREE_TYPE (fn);
DECL_TEMPLATE_RESULT (tmpl) = fn;
@@ -5995,7 +6002,7 @@ num_innermost_template_parms (tree tmpl)
the other template. */
static tree
-get_underlying_template (tree tmpl)
+get_underlying_template (tree tmpl, tsubst_flags_t complain)
{
gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
while (DECL_ALIAS_TEMPLATE_P (tmpl))
@@ -6013,7 +6020,8 @@ static tree
break;
tree alias_args = INNERMOST_TEMPLATE_ARGS
- (template_parms_to_args (DECL_TEMPLATE_PARMS (tmpl)));
+ (template_parms_to_args (DECL_TEMPLATE_PARMS (tmpl),
+ complain));
if (!comp_template_args (TI_ARGS (tinfo), alias_args))
break;
@@ -7006,7 +7014,7 @@ coerce_template_args_for_ttp (tree templ, tree arg
if (DECL_TEMPLATE_SPECIALIZATION (outer))
/* We want arguments for the partial specialization, not arguments for
the primary template. */
- outer = template_parms_to_args (DECL_TEMPLATE_PARMS (outer));
+ outer = template_parms_to_args (DECL_TEMPLATE_PARMS (outer), complain);
else
outer = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (outer)));
}
@@ -7023,7 +7031,7 @@ coerce_template_args_for_ttp (tree templ, tree arg
!= TEMPLATE_TYPE_LEVEL (TREE_TYPE (templ)))
relevant_template_parms = TREE_CHAIN (relevant_template_parms);
- outer = template_parms_to_args (relevant_template_parms);
+ outer = template_parms_to_args (relevant_template_parms, complain);
}
if (outer)
@@ -7267,7 +7275,7 @@ coerce_template_template_parms (tree parm_parms,
/* So coerce P's args to apply to A's parms, and then deduce between A's
args and the converted args. If that succeeds, A is at least as
specialized as P, so they match.*/
- tree pargs = template_parms_level_to_args (parm_parms);
+ tree pargs = template_parms_level_to_args (parm_parms, complain);
++processing_template_decl;
pargs = coerce_template_parms (arg_parms, pargs, NULL_TREE, tf_none,
/*require_all*/true, /*use_default*/true);
@@ -7275,7 +7283,7 @@ coerce_template_template_parms (tree parm_parms,
if (pargs != error_mark_node)
{
tree targs = make_tree_vec (nargs);
- tree aargs = template_parms_level_to_args (arg_parms);
+ tree aargs = template_parms_level_to_args (arg_parms, complain);
if (!unify (arg_parms, targs, aargs, pargs, UNIFY_ALLOW_NONE,
/*explain*/false))
return 1;
@@ -7493,7 +7501,8 @@ is_compatible_template_arg (tree parm, tree arg)
// words, because coercion is successful, this conversion will be valid.
if (parm_cons)
{
- tree args = template_parms_to_args (DECL_TEMPLATE_PARMS (arg));
+ tree args = template_parms_to_args (DECL_TEMPLATE_PARMS (arg),
+ tf_none);
parm_cons = tsubst_constraint_info (parm_cons,
INNERMOST_TEMPLATE_ARGS (args),
tf_none, NULL_TREE);
@@ -7678,7 +7687,7 @@ convert_template_argument (tree parm,
/* Strip alias templates that are equivalent to another
template. */
- arg = get_underlying_template (arg);
+ arg = get_underlying_template (arg, complain);
argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
if (coerce_template_template_parms (parmparm, argparm,
@@ -7694,7 +7703,7 @@ convert_template_argument (tree parm,
if (DECL_TEMPLATE_TEMPLATE_PARM_P (val))
val = TREE_TYPE (val);
if (TREE_CODE (orig_arg) == TYPE_PACK_EXPANSION)
- val = make_pack_expansion (val);
+ val = make_pack_expansion (val, complain);
}
}
else
@@ -8188,7 +8197,7 @@ coerce_template_parms (tree parms,
else if (TYPE_P (conv) && !TYPE_P (pattern))
/* Recover from missing typename. */
TREE_VEC_ELT (inner_args, arg_idx)
- = make_pack_expansion (conv);
+ = make_pack_expansion (conv, complain);
/* We don't know how many args we have yet, just
use the unconverted ones for now. */
@@ -8697,7 +8706,7 @@ lookup_template_class_1 (tree d1, tree arglist, tr
the alias to avoid problems with a pack expansion passed to a non-pack
alias template parameter (DR 1430). */
if (pack_expansion_args_count (INNERMOST_TEMPLATE_ARGS (arglist)))
- templ = get_underlying_template (templ);
+ templ = get_underlying_template (templ, complain);
if (DECL_TEMPLATE_TEMPLATE_PARM_P (templ))
{
@@ -11161,7 +11170,7 @@ gen_elem_of_pack_expansion_instantiation (tree pat
the Ith element resulting from the substituting is going to
be a pack expansion as well. */
if (ith_elem_is_expansion)
- t = make_pack_expansion (t);
+ t = make_pack_expansion (t, complain);
return t;
}
@@ -11573,7 +11582,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_f
/* We got some full packs, but we can't substitute them in until we
have values for all the packs. So remember these until then. */
- t = make_pack_expansion (pattern);
+ t = make_pack_expansion (pattern, complain);
PACK_EXPANSION_EXTRA_ARGS (t) = args;
return t;
}
@@ -11588,7 +11597,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_f
/*integral_constant_expression_p=*/false);
else
t = tsubst (pattern, args, complain, in_decl);
- t = make_pack_expansion (t);
+ t = make_pack_expansion (t, complain);
return t;
}
@@ -12551,7 +12560,8 @@ tsubst_template_decl (tree t, tree args, tsubst_fl
DECL_CONTEXT (r) = DECL_CONTEXT (new_decl);
if (lambda_fntype)
{
- tree args = template_parms_to_args (DECL_TEMPLATE_PARMS (r));
+ tree args = template_parms_to_args (DECL_TEMPLATE_PARMS (r),
+ complain);
DECL_TEMPLATE_INFO (new_decl) = build_template_info (r, args);
}
else
@@ -21323,7 +21333,7 @@ unify (tree tparms, tree targs, tree parm, tree ar
if (REFERENCE_REF_P (arg))
arg = TREE_OPERAND (arg, 0);
if (pexp)
- arg = make_pack_expansion (arg);
+ arg = make_pack_expansion (arg, complain);
return unify (tparms, targs, TREE_OPERAND (parm, 0), arg,
strict, explain_p);
}
@@ -25378,7 +25388,7 @@ rewrite_template_parm (tree olddecl, unsigned inde
for (int i = 0; i < depth; ++i)
TREE_VEC_ELT (ttargs, i) = TREE_VEC_ELT (tsubst_args, i);
TREE_VEC_ELT (ttargs, depth)
- = template_parms_level_to_args (ttparms);
+ = template_parms_level_to_args (ttparms, complain);
// Substitute ttargs into ttparms to fix references to
// other template parameters.
ttparms = tsubst_template_parms_level (ttparms, ttargs,
@@ -25385,7 +25395,7 @@ rewrite_template_parm (tree olddecl, unsigned inde
complain);
// Now substitute again with args based on tparms, to reduce
// the level of the ttparms.
- ttargs = current_template_args ();
+ ttargs = current_template_args (complain);
ttparms = tsubst_template_parms_level (ttparms, ttargs,
complain);
// Finally, tack the adjusted parms onto tparms.
@@ -25527,12 +25537,13 @@ build_deduction_guide (tree ctor, tree outer_args,
= tsubst_constraint_info (TEMPLATE_PARM_CONSTRAINTS (oldelt),
tsubst_args, complain, ctor);
TREE_VEC_ELT (new_vec, index) = list;
- TMPL_ARG (tsubst_args, depth, i) = template_parm_to_arg (list);
+ TMPL_ARG (tsubst_args, depth, i)
+ = template_parm_to_arg (list, complain);
}
/* Now we have a final set of template parms to substitute into the
function signature. */
- targs = template_parms_to_args (tparms);
+ targs = template_parms_to_args (tparms, complain);
fparms = tsubst_arg_types (fparms, tsubst_args, NULL_TREE,
complain, ctor);
fargs = tsubst (fargs, tsubst_args, complain, ctor);
@@ -25950,7 +25961,7 @@ do_auto_deduction (tree type, tree init, tree auto
}
if (processing_template_decl && context != adc_unify)
- outer_targs = current_template_args ();
+ outer_targs = current_template_args (complain);
targs = add_to_template_args (outer_targs, targs);
return tsubst (type, targs, complain, NULL_TREE);
}
@@ -26187,7 +26198,8 @@ convert_generic_types_to_packs (tree parm, int sta
template parms. */
if (depth > 1)
replacement = add_to_template_args (template_parms_to_args
- (TREE_CHAIN (current_template_parms)),
+ (TREE_CHAIN (current_template_parms),
+ tf_none),
replacement);
return tsubst (parm, replacement, tf_none, NULL_TREE);
===================================================================
@@ -1208,7 +1208,7 @@ cp_build_qualified_type_real (tree type,
tree t = PACK_EXPANSION_PATTERN (type);
t = cp_build_qualified_type_real (t, type_quals, complain);
- return make_pack_expansion (t);
+ return make_pack_expansion (t, complain);
}
/* A reference or method type shall not be cv-qualified.
===================================================================
@@ -0,0 +1,28 @@
+// PR c++/81957
+// { dg-do compile { target c++11 } }
+
+template <class T, T v>
+struct integral_constant { };
+
+struct f {
+ template<bool b, typename Int>
+ void operator()(integral_constant<bool,b>, Int i) {
+ }
+};
+
+template<bool...Bs, typename F, typename ...T>
+auto dispatch(F f, T...t) -> decltype(f(integral_constant<bool,Bs>()..., t...)) {
+ return f(integral_constant<bool,Bs>()..., t...);
+}
+
+template<bool...Bs, typename F, typename ...T>
+auto dispatch(F f, bool b, T...t) -> decltype(dispatch<Bs..., true>(f, t...)) {
+ if (b)
+ return dispatch<Bs..., true>(f, t...);
+ else
+ return dispatch<Bs..., false>(f, t...);
+}
+
+int main() {
+ dispatch(f(), true, 5);
+}