1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
|
/*******************************************************************\
Module: Label function pointer call sites unit tests
Author: Daniel Poetzl
\*******************************************************************/
#include <testing-utils/get_goto_model_from_c.h>
#include <testing-utils/use_catch.h>
#include <goto-programs/label_function_pointer_call_sites.h>
#include <util/pointer_expr.h>
TEST_CASE("Label function pointer call sites", "[core]")
{
const std::string code = R"(
void f() {}
void g() {}
void h()
{
f();
void (*fp)() = f;
fp();
(1 ? f : g)();
}
void main() { h(); }
)";
goto_modelt goto_model = get_goto_model_from_c(code);
label_function_pointer_call_sites(goto_model);
auto &h = goto_model.goto_functions.function_map.at("h");
for_each_instruction_if(
h,
[](goto_programt::const_targett it) { return it->is_function_call(); },
[](goto_programt::const_targett it) {
static int call_count = 0;
switch(call_count)
{
case 0:
// first call instruction
REQUIRE(it->call_function().id() == ID_symbol);
break;
case 1:
{
// second call instruction
const auto &fp_symbol =
to_symbol_expr(to_dereference_expr(it->call_function()).pointer())
.get_identifier();
REQUIRE(fp_symbol == "h.function_pointer_call.1");
break;
}
case 2:
{
// third call instruction
const auto &fp_symbol =
to_symbol_expr(to_dereference_expr(it->call_function()).pointer())
.get_identifier();
REQUIRE(fp_symbol == "h.function_pointer_call.2");
auto it_prev = std::prev(it);
const auto &lhs = it_prev->assign_lhs();
const auto &rhs = it_prev->assign_rhs();
REQUIRE(
to_symbol_expr(lhs).get_identifier() == "h.function_pointer_call.2");
REQUIRE(rhs.id() == ID_if);
break;
}
default:
break;
}
call_count++;
});
}
|