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

Reply via email to