Skip to content

Commit 2b8a8fc

Browse files
committed
Variables leaving scope on jumping should always be marked dead
Even if new variables would be introduced to the scope, the existing variables which go out of scope still need to be marked as dead and/or have their destructors called. The placeholder for construction is moved to after the destruction, as destructions should be done first.
1 parent e911fa9 commit 2b8a8fc

File tree

2 files changed

+38
-34
lines changed

2 files changed

+38
-34
lines changed

regression/cbmc/destructors/enter_lexical_block.desc

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ CORE
22
main.c
33
--unwind 10 --show-goto-functions
44
activate-multi-line-match
5-
(?P<comment_block>\/\/ [0-9]+ file main\.c line [0-9]+ function main)[\s]*5: .*newAlloc4 : struct tag-test[\s]*(?P>comment_block)[\s]*.*newAlloc4 := \{ 4 \}[\s]*(?P>comment_block)[\s]*.*newAlloc6 : struct tag-test[\s]*(?P>comment_block)[\s]*.*newAlloc6 := \{ 6 \}[\s]*(?P>comment_block)[\s]*.*newAlloc7 : struct tag-test[\s]*(?P>comment_block)[\s]*.*newAlloc7 := \{ 7 \}[\s]*(?P>comment_block)[\s]*GOTO 3
5+
(?P<comment_block>\/\/ [0-9]+ file main\.c line [0-9]+ function main)[\s]*5: .*newAlloc4 : struct tag-test[\s]*(?P>comment_block)[\s]*.*newAlloc4 := \{ 4 \}[\s]*(?P>comment_block)[\s]*.*newAlloc6 : struct tag-test[\s]*(?P>comment_block)[\s]*.*newAlloc6 := \{ 6 \}[\s]*(?P>comment_block)[\s]*.*newAlloc7 : struct tag-test[\s]*(?P>comment_block)[\s]*.*newAlloc7 := \{ 7 \}[\s]*(?P>comment_block)[\s]*.*DEAD main::1::2::2::newAlloc7[\s]*(?P>comment_block)[\s]*.*DEAD main::1::2::2::newAlloc6[\s]*(?P>comment_block)[\s]*.*DEAD main::1::2::2::newAlloc4[\s]*(?P>comment_block)[\s]*.*GOTO 3
66
^EXIT=0$
77
^SIGNAL=0$
88
--
@@ -22,8 +22,14 @@ Checks for:
2222
// 42 file main.c line 38 function main
2323
ASSIGN main::1::2::2::newAlloc7 := { 7 }
2424
// 43 file main.c line 39 function main
25+
DEAD main::1::2::2::newAlloc7
26+
// 44 file main.c line 39 function main
27+
DEAD main::1::2::2::newAlloc6
28+
// 45 file main.c line 39 function main
29+
DEAD main::1::2::2::newAlloc4
30+
// 46 file main.c line 39 function main
2531
GOTO 3
2632

2733
This asserts that when the GOTO is going into a lexical block that destructors
28-
are omitted. This used to be a limitation with the previous implementation and should
29-
now be fixable, but for consistency it acts in the same way.
34+
are not omitted. This used to be a limitation with the previous implementation
35+
and has now been fixed.

src/goto-programs/goto_convert.cpp

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -151,42 +151,40 @@ void goto_convertt::finish_gotos(goto_programt &dest, const irep_idt &mode)
151151
targets.destructor_stack.get_nearest_common_ancestor_info(
152152
goto_target, label_target);
153153

154-
bool not_prefix =
155-
intersection_result.right_depth_below_common_ancestor != 0;
156-
157154
// If our goto had no variables of note, just skip
158155
if(goto_target != 0)
159156
{
160157
// If the goto recorded a destructor stack, execute as much as is
161158
// appropriate for however many automatic variables leave scope.
162-
// We don't currently handle variables *entering* scope, which
163-
// is illegal for C++ non-pod types and impossible in Java in any case.
164-
if(not_prefix)
165-
{
166-
debug().source_location = i.source_location();
167-
debug() << "encountered goto '" << goto_label
168-
<< "' that enters one or more lexical blocks; "
169-
<< "omitting constructors and destructors" << eom;
170-
}
171-
else
172-
{
173-
debug().source_location = i.source_location();
174-
debug() << "adding goto-destructor code on jump to '" << goto_label
175-
<< "'" << eom;
176-
177-
node_indext end_destruct = intersection_result.common_ancestor;
178-
goto_programt destructor_code;
179-
unwind_destructor_stack(
180-
i.source_location(),
181-
destructor_code,
182-
mode,
183-
end_destruct,
184-
goto_target);
185-
dest.destructive_insert(g_it.first, destructor_code);
186-
187-
// This should leave iterators intact, as long as
188-
// goto_programt::instructionst is std::list.
189-
}
159+
debug().source_location = i.source_location();
160+
debug() << "adding goto-destructor code on jump to '" << goto_label
161+
<< "'" << eom;
162+
163+
node_indext end_destruct = intersection_result.common_ancestor;
164+
goto_programt destructor_code;
165+
unwind_destructor_stack(
166+
i.source_location(),
167+
destructor_code,
168+
mode,
169+
end_destruct,
170+
goto_target);
171+
dest.destructive_insert(g_it.first, destructor_code);
172+
173+
// This should leave iterators intact, as long as
174+
// goto_programt::instructionst is std::list.
175+
}
176+
177+
// We don't currently handle variables *entering* scope, which
178+
// is illegal for C++ non-pod types and impossible in Java in any case.
179+
// This is however valid C.
180+
const bool variables_added_to_scope =
181+
intersection_result.right_depth_below_common_ancestor > 0;
182+
if(variables_added_to_scope)
183+
{
184+
debug().source_location = i.source_location();
185+
debug() << "encountered goto '" << goto_label
186+
<< "' that enters one or more lexical blocks; "
187+
<< "omitting constructors." << eom;
190188
}
191189
}
192190
else

0 commit comments

Comments
 (0)