]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/47278 (hidden weak function not handled properly)
authorRichard Guenther <rguenther@suse.de>
Tue, 8 Mar 2011 13:03:34 +0000 (13:03 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Tue, 8 Mar 2011 13:03:34 +0000 (13:03 +0000)
2011-03-08  Richard Guenther  <rguenther@suse.de>

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

gcc/ChangeLog
gcc/cgraph.c
gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr47278-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr47278-2.c [new file with mode: 0644]
gcc/tree-inline.c
gcc/tree.h
gcc/varasm.c

index c03813142a62adf9ef98745dc43817f0b7542f41..328397bf6e0af5a0fa2a0b51df04f5a89413a69e 100644 (file)
@@ -1,3 +1,14 @@
+2011-03-08  Richard Guenther  <rguenther@suse.de>
+
+       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 <pthaugen@us.ibm.com>
 
        Backport from mainline
index c5be68f6a029648250145adb01ecd8912d82c8b5..29d5321866b2946fcb5ecd4b65e0716729082be1 100644 (file)
@@ -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;
 
index 44dd46251def31a5328946712e8139b1d9e2383e..1007bccc464464a302735c58515e2e2a831ee89a 100644 (file)
@@ -1,3 +1,8 @@
+2011-03-08  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/47278
+       * decl.c (finish_function): Use decl_replaceable_p.
+
 2011-03-01  Jason Merrill  <jason@redhat.com>
 
        PR c++/46159
index b69896ee2afd9bc762905c1ed682bfcb574cb337..b347c93423fbdc97e96f5279683bf8b8efd40ca4 100644 (file)
@@ -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
index 8159f7d5e36ca0950b2a1a99ce5bb544a1b77efe..645718ce7482d1e770ae428f6fe729d4988298fa 100644 (file)
@@ -1,3 +1,9 @@
+2011-03-08  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/47278
+       * gcc.dg/torture/pr47278-1.c: New testcase.
+       * gcc.dg/torture/pr47278-2.c: Likewise.
+
 2011-03-07  Pat Haugen <pthaugen@us.ibm.com>
 
        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 (file)
index 0000000..6655f18
--- /dev/null
@@ -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 (file)
index 0000000..89cfd49
--- /dev/null
@@ -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;
+}
index af1adf4c69658f6ec5bdda0233f74c3ee56ae3b5..3e69cdeb5797bf8d5dd6eaf9f5176fcb89cd5839 100644 (file)
@@ -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))
index 60e38ea0149a287d0ce485b4b174b2f4e56d5e05..c503c7d940bee89260e87c21f90807956f94065e 100644 (file)
@@ -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);
index af9adffd73d55ac020db7ae2671c50c101363cb6..0d6ecb314d66a24565c3902580c73f8744a89f3d 100644 (file)
@@ -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.  */