On Wed, Feb 15, 2017 at 03:19:23PM -0500, Jason Merrill wrote: > OK. > > > 2017-02-15 Jakub Jelinek <ja...@redhat.com> > > > > PR c++/79502 > > * pt.c (apply_late_template_attributes): If there are > > no dependent attributes, set *p to attributes. > > > > * g++.dg/cpp1z/nodiscard4.C: New test.
Unfortunately it broke bootstrap, *p can already contain some other attributes (like abi_tag) and then we ICE in apply_identity_attributes. Note the attrib54.C testcase ICEs even on vanilla trunk, so if there are any dependent attribute, it is preexisting issue. The following patch bootstrapped successfully, but I see +FAIL: g++.dg/ext/vector32.C -std=c++* (internal compiler error) +FAIL: g++.dg/ext/vector32a.C -std=c++* (internal compiler error) +FAIL: g++.dg/gomp/declare-simd-1.C -std=gnu++* (internal compiler error) +FAIL: g++.dg/gomp/declare-simd-1.C -std=gnu++* (test for excess errors) +FAIL: g++.dg/lto/20091219 cp_lto_20091219_0.o assemble, -O3 -flto (internal compiler error) +FAIL: g++.dg/vect/simd-clone-4.cc -std=c++* (test for excess errors) +FAIL: g++.dg/vect/simd-clone-5.cc -std=c++* (test for excess errors) on i686-linux (x86_64-linux regtest still running). So there are further issues. 2017-02-16 Jakub Jelinek <ja...@redhat.com> PR c++/79502 * pt.c (apply_late_template_attributes): If there are no dependent attributes, set *p to attributes. If there were some attributes in *p previously with or without dependent attributes, chain them after the new attributes. * g++.dg/cpp1z/nodiscard4.C: New test. * g++.dg/ext/attrib53.C: New test. * g++.dg/ext/attrib54.C: New test. * g++.dg/ext/attrib55.C: New test. --- gcc/cp/pt.c.jj 2017-02-16 12:00:20.044455757 +0100 +++ gcc/cp/pt.c 2017-02-16 15:07:31.678727294 +0100 @@ -10094,6 +10094,7 @@ apply_late_template_attributes (tree *de { tree late_attrs = NULL_TREE; tree *q = &late_attrs; + tree prev = *p; for (*p = attributes; *p; ) { @@ -10110,9 +10111,14 @@ apply_late_template_attributes (tree *de else p = &TREE_CHAIN (t); } + *p = prev; cplus_decl_attributes (decl_p, late_attrs, attr_flags); } + else if (*p == NULL) + *p = attributes; + else if (attributes) + *p = chainon (copy_list (attributes), *p); } /* Perform (or defer) access check for typedefs that were referenced --- gcc/testsuite/g++.dg/cpp1z/nodiscard4.C.jj 2017-02-16 14:04:22.602748039 +0100 +++ gcc/testsuite/g++.dg/cpp1z/nodiscard4.C 2017-02-16 14:04:22.601748053 +0100 @@ -0,0 +1,14 @@ +// PR c++/79502 +// { dg-do compile { target c++11 } } + +template<typename> +struct [[nodiscard]] missiles {}; + +missiles<void> make() { return {}; } +missiles<void> (*fnptr)() = make; + +int main() +{ + make(); // { dg-warning "ignoring returned value of type" } + fnptr(); // { dg-warning "ignoring returned value of type" } +} --- gcc/testsuite/g++.dg/ext/attrib53.C.jj 2017-02-16 15:08:18.635107840 +0100 +++ gcc/testsuite/g++.dg/ext/attrib53.C 2017-02-16 15:09:50.210899761 +0100 @@ -0,0 +1,21 @@ +// { dg-do compile { target c++11 } } + +inline namespace N __attribute__((__abi_tag__ ("foo"))) {} +template <typename> struct A; +namespace N { +template <typename> class B; +} +template <typename> class C {}; +template <typename> struct D { + template <typename _Up> using G = C<_Up>; +}; +template <typename T> struct F { + template <typename U> struct H { + typedef typename D<T>::template G<U> I; + }; +}; +template <typename T, typename = C<T>> struct J { + C<A<const B<char>>> L; + typedef F<C<int>>::H<A<const B<char>>>::I M; + J<M> *a; +}; --- gcc/testsuite/g++.dg/cpp0x/attrib54.C.jj 2017-02-16 15:08:21.739066892 +0100 +++ gcc/testsuite/g++.dg/cpp0x/attrib54.C 2017-02-16 15:10:02.461738146 +0100 @@ -0,0 +1,21 @@ +// { dg-do compile { target c++11 } } + +inline namespace N __attribute__((__abi_tag__ ("foo"))) {} +template <typename> struct A {}; +namespace N { +template <typename> class B {}; +} +template <typename T> class __attribute__((__aligned__ (sizeof (T)))) C {}; +template <typename> struct D { + template <typename _Up> using G = C<_Up>; +}; +template <typename T> struct F { + template <typename U> struct H { + typedef typename D<T>::template G<U> I; + }; +}; +template <typename T, typename = C<T>> struct J { + C<A<const B<char>>> L; + typedef F<C<int>>::H<A<const B<char>>>::I M; + J<M> *a; +}; --- gcc/testsuite/g++.dg/cpp0x/attrib55.C.jj 2017-02-16 15:08:26.801000114 +0100 +++ gcc/testsuite/g++.dg/cpp0x/attrib55.C 2017-02-16 15:10:11.422619933 +0100 @@ -0,0 +1,21 @@ +// { dg-do compile { target c++11 } } + +inline namespace N __attribute__((__abi_tag__ ("foo"))) {} +template <typename> struct A {}; +namespace N { +template <typename> class B {}; +} +template <typename T> class __attribute__((__unused__)) C {}; +template <typename> struct D { + template <typename _Up> using G = C<_Up>; +}; +template <typename T> struct F { + template <typename U> struct H { + typedef typename D<T>::template G<U> I; + }; +}; +template <typename T, typename = C<T>> struct J { + C<A<const B<char>>> L; + typedef F<C<int>>::H<A<const B<char>>>::I M; + J<M> *a; +}; Jakub