@@ -6,9 +6,11 @@ Author: Daniel Poetzl
6
6
7
7
\*******************************************************************/
8
8
9
+ #include < testing-utils/get_goto_model_from_c.h>
9
10
#include < testing-utils/message.h>
10
11
#include < testing-utils/use_catch.h>
11
12
13
+ #include < goto-programs/label_function_pointer_call_sites.h>
12
14
#include < goto-programs/restrict_function_pointers.h>
13
15
14
16
#include < json/json_parser.h>
@@ -17,23 +19,22 @@ class fp_restrictionst : public function_pointer_restrictionst
17
19
{
18
20
friend void restriction_parsing_test ();
19
21
friend void merge_restrictions_test ();
22
+ friend void get_function_pointer_by_name_restrictions_test ();
20
23
};
21
24
22
25
void restriction_parsing_test ()
23
26
{
24
27
{
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" );
28
30
REQUIRE (res.first == " func1" );
29
31
REQUIRE (res.second .size () == 1 );
30
32
REQUIRE (res.second .find (" func2" ) != res.second .end ());
31
33
}
32
34
33
35
{
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" );
37
38
REQUIRE (res.first == " func1" );
38
39
REQUIRE (res.second .size () == 2 );
39
40
REQUIRE (res.second .find (" func2" ) != res.second .end ());
@@ -92,6 +93,137 @@ void merge_restrictions_test()
92
93
REQUIRE (fp2_restrictions.count (" func1" ) == 1 );
93
94
}
94
95
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
+
95
227
TEST_CASE (" Restriction parsing" , " [core]" )
96
228
{
97
229
restriction_parsing_test ();
@@ -152,3 +284,10 @@ TEST_CASE("Json conversion", "[core]")
152
284
function_pointer_restrictions1.restrictions ==
153
285
function_pointer_restrictions2.restrictions );
154
286
}
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