diff options
author | Mark Mitchell <mark@codesourcery.com> | 2007-02-11 18:58:05 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2007-02-11 18:58:05 +0000 |
commit | 56fd65c7d9a3fd9ab80a627eb6caf24483801ff5 (patch) | |
tree | 37425a6a59c6e2da923d37b739cbb1c65f2cfbd9 /gcc | |
parent | f57d17f1fc2f31047644ed6f18f1087f65f8f88b (diff) | |
download | gcc-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/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/decl.c | 2 | ||||
-rw-r--r-- | gcc/cp/tree.c | 10 | ||||
-rw-r--r-- | gcc/except.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/eh/comdat1.C | 42 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/eh/weak1-a.cc | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/eh/weak1.C | 23 | ||||
-rw-r--r-- | gcc/tree.h | 20 |
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; + } +} @@ -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. */ |