PR target/29487
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 11 Feb 2007 18:58:05 +0000 (18:58 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 11 Feb 2007 18:58:05 +0000 (18:58 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@121819 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/tree.c
gcc/except.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/eh/comdat1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/eh/weak1-a.cc [new file with mode: 0644]
gcc/testsuite/g++.dg/eh/weak1.C [new file with mode: 0644]
gcc/tree.h

index c7fce63..ce0f2ae 100644 (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>
index 9fcd66a..f4afe06 100644 (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.
index b6d0e53..2212254 100644 (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
index 78545e1..a3d11a3 100644 (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;
index 9f40dc4..dc51079 100644 (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;
index 8f912c2..3f38b0c 100644 (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>
 
diff --git a/gcc/testsuite/g++.dg/eh/comdat1.C b/gcc/testsuite/g++.dg/eh/comdat1.C
new file mode 100644 (file)
index 0000000..4a11805
--- /dev/null
@@ -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 (file)
index 0000000..1885fae
--- /dev/null
@@ -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 (file)
index 0000000..09f2fcb
--- /dev/null
@@ -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;
+  }
+}
index 26e0676..c672d94 100644 (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.  */