Skip to content

Commit f8c51eb

Browse files
Peter Schrammelpeterschrammel
Peter Schrammel
authored andcommitted
detect recursion on inlining
1 parent 403aa32 commit f8c51eb

File tree

2 files changed

+85
-63
lines changed

2 files changed

+85
-63
lines changed

src/goto-programs/goto_inline.cpp

Lines changed: 72 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ void goto_inlinet::parameter_assignments(
4343

4444
const code_typet::parameterst &parameter_types=
4545
code_type.parameters();
46-
46+
4747
// iterates over the types of the parameters
4848
for(code_typet::parameterst::const_iterator
4949
it2=parameter_types.begin();
@@ -72,7 +72,7 @@ void goto_inlinet::parameter_assignments(
7272
decl->code=code_declt(symbol.symbol_expr());
7373
decl->code.add_source_location()=source_location;
7474
decl->source_location=source_location;
75-
decl->function=function_name;
75+
decl->function=function_name;
7676
}
7777

7878
// this is the actual parameter
@@ -93,7 +93,7 @@ void goto_inlinet::parameter_assignments(
9393

9494
// nil means "don't assign"
9595
if(actual.is_nil())
96-
{
96+
{
9797
}
9898
else
9999
{
@@ -103,7 +103,7 @@ void goto_inlinet::parameter_assignments(
103103
{
104104
const typet &f_partype = ns.follow(par_type);
105105
const typet &f_acttype = ns.follow(actual.type());
106-
106+
107107
// we are willing to do some conversion
108108
if((f_partype.id()==ID_pointer &&
109109
f_acttype.id()==ID_pointer) ||
@@ -118,7 +118,7 @@ void goto_inlinet::parameter_assignments(
118118
f_partype.id()==ID_bool) &&
119119
(f_acttype.id()==ID_signedbv ||
120120
f_acttype.id()==ID_unsignedbv ||
121-
f_acttype.id()==ID_bool))
121+
f_acttype.id()==ID_bool))
122122
{
123123
actual.make_typecast(par_type);
124124
}
@@ -144,7 +144,7 @@ void goto_inlinet::parameter_assignments(
144144
dest.add_instruction(ASSIGN);
145145
dest.instructions.back().source_location=source_location;
146146
dest.instructions.back().code.swap(assignment);
147-
dest.instructions.back().function=function_name;
147+
dest.instructions.back().function=function_name;
148148
}
149149

150150
if(it1!=arguments.end())
@@ -177,7 +177,7 @@ void goto_inlinet::parameter_destruction(
177177
{
178178
const code_typet::parameterst &parameter_types=
179179
code_type.parameters();
180-
180+
181181
// iterates over the types of the parameters
182182
for(code_typet::parameterst::const_iterator
183183
it=parameter_types.begin();
@@ -203,7 +203,7 @@ void goto_inlinet::parameter_destruction(
203203
dead->code=code_deadt(symbol.symbol_expr());
204204
dead->code.add_source_location()=source_location;
205205
dead->source_location=source_location;
206-
dead->function=function_name;
206+
dead->function=function_name;
207207
}
208208
}
209209
}
@@ -242,10 +242,10 @@ void goto_inlinet::replace_return(
242242
warning_msg();
243243
continue;
244244
}
245-
245+
246246
goto_programt tmp;
247247
goto_programt::targett assignment=tmp.add_instruction(ASSIGN);
248-
248+
249249
code_assignt code_assign(lhs, it->code.op0());
250250

251251
// this may happen if the declared return type at the call site
@@ -257,28 +257,28 @@ void goto_inlinet::replace_return(
257257
assignment->code=code_assign;
258258
assignment->source_location=it->source_location;
259259
assignment->function=it->function;
260-
260+
261261
if(constrain.is_not_nil() && !constrain.is_true())
262262
{
263263
codet constrain(ID_bp_constrain);
264264
constrain.reserve_operands(2);
265265
constrain.move_to_operands(assignment->code);
266266
constrain.copy_to_operands(constrain);
267267
}
268-
268+
269269
dest.insert_before_swap(it, *assignment);
270270
it++;
271271
}
272272
else if(!it->code.operands().empty())
273273
{
274274
goto_programt tmp;
275275
goto_programt::targett expression=tmp.add_instruction(OTHER);
276-
276+
277277
expression->code=codet(ID_expression);
278278
expression->code.move_to_operands(it->code.op0());
279279
expression->source_location=it->source_location;
280280
expression->function=it->function;
281-
281+
282282
dest.insert_before_swap(it, *expression);
283283
it++;
284284
}
@@ -294,7 +294,7 @@ void goto_inlinet::replace_return(
294294
<< it->code.pretty() << eom;
295295
continue;
296296
}
297-
297+
298298
code_assignt code_assign(lhs, it->code.op0());
299299

300300
// this may happen if the declared return type at the call site
@@ -357,7 +357,7 @@ void replace_location(
357357
irep_idt property_id=dest.get_property_id();
358358

359359
dest=new_location;
360-
360+
361361
if(comment!=irep_idt()) dest.set_comment(comment);
362362
if(property_class!=irep_idt()) dest.set_property_class(property_class);
363363
if(property_id!=irep_idt()) dest.set_property_id(property_id);
@@ -409,7 +409,7 @@ void goto_inlinet::expand_function_call(
409409
{
410410
// look it up
411411
const irep_idt identifier=function.get_identifier();
412-
412+
413413
// we ignore certain calls
414414
if(identifier=="__CPROVER_cleanup" ||
415415
identifier=="__CPROVER_set_must" ||
@@ -421,7 +421,7 @@ void goto_inlinet::expand_function_call(
421421
target++;
422422
return; // ignore
423423
}
424-
424+
425425
// see if we are already expanding it
426426
if(recursion_set.find(identifier)!=recursion_set.end())
427427
{
@@ -435,8 +435,9 @@ void goto_inlinet::expand_function_call(
435435
// Uh. Buh. Give up.
436436
warning().source_location=function.find_source_location();
437437
warning() << "recursion is ignored" << eom;
438+
is_recursion_detected=true;
438439
target->make_skip();
439-
440+
440441
target++;
441442
return;
442443
}
@@ -456,10 +457,10 @@ void goto_inlinet::expand_function_call(
456457
error() << "failed to find function `" << identifier << "'" << eom;
457458
throw 0;
458459
}
459-
460+
460461
const goto_functionst::goto_functiont &f=m_it->second;
461462

462-
// see if we need to inline this
463+
// see if we need to inline this
463464
if(!full)
464465
{
465466
if(!f.body_available() ||
@@ -479,10 +480,10 @@ void goto_inlinet::expand_function_call(
479480

480481
goto_programt tmp2;
481482
tmp2.copy_from(f.body);
482-
483+
483484
assert(tmp2.instructions.back().is_end_function());
484485
tmp2.instructions.back().type=LOCATION;
485-
486+
486487
replace_return(tmp2, lhs, constrain);
487488

488489
goto_programt tmp;
@@ -494,11 +495,11 @@ void goto_inlinet::expand_function_call(
494495
{
495496
source_locationt new_source_location=
496497
function.find_source_location();
497-
498+
498499
if(new_source_location.is_not_nil())
499500
{
500501
new_source_location.set_hide();
501-
502+
502503
Forall_goto_program_instructions(it, tmp)
503504
{
504505
if(it->function==identifier)
@@ -520,10 +521,10 @@ void goto_inlinet::expand_function_call(
520521
}
521522
}
522523

523-
// set up location instruction for function call
524+
// set up location instruction for function call
524525
target->type=LOCATION;
525526
target->code.clear();
526-
527+
527528
goto_programt::targett next_target(target);
528529
next_target++;
529530

@@ -551,7 +552,7 @@ void goto_inlinet::expand_function_call(
551552
t->source_location=target->source_location;
552553
t->function=target->function;
553554
}
554-
555+
555556
// return value
556557
if(lhs.is_not_nil())
557558
{
@@ -560,7 +561,7 @@ void goto_inlinet::expand_function_call(
560561

561562
code_assignt code(lhs, rhs);
562563
code.add_source_location()=target->source_location;
563-
564+
564565
goto_programt::targett t=tmp.add_instruction(ASSIGN);
565566
t->source_location=target->source_location;
566567
t->function=target->function;
@@ -592,7 +593,7 @@ Function: goto_inlinet::goto_inline
592593
void goto_inlinet::goto_inline(goto_programt &dest)
593594
{
594595
goto_inline_rec(dest, true);
595-
replace_return(dest,
596+
replace_return(dest,
596597
static_cast<const exprt &>(get_nil_irep()),
597598
static_cast<const exprt &>(get_nil_irep()));
598599
}
@@ -614,18 +615,18 @@ void goto_inlinet::goto_inline_rec(
614615
bool full)
615616
{
616617
// already done?
617-
618+
618619
if(finished_inlining_set.find(f_it->first)!=
619620
finished_inlining_set.end())
620621
return; // yes
621-
622+
622623
// do it
623-
624+
624625
goto_inline_rec(f_it->second.body, full);
625-
626+
626627
// remember we did it
627-
628-
finished_inlining_set.insert(f_it->first);
628+
629+
finished_inlining_set.insert(f_it->first);
629630
}
630631

631632
/*******************************************************************\
@@ -655,7 +656,7 @@ void goto_inlinet::goto_inline_rec(goto_programt &dest, bool full)
655656

656657
if(changed)
657658
{
658-
remove_skip(dest);
659+
remove_skip(dest);
659660
dest.update();
660661
}
661662
}
@@ -711,15 +712,15 @@ bool goto_inlinet::inline_instruction(
711712
}
712713
}
713714

714-
// advance iterator
715+
// advance iterator
715716
it++;
716717

717-
return false;
718+
return false;
718719
}
719720

720721
/*******************************************************************\
721722
722-
Function: goto_inline
723+
Function: goto_inlinet::operator()
723724
724725
Inputs:
725726
@@ -729,43 +730,38 @@ Function: goto_inline
729730
730731
\*******************************************************************/
731732

732-
void goto_inline(
733-
goto_functionst &goto_functions,
734-
const namespacet &ns,
735-
message_handlert &message_handler)
733+
void goto_inlinet::operator()()
736734
{
737-
goto_inlinet goto_inline(goto_functions, ns, message_handler);
738-
739735
try
740736
{
741737
// find entry point
742738
goto_functionst::function_mapt::iterator it=
743739
goto_functions.function_map.find(goto_functionst::entry_point());
744-
740+
745741
if(it==goto_functions.function_map.end())
746742
return;
747-
748-
goto_inline.goto_inline(it->second.body);
743+
744+
goto_inline(it->second.body);
749745
}
750746

751747
catch(int)
752748
{
753-
goto_inline.error();
749+
error();
754750
throw 0;
755751
}
756752

757753
catch(const char *e)
758754
{
759-
goto_inline.error() << e << messaget::eom;
755+
error() << e << messaget::eom;
760756
throw 0;
761757
}
762758

763759
catch(const std::string &e)
764760
{
765-
goto_inline.error() << e << messaget::eom;
761+
error() << e << messaget::eom;
766762
throw 0;
767763
}
768-
764+
769765
// clean up
770766
for(goto_functionst::function_mapt::iterator
771767
it=goto_functions.function_map.begin();
@@ -787,6 +783,27 @@ Function: goto_inline
787783
788784
\*******************************************************************/
789785

786+
void goto_inline(
787+
goto_functionst &goto_functions,
788+
const namespacet &ns,
789+
message_handlert &message_handler)
790+
{
791+
goto_inlinet goto_inline(goto_functions, ns, message_handler);
792+
goto_inline();
793+
}
794+
795+
/*******************************************************************\
796+
797+
Function: goto_inline
798+
799+
Inputs:
800+
801+
Outputs:
802+
803+
Purpose:
804+
805+
\*******************************************************************/
806+
790807
void goto_inline(
791808
goto_modelt &goto_model,
792809
message_handlert &message_handler)
@@ -817,9 +834,9 @@ void goto_partial_inline(
817834
goto_functions,
818835
ns,
819836
message_handler);
820-
837+
821838
goto_inline.smallfunc_limit=_smallfunc_limit;
822-
839+
823840
try
824841
{
825842
for(goto_functionst::function_mapt::iterator

0 commit comments

Comments
 (0)