/* 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 // // TODO: Make noundef unconditional when LLVM 14 is the oldest supported version. // CHECK: @test1({{.*}}, i32 {{(noundef )?}}-1, %struct.foo* {{(noundef )?}}byval{{.*}} %struct.bar* {{(noundef )?}}byval // CHECK: @test2({{.*}}, %struct.foo* {{(noundef )?}}byval{{.*}} %struct.bar* {{(noundef )?}}byval #include #include #include 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); }