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:
parent
f57d17f1fc
commit
56fd65c7d9
|
@ -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>
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
extern void f() {
|
||||
throw 7;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
20
gcc/tree.h
20
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. */
|
||||
|
|
Loading…
Reference in New Issue