diff mbox series

c++: alias template with dependent attributes [PR115897]

Message ID 20240712185328.113699-1-ppalka@redhat.com
State New
Headers show
Series c++: alias template with dependent attributes [PR115897] | expand

Commit Message

Patrick Palka July 12, 2024, 6:53 p.m. UTC
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk/14?

-- >8 --

Here we're prematurely stripping the dependent alias template-id A<T> to
its defining-type-id T when used as a template argument, which in turn
causes us to essentially ignore A's vector_size attribute.  It seems this
has always been an issue for class template-ids, but after r14-2170
variable template-ids are affected as well.

To fix this, it seems natural to mark alias templates that have a
dependent attribute as complex, alongside e.g. constrained alias
templates, which prevents us from looking through them prematurely.

	PR c++/115897

gcc/cp/ChangeLog:

	* pt.cc (complex_alias_template_p): Return true for an alias
	template with attributes.
	(get_underlying_template): Don't look through an alias template
	with attributes.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp0x/alias-decl-77.C: New test.
---
 gcc/cp/pt.cc                               | 10 +++++++
 gcc/testsuite/g++.dg/cpp0x/alias-decl-77.C | 32 ++++++++++++++++++++++
 2 files changed, 42 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-77.C

Comments

Jason Merrill July 15, 2024, 9:25 p.m. UTC | #1
On 7/12/24 2:53 PM, Patrick Palka wrote:
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk/14?
> 
> -- >8 --
> 
> Here we're prematurely stripping the dependent alias template-id A<T> to
> its defining-type-id T when used as a template argument, which in turn
> causes us to essentially ignore A's vector_size attribute.  It seems this
> has always been an issue for class template-ids, but after r14-2170
> variable template-ids are affected as well.
> 
> To fix this, it seems natural to mark alias templates that have a
> dependent attribute as complex, alongside e.g. constrained alias
> templates, which prevents us from looking through them prematurely.
> 
> 	PR c++/115897
> 
> gcc/cp/ChangeLog:
> 
> 	* pt.cc (complex_alias_template_p): Return true for an alias
> 	template with attributes.
> 	(get_underlying_template): Don't look through an alias template
> 	with attributes.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/cpp0x/alias-decl-77.C: New test.
> ---
>   gcc/cp/pt.cc                               | 10 +++++++
>   gcc/testsuite/g++.dg/cpp0x/alias-decl-77.C | 32 ++++++++++++++++++++++
>   2 files changed, 42 insertions(+)
>   create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-77.C
> 
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index e38e02488be..8239392923f 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -6628,6 +6628,11 @@ complex_alias_template_p (const_tree tmpl, tree *seen_out)
>     if (get_constraints (tmpl))
>       return true;
>   
> +  /* An alias with dependent type attributes is complex.  */
> +  if (any_dependent_type_attributes_p (DECL_ATTRIBUTES
> +				       (DECL_TEMPLATE_RESULT (tmpl))))
> +    return true;
> +
>     if (!complex_alias_tmpl_info)
>       complex_alias_tmpl_info = hash_map<const_tree, tree>::create_ggc (13);
>   
> @@ -6780,6 +6785,11 @@ get_underlying_template (tree tmpl)
>         if (!at_least_as_constrained (underlying, tmpl))
>   	break;
>   
> +      /* If TMPL adds dependent attributes, it isn't equivalent.  */
> +      if (any_dependent_type_attributes_p (DECL_ATTRIBUTES
> +					   (DECL_TEMPLATE_RESULT (tmpl))))
> +	break;
> +
>         /* Alias is equivalent.  Strip it and repeat.  */
>         tmpl = underlying;
>       }
> diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-77.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-77.C
> new file mode 100644
> index 00000000000..d518c040a92
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-77.C
> @@ -0,0 +1,32 @@
> +// 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>
> +using A [[gnu::vector_size(16)]] = T;
> +
> +template<class T>
> +using B = T;
> +
> +template<class T>
> +using C [[gnu::vector_size(16)]] = B<T>;
> +
> +template<class T>
> +void f() {
> +  static_assert(!is_same<T, A<T>>::value, "");
> +  static_assert(!is_same<T, C<T>>::value, "");

How about a positive test that A<T> and C<T> are the same?  OK with that 
change.

> +#if __cpp_variable_templates
> +  static_assert(!is_same_v<T, A<T>>, "");
> +  static_assert(!is_same_v<T, C<T>>, "");
> +#endif
> +};
> +
> +template void f<float>();
diff mbox series

Patch

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index e38e02488be..8239392923f 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -6628,6 +6628,11 @@  complex_alias_template_p (const_tree tmpl, tree *seen_out)
   if (get_constraints (tmpl))
     return true;
 
+  /* An alias with dependent type attributes is complex.  */
+  if (any_dependent_type_attributes_p (DECL_ATTRIBUTES
+				       (DECL_TEMPLATE_RESULT (tmpl))))
+    return true;
+
   if (!complex_alias_tmpl_info)
     complex_alias_tmpl_info = hash_map<const_tree, tree>::create_ggc (13);
 
@@ -6780,6 +6785,11 @@  get_underlying_template (tree tmpl)
       if (!at_least_as_constrained (underlying, tmpl))
 	break;
 
+      /* If TMPL adds dependent attributes, it isn't equivalent.  */
+      if (any_dependent_type_attributes_p (DECL_ATTRIBUTES
+					   (DECL_TEMPLATE_RESULT (tmpl))))
+	break;
+
       /* Alias is equivalent.  Strip it and repeat.  */
       tmpl = underlying;
     }
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-77.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-77.C
new file mode 100644
index 00000000000..d518c040a92
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-77.C
@@ -0,0 +1,32 @@ 
+// 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>
+using A [[gnu::vector_size(16)]] = T;
+
+template<class T>
+using B = T;
+
+template<class T>
+using C [[gnu::vector_size(16)]] = B<T>;
+
+template<class T>
+void f() {
+  static_assert(!is_same<T, A<T>>::value, "");
+  static_assert(!is_same<T, C<T>>::value, "");
+
+#if __cpp_variable_templates
+  static_assert(!is_same_v<T, A<T>>, "");
+  static_assert(!is_same_v<T, C<T>>, "");
+#endif
+};
+
+template void f<float>();