aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDaniel Berlin <dberlin@dberlin.org>2005-03-15 01:26:35 +0000
committerDaniel Berlin <dberlin@gcc.gnu.org>2005-03-15 01:26:35 +0000
commit9044951e0d66b05fb6f5b2982a99857d67d7c486 (patch)
tree5152c9ec2737c779726a8e050244706fcefdc704 /gcc
parent50668cf626cf30043890f1000f500ce69a54fedb (diff)
downloadgcc-9044951e0d66b05fb6f5b2982a99857d67d7c486.zip
gcc-9044951e0d66b05fb6f5b2982a99857d67d7c486.tar.gz
gcc-9044951e0d66b05fb6f5b2982a99857d67d7c486.tar.bz2
re PR tree-optimization/20458 (structure aliasing causes wrong code)
2005-03-14 Daniel Berlin <dberlin@dberlin.org> Fix PR tree-optimization/20458 * tree-flow-inline.h (mark_call_clobbered): Don't fiddle DECL_EXTERNAL on STRUCT_FIELD tags. (clear_call_clobbered): Ditto. * tree-ssa-operands.c (note_addressable): Make sure the original variable doesn't slip into the addressable list if we have subvars. * tree-tailcall.c (suitable_for_tail_opt_p): Look at STRUCT_FIELD tags too. From-SVN: r96462
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr20458.C37
-rw-r--r--gcc/tree-flow-inline.h4
-rw-r--r--gcc/tree-ssa-operands.c4
-rw-r--r--gcc/tree-tailcall.c7
5 files changed, 59 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 13e2a83..010a9ad 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2005-03-14 Daniel Berlin <dberlin@dberlin.org>
+
+ Fix PR tree-optimization/20458
+
+ * tree-flow-inline.h (mark_call_clobbered): Don't fiddle
+ DECL_EXTERNAL on STRUCT_FIELD tags.
+ (clear_call_clobbered): Ditto.
+ * tree-ssa-operands.c (note_addressable): Make sure the original
+ variable doesn't slip into the addressable list if we have
+ subvars.
+ * tree-tailcall.c (suitable_for_tail_opt_p): Look at STRUCT_FIELD
+ tags too.
+
2005-03-14 Geoffrey Keating <geoffk@apple.com>
* doc/cppopts.texi (-fexec-charset): Add concept index entry.
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr20458.C b/gcc/testsuite/g++.dg/tree-ssa/pr20458.C
new file mode 100644
index 0000000..d4e7d1a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr20458.C
@@ -0,0 +1,37 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+/* The tail call optimization would inapproriately tail call the
+ destructors due to not recognizing a call clobbered variable */
+namespace std
+{
+ class locale
+ {
+ public:
+ locale();
+ ~locale();
+ };
+}
+
+struct B
+{
+ std::locale _M_buf_locale;
+ virtual ~B() {}
+};
+
+struct C : public B
+{
+ char *s;
+};
+
+void foo ()
+{
+ C c;
+}
+
+int main()
+{
+ foo ();
+ return 0;
+}
+
diff --git a/gcc/tree-flow-inline.h b/gcc/tree-flow-inline.h
index 7701e5c..2d29eb2 100644
--- a/gcc/tree-flow-inline.h
+++ b/gcc/tree-flow-inline.h
@@ -619,7 +619,7 @@ mark_call_clobbered (tree var)
variable. This is because the pointer that VAR represents has
been found to point to either an arbitrary location or to a known
location in global memory. */
- if (ann->mem_tag_kind != NOT_A_TAG)
+ if (ann->mem_tag_kind != NOT_A_TAG && ann->mem_tag_kind != STRUCT_FIELD)
DECL_EXTERNAL (var) = 1;
bitmap_set_bit (call_clobbered_vars, ann->uid);
ssa_call_clobbered_cache_valid = false;
@@ -631,7 +631,7 @@ static inline void
clear_call_clobbered (tree var)
{
var_ann_t ann = var_ann (var);
- if (ann->mem_tag_kind != NOT_A_TAG)
+ if (ann->mem_tag_kind != NOT_A_TAG && ann->mem_tag_kind != STRUCT_FIELD)
DECL_EXTERNAL (var) = 0;
bitmap_clear_bit (call_clobbered_vars, ann->uid);
ssa_call_clobbered_cache_valid = false;
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index 2a63d08..a3b44e2 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -1729,7 +1729,7 @@ note_addressable (tree var, stmt_ann_t s_ann)
if (s_ann->addresses_taken == NULL)
s_ann->addresses_taken = BITMAP_GGC_ALLOC ();
- bitmap_set_bit (s_ann->addresses_taken, var_ann (var)->uid);
+
if (var_can_have_subvars (var)
&& (svars = get_subvars_for_var (var)))
{
@@ -1737,6 +1737,8 @@ note_addressable (tree var, stmt_ann_t s_ann)
for (sv = svars; sv; sv = sv->next)
bitmap_set_bit (s_ann->addresses_taken, var_ann (sv->var)->uid);
}
+ else
+ bitmap_set_bit (s_ann->addresses_taken, var_ann (var)->uid);
}
}
diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c
index 8f4778d..3c2036c 100644
--- a/gcc/tree-tailcall.c
+++ b/gcc/tree-tailcall.c
@@ -137,14 +137,15 @@ suitable_for_tail_opt_p (void)
if (current_function_stdarg)
return false;
- /* No local variable should be call-clobbered. We ignore any kind
- of memory tag, as these are not real variables. */
+ /* No local variable nor structure field should be call-clobbered. We
+ ignore any kind of memory tag, as these are not real variables. */
for (i = 0; i < (int) VARRAY_ACTIVE_SIZE (referenced_vars); i++)
{
tree var = VARRAY_TREE (referenced_vars, i);
if (!(TREE_STATIC (var) || DECL_EXTERNAL (var))
- && var_ann (var)->mem_tag_kind == NOT_A_TAG
+ && (var_ann (var)->mem_tag_kind == NOT_A_TAG
+ || var_ann (var)->mem_tag_kind == STRUCT_FIELD)
&& is_call_clobbered (var))
return false;
}