mirror of git://gcc.gnu.org/git/gcc.git
Implement P0522R0, matching of template template arguments.
gcc/c-family/ * c.opt (-fnew-ttp-matching): New flag. * c-opts.c (c_common_post_options): Default on if -std=c++1z. gcc/cp/ * pt.c (coerce_template_template_parms): Allow a template argument that's less specialized than the parameter. (unify_bound_ttp_args): Adjust parm's args to apply to arg's template. (coerce_template_args_for_ttp): Split out from lookup_template_class_1. (coerce_ttp_args_for_tta, store_defaulted_ttp) (lookup_defaulted_ttp, add_defaults_to_ttp): New. (process_partial_specialization): Set DECL_CONTEXT of template template-parameters. (coerce_template_parms): Only inform when complain. (expand_template_argument_pack): Handle error_mark_node. (convert_template_argument, template_args_equal, unify): Handle any_targ_node. * cp-tree.h (enum cp_tree_index): Add CPTI_ANY_TARG. (any_targ_node): New. * decl.c (cxx_init_decl_processing): Set it. * name-lookup.c (consider_binding_level): Ignore names with embedded spaces. From-SVN: r243871
This commit is contained in:
parent
3c75aaa3d8
commit
31bfc9b9dd
|
|
@ -1,3 +1,8 @@
|
||||||
|
2016-12-21 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
|
* c.opt (-fnew-ttp-matching): New flag.
|
||||||
|
* c-opts.c (c_common_post_options): Default on if -std=c++1z.
|
||||||
|
|
||||||
2016-12-14 Martin Jambor <mjambor@suse.cz>
|
2016-12-14 Martin Jambor <mjambor@suse.cz>
|
||||||
|
|
||||||
* c-omp.c: Include omp-general.h instead of omp-low.h.
|
* c-omp.c: Include omp-general.h instead of omp-low.h.
|
||||||
|
|
|
||||||
|
|
@ -920,6 +920,10 @@ c_common_post_options (const char **pfilename)
|
||||||
if (!global_options_set.x_flag_new_inheriting_ctors)
|
if (!global_options_set.x_flag_new_inheriting_ctors)
|
||||||
flag_new_inheriting_ctors = abi_version_at_least (11);
|
flag_new_inheriting_ctors = abi_version_at_least (11);
|
||||||
|
|
||||||
|
/* For GCC 7, only enable DR150 resolution by default if -std=c++1z. */
|
||||||
|
if (!global_options_set.x_flag_new_ttp)
|
||||||
|
flag_new_ttp = (cxx_dialect >= cxx1z);
|
||||||
|
|
||||||
if (cxx_dialect >= cxx11)
|
if (cxx_dialect >= cxx11)
|
||||||
{
|
{
|
||||||
/* If we're allowing C++0x constructs, don't warn about C++98
|
/* If we're allowing C++0x constructs, don't warn about C++98
|
||||||
|
|
|
||||||
|
|
@ -1443,6 +1443,10 @@ C++ ObjC++ Joined Ignore Warn(switch %qs is no longer supported)
|
||||||
fnew-abi
|
fnew-abi
|
||||||
C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
|
C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
|
||||||
|
|
||||||
|
fnew-ttp-matching
|
||||||
|
C++ ObjC++ Var(flag_new_ttp)
|
||||||
|
Implement resolution of DR 150 for matching of template template arguments.
|
||||||
|
|
||||||
fnext-runtime
|
fnext-runtime
|
||||||
ObjC ObjC++ LTO Report RejectNegative Var(flag_next_runtime)
|
ObjC ObjC++ LTO Report RejectNegative Var(flag_next_runtime)
|
||||||
Generate code for NeXT (Apple Mac OS X) runtime environment.
|
Generate code for NeXT (Apple Mac OS X) runtime environment.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,26 @@
|
||||||
2016-12-21 Jason Merrill <jason@redhat.com>
|
2016-12-21 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
|
Implement P0522R0, matching of template template arguments.
|
||||||
|
* pt.c (coerce_template_template_parms): Allow a template argument
|
||||||
|
that's less specialized than the parameter.
|
||||||
|
(unify_bound_ttp_args): Adjust parm's args to apply to arg's
|
||||||
|
template.
|
||||||
|
(coerce_template_args_for_ttp): Split out from
|
||||||
|
lookup_template_class_1.
|
||||||
|
(coerce_ttp_args_for_tta, store_defaulted_ttp)
|
||||||
|
(lookup_defaulted_ttp, add_defaults_to_ttp): New.
|
||||||
|
(process_partial_specialization): Set DECL_CONTEXT of
|
||||||
|
template template-parameters.
|
||||||
|
(coerce_template_parms): Only inform when complain.
|
||||||
|
(expand_template_argument_pack): Handle error_mark_node.
|
||||||
|
(convert_template_argument, template_args_equal, unify): Handle
|
||||||
|
any_targ_node.
|
||||||
|
* cp-tree.h (enum cp_tree_index): Add CPTI_ANY_TARG.
|
||||||
|
(any_targ_node): New.
|
||||||
|
* decl.c (cxx_init_decl_processing): Set it.
|
||||||
|
* name-lookup.c (consider_binding_level): Ignore names with embedded
|
||||||
|
spaces.
|
||||||
|
|
||||||
PR c++/42329
|
PR c++/42329
|
||||||
* pt.c (unify_bound_ttp_args): Split out from unify.
|
* pt.c (unify_bound_ttp_args): Split out from unify.
|
||||||
(try_class_unification): Handle BOUND_TEMPLATE_TEMPLATE_PARM.
|
(try_class_unification): Handle BOUND_TEMPLATE_TEMPLATE_PARM.
|
||||||
|
|
|
||||||
|
|
@ -1140,6 +1140,8 @@ enum cp_tree_index
|
||||||
|
|
||||||
CPTI_ALIGN_TYPE,
|
CPTI_ALIGN_TYPE,
|
||||||
|
|
||||||
|
CPTI_ANY_TARG,
|
||||||
|
|
||||||
CPTI_MAX
|
CPTI_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1245,6 +1247,9 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
|
||||||
|
|
||||||
#define keyed_classes cp_global_trees[CPTI_KEYED_CLASSES]
|
#define keyed_classes cp_global_trees[CPTI_KEYED_CLASSES]
|
||||||
|
|
||||||
|
/* A node which matches any template argument. */
|
||||||
|
#define any_targ_node cp_global_trees[CPTI_ANY_TARG]
|
||||||
|
|
||||||
/* Node to indicate default access. This must be distinct from the
|
/* Node to indicate default access. This must be distinct from the
|
||||||
access nodes in tree.h. */
|
access nodes in tree.h. */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4161,6 +4161,9 @@ cxx_init_decl_processing (void)
|
||||||
global_type_node = make_node (LANG_TYPE);
|
global_type_node = make_node (LANG_TYPE);
|
||||||
record_unknown_type (global_type_node, "global type");
|
record_unknown_type (global_type_node, "global type");
|
||||||
|
|
||||||
|
any_targ_node = make_node (LANG_TYPE);
|
||||||
|
record_unknown_type (any_targ_node, "any type");
|
||||||
|
|
||||||
/* Now, C++. */
|
/* Now, C++. */
|
||||||
current_lang_name = lang_name_cplusplus;
|
current_lang_name = lang_name_cplusplus;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4758,8 +4758,10 @@ consider_binding_level (tree name, best_match <tree, tree> &bm,
|
||||||
&& DECL_ANTICIPATED (d))
|
&& DECL_ANTICIPATED (d))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (DECL_NAME (d))
|
if (tree name = DECL_NAME (d))
|
||||||
bm.consider (DECL_NAME (d));
|
/* Ignore internal names with spaces in them. */
|
||||||
|
if (!strchr (IDENTIFIER_POINTER (name), ' '))
|
||||||
|
bm.consider (DECL_NAME (d));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
292
gcc/cp/pt.c
292
gcc/cp/pt.c
|
|
@ -3836,6 +3836,9 @@ check_for_bare_parameter_packs (tree t)
|
||||||
tree
|
tree
|
||||||
expand_template_argument_pack (tree args)
|
expand_template_argument_pack (tree args)
|
||||||
{
|
{
|
||||||
|
if (args == error_mark_node)
|
||||||
|
return error_mark_node;
|
||||||
|
|
||||||
tree result_args = NULL_TREE;
|
tree result_args = NULL_TREE;
|
||||||
int in_arg, out_arg = 0, nargs = args ? TREE_VEC_LENGTH (args) : 0;
|
int in_arg, out_arg = 0, nargs = args ? TREE_VEC_LENGTH (args) : 0;
|
||||||
int num_result_args = -1;
|
int num_result_args = -1;
|
||||||
|
|
@ -4758,6 +4761,15 @@ process_partial_specialization (tree decl)
|
||||||
DECL_TEMPLATE_INFO (tmpl) = build_template_info (maintmpl, specargs);
|
DECL_TEMPLATE_INFO (tmpl) = build_template_info (maintmpl, specargs);
|
||||||
DECL_PRIMARY_TEMPLATE (tmpl) = maintmpl;
|
DECL_PRIMARY_TEMPLATE (tmpl) = maintmpl;
|
||||||
|
|
||||||
|
/* Give template template parms a DECL_CONTEXT of the template
|
||||||
|
for which they are a parameter. */
|
||||||
|
for (i = 0; i < ntparms; ++i)
|
||||||
|
{
|
||||||
|
tree parm = TREE_VALUE (TREE_VEC_ELT (inner_parms, i));
|
||||||
|
if (TREE_CODE (parm) == TEMPLATE_DECL)
|
||||||
|
DECL_CONTEXT (parm) = tmpl;
|
||||||
|
}
|
||||||
|
|
||||||
if (VAR_P (decl))
|
if (VAR_P (decl))
|
||||||
/* We didn't register this in check_explicit_specialization so we could
|
/* We didn't register this in check_explicit_specialization so we could
|
||||||
wait until the constraints were set. */
|
wait until the constraints were set. */
|
||||||
|
|
@ -6863,11 +6875,164 @@ coerce_template_template_parm (tree parm,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Coerce template argument list ARGLIST for use with template
|
||||||
|
template-parameter TEMPL. */
|
||||||
|
|
||||||
|
static tree
|
||||||
|
coerce_template_args_for_ttp (tree templ, tree arglist,
|
||||||
|
tsubst_flags_t complain)
|
||||||
|
{
|
||||||
|
/* Consider an example where a template template parameter declared as
|
||||||
|
|
||||||
|
template <class T, class U = std::allocator<T> > class TT
|
||||||
|
|
||||||
|
The template parameter level of T and U are one level larger than
|
||||||
|
of TT. To proper process the default argument of U, say when an
|
||||||
|
instantiation `TT<int>' is seen, we need to build the full
|
||||||
|
arguments containing {int} as the innermost level. Outer levels,
|
||||||
|
available when not appearing as default template argument, can be
|
||||||
|
obtained from the arguments of the enclosing template.
|
||||||
|
|
||||||
|
Suppose that TT is later substituted with std::vector. The above
|
||||||
|
instantiation is `TT<int, std::allocator<T> >' with TT at
|
||||||
|
level 1, and T at level 2, while the template arguments at level 1
|
||||||
|
becomes {std::vector} and the inner level 2 is {int}. */
|
||||||
|
|
||||||
|
tree outer = DECL_CONTEXT (templ);
|
||||||
|
if (outer)
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
else
|
||||||
|
outer = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (outer)));
|
||||||
|
}
|
||||||
|
else if (current_template_parms)
|
||||||
|
{
|
||||||
|
/* This is an argument of the current template, so we haven't set
|
||||||
|
DECL_CONTEXT yet. */
|
||||||
|
tree relevant_template_parms;
|
||||||
|
|
||||||
|
/* Parameter levels that are greater than the level of the given
|
||||||
|
template template parm are irrelevant. */
|
||||||
|
relevant_template_parms = current_template_parms;
|
||||||
|
while (TMPL_PARMS_DEPTH (relevant_template_parms)
|
||||||
|
!= TEMPLATE_TYPE_LEVEL (TREE_TYPE (templ)))
|
||||||
|
relevant_template_parms = TREE_CHAIN (relevant_template_parms);
|
||||||
|
|
||||||
|
outer = template_parms_to_args (relevant_template_parms);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outer)
|
||||||
|
arglist = add_to_template_args (outer, arglist);
|
||||||
|
|
||||||
|
tree parmlist = DECL_INNERMOST_TEMPLATE_PARMS (templ);
|
||||||
|
return coerce_template_parms (parmlist, arglist, templ,
|
||||||
|
complain,
|
||||||
|
/*require_all_args=*/true,
|
||||||
|
/*use_default_args=*/true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A cache of template template parameters with match-all default
|
||||||
|
arguments. */
|
||||||
|
static GTY((deletable)) hash_map<tree,tree> *defaulted_ttp_cache;
|
||||||
|
static void
|
||||||
|
store_defaulted_ttp (tree v, tree t)
|
||||||
|
{
|
||||||
|
if (!defaulted_ttp_cache)
|
||||||
|
defaulted_ttp_cache = hash_map<tree,tree>::create_ggc (13);
|
||||||
|
defaulted_ttp_cache->put (v, t);
|
||||||
|
}
|
||||||
|
static tree
|
||||||
|
lookup_defaulted_ttp (tree v)
|
||||||
|
{
|
||||||
|
if (defaulted_ttp_cache)
|
||||||
|
if (tree *p = defaulted_ttp_cache->get (v))
|
||||||
|
return *p;
|
||||||
|
return NULL_TREE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* T is a bound template template-parameter. Copy its arguments into default
|
||||||
|
arguments of the template template-parameter's template parameters. */
|
||||||
|
|
||||||
|
static tree
|
||||||
|
add_defaults_to_ttp (tree otmpl)
|
||||||
|
{
|
||||||
|
if (tree c = lookup_defaulted_ttp (otmpl))
|
||||||
|
return c;
|
||||||
|
|
||||||
|
tree ntmpl = copy_node (otmpl);
|
||||||
|
|
||||||
|
tree ntype = copy_node (TREE_TYPE (otmpl));
|
||||||
|
TYPE_STUB_DECL (ntype) = TYPE_NAME (ntype) = ntmpl;
|
||||||
|
TYPE_MAIN_VARIANT (ntype) = ntype;
|
||||||
|
TYPE_POINTER_TO (ntype) = TYPE_REFERENCE_TO (ntype) = NULL_TREE;
|
||||||
|
TYPE_NAME (ntype) = ntmpl;
|
||||||
|
SET_TYPE_STRUCTURAL_EQUALITY (ntype);
|
||||||
|
|
||||||
|
tree idx = TEMPLATE_TYPE_PARM_INDEX (ntype)
|
||||||
|
= copy_node (TEMPLATE_TYPE_PARM_INDEX (ntype));
|
||||||
|
TEMPLATE_PARM_DECL (idx) = ntmpl;
|
||||||
|
TREE_TYPE (ntmpl) = TREE_TYPE (idx) = ntype;
|
||||||
|
|
||||||
|
tree oparms = DECL_TEMPLATE_PARMS (otmpl);
|
||||||
|
tree parms = DECL_TEMPLATE_PARMS (ntmpl) = copy_node (oparms);
|
||||||
|
TREE_CHAIN (parms) = TREE_CHAIN (oparms);
|
||||||
|
tree vec = TREE_VALUE (parms) = copy_node (TREE_VALUE (parms));
|
||||||
|
for (int i = 0; i < TREE_VEC_LENGTH (vec); ++i)
|
||||||
|
{
|
||||||
|
tree o = TREE_VEC_ELT (vec, i);
|
||||||
|
if (!template_parameter_pack_p (TREE_VALUE (o)))
|
||||||
|
{
|
||||||
|
tree n = TREE_VEC_ELT (vec, i) = copy_node (o);
|
||||||
|
TREE_PURPOSE (n) = any_targ_node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
store_defaulted_ttp (otmpl, ntmpl);
|
||||||
|
return ntmpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ARG is a bound potential template template-argument, and PARGS is a list
|
||||||
|
of arguments for the corresponding template template-parameter. Adjust
|
||||||
|
PARGS as appropriate for application to ARG's template, and if ARG is a
|
||||||
|
BOUND_TEMPLATE_TEMPLATE_PARM, possibly adjust it to add default template
|
||||||
|
arguments to the template template parameter. */
|
||||||
|
|
||||||
|
static tree
|
||||||
|
coerce_ttp_args_for_tta (tree& arg, tree pargs, tsubst_flags_t complain)
|
||||||
|
{
|
||||||
|
++processing_template_decl;
|
||||||
|
tree arg_tmpl = TYPE_TI_TEMPLATE (arg);
|
||||||
|
if (DECL_TEMPLATE_TEMPLATE_PARM_P (arg_tmpl))
|
||||||
|
{
|
||||||
|
/* When comparing two template template-parameters in partial ordering,
|
||||||
|
rewrite the one currently being used as an argument to have default
|
||||||
|
arguments for all parameters. */
|
||||||
|
arg_tmpl = add_defaults_to_ttp (arg_tmpl);
|
||||||
|
pargs = coerce_template_args_for_ttp (arg_tmpl, pargs, complain);
|
||||||
|
if (pargs != error_mark_node)
|
||||||
|
arg = bind_template_template_parm (TREE_TYPE (arg_tmpl),
|
||||||
|
TYPE_TI_ARGS (arg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tree aparms
|
||||||
|
= INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (arg_tmpl));
|
||||||
|
pargs = coerce_template_parms (aparms, pargs, arg_tmpl, complain,
|
||||||
|
/*require_all*/true,
|
||||||
|
/*use_default*/true);
|
||||||
|
}
|
||||||
|
--processing_template_decl;
|
||||||
|
return pargs;
|
||||||
|
}
|
||||||
|
|
||||||
/* Subroutine of unify for the case when PARM is a
|
/* Subroutine of unify for the case when PARM is a
|
||||||
BOUND_TEMPLATE_TEMPLATE_PARM. */
|
BOUND_TEMPLATE_TEMPLATE_PARM. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
unify_bound_ttp_args (tree tparms, tree targs, tree parm, tree arg,
|
unify_bound_ttp_args (tree tparms, tree targs, tree parm, tree& arg,
|
||||||
bool explain_p)
|
bool explain_p)
|
||||||
{
|
{
|
||||||
tree parmvec = TYPE_TI_ARGS (parm);
|
tree parmvec = TYPE_TI_ARGS (parm);
|
||||||
|
|
@ -6878,10 +7043,27 @@ unify_bound_ttp_args (tree tparms, tree targs, tree parm, tree arg,
|
||||||
parmvec = expand_template_argument_pack (parmvec);
|
parmvec = expand_template_argument_pack (parmvec);
|
||||||
argvec = expand_template_argument_pack (argvec);
|
argvec = expand_template_argument_pack (argvec);
|
||||||
|
|
||||||
if (unify (tparms, targs, parmvec, argvec,
|
tree nparmvec = parmvec;
|
||||||
|
if (flag_new_ttp)
|
||||||
|
{
|
||||||
|
/* In keeping with P0522R0, adjust P's template arguments
|
||||||
|
to apply to A's template; then flatten it again. */
|
||||||
|
nparmvec = coerce_ttp_args_for_tta (arg, parmvec, tf_none);
|
||||||
|
nparmvec = expand_template_argument_pack (nparmvec);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unify (tparms, targs, nparmvec, argvec,
|
||||||
UNIFY_ALLOW_NONE, explain_p))
|
UNIFY_ALLOW_NONE, explain_p))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
/* If the P0522 adjustment eliminated a pack expansion, deduce
|
||||||
|
empty packs. */
|
||||||
|
if (flag_new_ttp
|
||||||
|
&& TREE_VEC_LENGTH (nparmvec) < TREE_VEC_LENGTH (parmvec)
|
||||||
|
&& unify_pack_expansion (tparms, targs, parmvec, argvec,
|
||||||
|
DEDUCE_EXACT, /*sub*/true, explain_p))
|
||||||
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -6914,6 +7096,48 @@ coerce_template_template_parms (tree parm_parms,
|
||||||
nparms = TREE_VEC_LENGTH (parm_parms);
|
nparms = TREE_VEC_LENGTH (parm_parms);
|
||||||
nargs = TREE_VEC_LENGTH (arg_parms);
|
nargs = TREE_VEC_LENGTH (arg_parms);
|
||||||
|
|
||||||
|
if (flag_new_ttp)
|
||||||
|
{
|
||||||
|
/* P0522R0: A template template-parameter P is at least as specialized as
|
||||||
|
a template template-argument A if, given the following rewrite to two
|
||||||
|
function templates, the function template corresponding to P is at
|
||||||
|
least as specialized as the function template corresponding to A
|
||||||
|
according to the partial ordering rules for function templates
|
||||||
|
([temp.func.order]). Given an invented class template X with the
|
||||||
|
template parameter list of A (including default arguments):
|
||||||
|
|
||||||
|
* Each of the two function templates has the same template parameters,
|
||||||
|
respectively, as P or A.
|
||||||
|
|
||||||
|
* Each function template has a single function parameter whose type is
|
||||||
|
a specialization of X with template arguments corresponding to the
|
||||||
|
template parameters from the respective function template where, for
|
||||||
|
each template parameter PP in the template parameter list of the
|
||||||
|
function template, a corresponding template argument AA is formed. If
|
||||||
|
PP declares a parameter pack, then AA is the pack expansion
|
||||||
|
PP... ([temp.variadic]); otherwise, AA is the id-expression PP.
|
||||||
|
|
||||||
|
If the rewrite produces an invalid type, then P is not at least as
|
||||||
|
specialized as A. */
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
++processing_template_decl;
|
||||||
|
pargs = coerce_template_parms (arg_parms, pargs, NULL_TREE, tf_none,
|
||||||
|
/*require_all*/true, /*use_default*/true);
|
||||||
|
--processing_template_decl;
|
||||||
|
if (pargs != error_mark_node)
|
||||||
|
{
|
||||||
|
tree targs = make_tree_vec (nargs);
|
||||||
|
tree aargs = template_parms_level_to_args (arg_parms);
|
||||||
|
if (!unify (arg_parms, targs, aargs, pargs, UNIFY_ALLOW_NONE,
|
||||||
|
/*explain*/false))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Determine whether we have a parameter pack at the end of the
|
/* Determine whether we have a parameter pack at the end of the
|
||||||
template template parameter's template parameter list. */
|
template template parameter's template parameter list. */
|
||||||
if (TREE_VEC_ELT (parm_parms, nparms - 1) != error_mark_node)
|
if (TREE_VEC_ELT (parm_parms, nparms - 1) != error_mark_node)
|
||||||
|
|
@ -7172,6 +7396,9 @@ convert_template_argument (tree parm,
|
||||||
if (TREE_CODE (arg) == WILDCARD_DECL)
|
if (TREE_CODE (arg) == WILDCARD_DECL)
|
||||||
return convert_wildcard_argument (parm, arg);
|
return convert_wildcard_argument (parm, arg);
|
||||||
|
|
||||||
|
if (arg == any_targ_node)
|
||||||
|
return arg;
|
||||||
|
|
||||||
if (TREE_CODE (arg) == TREE_LIST
|
if (TREE_CODE (arg) == TREE_LIST
|
||||||
&& TREE_CODE (TREE_VALUE (arg)) == OFFSET_REF)
|
&& TREE_CODE (TREE_VALUE (arg)) == OFFSET_REF)
|
||||||
{
|
{
|
||||||
|
|
@ -7822,8 +8049,9 @@ coerce_template_parms (tree parms,
|
||||||
in_decl);
|
in_decl);
|
||||||
if (conv == error_mark_node)
|
if (conv == error_mark_node)
|
||||||
{
|
{
|
||||||
inform (input_location, "so any instantiation with a "
|
if (complain & tf_error)
|
||||||
"non-empty parameter pack would be ill-formed");
|
inform (input_location, "so any instantiation with a "
|
||||||
|
"non-empty parameter pack would be ill-formed");
|
||||||
++lost;
|
++lost;
|
||||||
}
|
}
|
||||||
else if (TYPE_P (conv) && !TYPE_P (pattern))
|
else if (TYPE_P (conv) && !TYPE_P (pattern))
|
||||||
|
|
@ -7987,6 +8215,8 @@ template_args_equal (tree ot, tree nt)
|
||||||
return 1;
|
return 1;
|
||||||
if (nt == NULL_TREE || ot == NULL_TREE)
|
if (nt == NULL_TREE || ot == NULL_TREE)
|
||||||
return false;
|
return false;
|
||||||
|
if (nt == any_targ_node || ot == any_targ_node)
|
||||||
|
return true;
|
||||||
|
|
||||||
if (TREE_CODE (nt) == TREE_VEC)
|
if (TREE_CODE (nt) == TREE_VEC)
|
||||||
/* For member templates */
|
/* For member templates */
|
||||||
|
|
@ -8328,57 +8558,8 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
|
||||||
|
|
||||||
if (DECL_TEMPLATE_TEMPLATE_PARM_P (templ))
|
if (DECL_TEMPLATE_TEMPLATE_PARM_P (templ))
|
||||||
{
|
{
|
||||||
/* Create a new TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM node to store
|
|
||||||
template arguments */
|
|
||||||
|
|
||||||
tree parm;
|
tree parm;
|
||||||
tree arglist2;
|
tree arglist2 = coerce_template_args_for_ttp (templ, arglist, complain);
|
||||||
tree outer;
|
|
||||||
|
|
||||||
parmlist = DECL_INNERMOST_TEMPLATE_PARMS (templ);
|
|
||||||
|
|
||||||
/* Consider an example where a template template parameter declared as
|
|
||||||
|
|
||||||
template <class T, class U = std::allocator<T> > class TT
|
|
||||||
|
|
||||||
The template parameter level of T and U are one level larger than
|
|
||||||
of TT. To proper process the default argument of U, say when an
|
|
||||||
instantiation `TT<int>' is seen, we need to build the full
|
|
||||||
arguments containing {int} as the innermost level. Outer levels,
|
|
||||||
available when not appearing as default template argument, can be
|
|
||||||
obtained from the arguments of the enclosing template.
|
|
||||||
|
|
||||||
Suppose that TT is later substituted with std::vector. The above
|
|
||||||
instantiation is `TT<int, std::allocator<T> >' with TT at
|
|
||||||
level 1, and T at level 2, while the template arguments at level 1
|
|
||||||
becomes {std::vector} and the inner level 2 is {int}. */
|
|
||||||
|
|
||||||
outer = DECL_CONTEXT (templ);
|
|
||||||
if (outer)
|
|
||||||
outer = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (outer)));
|
|
||||||
else if (current_template_parms)
|
|
||||||
{
|
|
||||||
/* This is an argument of the current template, so we haven't set
|
|
||||||
DECL_CONTEXT yet. */
|
|
||||||
tree relevant_template_parms;
|
|
||||||
|
|
||||||
/* Parameter levels that are greater than the level of the given
|
|
||||||
template template parm are irrelevant. */
|
|
||||||
relevant_template_parms = current_template_parms;
|
|
||||||
while (TMPL_PARMS_DEPTH (relevant_template_parms)
|
|
||||||
!= TEMPLATE_TYPE_LEVEL (TREE_TYPE (templ)))
|
|
||||||
relevant_template_parms = TREE_CHAIN (relevant_template_parms);
|
|
||||||
|
|
||||||
outer = template_parms_to_args (relevant_template_parms);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outer)
|
|
||||||
arglist = add_to_template_args (outer, arglist);
|
|
||||||
|
|
||||||
arglist2 = coerce_template_parms (parmlist, arglist, templ,
|
|
||||||
complain,
|
|
||||||
/*require_all_args=*/true,
|
|
||||||
/*use_default_args=*/true);
|
|
||||||
if (arglist2 == error_mark_node
|
if (arglist2 == error_mark_node
|
||||||
|| (!uses_template_parms (arglist2)
|
|| (!uses_template_parms (arglist2)
|
||||||
&& check_instantiated_args (templ, arglist2, complain)))
|
&& check_instantiated_args (templ, arglist2, complain)))
|
||||||
|
|
@ -19950,6 +20131,9 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
|
||||||
template args from other function args. */
|
template args from other function args. */
|
||||||
return unify_success (explain_p);
|
return unify_success (explain_p);
|
||||||
|
|
||||||
|
if (parm == any_targ_node || arg == any_targ_node)
|
||||||
|
return unify_success (explain_p);
|
||||||
|
|
||||||
/* If PARM uses template parameters, then we can't bail out here,
|
/* If PARM uses template parameters, then we can't bail out here,
|
||||||
even if ARG == PARM, since we won't record unifications for the
|
even if ARG == PARM, since we won't record unifications for the
|
||||||
template parameters. We might need them if we're trying to
|
template parameters. We might need them if we're trying to
|
||||||
|
|
|
||||||
|
|
@ -201,6 +201,7 @@ in the following sections.
|
||||||
-fno-implicit-inline-templates @gol
|
-fno-implicit-inline-templates @gol
|
||||||
-fno-implement-inlines -fms-extensions @gol
|
-fno-implement-inlines -fms-extensions @gol
|
||||||
-fnew-inheriting-ctors @gol
|
-fnew-inheriting-ctors @gol
|
||||||
|
-fnew-ttp-matching @gol
|
||||||
-fno-nonansi-builtins -fnothrow-opt -fno-operator-names @gol
|
-fno-nonansi-builtins -fnothrow-opt -fno-operator-names @gol
|
||||||
-fno-optional-diags -fpermissive @gol
|
-fno-optional-diags -fpermissive @gol
|
||||||
-fno-pretty-templates @gol
|
-fno-pretty-templates @gol
|
||||||
|
|
@ -2455,6 +2456,14 @@ inheritance. This is part of C++17 but also considered to be a Defect
|
||||||
Report against C++11 and C++14. This flag is enabled by default
|
Report against C++11 and C++14. This flag is enabled by default
|
||||||
unless @option{-fabi-version=10} or lower is specified.
|
unless @option{-fabi-version=10} or lower is specified.
|
||||||
|
|
||||||
|
@item -fnew-ttp-matching
|
||||||
|
@opindex fnew-ttp-matching
|
||||||
|
Enable the P0522 resolution to Core issue 150, template template
|
||||||
|
parameters and default arguments: this allows a template with default
|
||||||
|
template arguments as an argument for a template template parameter
|
||||||
|
with fewer template parameters. This flag is enabled by default for
|
||||||
|
@option{-std=c++1z}.
|
||||||
|
|
||||||
@item -fno-nonansi-builtins
|
@item -fno-nonansi-builtins
|
||||||
@opindex fno-nonansi-builtins
|
@opindex fno-nonansi-builtins
|
||||||
Disable built-in declarations of functions that are not mandated by
|
Disable built-in declarations of functions that are not mandated by
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// { dg-do compile { target c++11 } }
|
// { dg-do compile { target c++11 } }
|
||||||
|
// { dg-options -fno-new-ttp-matching }
|
||||||
template<class T> class A { /* ... */ };
|
template<class T> class A { /* ... */ };
|
||||||
template<class T, class U = T> class B { /* ... */ };
|
template<class T, class U = T> class B { /* ... */ };
|
||||||
template<class... Types> class C { /* ... */ };
|
template<class... Types> class C { /* ... */ };
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
// CWG 150: Matching of template template-arguments excludes compatible
|
||||||
|
// templates
|
||||||
|
// { dg-options -fnew-ttp-matching }
|
||||||
|
|
||||||
|
template<class T> class A { /* ... */ };
|
||||||
|
template<class T, class U = T> class B { /* ... */ };
|
||||||
|
template<template<class> class P> class X { /* ... */ };
|
||||||
|
X<A> xa; // OK
|
||||||
|
X<B> xb; // OK since P0522R0
|
||||||
|
|
||||||
|
#if __cpp_variadic_templates
|
||||||
|
template <class ... Types> class C { /* ... */ };
|
||||||
|
template<template<class ...> class Q> class Y { /* ... */ };
|
||||||
|
X<C> xc; // OK since P0522R0
|
||||||
|
Y<A> ya; // OK
|
||||||
|
Y<B> yb; // OK
|
||||||
|
Y<C> yc; // OK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __cpp_template_auto
|
||||||
|
template<auto n> class D { /* ... */ };
|
||||||
|
template<template<int> class R> class Z { /* ... */ };
|
||||||
|
Z<D> zd; // OK
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
// { dg-do compile { target c++11 } }
|
||||||
|
|
||||||
|
template<typename _Tp>
|
||||||
|
struct get_first_arg;
|
||||||
|
|
||||||
|
template<template<typename, typename...> class _Template, typename _Tp,
|
||||||
|
typename... _Types>
|
||||||
|
struct get_first_arg<_Template<_Tp, _Types...>>
|
||||||
|
{ using type = _Tp; };
|
||||||
|
|
||||||
|
template<typename T> struct A { };
|
||||||
|
|
||||||
|
template<class,class> struct same;
|
||||||
|
template<class T> struct same<T,T> {};
|
||||||
|
|
||||||
|
same<get_first_arg<A<int>>::type,
|
||||||
|
int> x;
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
// { dg-do compile { target c++11 } }
|
||||||
|
|
||||||
|
template <typename, typename> struct A { };
|
||||||
|
template <typename T> struct B { };
|
||||||
|
|
||||||
|
template <typename T, template <T...> class C, T... Is>
|
||||||
|
struct A<B<T>, C<Is...>>
|
||||||
|
{
|
||||||
|
using type = C<Is...>;
|
||||||
|
};
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
// PR c++/33213
|
// PR c++/33213
|
||||||
// { dg-do compile { target c++11 } }
|
// { dg-do compile { target c++11 } }
|
||||||
|
// { dg-options -fno-new-ttp-matching }
|
||||||
|
|
||||||
template<template<typename> class...> struct A;
|
template<template<typename> class...> struct A;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
// PR c++/33213
|
||||||
|
// { dg-do compile { target c++11 } }
|
||||||
|
// { dg-options -fnew-ttp-matching }
|
||||||
|
|
||||||
|
template<template<typename> class...> struct A;
|
||||||
|
|
||||||
|
template<template<typename...> class... B> struct A<B...> {};
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
// PR c++/32565
|
// PR c++/32565
|
||||||
// { dg-do compile { target c++11 } }
|
// { dg-do compile { target c++11 } }
|
||||||
|
// { dg-options -fno-new-ttp-matching }
|
||||||
|
|
||||||
template<typename...> struct A1;
|
template<typename...> struct A1;
|
||||||
template<template<int, int...> class T> struct A1<T<0, 1> > {};
|
template<template<int, int...> class T> struct A1<T<0, 1> > {};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
// PR c++/32565
|
||||||
|
// { dg-do compile { target c++11 } }
|
||||||
|
// { dg-options -fnew-ttp-matching }
|
||||||
|
|
||||||
|
template<typename...> struct A1;
|
||||||
|
template<template<int, int...> class T> struct A1<T<0, 1> > {};
|
||||||
|
template<int, int, int...> struct B1 {};
|
||||||
|
A1<B1<0, 1> > a1;
|
||||||
|
template<int...> struct B2 {};
|
||||||
|
A1<B2<0, 1> > a2;
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
// CWG 150: Matching of template template-arguments excludes compatible
|
||||||
|
// templates
|
||||||
|
|
||||||
|
// { dg-options -fnew-ttp-matching }
|
||||||
|
|
||||||
|
template<class T, class U = T> class B { /* ... */ };
|
||||||
|
#if __cpp_variadic_templates
|
||||||
|
template <class ... Types> class C { /* ... */ };
|
||||||
|
#endif
|
||||||
|
template<template<class> class P, class T> void f(P<T>);
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
f(B<int>());
|
||||||
|
f(B<int,float>()); // { dg-error "no match" }
|
||||||
|
#if __cpp_variadic_templates
|
||||||
|
f(C<int>());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
// { dg-options -fno-new-ttp-matching }
|
||||||
|
|
||||||
template <template <typename> class C>
|
template <template <typename> class C>
|
||||||
void f() {}
|
void f() {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
// { dg-options -fnew-ttp-matching }
|
||||||
|
|
||||||
|
template <template <typename> class C>
|
||||||
|
void f() {}
|
||||||
|
|
||||||
|
template <typename T, typename U = int>
|
||||||
|
struct S {};
|
||||||
|
|
||||||
|
template void f<S>();
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
// { dg-options -fno-new-ttp-matching }
|
||||||
|
|
||||||
template <template <typename> class C>
|
template <template <typename> class C>
|
||||||
void f(C<double>) {}
|
void f(C<double>) {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
// { dg-options -fnew-ttp-matching }
|
||||||
|
|
||||||
|
template <template <typename> class C>
|
||||||
|
void f(C<double>) {}
|
||||||
|
|
||||||
|
template <typename T, typename U = int>
|
||||||
|
struct S {};
|
||||||
|
|
||||||
|
template void f(S<double>);
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
// { dg-options -fno-new-ttp-matching }
|
||||||
// { dg-do compile }
|
// { dg-do compile }
|
||||||
namespace mpl {
|
namespace mpl {
|
||||||
template <typename, typename = int> struct lambda;
|
template <typename, typename = int> struct lambda;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// { dg-do assemble }
|
// { dg-options -fno-new-ttp-matching }
|
||||||
|
|
||||||
template <int i> class C {};
|
template <int i> class C {};
|
||||||
template <template <long> class TT> class D {};
|
template <template <long> class TT> class D {};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
// { dg-options -fnew-ttp-matching }
|
||||||
|
|
||||||
|
template <int i> class C {};
|
||||||
|
template <template <long> class TT> class D {};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
D<C> d;
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
2016-12-16 Jason Merrill <jason@redhat.com>
|
2016-12-21 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
* testsuite/util/testsuite_tr1.h (test_property): Don't define both
|
* testsuite/util/testsuite_tr1.h (test_property): Don't define both
|
||||||
variadic and non-variadic overloads.
|
variadic and non-variadic overloads.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue