aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2007-02-11 18:58:05 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2007-02-11 18:58:05 +0000
commit56fd65c7d9a3fd9ab80a627eb6caf24483801ff5 (patch)
tree37425a6a59c6e2da923d37b739cbb1c65f2cfbd9 /gcc
parentf57d17f1fc2f31047644ed6f18f1087f65f8f88b (diff)
downloadgcc-56fd65c7d9a3fd9ab80a627eb6caf24483801ff5.zip
gcc-56fd65c7d9a3fd9ab80a627eb6caf24483801ff5.tar.gz
gcc-56fd65c7d9a3fd9ab80a627eb6caf24483801ff5.tar.bz2
re PR target/29487 (Shared libstdc++ fails to link)
PR target/29487 * tree.h (DECL_REPLACEABLE_P): New macro. * except.c (set_nothrow_function_flags): Likewise. PR target/29487 * decl.c (finish_function): Use DECL_REPLACEABLE. * tree.c (cp_cannot_inline_tree_fn): Likewise. PR c++/29487 * g++.dg/eh/weak1-C: New test. * g++.dg/eh/weak1-a.cc: Likewise. * g++.dg/eh/comdat1.C: Likewise. From-SVN: r121819
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/decl.c2
-rw-r--r--gcc/cp/tree.c10
-rw-r--r--gcc/except.c5
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/g++.dg/eh/comdat1.C42
-rw-r--r--gcc/testsuite/g++.dg/eh/weak1-a.cc3
-rw-r--r--gcc/testsuite/g++.dg/eh/weak1.C23
-rw-r--r--gcc/tree.h20
10 files changed, 115 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c7fce63..ce0f2ae 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2007-02-06 Mark Mitchell <mark@codesourcery.com>
+
+ PR target/29487
+ * tree.h (DECL_REPLACEABLE_P): New macro.
+ * except.c (set_nothrow_function_flags): Likewise.
+
2007-02-11 Tehila Meyzels <tehila@il.ibm.com>
Ira Rosen <irar@il.ibm.com>
Dorit Nuzman <dorit@il.ibm.com>
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 9fcd66a..f4afe06 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2007-02-06 Mark Mitchell <mark@codesourcery.com>
+
+ PR target/29487
+ * decl.c (finish_function): Use DECL_REPLACEABLE.
+ * tree.c (cp_cannot_inline_tree_fn): Likewise.
+
2007-02-10 Gabriel Dos Reis <gdr@integrable-solutions.net>
* parser.c (cp_parser_primary_expression): Reformat overly long lines.
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index b6d0e53..2212254 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -11225,7 +11225,7 @@ finish_function (int flags)
if (!processing_template_decl
&& !cp_function_chain->can_throw
&& !flag_non_call_exceptions
- && targetm.binds_local_p (fndecl))
+ && !DECL_REPLACEABLE_P (fndecl))
TREE_NOTHROW (fndecl) = 1;
/* This must come after expand_function_end because cleanups might
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 78545e1..a3d11a3 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2209,13 +2209,9 @@ cp_cannot_inline_tree_fn (tree* fnp)
&& lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL)
return 1;
- /* Don't auto-inline anything that might not be bound within
- this unit of translation.
- Exclude comdat functions from this rule. While they can be bound
- to the other unit, they all must be the same. This is especially
- important so templates can inline. */
- if (!DECL_DECLARED_INLINE_P (fn) && !(*targetm.binds_local_p) (fn)
- && !DECL_COMDAT (fn))
+ /* Don't auto-inline functions that might be replaced at link-time
+ with an alternative definition. */
+ if (!DECL_DECLARED_INLINE_P (fn) && DECL_REPLACEABLE_P (fn))
{
DECL_UNINLINABLE (fn) = 1;
return 1;
diff --git a/gcc/except.c b/gcc/except.c
index 9f40dc4..dc51079 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -2785,7 +2785,10 @@ set_nothrow_function_flags (void)
{
rtx insn;
- if (!targetm.binds_local_p (current_function_decl))
+ /* If we don't know that this implementation of the function will
+ actually be used, then we must not set TREE_NOTHROW, since
+ callers must not assume that this function does not throw. */
+ if (DECL_REPLACEABLE_P (current_function_decl))
return 0;
TREE_NOTHROW (current_function_decl) = 1;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8f912c2..3f38b0c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2007-02-06 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/29487
+ * g++.dg/eh/weak1-C: New test.
+ * g++.dg/eh/weak1-a.cc: Likewise.
+ * g++.dg/eh/comdat1.C: Likewise.
+
2007-02-11 Tehila Meyzels <tehila@il.ibm.com>
Dorit Nuzman <dorit@il.ibm.com>
diff --git a/gcc/testsuite/g++.dg/eh/comdat1.C b/gcc/testsuite/g++.dg/eh/comdat1.C
new file mode 100644
index 0000000..4a11805
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/comdat1.C
@@ -0,0 +1,42 @@
+// PR target/29487
+// { dg-do link }
+// { dg-options "-O2" }
+
+/* This function is not defined. The compiler should optimize away
+ all calls to it. */
+extern void undefined () throw ();
+
+extern void f1();
+
+inline void f2() {
+ f1();
+}
+
+/* This function will be COMDAT if not inlined. */
+inline void f1() {}
+
+/* This function will be COMDAT. */
+template <typename T>
+void f3() {
+ if (false)
+ throw 3;
+}
+
+inline void f4() {
+ if (false)
+ throw 7;
+}
+
+int main () {
+ try {
+ f1();
+ f2();
+ f3<int>();
+ f4();
+ } catch (...) {
+ /* The compiler should recognize that none of the functions above
+ can throw exceptions, and therefore remove this code as
+ unreachable. */
+ undefined ();
+ }
+}
diff --git a/gcc/testsuite/g++.dg/eh/weak1-a.cc b/gcc/testsuite/g++.dg/eh/weak1-a.cc
new file mode 100644
index 0000000..1885fae
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/weak1-a.cc
@@ -0,0 +1,3 @@
+extern void f() {
+ throw 7;
+}
diff --git a/gcc/testsuite/g++.dg/eh/weak1.C b/gcc/testsuite/g++.dg/eh/weak1.C
new file mode 100644
index 0000000..09f2fcb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/weak1.C
@@ -0,0 +1,23 @@
+// PR target/29487
+// { dg-require-weak "" }
+// { dg-do run { xfail "hppa*-hp-hpux11.*" } }
+// { dg-additional-sources "weak1-a.cc" }
+// { dg-options "-O2" }
+
+extern __attribute__((weak))
+void f() {
+}
+
+int main () {
+ try {
+ f();
+ return 1;
+ } catch (int i) {
+ /* Although the implementation of f in this file does not throw
+ any exceptions, it is weak, and may therefore be replaced at
+ link time. Therefore, the compiler must not optimize away this
+ catch clause. */
+ if (i != 7)
+ return 2;
+ }
+}
diff --git a/gcc/tree.h b/gcc/tree.h
index 26e0676..c672d94 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -2901,6 +2901,26 @@ extern void decl_restrict_base_insert (tree, tree);
something which is DECL_COMDAT. */
#define DECL_COMDAT(NODE) (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.comdat_flag)
+/* A replaceable function is one which may be replaced at link-time
+ with an entirely different definition, provided that the
+ replacement has the same type. For example, functions declared
+ with __attribute__((weak)) on most systems are replaceable.
+
+ COMDAT functions are not replaceable, since all definitions of the
+ function must be equivalent. It is important that COMDAT functions
+ not be treated as replaceable so that use of C++ template
+ instantiations is not penalized.
+
+ For example, DECL_REPLACEABLE is used to determine whether or not a
+ function (including a template instantiation) which is not
+ explicitly declared "inline" can be inlined. If the function is
+ DECL_REPLACEABLE then it is not safe to do the inlining, since the
+ implementation chosen at link-time may be different. However, a
+ function that is not DECL_REPLACEABLE can be inlined, since all
+ versions of the function will be functionally identical. */
+#define DECL_REPLACEABLE_P(NODE) \
+ (!DECL_COMDAT (NODE) && !targetm.binds_local_p (NODE))
+
/* The name of the object as the assembler will see it (but before any
translations made by ASM_OUTPUT_LABELREF). Often this is the same
as DECL_NAME. It is an IDENTIFIER_NODE. */