about summary refs log tree commit diff homepage
path: root/test/Feature/VarArgByVal.c
blob: 42718bb95d6d438179f44d986f1ad3fd07919465 (plain) (blame)
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);
}