extern int is_specialization_of (tree, tree);
extern bool is_specialization_of_friend (tree, tree);
extern bool comp_template_args (tree, tree, tree * = NULL,
- tree * = NULL, bool = false);
-extern int template_args_equal (tree, tree, bool = false);
+ tree * = NULL);
+extern int template_args_equal (tree, tree);
extern tree maybe_process_partial_specialization (tree);
extern tree most_specialized_instantiation (tree);
extern tree most_specialized_partial_spec (tree, tsubst_flags_t, bool = false);
int comparing_specializations;
int comparing_dependent_aliases;
+/* Whether we are comparing template arguments during partial ordering
+ (and therefore want the comparison to look through dependent alias
+ template specializations). */
+
+static int comparing_for_partial_ordering;
+
/* Returns true iff two spec_entry nodes are equivalent. */
bool
default:
if (tree canonical = TYPE_CANONICAL (arg))
val = iterative_hash_object (TYPE_HASH (canonical), val);
+ else if (tree ti = TYPE_TEMPLATE_INFO (arg))
+ {
+ val = iterative_hash_template_arg (TI_TEMPLATE (ti), val);
+ val = iterative_hash_template_arg (TI_ARGS (ti), val);
+ }
break;
}
/* Returns 1 if template args OT and NT are equivalent. */
int
-template_args_equal (tree ot, tree nt, bool partial_order /* = false */)
+template_args_equal (tree ot, tree nt)
{
if (nt == ot)
return 1;
During partial ordering, however, we need to treat them normally so we can
order uses of the same alias with different cv-qualification (79960). */
auto cso = make_temp_override (comparing_dependent_aliases);
- if (!partial_order)
+ if (!comparing_for_partial_ordering)
++comparing_dependent_aliases;
if (TREE_CODE (nt) == TREE_VEC || TREE_CODE (ot) == TREE_VEC)
bool
comp_template_args (tree oldargs, tree newargs,
- tree *oldarg_ptr /* = NULL */, tree *newarg_ptr /* = NULL */,
- bool partial_order /* = false */)
+ tree *oldarg_ptr /* = NULL */, tree *newarg_ptr /* = NULL */)
{
if (oldargs == newargs)
return true;
tree nt = TREE_VEC_ELT (newargs, i);
tree ot = TREE_VEC_ELT (oldargs, i);
- if (! template_args_equal (ot, nt, partial_order))
+ if (! template_args_equal (ot, nt))
{
if (oldarg_ptr != NULL)
*oldarg_ptr = ot;
return true;
}
-inline bool
+static bool
comp_template_args_porder (tree oargs, tree nargs)
{
- return comp_template_args (oargs, nargs, NULL, NULL, true);
+ ++comparing_for_partial_ordering;
+ bool equal = comp_template_args (oargs, nargs);
+ --comparing_for_partial_ordering;
+ return equal;
}
/* Implement a freelist interface for objects of type T.
mutated after the fact by duplicate_decls), so just require
structural equality in this case (PR52830). */
return true;
+ else if (TYPE_P (arg)
+ && TYPE_STRUCTURAL_EQUALITY_P (arg)
+ && dependent_alias_template_spec_p (arg, nt_transparent))
+ /* Require structural equality for specializations written
+ in terms of a dependent alias template specialization. */
+ return true;
+ else if (CLASS_TYPE_P (arg)
+ && TYPE_TEMPLATE_INFO (arg)
+ && TYPE_STRUCTURAL_EQUALITY_P (arg))
+ /* Require structural equality for specializations written
+ in terms of a class template specialization that itself
+ needs structural equality. */
+ return true;
}
}
}
--- /dev/null
+// PR c++/90679
+// A version of alias-decl-75.C where the specializations of the
+// complex alias template first_t are dependent.
+// { dg-do compile { target c++11 } }
+
+template<class T, class...>
+using first_t = T;
+
+template<class T>
+struct A;
+
+template<class T>
+struct traits;
+
+template<class T>
+struct traits<A<first_t<T, T&>>> {
+ static constexpr int value = 1;
+};
+
+template<class T>
+struct traits<A<first_t<const T, T&>>> {
+ static constexpr int value = 2;
+};
+
+static_assert(traits<A<int>>::value == 1, "");
+static_assert(traits<A<const int>>::value == 2, ""); // { dg-bogus "ambiguous" }
--- /dev/null
+// PR c++/90679
+// A version of alias-decl-75a.C where the alias template specialization
+// appears as a more deeply nested template argument.
+// { dg-do compile { target c++11 } }
+
+template<class T, class...>
+using first_t = T;
+
+template<class T>
+struct A;
+
+template<class T>
+struct traits;
+
+template<class T>
+struct traits<A<A<first_t<T, T&>>>> {
+ static constexpr int value = 1;
+};
+
+template<class T>
+struct traits<A<A<first_t<const T, T&>>>> {
+ static constexpr int value = 2;
+};
+
+static_assert(traits<A<A<int>>>::value == 1, "");
+static_assert(traits<A<A<const int>>>::value == 2, ""); // { dg-bogus "ambiguous" }