diff mbox

vector garbaged collected while still in use

Message ID CAAkRFZ+BxS0WrUa37cGSN1SBzSfa3w8c-MdxzyVrWZCL0Ct0tw@mail.gmail.com
State New
Headers show

Commit Message

Xinliang David Li Nov. 7, 2011, 7:53 a.m. UTC
I have seen compiler build error (segmentation fault) in libstdc++-v3.
It turns out that a vector allocated in gc memory is GCed before the
vector is released. The gc call is from a call to synethesize_method
from cp_finish_decl.

The following patch fixes the problem. Compiler bootstraps and tested
on linux/x86-64. Ok for trunk (or better fix suggested)?

thanks,

David

2011-11-05  Xinliang David Li  <davidxl@google.com>

        * cp/decl.c (cp_finish_decl): Prevent cleanups from
        being garbage collected before being released.

Comments

Richard Biener Nov. 7, 2011, 9:56 a.m. UTC | #1
On Mon, Nov 7, 2011 at 8:53 AM, Xinliang David Li <davidxl@google.com> wrote:
> I have seen compiler build error (segmentation fault) in libstdc++-v3.
> It turns out that a vector allocated in gc memory is GCed before the
> vector is released. The gc call is from a call to synethesize_method
> from cp_finish_decl.
>
> The following patch fixes the problem. Compiler bootstraps and tested
> on linux/x86-64. Ok for trunk (or better fix suggested)?

The context looks different on trunk.  Do you have a backtrace on where
we ggc collect from a frame starting at cp_finish_decl?

