PR c++/79960 - alias templates and partial ordering

* pt.c (comp_template_args): Add partial_order parm.
	(template_args_equal): Likewise.
	(comp_template_args_porder): New.
	(get_partial_spec_bindings): Use it.

From-SVN: r246042
This commit is contained in:
Jason Merrill 2017-03-10 12:35:54 -05:00 committed by Jason Merrill
parent 8e2c69b489
commit 0c942f3eda
4 changed files with 59 additions and 9 deletions

View File

@ -1,3 +1,11 @@
2017-03-10 Jason Merrill <jason@redhat.com>
PR c++/79960 - alias templates and partial ordering
* pt.c (comp_template_args): Add partial_order parm.
(template_args_equal): Likewise.
(comp_template_args_porder): New.
(get_partial_spec_bindings): Use it.
2017-03-10 Marek Polacek <polacek@redhat.com>
PR c++/79967

View File

@ -6208,8 +6208,8 @@ extern int is_specialization_of (tree, tree);
extern bool is_specialization_of_friend (tree, tree);
extern tree get_pattern_parm (tree, tree);
extern int comp_template_args (tree, tree, tree * = NULL,
tree * = NULL);
extern int template_args_equal (tree, tree);
tree * = NULL, bool = false);
extern int template_args_equal (tree, tree, bool = false);
extern tree maybe_process_partial_specialization (tree);
extern tree most_specialized_instantiation (tree);
extern void print_candidates (tree);

View File

@ -8240,7 +8240,7 @@ coerce_innermost_template_parms (tree parms,
/* Returns 1 if template args OT and NT are equivalent. */
int
template_args_equal (tree ot, tree nt)
template_args_equal (tree ot, tree nt, bool partial_order /* = false */)
{
if (nt == ot)
return 1;
@ -8288,8 +8288,13 @@ template_args_equal (tree ot, tree nt)
template argument; we need them to be distinct so that we
substitute into the specialization arguments at instantiation
time. And aliases can't be equivalent without being ==, so
we don't need to look any deeper. */
if (TYPE_ALIAS_P (nt) || TYPE_ALIAS_P (ot))
we don't need to look any deeper.
During partial ordering, however, we need to treat them normally so
that we can order uses of the same alias with different
cv-qualification (79960). */
if (!partial_order
&& (TYPE_ALIAS_P (nt) || TYPE_ALIAS_P (ot)))
return false;
else
return same_type_p (ot, nt);
@ -8321,7 +8326,8 @@ template_args_equal (tree ot, tree nt)
int
comp_template_args (tree oldargs, tree newargs,
tree *oldarg_ptr, tree *newarg_ptr)
tree *oldarg_ptr, tree *newarg_ptr,
bool partial_order)
{
int i;
@ -8339,7 +8345,7 @@ comp_template_args (tree oldargs, tree newargs,
tree nt = TREE_VEC_ELT (newargs, i);
tree ot = TREE_VEC_ELT (oldargs, i);
if (! template_args_equal (ot, nt))
if (! template_args_equal (ot, nt, partial_order))
{
if (oldarg_ptr != NULL)
*oldarg_ptr = ot;
@ -8351,6 +8357,12 @@ comp_template_args (tree oldargs, tree newargs,
return 1;
}
inline bool
comp_template_args_porder (tree oargs, tree nargs)
{
return comp_template_args (oargs, nargs, NULL, NULL, true);
}
static void
add_pending_template (tree d)
{
@ -21584,8 +21596,8 @@ get_partial_spec_bindings (tree tmpl, tree spec_tmpl, tree args)
if (spec_args == error_mark_node
/* We only need to check the innermost arguments; the other
arguments will always agree. */
|| !comp_template_args (INNERMOST_TEMPLATE_ARGS (spec_args),
INNERMOST_TEMPLATE_ARGS (args)))
|| !comp_template_args_porder (INNERMOST_TEMPLATE_ARGS (spec_args),
INNERMOST_TEMPLATE_ARGS (args)))
return NULL_TREE;
/* Now that we have bindings for all of the template arguments,

View File

@ -0,0 +1,30 @@
// PR c++/79960
// { dg-do compile { target c++11 } }
using size_t = decltype(sizeof(0));
template<typename T> struct tuple_size;
template<typename T, size_t U = tuple_size<T>::value>
using __has_tuple_size = T;
template<typename T> struct tuple_size<const __has_tuple_size<T>> {
static constexpr size_t value = tuple_size<T>::value;
};
template<typename T> struct tuple_size<volatile __has_tuple_size<T>> {
static constexpr size_t value = tuple_size<T>::value;
};
template<typename T> struct tuple_size<const __has_tuple_size<volatile T>> {
static constexpr size_t value = tuple_size<T>::value;
};
template<typename... T> struct tuple { };
template<typename... T> struct tuple_size<tuple<T...>> {
static constexpr size_t value = sizeof...(T);
};
static_assert( tuple_size<const tuple<>>::value == 0, "" ); // OK
static_assert( tuple_size<volatile tuple<>>::value == 0, "" ); // OK
static_assert( tuple_size<const volatile tuple<>>::value == 0, "" ); // FAIL