diff options
author | Jakub Jelinek <jakub@redhat.com> | 2017-02-16 20:49:19 +0100 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2017-02-16 14:49:19 -0500 |
commit | 790ecf853295e25cdd3f92113bc9dca1cf143040 (patch) | |
tree | 46815e5e2d7e39820e47d6fbf4a625d01bb9f081 | |
parent | dbd0ef6d89f370c51b29f22b8da07ad446192eee (diff) | |
download | gcc-790ecf853295e25cdd3f92113bc9dca1cf143040.zip gcc-790ecf853295e25cdd3f92113bc9dca1cf143040.tar.gz gcc-790ecf853295e25cdd3f92113bc9dca1cf143040.tar.bz2 |
PR c++/79502 - lost nodiscard attribute
* pt.c (apply_late_template_attributes): Do apply non-dependent
attributes to types.
Co-Authored-By: Jason Merrill <jason@redhat.com>
From-SVN: r245516
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/pt.c | 32 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/attrib54.C | 21 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/attrib55.C | 21 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1z/nodiscard4.C | 14 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/attrib53.C | 21 |
6 files changed, 107 insertions, 9 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 66c491e..11ef320 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2017-02-16 Jakub Jelinek <jakub@redhat.com> + Jason Merrill <jason@redhat.com> + + PR c++/79502 - lost nodiscard attribute + * pt.c (apply_late_template_attributes): Do apply non-dependent + attributes to types. + 2017-02-16 Jason Merrill <jason@redhat.com> PR c++/78572 - ICE with self-modifying array initializer diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 712fb69..73d6be3 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 is 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; +}; |