On Thu, Feb 16, 2017 at 11:33 AM, Jakub Jelinek <ja...@redhat.com> wrote: > 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.
Here's the variant of your patch that I'm applying.
commit 3a5098ff79743f89c2e0e3cfa6a00ee82ec26b78 Author: Jason Merrill <ja...@redhat.com> Date: Thu Feb 16 13:05:56 2017 -0500 PR c++/79502 - lost nodiscard attribute * pt.c (apply_late_template_attributes): Do apply non-dependent attributes to types. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 712fb69..c468268 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -10073,29 +10073,43 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags, tree t; tree *p; - for (t = attributes; t; t = TREE_CHAIN (t)) - if (ATTR_IS_DEPENDENT (t)) - { - last_dep = t; - attributes = copy_list (attributes); - break; - } + if (attributes == NULL_TREE) + return; if (DECL_P (*decl_p)) { if (TREE_TYPE (*decl_p) == error_mark_node) return; p = &DECL_ATTRIBUTES (*decl_p); + /* DECL_ATTRIBUTES comes from copy_node in tsubst_decl, and identical + to our attributes parameter. */ + gcc_assert (*p == attributes); } else - p = &TYPE_ATTRIBUTES (*decl_p); + { + p = &TYPE_ATTRIBUTES (*decl_p); + /* TYPE_ATTRIBUTES was set up (with abi_tag and may_alias) in + lookup_template_class_1, and should be preserved. */ + gcc_assert (*p != attributes); + while (*p) + p = &TREE_CHAIN (*p); + } + for (t = attributes; t; t = TREE_CHAIN (t)) + if (ATTR_IS_DEPENDENT (t)) + { + last_dep = t; + attributes = copy_list (attributes); + break; + } + + *p = attributes; if (last_dep) { tree late_attrs = NULL_TREE; tree *q = &late_attrs; - for (*p = attributes; *p; ) + for (; *p; ) { t = *p; if (ATTR_IS_DEPENDENT (t)) diff --git a/gcc/testsuite/g++.dg/cpp0x/attrib54.C b/gcc/testsuite/g++.dg/cpp0x/attrib54.C new file mode 100644 index 0000000..e5817c3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/attrib54.C @@ -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; +}; diff --git a/gcc/testsuite/g++.dg/cpp0x/attrib55.C b/gcc/testsuite/g++.dg/cpp0x/attrib55.C new file mode 100644 index 0000000..79d0c8c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/attrib55.C @@ -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; +}; diff --git a/gcc/testsuite/g++.dg/cpp1z/nodiscard4.C b/gcc/testsuite/g++.dg/cpp1z/nodiscard4.C new file mode 100644 index 0000000..8a95c94 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/nodiscard4.C @@ -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" } +} diff --git a/gcc/testsuite/g++.dg/ext/attrib53.C b/gcc/testsuite/g++.dg/ext/attrib53.C new file mode 100644 index 0000000..408433d --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/attrib53.C @@ -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; +};