Message ID | 20211119100624.GN2646553@tucnak |
---|---|
State | Committed |
Headers | show |
Series | c++: Avoid adding implicit attributes during apply_late_template_attributes [PR101180] | expand |
On 11/19/21 05:06, Jakub Jelinek wrote: > Hi! > > decl_attributes and its caller cplus_decl_attributes sometimes add > implicit attributes, e.g. optimize attribute if #pragma GCC optimize > is active, target attribute if #pragma GCC target is active, or > e.g. omp declare target attribute if in between #pragma omp declare target > and #pragma omp end declare target. > > For templates that seems highly undesirable to me though, they should > get those implicit attributes from the spot the templates were parsed > (and they do get that), then tsubst through copy_node copies those > attributes, but then apply_late_template_attributes can or does add > a new set from the spot where they are instantiated, which can be pretty > random point of first use of the template. > > Consider e.g. > #pragma GCC push_options > #pragma GCC target "avx" > template <int N> > inline void foo () > { > } > #pragma GCC pop_options > #pragma GCC push_options > #pragma GCC target "crc32" > void > bar () > { > foo<0> (); > } > #pragma GCC pop_options > testcase where the intention is that foo has avx target attribute > and bar has crc32 target attribute, but we end up with > __attribute__((target ("crc32"), target ("avx"))) > on foo<0> (and due to yet another bug actually don't enable avx > in foo<0>). In this particular case it is a regression caused > by r12-299-ga0fdff3cf33f7284 which apparently calls > cplus_decl_attributes even if attributes != NULL but late_attrs > is NULL, before those changes we didn't call it in those cases. > But, if there is at least one unrelated dependent attribute this > would happen already in older releases. > > The following patch fixes that by temporarily overriding the variables > that control the addition of the implicit attributes. OK. > Shall we also change the function so that it doesn't call > cplus_decl_attributes if late_attrs is NULL [...]? Please. > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > 2021-11-19 Jakub Jelinek <jakub@redhat.com> > > PR c++/101180 > * pt.c (apply_late_template_attributes): Temporarily override > current_optimize_pragma, optimization_current_node, > current_target_pragma and scope_chain->omp_declare_target_attribute, > so that cplus_decl_attributes doesn't add implicit attributes. > > * g++.target/i386/pr101180.C: New test. > > --- gcc/cp/pt.c.jj 2021-11-18 12:33:22.025628027 +0100 > +++ gcc/cp/pt.c 2021-11-18 19:08:52.800539490 +0100 > @@ -11722,6 +11722,17 @@ apply_late_template_attributes (tree *de > q = &TREE_CHAIN (*q); > } > > + /* cplus_decl_attributes can add some attributes implicitly. For templates, > + those attributes should have been added already when those templates were > + parsed, and shouldn't be added based on from which context they are > + first time instantiated. */ > + auto o1 = make_temp_override (current_optimize_pragma, NULL_TREE); > + auto o2 = make_temp_override (optimization_current_node, > + optimization_default_node); > + auto o3 = make_temp_override (current_target_pragma, NULL_TREE); > + auto o4 = make_temp_override (scope_chain->omp_declare_target_attribute, > + NULL); > + > cplus_decl_attributes (decl_p, late_attrs, attr_flags); > > return true; > --- gcc/testsuite/g++.target/i386/pr101180.C.jj 2021-11-18 19:11:50.512009888 +0100 > +++ gcc/testsuite/g++.target/i386/pr101180.C 2021-11-18 19:11:33.066258216 +0100 > @@ -0,0 +1,25 @@ > +// PR c++/101180 > +// { dg-do compile { target c++11 } } > + > +#pragma GCC target "avx" > +template <typename> struct A {}; > +#pragma GCC push_options > +#pragma GCC target "avx,avx2,bmi,bmi2,fma,f16c" > +template <typename T> using B = A<T>; > +template <typename> struct C; > +template <> struct C<float> { > + __attribute__((always_inline)) float operator()(long) { return .0f; } > +}; > +long d; > +template <typename T> void e(B<T>) { > + T{C<T>()(d)}; > +} > +template <typename T, typename FromT> void f(T d, FromT) { > + e(d); > +} > +int g; > +void h() { > + A<float> i; > + f(i, g); > +} > +#pragma GCC pop_options > > Jakub >
--- gcc/cp/pt.c.jj 2021-11-18 12:33:22.025628027 +0100 +++ gcc/cp/pt.c 2021-11-18 19:08:52.800539490 +0100 @@ -11722,6 +11722,17 @@ apply_late_template_attributes (tree *de q = &TREE_CHAIN (*q); } + /* cplus_decl_attributes can add some attributes implicitly. For templates, + those attributes should have been added already when those templates were + parsed, and shouldn't be added based on from which context they are + first time instantiated. */ + auto o1 = make_temp_override (current_optimize_pragma, NULL_TREE); + auto o2 = make_temp_override (optimization_current_node, + optimization_default_node); + auto o3 = make_temp_override (current_target_pragma, NULL_TREE); + auto o4 = make_temp_override (scope_chain->omp_declare_target_attribute, + NULL); + cplus_decl_attributes (decl_p, late_attrs, attr_flags); return true; --- gcc/testsuite/g++.target/i386/pr101180.C.jj 2021-11-18 19:11:50.512009888 +0100 +++ gcc/testsuite/g++.target/i386/pr101180.C 2021-11-18 19:11:33.066258216 +0100 @@ -0,0 +1,25 @@ +// PR c++/101180 +// { dg-do compile { target c++11 } } + +#pragma GCC target "avx" +template <typename> struct A {}; +#pragma GCC push_options +#pragma GCC target "avx,avx2,bmi,bmi2,fma,f16c" +template <typename T> using B = A<T>; +template <typename> struct C; +template <> struct C<float> { + __attribute__((always_inline)) float operator()(long) { return .0f; } +}; +long d; +template <typename T> void e(B<T>) { + T{C<T>()(d)}; +} +template <typename T, typename FromT> void f(T d, FromT) { + e(d); +} +int g; +void h() { + A<float> i; + f(i, g); +} +#pragma GCC pop_options