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
+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.
2005-03-14 Geoffrey Keating <geoffk@apple.com>
* doc/cppopts.texi (-fexec-charset): Add concept index entry.
--- /dev/null
+/* { 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;
+}
+
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. */
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;
DECL_EXTERNAL (var) = 1;
bitmap_set_bit (call_clobbered_vars, ann->uid);
ssa_call_clobbered_cache_valid = false;
clear_call_clobbered (tree var)
{
var_ann_t ann = var_ann (var);
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;
DECL_EXTERNAL (var) = 0;
bitmap_clear_bit (call_clobbered_vars, ann->uid);
ssa_call_clobbered_cache_valid = false;
if (s_ann->addresses_taken == NULL)
s_ann->addresses_taken = BITMAP_GGC_ALLOC ();
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)))
{
if (var_can_have_subvars (var)
&& (svars = get_subvars_for_var (var)))
{
for (sv = svars; sv; sv = sv->next)
bitmap_set_bit (s_ann->addresses_taken, var_ann (sv->var)->uid);
}
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);
if (current_function_stdarg)
return false;
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))
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;
}
&& is_call_clobbered (var))
return false;
}