function, two inside the body of a function in a local class, etc.) */
extern int function_depth;
-/* Nonzero if we are inside eq_specializations, which affects
- comparison of PARM_DECLs in cp_tree_equal and alias specializations
- in structrual_comptypes. */
+/* Nonzero if we are inside spec_hasher::equal, which affects
+ comparison of PARM_DECLs in cp_tree_equal. */
extern int comparing_specializations;
+/* Nonzero if we want different dependent aliases to compare as unequal.
+ FIXME we should always do this except during deduction/ordering. */
+extern int comparing_dependent_aliases;
+
/* When comparing specializations permit context _FROM to match _TO. */
extern tree map_context_from;
extern tree map_context_to;
/* Restricts tree and type comparisons. */
int comparing_specializations;
+int comparing_dependent_aliases;
/* Returns true iff two spec_entry nodes are equivalent. */
int equal;
++comparing_specializations;
+ ++comparing_dependent_aliases;
equal = (e1->tmpl == e2->tmpl
&& comp_template_args (e1->args, e2->args));
if (equal && flag_concepts
tree c2 = e2->spec ? get_constraints (e2->spec) : NULL_TREE;
equal = equivalent_constraints (c1, c2);
}
+ --comparing_dependent_aliases;
--comparing_specializations;
return equal;
tree
dependent_alias_template_spec_p (const_tree t, bool transparent_typedefs)
{
- if (!TYPE_P (t) || !typedef_variant_p (t))
+ if (t == error_mark_node)
+ return NULL_TREE;
+ gcc_assert (TYPE_P (t));
+
+ if (!typedef_variant_p (t))
return NULL_TREE;
tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (t);
if (class_nttp_const_wrapper_p (ot))
ot = TREE_OPERAND (ot, 0);
+ /* DR 1558: Don't treat an alias template specialization with dependent
+ arguments as equivalent to its underlying type when used as a 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.
+
+ 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)
+ ++comparing_dependent_aliases;
+
if (TREE_CODE (nt) == TREE_VEC || TREE_CODE (ot) == TREE_VEC)
/* For member templates */
return TREE_CODE (ot) == TREE_CODE (nt) && comp_template_args (ot, nt);
{
if (!(TYPE_P (nt) && TYPE_P (ot)))
return false;
- /* Don't treat an alias template specialization with dependent
- arguments as equivalent to its underlying type when used as a
- 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.
-
- 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);
+ return same_type_p (ot, nt);
}
else
{
{
DECL_ORIGINAL_TYPE (r) = NULL_TREE;
set_underlying_type (r);
- if (TYPE_DECL_ALIAS_P (r))
- /* An alias template specialization can be dependent
- even if its underlying type is not. */
- TYPE_DEPENDENT_P_VALID (TREE_TYPE (r)) = false;
}
layout_decl (r, 0);
tree r = instantiate_template (tmpl, args, complain);
pop_tinst_level ();
+ if (tree d = dependent_alias_template_spec_p (TREE_TYPE (r), nt_opaque))
+ {
+ /* An alias template specialization can be dependent
+ even if its underlying type is not. */
+ TYPE_DEPENDENT_P (d) = true;
+ TYPE_DEPENDENT_P_VALID (d) = true;
+ /* Sometimes a dependent alias spec is equivalent to its expansion,
+ sometimes not. So always use structural_comptypes. */
+ SET_TYPE_STRUCTURAL_EQUALITY (d);
+ }
+
return r;
}
/* Both should be types that are not obviously the same. */
gcc_checking_assert (t1 != t2 && TYPE_P (t1) && TYPE_P (t2));
+ /* Suppress typename resolution under spec_hasher::equal in place of calling
+ push_to_top_level there. */
if (!comparing_specializations)
{
/* TYPENAME_TYPEs should be resolved if the qualifying scope is the
return false;
check_alias:
- if (comparing_specializations)
+ if (comparing_dependent_aliases)
{
/* Don't treat an alias template specialization with dependent
arguments as equivalent to its underlying type when used as a
if (t1 == error_mark_node || t2 == error_mark_node)
return false;
- if (strict == COMPARE_STRICT && comparing_specializations
- && (t1 != TYPE_CANONICAL (t1) || t2 != TYPE_CANONICAL (t2)))
- /* If comparing_specializations, treat dependent aliases as distinct. */
- strict = COMPARE_STRUCTURAL;
-
if (strict == COMPARE_STRICT)
{
if (TYPE_STRUCTURAL_EQUALITY_P (t1) || TYPE_STRUCTURAL_EQUALITY_P (t2))