PR tree-optimization/29484
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 3 Jan 2008 08:33:57 +0000 (08:33 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 3 Jan 2008 08:33:57 +0000 (08:33 +0000)
* tree-inline.c (inline_forbidden_p_2): New function.
(inline_forbidden_p): Disallow inlining if some static var
has an address of a local LABEL_DECL in its initializer.
* doc/extend.texi (Labels as Values): Document &&foo behaviour
vs. inlining.

* gcc.c-torture/execute/20071220-1.c: New test.
* gcc.c-torture/execute/20071220-2.c: New test.

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

gcc/ChangeLog
gcc/doc/extend.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20071220-1.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/20071220-2.c [new file with mode: 0644]
gcc/tree-inline.c

index f5516e7..e7098d0 100644 (file)
@@ -1,3 +1,12 @@
+2008-01-03  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/29484
+       * tree-inline.c (inline_forbidden_p_2): New function.
+       (inline_forbidden_p): Disallow inlining if some static var
+       has an address of a local LABEL_DECL in its initializer.
+       * doc/extend.texi (Labels as Values): Document &&foo behaviour
+       vs. inlining.
+
 2007-12-19  Sebastian Pop  <sebastian.pop@amd.com>
 
        PR tree-optimization/34635
index c86052e..34a5a46 100644 (file)
@@ -370,6 +370,12 @@ This is more friendly to code living in shared libraries, as it reduces
 the number of dynamic relocations that are needed, and by consequence,
 allows the data to be read-only.
 
+The @code{&&foo} expressions for the same label might have different values
+if the containing function is inlined or cloned.  If a program relies on
+them being always the same, @code{__attribute__((__noinline__))} should
+be used to prevent inlining.  If @code{&&foo} is used
+in a static variable initializer, inlining is forbidden.
+
 @node Nested Functions
 @section Nested Functions
 @cindex nested functions
index ff42813..abf7969 100644 (file)
@@ -1,3 +1,9 @@
+2008-01-03  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/29484
+       * gcc.c-torture/execute/20071220-1.c: New test.
+       * gcc.c-torture/execute/20071220-2.c: New test.
+
 2007-12-19  Sebastian Pop  <sebastian.pop@amd.com>
 
        PR tree-optimization/34635
diff --git a/gcc/testsuite/gcc.c-torture/execute/20071220-1.c b/gcc/testsuite/gcc.c-torture/execute/20071220-1.c
new file mode 100644 (file)
index 0000000..00c2fa5
--- /dev/null
@@ -0,0 +1,40 @@
+/* PR tree-optimization/29484 */
+
+extern void abort (void);
+
+void *__attribute__((noinline))
+baz (void **lab)
+{
+  asm volatile ("" : "+r" (lab));
+  return *lab;
+}
+
+static inline
+int bar (void)
+{
+  static void *b[] = { &&addr };
+  void *p = baz (b);
+  goto *p;
+addr:
+  return 17;
+}
+
+int __attribute__((noinline))
+f1 (void)
+{
+  return bar ();
+}
+
+int __attribute__((noinline))
+f2 (void)
+{
+  return bar ();
+}
+
+int
+main (void)
+{
+  if (f1 () != 17 || f1 () != 17 || f2 () != 17 || f2 () != 17)
+    abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/20071220-2.c b/gcc/testsuite/gcc.c-torture/execute/20071220-2.c
new file mode 100644 (file)
index 0000000..93fa9de
--- /dev/null
@@ -0,0 +1,39 @@
+/* PR tree-optimization/29484 */
+
+extern void abort (void);
+
+void *__attribute__((noinline))
+baz (void **lab)
+{
+  asm volatile ("" : "+r" (lab));
+  return *lab;
+}
+
+static inline
+int bar (void)
+{
+  static void *b[] = { &&addr };
+  baz (b);
+addr:
+  return 17;
+}
+
+int __attribute__((noinline))
+f1 (void)
+{
+  return bar ();
+}
+
+int __attribute__((noinline))
+f2 (void)
+{
+  return bar ();
+}
+
+int
+main (void)
+{
+  if (f1 () != 17 || f1 () != 17 || f2 () != 17 || f2 () != 17)
+    abort ();
+  return 0;
+}
index 1efc0ed..ebb413a 100644 (file)
@@ -1951,6 +1951,27 @@ inline_forbidden_p_1 (tree *nodep, int *walk_subtrees ATTRIBUTE_UNUSED,
   return NULL_TREE;
 }
 
+static tree
+inline_forbidden_p_2 (tree *nodep, int *walk_subtrees,
+                     void *fnp)
+{
+  tree node = *nodep;
+  tree fn = (tree) fnp;
+
+  if (TREE_CODE (node) == LABEL_DECL && DECL_CONTEXT (node) == fn)
+    {
+      inline_forbidden_reason
+       = G_("function %q+F can never be inlined "
+            "because it saves address of local label in a static variable");
+      return node;
+    }
+
+  if (TYPE_P (node))
+    *walk_subtrees = 0;
+
+  return NULL_TREE;
+}
+
 /* Return subexpression representing possible alloca call, if any.  */
 static tree
 inline_forbidden_p (tree fndecl)
@@ -1959,16 +1980,31 @@ inline_forbidden_p (tree fndecl)
   block_stmt_iterator bsi;
   basic_block bb;
   tree ret = NULL_TREE;
+  struct function *fun = DECL_STRUCT_FUNCTION (fndecl);
+  tree step;
 
-  FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (fndecl))
+  FOR_EACH_BB_FN (bb, fun)
     for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
       {
        ret = walk_tree_without_duplicates (bsi_stmt_ptr (bsi),
-                                   inline_forbidden_p_1, fndecl);
+                                           inline_forbidden_p_1, fndecl);
        if (ret)
          goto egress;
       }
 
+  for (step = fun->unexpanded_var_list; step; step = TREE_CHAIN (step))
+    {
+      tree decl = TREE_VALUE (step);
+      if (TREE_CODE (decl) == VAR_DECL
+         && TREE_STATIC (decl)
+         && !DECL_EXTERNAL (decl)
+         && DECL_INITIAL (decl))
+       ret = walk_tree_without_duplicates (&DECL_INITIAL (decl),
+                                           inline_forbidden_p_2, fndecl);
+       if (ret)
+         goto egress;
+    }
+
 egress:
   input_location = saved_loc;
   return ret;