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>
|
||||
|
||||
* 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)
|
||||
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 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
|
||||
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
|
||||
ObjC ObjC++ LTO Report RejectNegative Var(flag_next_runtime)
|
||||
Generate code for NeXT (Apple Mac OS X) runtime environment.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,26 @@
|
|||
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
|
||||
* pt.c (unify_bound_ttp_args): Split out from unify.
|
||||
(try_class_unification): Handle BOUND_TEMPLATE_TEMPLATE_PARM.
|
||||
|
|
|
|||
|
|
@ -1140,6 +1140,8 @@ enum cp_tree_index
|
|||
|
||||
CPTI_ALIGN_TYPE,
|
||||
|
||||
CPTI_ANY_TARG,
|
||||
|
||||
CPTI_MAX
|
||||
};
|
||||
|
||||
|
|
@ -1245,6 +1247,9 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
|
|||
|
||||
#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
|
||||
access nodes in tree.h. */
|
||||
|
||||
|
|
|
|||
|
|
@ -4161,6 +4161,9 @@ cxx_init_decl_processing (void)
|
|||
global_type_node = make_node (LANG_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++. */
|
||||
current_lang_name = lang_name_cplusplus;
|
||||
|
||||
|
|
|
|||
|
|
@ -4758,8 +4758,10 @@ consider_binding_level (tree name, best_match <tree, tree> &bm,
|
|||
&& DECL_ANTICIPATED (d))
|
||||
continue;
|
||||
|
||||
if (DECL_NAME (d))
|
||||
bm.consider (DECL_NAME (d));
|
||||
if (tree name = 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
|
||||
expand_template_argument_pack (tree args)
|
||||
{
|
||||
if (args == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
tree result_args = NULL_TREE;
|
||||
int in_arg, out_arg = 0, nargs = args ? TREE_VEC_LENGTH (args) : 0;
|
||||
int num_result_args = -1;
|
||||
|
|
@ -4758,6 +4761,15 @@ process_partial_specialization (tree decl)
|
|||
DECL_TEMPLATE_INFO (tmpl) = build_template_info (maintmpl, specargs);
|
||||
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))
|
||||
/* We didn't register this in check_explicit_specialization so we could
|
||||
wait until the constraints were set. */
|
||||
|
|
@ -6863,11 +6875,164 @@ coerce_template_template_parm (tree parm,
|
|||
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
|
||||
BOUND_TEMPLATE_TEMPLATE_PARM. */
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
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))
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -6914,6 +7096,48 @@ coerce_template_template_parms (tree parm_parms,
|
|||
nparms = TREE_VEC_LENGTH (parm_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
|
||||
template template parameter's template parameter list. */
|
||||
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)
|
||||
return convert_wildcard_argument (parm, arg);
|
||||
|
||||
if (arg == any_targ_node)
|
||||
return arg;
|
||||
|
||||
if (TREE_CODE (arg) == TREE_LIST
|
||||
&& TREE_CODE (TREE_VALUE (arg)) == OFFSET_REF)
|
||||
{
|
||||
|
|
@ -7822,8 +8049,9 @@ coerce_template_parms (tree parms,
|
|||
in_decl);
|
||||
if (conv == error_mark_node)
|
||||
{
|
||||
inform (input_location, "so any instantiation with a "
|
||||
"non-empty parameter pack would be ill-formed");
|
||||
if (complain & tf_error)
|
||||
inform (input_location, "so any instantiation with a "
|
||||
"non-empty parameter pack would be ill-formed");
|
||||
++lost;
|
||||
}
|
||||
else if (TYPE_P (conv) && !TYPE_P (pattern))
|
||||
|
|
@ -7987,6 +8215,8 @@ template_args_equal (tree ot, tree nt)
|
|||
return 1;
|
||||
if (nt == NULL_TREE || ot == NULL_TREE)
|
||||
return false;
|
||||
if (nt == any_targ_node || ot == any_targ_node)
|
||||
return true;
|
||||
|
||||
if (TREE_CODE (nt) == TREE_VEC)
|
||||
/* 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))
|
||||
{
|
||||
/* Create a new TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM node to store
|
||||
template arguments */
|
||||
|
||||
tree parm;
|
||||
tree arglist2;
|
||||
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);
|
||||
tree arglist2 = coerce_template_args_for_ttp (templ, arglist, complain);
|
||||
if (arglist2 == error_mark_node
|
||||
|| (!uses_template_parms (arglist2)
|
||||
&& 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. */
|
||||
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,
|
||||
even if ARG == PARM, since we won't record unifications for the
|
||||
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-implement-inlines -fms-extensions @gol
|
||||
-fnew-inheriting-ctors @gol
|
||||
-fnew-ttp-matching @gol
|
||||
-fno-nonansi-builtins -fnothrow-opt -fno-operator-names @gol
|
||||
-fno-optional-diags -fpermissive @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
|
||||
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
|
||||
@opindex fno-nonansi-builtins
|
||||
Disable built-in declarations of functions that are not mandated by
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
|
||||
// { dg-options -fno-new-ttp-matching }
|
||||
template<class T> class A { /* ... */ };
|
||||
template<class T, class U = T> class B { /* ... */ };
|
||||
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
|
||||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options -fno-new-ttp-matching }
|
||||
|
||||
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
|
||||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options -fno-new-ttp-matching }
|
||||
|
||||
template<typename...> struct A1;
|
||||
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>
|
||||
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>
|
||||
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 }
|
||||
namespace mpl {
|
||||
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 <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
|
||||
variadic and non-variadic overloads.
|
||||
|
|
|
|||
Loading…
Reference in New Issue