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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
/* This test checks that KLEE correctly handles variadic arguments with the
byval attribute */
// RUN: %clang %s -emit-llvm %O0opt -c -g -o %t1.bc
// RUN: rm -rf %t.klee-out
// RUN: %klee --exit-on-error --output-dir=%t.klee-out %t1.bc
// RUN: FileCheck %s --input-file=%t.klee-out/assembly.ll
// CHECK: @test1({{.*}}, i32 -1, %struct.foo* byval{{.*}} %struct.bar* byval
// CHECK: @test2({{.*}}, %struct.foo* byval{{.*}} %struct.bar* byval
#include <stdarg.h>
#include <assert.h>
#include <stdio.h>
struct foo {
char f1;
long long f2;
long long f3;
char f4;
long f5;
int f6;
char f7;
};
struct bar {
long long int f1;
char f2;
long long f3;
char f4;
long f5;
};
struct foo test1(int x, ...) {
va_list ap;
va_start(ap, x);
assert(x == -1);
struct foo f = va_arg(ap, struct foo);
assert(f.f1 == 1);
assert(f.f2 == 2);
assert(f.f3 == 3);
assert(f.f4 == 4);
assert(f.f5 == 5);
assert(f.f6 == 6);
assert(f.f7 == 7);
struct bar b = va_arg(ap, struct bar);
assert(b.f1 == 11);
assert(b.f2 == 12);
assert(b.f3 == 13);
assert(b.f4 == 14);
assert(b.f5 == 15);
va_end(ap);
f.f1++;
return f;
}
struct foo test2(int x, long long int l, ...) {
va_list ap;
va_start(ap, l);
assert(x == 10);
assert(l == 1000);
int i = va_arg(ap, int);
assert(i == 10);
struct foo f = va_arg(ap, struct foo);
assert(f.f1 == 1);
assert(f.f2 == 2);
assert(f.f3 == 3);
assert(f.f4 == 4);
assert(f.f5 == 5);
assert(f.f6 == 6);
assert(f.f7 == 7);
l = va_arg(ap, long long int);
assert(l == 1000);
struct bar b = va_arg(ap, struct bar);
assert(b.f1 == 11);
assert(b.f2 == 12);
assert(b.f3 == 13);
assert(b.f4 == 14);
assert(b.f5 == 15);
f = va_arg(ap, struct foo);
assert(f.f1 == 10);
assert(f.f2 == 20);
assert(f.f3 == 30);
assert(f.f4 == 40);
assert(f.f5 == 50);
assert(f.f6 == 60);
assert(f.f7 == 70);
b = va_arg(ap, struct bar);
assert(b.f1 == 1);
assert(b.f2 == 3);
assert(b.f3 == 5);
assert(b.f4 == 7);
assert(b.f5 == 9);
va_end(ap);
f.f1++;
return f;
}
int main() {
struct foo f = { 1, 2, 3, 4, 5, 6, 7 };
struct bar b = { 11, 12, 13, 14, 15 };
struct foo res = test1(-1, f, b);
assert(res.f1 == 2);
assert(res.f2 == 2);
assert(res.f3 == 3);
assert(res.f4 == 4);
assert(res.f5 == 5);
assert(res.f6 == 6);
assert(res.f7 == 7);
// check that f was not modified, as it's passed by value
assert(f.f1 == 1);
int i = 10;
long long int l = 1000;
struct foo f2 = { 10, 20, 30, 40, 50, 60, 70 };
struct bar b2 = { 1, 3, 5, 7, 9 };
test2(i, l, i, f, l, b, f2, b2);
}
|