From: Richard Guenther Date: Tue, 8 Mar 2011 13:03:34 +0000 (+0000) Subject: re PR tree-optimization/47278 (hidden weak function not handled properly) X-Git-Tag: releases/gcc-4.5.3~171 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fbb0378a23f74870ccedb755a0a4bdca2beda48a;p=thirdparty%2Fgcc.git re PR tree-optimization/47278 (hidden weak function not handled properly) 2011-03-08 Richard Guenther PR tree-optimization/47278 * tree.h (DECL_REPLACEABLE_P): Remove. (decl_replaceable_p): Declare. (decl_binds_to_current_def_p): Likewise. * varasm.c (decl_replaceable_p): New function. (decl_binds_to_current_def_p): Likewise. * cgraph.c (cgraph_function_body_availability): Use decl_replaceable_p. * tree-inline.c (inlinable_function_p): Likewise. cp/ * decl.c (finish_function): Use decl_replaceable_p. testsuite/ * gcc.dg/torture/pr47278-1.c: New testcase. * gcc.dg/torture/pr47278-2.c: Likewise. From-SVN: r170775 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c03813142a62..328397bf6e0a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2011-03-08 Richard Guenther + + PR tree-optimization/47278 + * tree.h (DECL_REPLACEABLE_P): Remove. + (decl_replaceable_p): Declare. + (decl_binds_to_current_def_p): Likewise. + * varasm.c (decl_replaceable_p): New function. + (decl_binds_to_current_def_p): Likewise. + * cgraph.c (cgraph_function_body_availability): Use decl_replaceable_p. + * tree-inline.c (inlinable_function_p): Likewise. + 2011-03-07 Pat Haugen Backport from mainline diff --git a/gcc/cgraph.c b/gcc/cgraph.c index c5be68f6a029..29d5321866b2 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -2093,7 +2093,7 @@ cgraph_function_body_availability (struct cgraph_node *node) AVAIL_AVAILABLE here? That would be good reason to preserve this bit. */ - else if (DECL_REPLACEABLE_P (node->decl) && !DECL_EXTERNAL (node->decl)) + else if (decl_replaceable_p (node->decl) && !DECL_EXTERNAL (node->decl)) avail = AVAIL_OVERWRITABLE; else avail = AVAIL_AVAILABLE; diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 44dd46251def..1007bccc4644 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2011-03-08 Richard Guenther + + PR tree-optimization/47278 + * decl.c (finish_function): Use decl_replaceable_p. + 2011-03-01 Jason Merrill PR c++/46159 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index b69896ee2afd..b347c93423fb 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -12502,7 +12502,7 @@ finish_function (int flags) if (!processing_template_decl && !cp_function_chain->can_throw && !flag_non_call_exceptions - && !DECL_REPLACEABLE_P (fndecl)) + && !decl_replaceable_p (fndecl)) TREE_NOTHROW (fndecl) = 1; /* This must come after expand_function_end because cleanups might diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8159f7d5e36c..645718ce7482 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2011-03-08 Richard Guenther + + PR tree-optimization/47278 + * gcc.dg/torture/pr47278-1.c: New testcase. + * gcc.dg/torture/pr47278-2.c: Likewise. + 2011-03-07 Pat Haugen Backport from mainline diff --git a/gcc/testsuite/gcc.dg/torture/pr47278-1.c b/gcc/testsuite/gcc.dg/torture/pr47278-1.c new file mode 100644 index 000000000000..6655f18c4345 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr47278-1.c @@ -0,0 +1,4 @@ +/* { dg-do run } */ +/* { dg-additional-sources "pr47278-2.c" } */ + +int foo (void) { return 1; } diff --git a/gcc/testsuite/gcc.dg/torture/pr47278-2.c b/gcc/testsuite/gcc.dg/torture/pr47278-2.c new file mode 100644 index 000000000000..89cfd4927df2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr47278-2.c @@ -0,0 +1,13 @@ +extern void abort (void); + +int __attribute__((weak,visibility("hidden"))) foo (void) +{ + return 0; +} + +int main() +{ + if (foo() != 1) + abort (); + return 0; +} diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index af1adf4c6965..3e69cdeb5797 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -3067,7 +3067,7 @@ tree_inlinable_function_p (tree fn) /* Don't auto-inline anything that might not be bound within this unit of translation. */ else if (!DECL_DECLARED_INLINE_P (fn) - && DECL_REPLACEABLE_P (fn)) + && decl_replaceable_p (fn)) inlinable = false; else if (!function_attribute_inlinable_p (fn)) diff --git a/gcc/tree.h b/gcc/tree.h index 60e38ea0149a..c503c7d940be 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2913,26 +2913,6 @@ struct GTY(()) tree_parm_decl { #define DECL_COMDAT_GROUP(NODE) (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.comdat_group) -/* 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. */ @@ -5145,6 +5125,8 @@ extern void finish_aliases_1 (void); extern void finish_aliases_2 (void); extern tree emutls_decl (tree); extern void remove_unreachable_alias_pairs (void); +extern bool decl_replaceable_p (tree); +extern bool decl_binds_to_current_def_p (tree); /* In stmt.c */ extern void expand_computed_goto (tree); diff --git a/gcc/varasm.c b/gcc/varasm.c index af9adffd73d5..0d6ecb314d66 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -6691,6 +6691,51 @@ default_binds_local_p_1 (const_tree exp, int shlib) return local_p; } +/* Return true when references to DECL must bind to current definition in + final executable. + + The condition is usually equivalent to whether the function binds to the + current module (shared library or executable), that is to binds_local_p. + We use this fact to avoid need for another target hook and implement + the logic using binds_local_p and just special cases where + decl_binds_to_current_def_p is stronger than binds local_p. In particular + the weak definitions (that can be overwritten at linktime by other + definition from different object file) and when resolution info is available + we simply use the knowledge passed to us by linker plugin. */ +bool +decl_binds_to_current_def_p (tree decl) +{ + gcc_assert (DECL_P (decl)); + if (!TREE_PUBLIC (decl)) + return true; + if (!targetm.binds_local_p (decl)) + return false; + /* Otherwise we have to assume the worst for DECL_WEAK (hidden weaks + binds localy but still can be overwritten). + This rely on fact that binds_local_p behave as decl_replaceable_p + for all other declaration types. */ + return !DECL_WEAK (decl); +} + +/* A replaceable function or variable 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. */ + +bool +decl_replaceable_p (tree decl) +{ + gcc_assert (DECL_P (decl)); + if (!TREE_PUBLIC (decl) || DECL_COMDAT (decl)) + return false; + return !decl_binds_to_current_def_p (decl); +} + /* Default function to output code that will globalize a label. A target must define GLOBAL_ASM_OP or provide its own function to globalize a label. */