+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>
}
}
+/* 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)))
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);
}
}
|= 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. */
/* [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))
{
+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
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" } }
}
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" } }
}
--- /dev/null
+/* 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" } }
--- /dev/null
+/* 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" } }
--- /dev/null
+/* 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" } }
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" } }
}