@@ -6,9 +6,11 @@ Author: Daniel Poetzl
66
77\*******************************************************************/
88
9+ #include < testing-utils/get_goto_model_from_c.h>
910#include < testing-utils/message.h>
1011#include < testing-utils/use_catch.h>
1112
13+ #include < goto-programs/label_function_pointer_call_sites.h>
1214#include < goto-programs/restrict_function_pointers.h>
1315
1416#include < json/json_parser.h>
@@ -17,23 +19,22 @@ class fp_restrictionst : public function_pointer_restrictionst
1719{
1820 friend void restriction_parsing_test ();
1921 friend void merge_restrictions_test ();
22+ friend void get_function_pointer_by_name_restrictions_test ();
2023};
2124
2225void restriction_parsing_test ()
2326{
2427 {
25- const auto res =
26- fp_restrictionst::parse_function_pointer_restriction (
27- " func1/func2" , " test" );
28+ const auto res = fp_restrictionst::parse_function_pointer_restriction (
29+ " func1/func2" , " test" );
2830 REQUIRE (res.first == " func1" );
2931 REQUIRE (res.second .size () == 1 );
3032 REQUIRE (res.second .find (" func2" ) != res.second .end ());
3133 }
3234
3335 {
34- const auto res =
35- fp_restrictionst::parse_function_pointer_restriction (
36- " func1/func2,func3" , " test" );
36+ const auto res = fp_restrictionst::parse_function_pointer_restriction (
37+ " func1/func2,func3" , " test" );
3738 REQUIRE (res.first == " func1" );
3839 REQUIRE (res.second .size () == 2 );
3940 REQUIRE (res.second .find (" func2" ) != res.second .end ());
@@ -92,6 +93,137 @@ void merge_restrictions_test()
9293 REQUIRE (fp2_restrictions.count (" func1" ) == 1 );
9394}
9495
96+ void get_function_pointer_by_name_restrictions_test ()
97+ {
98+ SECTION (" Translate parameter restriction to indexed restriction" )
99+ {
100+ const std::string code = R"(
101+ typedef void (*fp_t)(void);
102+ void f();
103+
104+ void func(fp_t fp)
105+ {
106+ f(); // ignored
107+
108+ fp();
109+ }
110+
111+ void main() {}
112+ )" ;
113+
114+ goto_modelt goto_model = get_goto_model_from_c (code);
115+ label_function_pointer_call_sites (goto_model);
116+
117+ const auto restrictions =
118+ fp_restrictionst::get_function_pointer_by_name_restrictions (
119+ {" func::fp/g" }, goto_model);
120+
121+ REQUIRE (restrictions.size () == 1 );
122+
123+ const auto set = restrictions.at (" func.function_pointer_call.1" );
124+ REQUIRE (set.size () == 1 );
125+ REQUIRE (set.count (" g" ) == 1 );
126+ }
127+
128+ SECTION (" Translate local nested variable restriction to indexed restriction" )
129+ {
130+ const std::string code = R"(
131+ typedef void (*fp_t)(void);
132+ void f();
133+
134+ void main()
135+ {
136+ f(); // ignored
137+
138+ {
139+ fp_t fp;
140+ fp();
141+ }
142+ }
143+ )" ;
144+
145+ goto_modelt goto_model = get_goto_model_from_c (code);
146+ label_function_pointer_call_sites (goto_model);
147+
148+ const auto restrictions =
149+ fp_restrictionst::get_function_pointer_by_name_restrictions (
150+ {" main::1::1::fp/g" }, goto_model);
151+
152+ REQUIRE (restrictions.size () == 1 );
153+
154+ const auto set = restrictions.at (" main.function_pointer_call.1" );
155+ REQUIRE (set.size () == 1 );
156+ REQUIRE (set.count (" g" ) == 1 );
157+ }
158+
159+ SECTION (" Translate global variable restriction to indexed restriction" )
160+ {
161+ const std::string code = R"(
162+ typedef void (*fp_t)(void);
163+ void f();
164+
165+ fp_t fp;
166+
167+ void main()
168+ {
169+ f(); // ignored
170+
171+ fp();
172+ }
173+ )" ;
174+
175+ goto_modelt goto_model = get_goto_model_from_c (code);
176+ label_function_pointer_call_sites (goto_model);
177+
178+ const auto restrictions =
179+ fp_restrictionst::get_function_pointer_by_name_restrictions (
180+ {" fp/g" }, goto_model);
181+
182+ REQUIRE (restrictions.size () == 1 );
183+
184+ const auto set = restrictions.at (" main.function_pointer_call.1" );
185+ REQUIRE (set.size () == 1 );
186+ REQUIRE (set.count (" g" ) == 1 );
187+ }
188+
189+ SECTION (
190+ " Translate a variable restriction to indexed restrictions, "
191+ " for the case when a function pointer is called more than once" )
192+ {
193+ const std::string code = R"(
194+ typedef void (*fp_t)(void);
195+ void f();
196+
197+ fp_t fp;
198+
199+ void main()
200+ {
201+ f(); // ignored
202+
203+ fp();
204+ fp(); // second call to same function pointer
205+ }
206+ )" ;
207+
208+ goto_modelt goto_model = get_goto_model_from_c (code);
209+ label_function_pointer_call_sites (goto_model);
210+
211+ const auto restrictions =
212+ fp_restrictionst::get_function_pointer_by_name_restrictions (
213+ {" fp/g" }, goto_model);
214+
215+ REQUIRE (restrictions.size () == 2 );
216+
217+ const auto set1 = restrictions.at (" main.function_pointer_call.1" );
218+ REQUIRE (set1.size () == 1 );
219+ REQUIRE (set1.count (" g" ) == 1 );
220+
221+ const auto set2 = restrictions.at (" main.function_pointer_call.2" );
222+ REQUIRE (set2.size () == 1 );
223+ REQUIRE (set2.count (" g" ) == 1 );
224+ }
225+ }
226+
95227TEST_CASE (" Restriction parsing" , " [core]" )
96228{
97229 restriction_parsing_test ();
@@ -152,3 +284,10 @@ TEST_CASE("Json conversion", "[core]")
152284 function_pointer_restrictions1.restrictions ==
153285 function_pointer_restrictions2.restrictions );
154286}
287+
288+ TEST_CASE (
289+ " Get function pointer by name restrictions" ,
290+ " [core][goto-programs][restrict-function-pointers]" )
291+ {
292+ get_function_pointer_by_name_restrictions_test ();
293+ }
0 commit comments