aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2018-03-02 00:16:52 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2018-03-01 17:16:52 -0700
commitf454bd6436a824b4be34e5e1ba5515c5bd339980 (patch)
treecee828d0eac6e44f1cc71a1ff52714d4f331aaa2
parentb3a0e110e06ad9383ba9a09be2ac61d3957596c5 (diff)
downloadgcc-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
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/decl.c64
-rw-r--r--gcc/testsuite/ChangeLog10
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-const.C3
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-malloc-3.C3
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-noinline-3.C45
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-noreturn-3.C54
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-nothrow-3.C60
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-pure.C3
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" } }
}