enum { nt_opaque = false, nt_transparent = true };
extern tree alias_template_specialization_p (const_tree, bool);
extern tree dependent_alias_template_spec_p (const_tree, bool);
+extern bool dependent_opaque_alias_p (const_tree);
extern tree get_template_parm_object (tree expr, tree mangle);
extern tree tparm_object_argument (tree);
extern bool explicit_class_specialization_p (tree);
}
}
+ if (is_typedef_decl (decl)
+ && (dependent_opaque_alias_p (TREE_TYPE (decl))
+ || dependent_alias_template_spec_p (TREE_TYPE (decl), nt_opaque)))
+ {
+ /* Manually mark such aliases as dependent so that dependent_type_p_r
+ doesn't have to handle them. */
+ TYPE_DEPENDENT_P_VALID (TREE_TYPE (decl)) = true;
+ TYPE_DEPENDENT_P (TREE_TYPE (decl)) = true;
+ /* The identity of such aliases is hairy; see structural_comptypes. */
+ SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (decl));
+ }
+
if (flag_implicit_templates
&& !is_friend
&& TREE_PUBLIC (decl)
if (tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (t))
if (PRIMARY_TEMPLATE_P (TI_TEMPLATE (tinfo)))
return CONST_CAST_TREE (t);
- if (transparent_typedefs)
+ if (transparent_typedefs && !dependent_opaque_alias_p (t))
return alias_template_specialization_p (DECL_ORIGINAL_TYPE
(TYPE_NAME (t)),
transparent_typedefs);
return true;
/* An alias with dependent type attributes is complex. */
- if (any_dependent_type_attributes_p (DECL_ATTRIBUTES
- (DECL_TEMPLATE_RESULT (tmpl))))
+ if (dependent_opaque_alias_p (TREE_TYPE (tmpl)))
return true;
if (!complex_alias_tmpl_info)
/* If T is a specialization of a complex alias template with a dependent
argument for an unused template parameter, return it; otherwise return
NULL_TREE. If T is a typedef to such a specialization, return the
- specialization. */
+ specialization. This predicate is usually checked alongside
+ dependent_opaque_alias_p. Whereas dependent_opaque_alias_p checks
+ type equivalence of an alias vs its expansion, this predicate more
+ broadly checks SFINAE equivalence. */
tree
dependent_alias_template_spec_p (const_tree t, bool transparent_typedefs)
}
}
- if (transparent_typedefs)
+ if (transparent_typedefs && !dependent_opaque_alias_p (t))
{
tree utype = DECL_ORIGINAL_TYPE (TYPE_NAME (t));
return dependent_alias_template_spec_p (utype, transparent_typedefs);
return NULL_TREE;
}
+/* Return true if substituting into T would yield a different type than
+ substituting into its expansion. This predicate is usually checked
+ alongside dependent_alias_template_spec_p. */
+
+bool
+dependent_opaque_alias_p (const_tree t)
+{
+ return (TYPE_P (t)
+ && typedef_variant_p (t)
+ && any_dependent_type_attributes_p (DECL_ATTRIBUTES
+ (TYPE_NAME (t))));
+}
+
/* Return the number of innermost template parameters in TMPL. */
static int
break;
/* If TMPL adds dependent type attributes, it isn't equivalent. */
- if (any_dependent_type_attributes_p (DECL_ATTRIBUTES
- (DECL_TEMPLATE_RESULT (tmpl))))
+ if (dependent_opaque_alias_p (TREE_TYPE (tmpl)))
break;
/* Alias is equivalent. Strip it and repeat. */
if (tree d = dependent_alias_template_spec_p (TREE_TYPE (r), nt_opaque))
{
+ /* Note this is also done at parse time from push_template_decl. */
/* An alias template specialization can be dependent
even if its underlying type is not. */
TYPE_DEPENDENT_P (d) = true;
if (TREE_CODE (type) == TYPENAME_TYPE)
return true;
- /* An alias template specialization can be dependent even if the
- resulting type is not. */
- if (dependent_alias_template_spec_p (type, nt_transparent))
- return true;
-
/* -- a cv-qualified type where the cv-unqualified type is
dependent.
No code is necessary for this bullet; the code below handles
return true;
else if (TYPE_P (arg)
&& TYPE_STRUCTURAL_EQUALITY_P (arg)
- && dependent_alias_template_spec_p (arg, nt_transparent))
+ && (dependent_alias_template_spec_p (arg, nt_opaque)
+ || dependent_opaque_alias_p (arg)))
/* Require structural equality for specializations written
in terms of a dependent alias template specialization. */
return true;
A with the same template arguments. */
ret = TREE_TYPE (TREE_TYPE (fprime));
if (ctad_kind == alias
- && (!same_type_p (atype, ret)
- /* FIXME this should mean they don't compare as equivalent. */
- || dependent_alias_template_spec_p (atype, nt_opaque)))
+ /* Use template_args_equal instead of same_type_p to get the
+ comparing_dependent_aliases behavior. */
+ && !template_args_equal (atype, ret))
{
tree same = finish_trait_expr (loc, CPTK_IS_DEDUCIBLE, tmpl, ret);
ci = append_constraint (ci, same);
&& !user_facing_original_type_p (t))
return t;
+ if (dependent_opaque_alias_p (t))
+ return t;
+
if (alias_template_specialization_p (t, nt_opaque))
{
if (dependent_alias_template_spec_p (t, nt_opaque)
- && (!(flags & STF_STRIP_DEPENDENT)
- || any_dependent_type_attributes_p (DECL_ATTRIBUTES
- (TYPE_NAME (t)))))
+ && !(flags & STF_STRIP_DEPENDENT))
/* DR 1558: However, if the template-id is dependent, subsequent
template argument substitution still applies to the template-id. */
return t;
return false;
check_alias:
- if (comparing_dependent_aliases)
- {
+ if (comparing_dependent_aliases
+ && (typedef_variant_p (t1) || typedef_variant_p (t2)))
+ {
+ tree dep1 = dependent_opaque_alias_p (t1) ? t1 : NULL_TREE;
+ tree dep2 = dependent_opaque_alias_p (t2) ? t2 : NULL_TREE;
+ if ((dep1 || dep2)
+ && (!(dep1 && dep2)
+ || !comp_type_attributes (DECL_ATTRIBUTES (TYPE_NAME (dep1)),
+ DECL_ATTRIBUTES (TYPE_NAME (dep2)))))
+ 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
time. And aliases can't be equivalent without being ==, so
we don't need to look any deeper. */
++processing_template_decl;
- tree dep1 = dependent_alias_template_spec_p (t1, nt_transparent);
- tree dep2 = dependent_alias_template_spec_p (t2, nt_transparent);
+ dep1 = dependent_alias_template_spec_p (t1, nt_transparent);
+ dep2 = dependent_alias_template_spec_p (t2, nt_transparent);
--processing_template_decl;
if ((dep1 || dep2) && dep1 != dep2)
return false;
template<class T>
void f() {
using B [[gnu::vector_size(16)]] = T;
- static_assert(!is_same<T, B>::value, ""); // { dg-bogus "" "" { xfail *-*-* } }
- static_assert(!is_same<A<T>, A<B>>::value, ""); // { dg-bogus "" "" { xfail *-*-* } }
+ static_assert(!is_same<T, B>::value, "");
+ static_assert(!is_same<A<T>, A<B>>::value, "");
#if __cpp_variable_templates
- static_assert(!is_same_v<T, B>, ""); // { dg-bogus "" "" { xfail c++14 } }
- static_assert(!is_same_v<A<T>, A<B>>, ""); // { dg-bogus "" "" { xfail c++14 } }
+ static_assert(!is_same_v<T, B>, "");
+ static_assert(!is_same_v<A<T>, A<B>>, "");
#endif
};
template<class T>
void g() {
using C [[gnu::vector_size(16)]] = T*;
- static_assert(!is_same<T*, C>::value, ""); // { dg-bogus "" "" { xfail *-*-* } }
- static_assert(!is_same<A<T*>, A<C>>::value, ""); // { dg-bogus "" "" { xfail *-*-* } }
+ static_assert(!is_same<T*, C>::value, "");
+ static_assert(!is_same<A<T*>, A<C>>::value, "");
#if __cpp_variable_templates
- static_assert(!is_same_v<T*, C>, ""); // { dg-bogus "" "" { xfail c++14 } }
- static_assert(!is_same_v<A<T*>, A<C>>, ""); // { dg-bogus "" "" { xfail c++14 } }
+ static_assert(!is_same_v<T*, C>, "");
+ static_assert(!is_same_v<A<T*>, A<C>>, "");
#endif
};
--- /dev/null
+// A version of alias-decl-79.C where defining-type-id of B and C
+// are not dependent and instead their vector_size attribute is.
+// PR c++/115897
+// { dg-do compile { target c++11 } }
+
+template<class T, class U>
+struct is_same { static constexpr bool value = __is_same(T, U); };
+
+#if __cpp_variable_templates
+template<class T, class U>
+constexpr bool is_same_v = __is_same(T, U);
+#endif
+
+template<class T> struct A;
+
+template<int N>
+void f() {
+ using T = float;
+ using B [[gnu::vector_size(N * sizeof(float))]] = T;
+ static_assert(!is_same<T, B>::value, "");
+ static_assert(!is_same<A<T>, A<B>>::value, "");
+#if __cpp_variable_templates
+ static_assert(!is_same_v<T, B>, "");
+ static_assert(!is_same_v<A<T>, A<B>>, "");
+#endif
+};
+
+template<int N>
+void g() {
+ using T = float*;
+ using C [[gnu::vector_size(N * sizeof(float*))]] = T;
+ static_assert(!is_same<T*, C>::value, "");
+ static_assert(!is_same<A<T*>, A<C>>::value, "");
+#if __cpp_variable_templates
+ static_assert(!is_same_v<T*, C>, "");
+ static_assert(!is_same_v<A<T*>, A<C>>, "");
+#endif
+};
+
+template void f<4>();
+template void g<4>();