diff options
author | Martin Sebor <msebor@redhat.com> | 2018-03-02 00:16:52 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2018-03-01 17:16:52 -0700 |
commit | f454bd6436a824b4be34e5e1ba5515c5bd339980 (patch) | |
tree | cee828d0eac6e44f1cc71a1ff52714d4f331aaa2 /gcc | |
parent | b3a0e110e06ad9383ba9a09be2ac61d3957596c5 (diff) | |
download | gcc-f454bd6436a824b4be34e5e1ba5515c5bd339980.zip gcc-f454bd6436a824b4be34e5e1ba5515c5bd339980.tar.gz gcc-f454bd6436a824b4be34e5e1ba5515c5bd339980.tar.bz2 |
PR c++/84294 - attributes on a function template redeclaration silently discarded
gcc/cp/ChangeLog:
PR c++/84294
* decl.c (check_redeclaration_no_default_args): Merge attributes
specified on redeclarations of the same function template.
Remove dead code.
gcc/testsuite/ChangeLog:
PR c++/84294
* g++.dg/ext/attr-const.C: Remove xfail.
* g++.dg/ext/attr-malloc-3.C: New test.
* g++.dg/ext/attr-noinline-3.C: New test.
* g++.dg/ext/attr-noreturn-3.C: New test.
* g++.dg/ext/attr-nothrow-3.C: New test.
* g++.dg/ext/attr-pure.C: Remove xfail.
From-SVN: r258121
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/decl.c | 64 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/attr-const.C | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/attr-malloc-3.C | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/attr-noinline-3.C | 45 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/attr-noreturn-3.C | 54 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/attr-nothrow-3.C | 60 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/attr-pure.C | 3 |
9 files changed, 208 insertions, 41 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d44845b..2d5363c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2018-03-01 Martin Sebor <msebor@redhat.com> + + PR c++/84294 + * decl.c (check_redeclaration_no_default_args): Merge attributes + specified on redeclarations of the same function template. + Remove dead code. + 2018-03-01 Marek Polacek <polacek@redhat.com> Jason Merrill <jason@redhat.com> diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index db64d12..735ed5d 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -1355,6 +1355,26 @@ check_redeclaration_no_default_args (tree decl) } } +/* Merge tree bits that correspond to attributes noreturn, nothrow, + const, malloc, and pure from NEWDECL with those of OLDDECL. */ + +static void +merge_attribute_bits (tree newdecl, tree olddecl) +{ + TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl); + TREE_THIS_VOLATILE (olddecl) |= TREE_THIS_VOLATILE (newdecl); + TREE_NOTHROW (newdecl) |= TREE_NOTHROW (olddecl); + TREE_NOTHROW (olddecl) |= TREE_NOTHROW (newdecl); + TREE_READONLY (newdecl) |= TREE_READONLY (olddecl); + TREE_READONLY (olddecl) |= TREE_READONLY (newdecl); + DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl); + DECL_IS_MALLOC (olddecl) |= DECL_IS_MALLOC (newdecl); + DECL_PURE_P (newdecl) |= DECL_PURE_P (olddecl); + DECL_PURE_P (olddecl) |= DECL_PURE_P (newdecl); + DECL_UNINLINABLE (newdecl) |= DECL_UNINLINABLE (olddecl); + DECL_UNINLINABLE (olddecl) |= DECL_UNINLINABLE (newdecl); +} + #define GNU_INLINE_P(fn) (DECL_DECLARED_INLINE_P (fn) \ && lookup_attribute ("gnu_inline", \ DECL_ATTRIBUTES (fn))) @@ -2048,6 +2068,8 @@ next_arg:; DECL_DISREGARD_INLINE_LIMITS (old_result) |= DECL_DISREGARD_INLINE_LIMITS (new_result); check_redeclaration_exception_specification (newdecl, olddecl); + + merge_attribute_bits (new_result, old_result); } } @@ -2228,18 +2250,7 @@ next_arg:; |= DECL_LOOPING_CONST_OR_PURE_P (olddecl); if (merge_attr) - { - TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl); - TREE_THIS_VOLATILE (olddecl) |= TREE_THIS_VOLATILE (newdecl); - TREE_NOTHROW (newdecl) |= TREE_NOTHROW (olddecl); - TREE_NOTHROW (olddecl) |= TREE_NOTHROW (newdecl); - TREE_READONLY (newdecl) |= TREE_READONLY (olddecl); - TREE_READONLY (olddecl) |= TREE_READONLY (newdecl); - DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl); - DECL_IS_MALLOC (olddecl) |= DECL_IS_MALLOC (newdecl); - DECL_PURE_P (newdecl) |= DECL_PURE_P (olddecl); - DECL_PURE_P (olddecl) |= DECL_PURE_P (newdecl); - } + merge_attribute_bits (newdecl, olddecl); else { /* Merge the noreturn bit. */ @@ -2412,32 +2423,15 @@ next_arg:; /* [temp.expl.spec/14] We don't inline explicit specialization just because the primary template says so. */ + gcc_assert (!merge_attr); - if (merge_attr) - { - /* But still keep DECL_DISREGARD_INLINE_LIMITS in sync with - the always_inline attribute. */ - if (DECL_DISREGARD_INLINE_LIMITS (olddecl) - && !DECL_DISREGARD_INLINE_LIMITS (newdecl)) - { - if (DECL_DECLARED_INLINE_P (newdecl)) - DECL_DISREGARD_INLINE_LIMITS (newdecl) = true; - else - DECL_ATTRIBUTES (newdecl) - = remove_attribute ("always_inline", - DECL_ATTRIBUTES (newdecl)); - } - } - else - { - DECL_DECLARED_INLINE_P (olddecl) - = DECL_DECLARED_INLINE_P (newdecl); + DECL_DECLARED_INLINE_P (olddecl) + = DECL_DECLARED_INLINE_P (newdecl); - DECL_DISREGARD_INLINE_LIMITS (olddecl) - = DECL_DISREGARD_INLINE_LIMITS (newdecl); + DECL_DISREGARD_INLINE_LIMITS (olddecl) + = DECL_DISREGARD_INLINE_LIMITS (newdecl); - DECL_UNINLINABLE (olddecl) = DECL_UNINLINABLE (newdecl); - } + DECL_UNINLINABLE (olddecl) = DECL_UNINLINABLE (newdecl); } else if (new_defines_function && DECL_INITIAL (olddecl)) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ef84baf..62fde2d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2018-03-01 Martin Sebor <msebor@redhat.com> + + PR c++/84294 + * g++.dg/ext/attr-const.C: Remove xfail. + * g++.dg/ext/attr-malloc-3.C: New test. + * g++.dg/ext/attr-noinline-3.C: New test. + * g++.dg/ext/attr-noreturn-3.C: New test. + * g++.dg/ext/attr-nothrow-3.C: New test. + * g++.dg/ext/attr-pure.C: Remove xfail. + 2018-03-02 Jakub Jelinek <jakub@redhat.com> PR sanitizer/70875 diff --git a/gcc/testsuite/g++.dg/ext/attr-const.C b/gcc/testsuite/g++.dg/ext/attr-const.C index 28f2c6e..17cdae6b 100644 --- a/gcc/testsuite/g++.dg/ext/attr-const.C +++ b/gcc/testsuite/g++.dg/ext/attr-const.C @@ -68,6 +68,5 @@ void test_fnone_const () if (i0 != i1) templ_none_const_failed (); - // The following fails (most likely) due to bug 84294. - // { dg-final { scan-tree-dump-not "templ_none_const_failed" "optimized" { xfail *-*-* } } } + // { dg-final { scan-tree-dump-not "templ_none_const_failed" "optimized" } } } diff --git a/gcc/testsuite/g++.dg/ext/attr-malloc-3.C b/gcc/testsuite/g++.dg/ext/attr-malloc-3.C index e4470af..5f91ee1 100644 --- a/gcc/testsuite/g++.dg/ext/attr-malloc-3.C +++ b/gcc/testsuite/g++.dg/ext/attr-malloc-3.C @@ -91,7 +91,6 @@ void test_templ_none_malloc (void) if (p == a) // must be false templ_none_malloc_failed (); // should be eliminated - // The following fails (most likely) due to bug 84294. // Verify that the call to templ_none_malloc_failed() is eliminated. - // { dg-final { scan-tree-dump-not "templ_none_malloc_failed" "optimized" { xfail *-*-* } } } + // { dg-final { scan-tree-dump-not "templ_none_malloc_failed" "optimized" } } } diff --git a/gcc/testsuite/g++.dg/ext/attr-noinline-3.C b/gcc/testsuite/g++.dg/ext/attr-noinline-3.C new file mode 100644 index 0000000..f3f9856 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/attr-noinline-3.C @@ -0,0 +1,45 @@ +/* PR c++/84294 - attributes on a function template redeclaration silently + discarded + { dg-do compile } + { dg-options "-O -fdump-tree-optimized" } */ + +template <void test ()> +void test_func () +{ + test (); +} + +int x; + +void __attribute__ ((noinline)) func_noinline_none (); +void func_noinline_none () { x = __LINE__; } + +template void test_func<func_noinline_none>(); +// { dg-final { scan-tree-dump-times "func_noinline_none *\\(\\);" 1 "optimized" } } + + +void func_none_noinline (); +void __attribute__ ((noinline)) func_none_noinline () { x = __LINE__; } + +template void test_func<func_none_noinline>(); +// { dg-final { scan-tree-dump-times "func_none_noinline *\\(\\);" 1 "optimized" } } + + +template <class> +void __attribute__ ((noinline)) templ_noinline_none () { x = __LINE__; } + +template <class> +void templa_noinline_none (); + +template void test_func<templ_noinline_none<int> >(); +// { dg-final { scan-tree-dump-times "templ_noinline_none<int> *\\(\\);" 1 "optimized" } } + + +template <class> +void templ_none_noinline (); + +template <class> +void __attribute__ ((noinline)) templ_none_noinline () { x = __LINE__; } + +template void test_func<templ_none_noinline<int> >(); +// { dg-final { scan-tree-dump-times "templ_none_noinline<int> *\\(\\);" 1 "optimized" } } diff --git a/gcc/testsuite/g++.dg/ext/attr-noreturn-3.C b/gcc/testsuite/g++.dg/ext/attr-noreturn-3.C new file mode 100644 index 0000000..819ed32 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/attr-noreturn-3.C @@ -0,0 +1,54 @@ +/* PR c++/84294 - attributes on a function template redeclaration silently + discarded + { dg-do compile } + { dg-options "-O -fdump-tree-optimized" } */ + +typedef void Func (); + +template <Func> +void fail_func (); + +template <Func test> +int test_func () +{ + test (); + + // Should be eliminated. + fail_func<test> (); + + // Expect no -Wreturn type here despite the absence of a return + // statement in a non-void function. +} // { dg-bogus "\\\[-Wreturn-type]" "bug 84621" { xfail *-*-* } } + +void __attribute__ ((noreturn)) func_noreturn_none (); +void func_noreturn_none (); + +template int test_func<func_noreturn_none>(); + + +void func_none_noreturn (); +void __attribute__ ((noreturn)) func_none_noreturn (); + +template int test_func<func_none_noreturn>(); + + +template <class> +void __attribute__ ((noreturn)) templ_noreturn_none (); + +template <class> +void templa_noreturn_none (); + +template int test_func<templ_noreturn_none<int> >(); + + +template <class> +void templ_none_noreturn (); + +template <class> +void __attribute__ ((noreturn)) templ_none_noreturn (); + +template int test_func<templ_none_noreturn<int> >(); + + +// Verify that calls to fail_func() specializations have been eliminated. +// { dg-final { scan-tree-dump-not "fail_func" "optimized" } } diff --git a/gcc/testsuite/g++.dg/ext/attr-nothrow-3.C b/gcc/testsuite/g++.dg/ext/attr-nothrow-3.C new file mode 100644 index 0000000..ed88826 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/attr-nothrow-3.C @@ -0,0 +1,60 @@ +/* PR c++/84294 - attributes on a function template redeclaration silently + discarded + { dg-do compile } + { dg-options "-O -fdump-tree-eh -fdump-tree-optimized" } */ + +typedef void Func (); + +template <Func> +void fail_func () throw (); + +template <Func test> +void test_func () throw () +{ + try + { + test (); + } + catch (...) + { + // Should be eliminated. + fail_func<test> (); + } +} + +void __attribute__ ((nothrow)) func_nothrow_none (); +void func_nothrow_none (); + +template void test_func<func_nothrow_none>(); + + +void func_none_nothrow (); +void __attribute__ ((nothrow)) func_none_nothrow (); + +template void test_func<func_none_nothrow>(); + + +template <class> +void __attribute__ ((nothrow)) templ_nothrow_none (); + +template <class> +void templa_nothrow_none (); + +template void test_func<templ_nothrow_none<int> >(); + + +template <class> +void templ_none_nothrow (); + +template <class> +void __attribute__ ((nothrow)) templ_none_nothrow (); + +template void test_func<templ_none_nothrow<int> >(); + + +// Verify that no exception handling code was emitted. +// { dg-final { scan-tree-dump-not "eh_dispatch" "eh" } } +// { dg-final { scan-tree-dump-not "resx" "eh" } } + +// Verify that calls to fail_func() specializations have been eliminated. +// { dg-final { scan-tree-dump-not "fail_func" "optimized" } } diff --git a/gcc/testsuite/g++.dg/ext/attr-pure.C b/gcc/testsuite/g++.dg/ext/attr-pure.C index 12532cb..0f25986 100644 --- a/gcc/testsuite/g++.dg/ext/attr-pure.C +++ b/gcc/testsuite/g++.dg/ext/attr-pure.C @@ -69,6 +69,5 @@ void test_fnone_const () if (i0 != i1) templ_none_const_failed (); - // The following fails (most likely) due to bug 84294. - // { dg-final { scan-tree-dump-not "templ_none_const_failed" "optimized" { xfail *-*-* } } } + // { dg-final { scan-tree-dump-not "templ_none_const_failed" "optimized" } } } |