From: Daniel Berlin Date: Tue, 15 Mar 2005 01:26:35 +0000 (+0000) Subject: re PR tree-optimization/20458 (structure aliasing causes wrong code) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=9044951e0d66b05fb6f5b2982a99857d67d7c486;p=gcc.git re PR tree-optimization/20458 (structure aliasing causes wrong code) 2005-03-14 Daniel Berlin 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 13e2a83a1e8..010a9ad003b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2005-03-14 Daniel Berlin + + 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 * 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 00000000000..d4e7d1a1a86 --- /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 7701e5cc7fd..2d29eb2ff13 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 2a63d0874a6..a3b44e22ea3 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 8f4778da0b3..3c2036cdeac 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; }