> thanks,
>
> David
>
> 2011-11-05  Xinliang David Li  <davidxl@google.com>
>
>        * cp/decl.c (cp_finish_decl): Prevent cleanups from
>        being garbage collected before being released.
>
>
> Index: cp/decl.c
> ===================================================================
> --- cp/decl.c   (revision 181013)
> +++ cp/decl.c   (working copy)
> @@ -5902,6 +5902,8 @@ value_dependent_init_p (tree init)
>    FLAGS is LOOKUP_ONLYCONVERTING if the = init syntax was used, else 0
>    if the (init) syntax was used.  */
>
> +static GTY (()) VEC(tree,gc) *cleanups_vec;
> +
>  void
>  cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
>                tree asmspec_tree, int flags)
> @@ -5914,6 +5916,7 @@ cp_finish_decl (tree decl, tree init, bo
>   bool var_definition_p = false;
>   tree auto_node;
>
> +  cleanups_vec = cleanups;
>   if (decl == error_mark_node)
>     return;
>   else if (! decl)
> @@ -6319,6 +6322,7 @@ cp_finish_decl (tree decl, tree init, bo
>   FOR_EACH_VEC_ELT (tree, cleanups, i, t)
>     push_cleanup (decl, t, false);
>   release_tree_vector (cleanups);
> +  cleanups_vec = NULL;
>
>   if (was_readonly)
>     TREE_READONLY (decl) = 1;
>
Xinliang David Li Nov. 7, 2011, 4:41 p.m. UTC | #2
Here is the stack trace when the watch point is hit (the watch point
is on address &cleanups->base.prefix.num

David

#0  memset () at ../sysdeps/x86_64/memset.S:336
#1  0x0000000000d1528d in poison_pages () at
/usr/local/google/davidxl/dev/gcc/tot/gcc/ggc-page.c:1983
#2  0x0000000000d15424 in ggc_collect () at
/usr/local/google/davidxl/dev/gcc/tot/gcc/ggc-page.c:2076
#3  0x0000000001028d7f in cgraph_finalize_function
(decl=0x7ffff577d600, nested=0 '\000') at
/usr/local/google/davidxl/dev/gcc/tot/gcc/cgraphunit.c:376
#4  0x0000000000988010 in expand_or_defer_fn (fn=0x7ffff577d600) at
/usr/local/google/davidxl/dev/gcc/tot/gcc/cp/semantics.c:3797
#5  0x0000000000a678a7 in maybe_clone_body (fn=0x7ffff5770700) at
/usr/local/google/davidxl/dev/gcc/tot/gcc/cp/optimize.c:426
#6  0x0000000000987aa3 in expand_or_defer_fn_1 (fn=0x7ffff5770700) at
/usr/local/google/davidxl/dev/gcc/tot/gcc/cp/semantics.c:3722
#7  0x0000000000987fe0 in expand_or_defer_fn (fn=0x7ffff5770700) at
/usr/local/google/davidxl/dev/gcc/tot/gcc/cp/semantics.c:3792
#8  0x000000000091c5f5 in synthesize_method (fndecl=0x7ffff5770700) at
/usr/local/google/davidxl/dev/gcc/tot/gcc/cp/method.c:773
#9  0x0000000000551fa0 in cp_finish_decl (decl=0x7ffff5770700,
init=0x7ffff6d8f898, init_const_expr_p=0 '\000', asmspec_tree=0x0,
flags=11) at /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/decl.c:6286
#10 0x00000000007c33e0 in cp_parser_init_declarator
(parser=0x7ffff68a5370, decl_specifiers=0x7fffffffced0, checks=0x0,
function_definition_allowed_p=1 '\001', member_p=0 '\000',
declares_class_or_enum=0, function_definition_p=0x7fffffffcf4e "",
maybe_range_for_decl=0x0) at
/usr/local/google/davidxl/dev/gcc/tot/gcc/cp/parser.c:15462
#11 0x00000000007ba512 in cp_parser_simple_declaration
(parser=0x7ffff68a5370, function_definition_allowed_p=1 '\001',
maybe_range_for_decl=0x0) at
/usr/local/google/davidxl/dev/gcc/tot/gcc/cp/parser.c:10301
#12 0x00000000007ba322 in cp_parser_block_declaration
(parser=0x7ffff68a5370, statement_p=0 '\000') at
/usr/local/google/davidxl/dev/gcc/tot/gcc/cp/parser.c:10187
#13 0x00000000007ba107 in cp_parser_declaration
(parser=0x7ffff68a5370) at
/usr/local/google/davidxl/dev/gcc/tot/gcc/cp/parser.c:10092
#14 0x00000000007b9cea in cp_parser_declaration_seq_opt
(parser=0x7ffff68a5370) at
/usr/local/google/davidxl/dev/gcc/tot/gcc/cp/parser.c:9978
#15 0x00000000007c1e36 in cp_parser_namespace_body
(parser=0x7ffff68a5370) at
/usr/local/google/davidxl/dev/gcc/tot/gcc/cp/parser.c:14633
#16 0x00000000007c1dec in cp_parser_namespace_definition
(parser=0x7ffff68a5370) at
/usr/local/google/davidxl/dev/gcc/tot/gcc/cp/parser.c:14614
#17 0x00000000007ba04d in cp_parser_declaration
(parser=0x7ffff68a5370) at
/usr/local/google/davidxl/dev/gcc/tot/gcc/cp/parser.c:10076
#18 0x00000000007b9cea in cp_parser_declaration_seq_opt
(parser=0x7ffff68a5370) at
/usr/local/google/davidxl/dev/gcc/tot/gcc/cp/parser.c:9978
#19 0x00000000007ac646 in cp_parser_translation_unit
(parser=0x7ffff68a5370) at
/usr/local/google/davidxl/dev/gcc/tot/gcc/cp/parser.c:3739
#20 0x00000000007e0682 in c_parse_file () at
/usr/local/google/davidxl/dev/gcc/tot/gcc/cp/parser.c:26714
#21 0x0000000000c5dc2b in c_common_parse_file () at
/usr/local/google/davidxl/dev/gcc/tot/gcc/c-family/c-opts.c:1122
#22 0x000000000203036f in compile_file () at
/usr/local/google/davidxl/dev/gcc/tot/gcc/toplev.c:565
#23 0x0000000002032584 in do_compile () at
/usr/local/google/davidxl/dev/gcc/tot/gcc/toplev.c:1930
#24 0x00000000020326fb in toplev_main (argc=71, argv=0x7fffffffd3c8)
at /usr/local/google/davidxl/dev/gcc/tot/gcc/toplev.c:2006
#25 0x0000000000cd97e0 in main (argc=71, argv=0x7fffffffd3c8) at
/usr/local/google/davidxl/dev/gcc/tot/gcc/main.c:36


On Mon, Nov 7, 2011 at 1:56 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Mon, Nov 7, 2011 at 8:53 AM, Xinliang David Li <davidxl@google.com> wrote:
>> I have seen compiler build error (segmentation fault) in libstdc++-v3.
>> It turns out that a vector allocated in gc memory is GCed before the
>> vector is released. The gc call is from a call to synethesize_method
>> from cp_finish_decl.
>>
>> The following patch fixes the problem. Compiler bootstraps and tested
>> on linux/x86-64. Ok for trunk (or better fix suggested)?
>
> The context looks different on trunk.  Do you have a backtrace on where
> we ggc collect from a frame starting at cp_finish_decl?
>
>> thanks,
>>
>> David
>>
>> 2011-11-05  Xinliang David Li  <davidxl@google.com>
>>
>>        * cp/decl.c (cp_finish_decl): Prevent cleanups from
>>        being garbage collected before being released.
>>
>>
>> Index: cp/decl.c
>> ===================================================================
>> --- cp/decl.c   (revision 181013)
>> +++ cp/decl.c   (working copy)
>> @@ -5902,6 +5902,8 @@ value_dependent_init_p (tree init)
>>    FLAGS is LOOKUP_ONLYCONVERTING if the = init syntax was used, else 0
>>    if the (init) syntax was used.  */
>>
>> +static GTY (()) VEC(tree,gc) *cleanups_vec;
>> +
>>  void
>>  cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
>>                tree asmspec_tree, int flags)
>> @@ -5914,6 +5916,7 @@ cp_finish_decl (tree decl, tree init, bo
>>   bool var_definition_p = false;
>>   tree auto_node;
>>
>> +  cleanups_vec = cleanups;
>>   if (decl == error_mark_node)
>>     return;
>>   else if (! decl)
>> @@ -6319,6 +6322,7 @@ cp_finish_decl (tree decl, tree init, bo
>>   FOR_EACH_VEC_ELT (tree, cleanups, i, t)
>>     push_cleanup (decl, t, false);
>>   release_tree_vector (cleanups);
>> +  cleanups_vec = NULL;
>>
>>   if (was_readonly)
>>     TREE_READONLY (decl) = 1;
>>
>
Richard Biener Nov. 7, 2011, 10:09 p.m. UTC | #3
On Mon, Nov 7, 2011 at 5:41 PM, Xinliang David Li <davidxl@google.com> wrote:
> Here is the stack trace when the watch point is hit (the watch point
> is on address &cleanups->base.prefix.num
>
> David
>
> #0  memset () at ../sysdeps/x86_64/memset.S:336
> #1  0x0000000000d1528d in poison_pages () at
> /usr/local/google/davidxl/dev/gcc/tot/gcc/ggc-page.c:1983
> #2  0x0000000000d15424 in ggc_collect () at
> /usr/local/google/davidxl/dev/gcc/tot/gcc/ggc-page.c:2076
> #3  0x0000000001028d7f in cgraph_finalize_function
> (decl=0x7ffff577d600, nested=0 '\000') at
> /usr/local/google/davidxl/dev/gcc/tot/gcc/cgraphunit.c:376

Hm.  We already conditionally arrange for cgraph_finalize_function to not
call ggc_collect - so it seems that doing so is even less safe than originally
thought.

Which means I think we should push calling ggc_collect to the callers,
which for the C++ frontend means ...

> #4  0x0000000000988010 in expand_or_defer_fn (fn=0x7ffff577d600) at
> /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/semantics.c:3797
> #5  0x0000000000a678a7 in maybe_clone_body (fn=0x7ffff5770700) at
> /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/optimize.c:426
> #6  0x0000000000987aa3 in expand_or_defer_fn_1 (fn=0x7ffff5770700) at
> /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/semantics.c:3722
> #7  0x0000000000987fe0 in expand_or_defer_fn (fn=0x7ffff5770700) at
> /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/semantics.c:3792
> #8  0x000000000091c5f5 in synthesize_method (fndecl=0x7ffff5770700) at
> /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/method.c:773
> #9  0x0000000000551fa0 in cp_finish_decl (decl=0x7ffff5770700,
> init=0x7ffff6d8f898, init_const_expr_p=0 '\000', asmspec_tree=0x0,
> flags=11) at /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/decl.c:6286

... probably here.  Though I'd also approve a patch that simply removes
the ggc_collect call (and the nested parameter).  Honza - you probably
added the ggc_collect - what's the reason to do it in this lowlevel place?

Thanks,
Richard.
Xinliang David Li Nov. 8, 2011, 5:10 p.m. UTC | #4
Here is the revised patch. Bootstrap and regression tested on linux/x86-64.

Honza, can you comment on the implication of this change?

thanks,

David

On Mon, Nov 7, 2011 at 2:09 PM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Mon, Nov 7, 2011 at 5:41 PM, Xinliang David Li <davidxl@google.com> wrote:
>> Here is the stack trace when the watch point is hit (the watch point
>> is on address &cleanups->base.prefix.num
>>
>> David
>>
>> #0  memset () at ../sysdeps/x86_64/memset.S:336
>> #1  0x0000000000d1528d in poison_pages () at
>> /usr/local/google/davidxl/dev/gcc/tot/gcc/ggc-page.c:1983
>> #2  0x0000000000d15424 in ggc_collect () at
>> /usr/local/google/davidxl/dev/gcc/tot/gcc/ggc-page.c:2076
>> #3  0x0000000001028d7f in cgraph_finalize_function
>> (decl=0x7ffff577d600, nested=0 '\000') at
>> /usr/local/google/davidxl/dev/gcc/tot/gcc/cgraphunit.c:376
>
> Hm.  We already conditionally arrange for cgraph_finalize_function to not
> call ggc_collect - so it seems that doing so is even less safe than originally
> thought.
>
> Which means I think we should push calling ggc_collect to the callers,
> which for the C++ frontend means ...
>
>> #4  0x0000000000988010 in expand_or_defer_fn (fn=0x7ffff577d600) at
>> /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/semantics.c:3797
>> #5  0x0000000000a678a7 in maybe_clone_body (fn=0x7ffff5770700) at
>> /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/optimize.c:426
>> #6  0x0000000000987aa3 in expand_or_defer_fn_1 (fn=0x7ffff5770700) at
>> /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/semantics.c:3722
>> #7  0x0000000000987fe0 in expand_or_defer_fn (fn=0x7ffff5770700) at
>> /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/semantics.c:3792
>> #8  0x000000000091c5f5 in synthesize_method (fndecl=0x7ffff5770700) at
>> /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/method.c:773
>> #9  0x0000000000551fa0 in cp_finish_decl (decl=0x7ffff5770700,
>> init=0x7ffff6d8f898, init_const_expr_p=0 '\000', asmspec_tree=0x0,
>> flags=11) at /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/decl.c:6286
>
> ... probably here.  Though I'd also approve a patch that simply removes
> the ggc_collect call (and the nested parameter).  Honza - you probably
> added the ggc_collect - what's the reason to do it in this lowlevel place?
>
> Thanks,
> Richard.
>
Richard Biener Nov. 9, 2011, 8:36 a.m. UTC | #5
On Tue, Nov 8, 2011 at 6:10 PM, Xinliang David Li <davidxl@google.com> wrote:
> Here is the revised patch. Bootstrap and regression tested on linux/x86-64.
>
> Honza, can you comment on the implication of this change?

Jason also seems to have touched this again, so maybe it's already
fixed?

> thanks,
>
> David
>
> On Mon, Nov 7, 2011 at 2:09 PM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Mon, Nov 7, 2011 at 5:41 PM, Xinliang David Li <davidxl@google.com> wrote:
>>> Here is the stack trace when the watch point is hit (the watch point
>>> is on address &cleanups->base.prefix.num
>>>
>>> David
>>>
>>> #0  memset () at ../sysdeps/x86_64/memset.S:336
>>> #1  0x0000000000d1528d in poison_pages () at
>>> /usr/local/google/davidxl/dev/gcc/tot/gcc/ggc-page.c:1983
>>> #2  0x0000000000d15424 in ggc_collect () at
>>> /usr/local/google/davidxl/dev/gcc/tot/gcc/ggc-page.c:2076
>>> #3  0x0000000001028d7f in cgraph_finalize_function
>>> (decl=0x7ffff577d600, nested=0 '\000') at
>>> /usr/local/google/davidxl/dev/gcc/tot/gcc/cgraphunit.c:376
>>
>> Hm.  We already conditionally arrange for cgraph_finalize_function to not
>> call ggc_collect - so it seems that doing so is even less safe than originally
>> thought.
>>
>> Which means I think we should push calling ggc_collect to the callers,
>> which for the C++ frontend means ...
>>
>>> #4  0x0000000000988010 in expand_or_defer_fn (fn=0x7ffff577d600) at
>>> /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/semantics.c:3797
>>> #5  0x0000000000a678a7 in maybe_clone_body (fn=0x7ffff5770700) at
>>> /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/optimize.c:426
>>> #6  0x0000000000987aa3 in expand_or_defer_fn_1 (fn=0x7ffff5770700) at
>>> /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/semantics.c:3722
>>> #7  0x0000000000987fe0 in expand_or_defer_fn (fn=0x7ffff5770700) at
>>> /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/semantics.c:3792
>>> #8  0x000000000091c5f5 in synthesize_method (fndecl=0x7ffff5770700) at
>>> /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/method.c:773
>>> #9  0x0000000000551fa0 in cp_finish_decl (decl=0x7ffff5770700,
>>> init=0x7ffff6d8f898, init_const_expr_p=0 '\000', asmspec_tree=0x0,
>>> flags=11) at /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/decl.c:6286
>>
>> ... probably here.  Though I'd also approve a patch that simply removes
>> the ggc_collect call (and the nested parameter).  Honza - you probably
>> added the ggc_collect - what's the reason to do it in this lowlevel place?
>>
>> Thanks,
>> Richard.
>>
>
Xinliang David Li Nov. 10, 2011, 5:55 p.m. UTC | #6
Looks like it is fixed already, so there is no need for this patch.

David

On Wed, Nov 9, 2011 at 12:36 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Tue, Nov 8, 2011 at 6:10 PM, Xinliang David Li <davidxl@google.com> wrote:
>> Here is the revised patch. Bootstrap and regression tested on linux/x86-64.
>>
>> Honza, can you comment on the implication of this change?
>
> Jason also seems to have touched this again, so maybe it's already
> fixed?
>
>> thanks,
>>
>> David
>>
>> On Mon, Nov 7, 2011 at 2:09 PM, Richard Guenther
>> <richard.guenther@gmail.com> wrote:
>>> On Mon, Nov 7, 2011 at 5:41 PM, Xinliang David Li <davidxl@google.com> wrote:
>>>> Here is the stack trace when the watch point is hit (the watch point
>>>> is on address &cleanups->base.prefix.num
>>>>
>>>> David
>>>>
>>>> #0  memset () at ../sysdeps/x86_64/memset.S:336
>>>> #1  0x0000000000d1528d in poison_pages () at
>>>> /usr/local/google/davidxl/dev/gcc/tot/gcc/ggc-page.c:1983
>>>> #2  0x0000000000d15424 in ggc_collect () at
>>>> /usr/local/google/davidxl/dev/gcc/tot/gcc/ggc-page.c:2076
>>>> #3  0x0000000001028d7f in cgraph_finalize_function
>>>> (decl=0x7ffff577d600, nested=0 '\000') at
>>>> /usr/local/google/davidxl/dev/gcc/tot/gcc/cgraphunit.c:376
>>>
>>> Hm.  We already conditionally arrange for cgraph_finalize_function to not
>>> call ggc_collect - so it seems that doing so is even less safe than originally
>>> thought.
>>>
>>> Which means I think we should push calling ggc_collect to the callers,
>>> which for the C++ frontend means ...
>>>
>>>> #4  0x0000000000988010 in expand_or_defer_fn (fn=0x7ffff577d600) at
>>>> /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/semantics.c:3797
>>>> #5  0x0000000000a678a7 in maybe_clone_body (fn=0x7ffff5770700) at
>>>> /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/optimize.c:426
>>>> #6  0x0000000000987aa3 in expand_or_defer_fn_1 (fn=0x7ffff5770700) at
>>>> /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/semantics.c:3722
>>>> #7  0x0000000000987fe0 in expand_or_defer_fn (fn=0x7ffff5770700) at
>>>> /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/semantics.c:3792
>>>> #8  0x000000000091c5f5 in synthesize_method (fndecl=0x7ffff5770700) at
>>>> /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/method.c:773
>>>> #9  0x0000000000551fa0 in cp_finish_decl (decl=0x7ffff5770700,
>>>> init=0x7ffff6d8f898, init_const_expr_p=0 '\000', asmspec_tree=0x0,
>>>> flags=11) at /usr/local/google/davidxl/dev/gcc/tot/gcc/cp/decl.c:6286
>>>
>>> ... probably here.  Though I'd also approve a patch that simply removes
>>> the ggc_collect call (and the nested parameter).  Honza - you probably
>>> added the ggc_collect - what's the reason to do it in this lowlevel place?
>>>
>>> Thanks,
>>> Richard.
>>>
>>
>
Jan Hubicka Nov. 14, 2011, 2:59 p.m. UTC | #7
> ... probably here.  Though I'd also approve a patch that simply removes
> the ggc_collect call (and the nested parameter).  Honza - you probably
> added the ggc_collect - what's the reason to do it in this lowlevel place?

The ggc_collect was always here. Before unit-at-a-time we used to run  
into backend at this place and when I got stuff into unit-at-a-time, I  
kept the collect as otherwise the frontends did not garbagecollect at  
all.
It is disabled for nested functions because nested functions did not  
compile immediately before.

Honza
>
> Thanks,
> Richard.
>
Jan Hubicka Nov. 14, 2011, 3:04 p.m. UTC | #8
> Here is the revised patch. Bootstrap and regression tested on linux/x86-64.
> 
> Honza, can you comment on the implication of this change?
Well, as I explained in previous email, this was traditinal place where
frontends collect garbage while parsing, so you would need to verify that all
the existing frontends actually do collect garbage resonably often.  The change
just adding GTY root seems better to me BTW.
C++ FE produce garbage and should thus garbage collect...

Honza
diff mbox

Patch

Index: cp/decl.c
===================================================================
--- cp/decl.c   (revision 181013)
+++ cp/decl.c   (working copy)
@@ -5902,6 +5902,8 @@  value_dependent_init_p (tree init)
    FLAGS is LOOKUP_ONLYCONVERTING if the = init syntax was used, else 0
    if the (init) syntax was used.  */

+static GTY (()) VEC(tree,gc) *cleanups_vec;
+
 void
 cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
                tree asmspec_tree, int flags)
@@ -5914,6 +5916,7 @@  cp_finish_decl (tree decl, tree init, bo
   bool var_definition_p = false;
   tree auto_node;

+  cleanups_vec = cleanups;
   if (decl == error_mark_node)
     return;
   else if (! decl)
@@ -6319,6 +6322,7 @@  cp_finish_decl (tree decl, tree init, bo
   FOR_EACH_VEC_ELT (tree, cleanups, i, t)
     push_cleanup (decl, t, false);
   release_tree_vector (cleanups);
+  cleanups_vec = NULL;

   if (was_readonly)
     TREE_READONLY (decl) = 1;