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
This commit is contained in:
Mark Mitchell 2007-02-11 18:58:05 +00:00 committed by Mark Mitchell
parent f57d17f1fc
commit 56fd65c7d9
10 changed files with 115 additions and 9 deletions

View File

@ -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>

View File

@ -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.

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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>

View File

@ -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 ();
}
}

View File

@ -0,0 +1,3 @@
extern void f() {
throw 7;
}

View File

@ -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;
}
}

View File

@ -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. */