Message ID | 567A07A0.1010008@gmail.com |
---|---|
State | New |
Headers | show |
On Tue, 22 Dec 2015, Martin Sebor wrote: > The attached patch adds handling of dependent arguments to > attribute aligned and attribute vector_size, fixing c++/58109 > and 69022 - attribute vector_size ignored with dependent bytes. In the longer term, Gaby used to suggest that internally we should represent the vector_size attribute as some kind of template __vector<scalar,size> (half-way between a template class and a template alias). The goal would be to avoid duplicating all the logic from templates into attributes. Of course that's much more work (even assuming that there isn't some big road-block, which there might be), and a little bit more code duplication as in your patch seems appropriate at this stage.
Ping: looking for review/approval of the patch below: https://gcc.gnu.org/ml/gcc-patches/2015-12/msg02074.html Thanks Martin On 12/22/2015 07:32 PM, Martin Sebor wrote: > The attached patch adds handling of dependent arguments to > attribute aligned and attribute vector_size, fixing c++/58109 > and 69022 - attribute vector_size ignored with dependent bytes. > > Tested on x86_64. > > Martin
Ping: https://gcc.gnu.org/ml/gcc-patches/2015-12/msg02074.html On 01/04/2016 09:49 PM, Martin Sebor wrote: > Ping: looking for review/approval of the patch below: > https://gcc.gnu.org/ml/gcc-patches/2015-12/msg02074.html > > Thanks > Martin > > On 12/22/2015 07:32 PM, Martin Sebor wrote: >> The attached patch adds handling of dependent arguments to >> attribute aligned and attribute vector_size, fixing c++/58109 >> and 69022 - attribute vector_size ignored with dependent bytes. >> >> Tested on x86_64. >> >> Martin >
On 12/22/2015 09:32 PM, Martin Sebor wrote: > + if (is_attribute_p ("aligned", name) > + || is_attribute_p ("vector_size", name)) > + { > + /* Attribute argument may be a dependent indentifier. */ > + if (tree t = args ? TREE_VALUE (args) : NULL_TREE) > + if (value_dependent_expression_p (t) > + || type_dependent_expression_p (t)) > + return true; > + } Instead of this, is_late_template_attribute should be fixed to check attribute_takes_identifier_p. Jason
On 01/11/2016 10:20 PM, Jason Merrill wrote: > On 12/22/2015 09:32 PM, Martin Sebor wrote: >> + if (is_attribute_p ("aligned", name) >> + || is_attribute_p ("vector_size", name)) >> + { >> + /* Attribute argument may be a dependent indentifier. */ >> + if (tree t = args ? TREE_VALUE (args) : NULL_TREE) >> + if (value_dependent_expression_p (t) >> + || type_dependent_expression_p (t)) >> + return true; >> + } > > Instead of this, is_late_template_attribute should be fixed to check > attribute_takes_identifier_p. attribute_takes_identifier_p() returns false for the aligned attribute and for vector_size (it returns true only for attributes cleanup, format, and mode, and none others). Are you suggesting to also change attribute_takes_identifier_p to return true for these attributes? That would likely mean changes to the C front end as well.) Thanks Martin
On 01/12/2016 11:11 AM, Martin Sebor wrote: > On 01/11/2016 10:20 PM, Jason Merrill wrote: >> On 12/22/2015 09:32 PM, Martin Sebor wrote: >>> + if (is_attribute_p ("aligned", name) >>> + || is_attribute_p ("vector_size", name)) >>> + { >>> + /* Attribute argument may be a dependent indentifier. */ >>> + if (tree t = args ? TREE_VALUE (args) : NULL_TREE) >>> + if (value_dependent_expression_p (t) >>> + || type_dependent_expression_p (t)) >>> + return true; >>> + } >> >> Instead of this, is_late_template_attribute should be fixed to check >> attribute_takes_identifier_p. > > attribute_takes_identifier_p() returns false for the aligned > attribute and for vector_size (it returns true only for > attributes cleanup, format, and mode, and none others). > > Are you suggesting to also change attribute_takes_identifier_p > to return true for these attributes? That would likely mean > changes to the C front end as well.) Jason, can you please clarify what you had in mind? I realize this isn't as severe as a codegen problem but I'd like to try to wrap it up in between higher priority tasks. > > Thanks > Martin
On 01/12/2016 01:11 PM, Martin Sebor wrote: > On 01/11/2016 10:20 PM, Jason Merrill wrote: >> On 12/22/2015 09:32 PM, Martin Sebor wrote: >>> + if (is_attribute_p ("aligned", name) >>> + || is_attribute_p ("vector_size", name)) >>> + { >>> + /* Attribute argument may be a dependent indentifier. */ >>> + if (tree t = args ? TREE_VALUE (args) : NULL_TREE) >>> + if (value_dependent_expression_p (t) >>> + || type_dependent_expression_p (t)) >>> + return true; >>> + } >> >> Instead of this, is_late_template_attribute should be fixed to check >> attribute_takes_identifier_p. > > attribute_takes_identifier_p() returns false for the aligned > attribute and for vector_size (it returns true only for > attributes cleanup, format, and mode, and none others). Right. The problem is this code in is_late_template_attribute: > /* If the first attribute argument is an identifier, only consider > second and following arguments. Attributes like mode, format, > cleanup and several target specific attributes aren't late > just because they have an IDENTIFIER_NODE as first argument. */ > if (arg == args && identifier_p (t)) > continue; It shouldn't skip an initial identifier if !attribute_takes_identifier_p. Jason
gcc/testsuite/ChangeLog: 2015-12-22 Martin Sebor <msebor@redhat.com> PR c++/58109 PR c++/69022 * g++.dg/cpp0x/alignas5.C: New test. * g++.dg/ext/vector29.C: Same. gcc/cp/ChangeLog: 2015-12-22 Martin Sebor <msebor@redhat.com> PR c++/58109 PR c++/69022 * decl2.c (is_late_template_attribute): Handle dependent argument to attribute align and attribute vector_size. Index: gcc/cp/decl2.c =================================================================== --- gcc/cp/decl2.c (revision 231903) +++ gcc/cp/decl2.c (working copy) @@ -1183,6 +1183,16 @@ if (args && PACK_EXPANSION_P (args)) return true; + if (is_attribute_p ("aligned", name) + || is_attribute_p ("vector_size", name)) + { + /* Attribute argument may be a dependent indentifier. */ + if (tree t = args ? TREE_VALUE (args) : NULL_TREE) + if (value_dependent_expression_p (t) + || type_dependent_expression_p (t)) + return true; + } + /* If any of the arguments are dependent expressions, we can't evaluate the attribute until instantiation time. */ for (arg = args; arg; arg = TREE_CHAIN (arg)) Index: gcc/testsuite/g++.dg/cpp0x/alignas5.C =================================================================== --- gcc/testsuite/g++.dg/cpp0x/alignas5.C (revision 0) +++ gcc/testsuite/g++.dg/cpp0x/alignas5.C (working copy) @@ -0,0 +1,45 @@ +// PR c++/58109 - alignas() fails to compile with constant expression +// { dg-do compile } + +template <typename T> +struct Base { + static const int Align = sizeof (T); +}; + +// Never instantiated. +template <typename T> +struct Derived: Base<T> +{ +#if __cplusplus >= 201102L + // This is the meat of the (simplified) regression test for c++/58109. + using B = Base<T>; + using B::Align; + + alignas (Align) char a [1]; + alignas (Align) T b [1]; +#else + // Fake the test for C++ 98. +# define Align Base<T>::Align +#endif + + char __attribute__ ((aligned (Align))) c [1]; + T __attribute__ ((aligned (Align))) d [1]; +}; + +// Instantiated to verify that the code is accepted even when instantiated. +template <typename T> +struct InstDerived: Base<T> +{ +#if __cplusplus >= 201102L + using B = Base<T>; + using B::Align; + + alignas (Align) char a [1]; + alignas (Align) T b [1]; +#endif + + char __attribute__ ((aligned (Align))) c [1]; + T __attribute__ ((aligned (Align))) d [1]; +}; + +InstDerived<int> dx; Index: gcc/testsuite/g++.dg/ext/vector29.C =================================================================== --- gcc/testsuite/g++.dg/ext/vector29.C (revision 0) +++ gcc/testsuite/g++.dg/ext/vector29.C (working copy) @@ -0,0 +1,53 @@ +// PR c++/69022 - attribute vector_size ignored with dependent bytes +// { dg-do compile } + +template <int N> +struct A { static const int X = N; }; + +#if __cplusplus >= 201202L +# define ASSERT(e) static_assert (e, #e) +#else +# define ASSERT(e) \ + do { struct S { bool: !!(e); } asrt; (void)&asrt; } while (0) +#endif + +template <class T, int N> +struct B: A<N> +{ +#if __cplusplus >= 201202L + using A<N>::X; +# define VecSize X +#else +# define VecSize A<N>::X +#endif + + static void foo () + { + char a __attribute__ ((vector_size (N))); + ASSERT (sizeof a == N); + + T b __attribute__ ((vector_size (N))); + ASSERT (sizeof b == N); + } + + static void bar () + { + char c1 __attribute__ ((vector_size (VecSize))); + ASSERT (sizeof c1 == VecSize); + + char c2 __attribute__ ((vector_size (A<N>::X))); + ASSERT (sizeof c2 == A<N>::X); + + T d1 __attribute__ ((vector_size (VecSize))); + ASSERT (sizeof d1 == VecSize); + + T d2 __attribute__ ((vector_size (A<N>::X))); + ASSERT (sizeof d2 == A<N>::X); + } +}; + +void bar () +{ + B<int, 16>::foo (); + B<int, 16>::bar (); +}