From eb079594363d78340613e05cb14f918136239880 Mon Sep 17 00:00:00 2001 From: dberlin Date: Tue, 15 Mar 2005 01:26:35 +0000 Subject: [PATCH] 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@96462 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 13 ++++++++++++ gcc/testsuite/g++.dg/tree-ssa/pr20458.C | 37 +++++++++++++++++++++++++++++++++ gcc/tree-flow-inline.h | 4 ++-- gcc/tree-ssa-operands.c | 4 +++- gcc/tree-tailcall.c | 7 ++++--- 5 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/g++.dg/tree-ssa/pr20458.C 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 + + 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 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; } -- 2.7.4