diff options
Diffstat (limited to 'clang/test')
| -rw-r--r-- | clang/test/CodeGen/ms_abi.c | 137 | ||||
| -rw-r--r-- | clang/test/PCH/Inputs/va_arg.h | 3 | ||||
| -rw-r--r-- | clang/test/PCH/va_arg.c | 6 | ||||
| -rw-r--r-- | clang/test/PCH/va_arg.cpp | 5 | ||||
| -rw-r--r-- | clang/test/PCH/va_arg.h | 7 | ||||
| -rw-r--r-- | clang/test/Sema/varargs-win64.c | 6 | ||||
| -rw-r--r-- | clang/test/Sema/varargs-x86-32.c | 5 | ||||
| -rw-r--r-- | clang/test/Sema/varargs-x86-64.c | 72 | ||||
| -rw-r--r-- | clang/test/SemaTemplate/instantiate-expr-3.cpp | 35 |
9 files changed, 267 insertions, 9 deletions
diff --git a/clang/test/CodeGen/ms_abi.c b/clang/test/CodeGen/ms_abi.c index 7c5c26fc41c..2cca24901b9 100644 --- a/clang/test/CodeGen/ms_abi.c +++ b/clang/test/CodeGen/ms_abi.c @@ -1,20 +1,145 @@ // RUN: %clang_cc1 -triple x86_64-unknown-freebsd10.0 -emit-llvm < %s | FileCheck -check-prefix=FREEBSD %s // RUN: %clang_cc1 -triple x86_64-pc-win32 -emit-llvm < %s | FileCheck -check-prefix=WIN64 %s +struct foo { + int x; + float y; + char z; +}; +// FREEBSD: %[[STRUCT_FOO:.*]] = type { i32, float, i8 } +// WIN64: %[[STRUCT_FOO:.*]] = type { i32, float, i8 } + void __attribute__((ms_abi)) f1(void); void __attribute__((sysv_abi)) f2(void); void f3(void) { -// FREEBSD: define void @f3() -// WIN64: define void @f3() + // FREEBSD-LABEL: define void @f3() + // WIN64-LABEL: define void @f3() f1(); -// FREEBSD: call x86_64_win64cc void @f1() -// WIN64: call void @f1() + // FREEBSD: call x86_64_win64cc void @f1() + // WIN64: call void @f1() f2(); -// FREEBSD: call void @f2() -// WIN64: call x86_64_sysvcc void @f2() + // FREEBSD: call void @f2() + // WIN64: call x86_64_sysvcc void @f2() } // FREEBSD: declare x86_64_win64cc void @f1() // FREEBSD: declare void @f2() // WIN64: declare void @f1() // WIN64: declare x86_64_sysvcc void @f2() +// Win64 ABI varargs +void __attribute__((ms_abi)) f4(int a, ...) { + // FREEBSD-LABEL: define x86_64_win64cc void @f4 + // WIN64-LABEL: define void @f4 + __builtin_ms_va_list ap; + __builtin_ms_va_start(ap, a); + // FREEBSD: %[[AP:.*]] = alloca i8* + // FREEBSD: call void @llvm.va_start + // WIN64: %[[AP:.*]] = alloca i8* + // WIN64: call void @llvm.va_start + int b = __builtin_va_arg(ap, int); + // FREEBSD: %[[AP_CUR:.*]] = load i8*, i8** %[[AP]] + // FREEBSD-NEXT: %[[AP_NEXT:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR]], i64 8 + // FREEBSD-NEXT: store i8* %[[AP_NEXT]], i8** %[[AP]] + // FREEBSD-NEXT: bitcast i8* %[[AP_CUR]] to i32* + // WIN64: %[[AP_CUR:.*]] = load i8*, i8** %[[AP]] + // WIN64-NEXT: %[[AP_NEXT:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR]], i64 8 + // WIN64-NEXT: store i8* %[[AP_NEXT]], i8** %[[AP]] + // WIN64-NEXT: bitcast i8* %[[AP_CUR]] to i32* + double _Complex c = __builtin_va_arg(ap, double _Complex); + // FREEBSD: %[[AP_CUR2:.*]] = load i8*, i8** %[[AP]] + // FREEBSD-NEXT: %[[AP_NEXT2:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR2]], i64 16 + // FREEBSD-NEXT: store i8* %[[AP_NEXT2]], i8** %[[AP]] + // FREEBSD-NEXT: bitcast i8* %[[AP_CUR2]] to { double, double }* + // WIN64: %[[AP_CUR2:.*]] = load i8*, i8** %[[AP]] + // WIN64-NEXT: %[[AP_NEXT2:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR2]], i64 16 + // WIN64-NEXT: store i8* %[[AP_NEXT2]], i8** %[[AP]] + // WIN64-NEXT: bitcast i8* %[[AP_CUR2]] to { double, double }* + struct foo d = __builtin_va_arg(ap, struct foo); + // FREEBSD: %[[AP_CUR3:.*]] = load i8*, i8** %[[AP]] + // FREEBSD-NEXT: %[[AP_NEXT3:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR3]], i64 16 + // FREEBSD-NEXT: store i8* %[[AP_NEXT3]], i8** %[[AP]] + // FREEBSD-NEXT: bitcast i8* %[[AP_CUR3]] to %[[STRUCT_FOO]]* + // WIN64: %[[AP_CUR3:.*]] = load i8*, i8** %[[AP]] + // WIN64-NEXT: %[[AP_NEXT3:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR3]], i64 16 + // WIN64-NEXT: store i8* %[[AP_NEXT3]], i8** %[[AP]] + // WIN64-NEXT: bitcast i8* %[[AP_CUR3]] to %[[STRUCT_FOO]]* + __builtin_ms_va_list ap2; + __builtin_ms_va_copy(ap2, ap); + // FREEBSD: %[[AP_VAL:.*]] = load i8*, i8** %[[AP]] + // FREEBSD-NEXT: store i8* %[[AP_VAL]], i8** %[[AP2:.*]] + // WIN64: %[[AP_VAL:.*]] = load i8*, i8** %[[AP]] + // WIN64-NEXT: store i8* %[[AP_VAL]], i8** %[[AP2:.*]] + __builtin_ms_va_end(ap); + // FREEBSD: call void @llvm.va_end + // WIN64: call void @llvm.va_end +} + +// Let's verify that normal va_lists work right on Win64, too. +void f5(int a, ...) { + // WIN64-LABEL: define void @f5 + __builtin_va_list ap; + __builtin_va_start(ap, a); + // WIN64: %[[AP:.*]] = alloca i8* + // WIN64: call void @llvm.va_start + int b = __builtin_va_arg(ap, int); + // WIN64: %[[AP_CUR:.*]] = load i8*, i8** %[[AP]] + // WIN64-NEXT: %[[AP_NEXT:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR]], i64 8 + // WIN64-NEXT: store i8* %[[AP_NEXT]], i8** %[[AP]] + // WIN64-NEXT: bitcast i8* %[[AP_CUR]] to i32* + double _Complex c = __builtin_va_arg(ap, double _Complex); + // WIN64: %[[AP_CUR2:.*]] = load i8*, i8** %[[AP]] + // WIN64-NEXT: %[[AP_NEXT2:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR2]], i64 16 + // WIN64-NEXT: store i8* %[[AP_NEXT2]], i8** %[[AP]] + // WIN64-NEXT: bitcast i8* %[[AP_CUR2]] to { double, double }* + struct foo d = __builtin_va_arg(ap, struct foo); + // WIN64: %[[AP_CUR3:.*]] = load i8*, i8** %[[AP]] + // WIN64-NEXT: %[[AP_NEXT3:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR3]], i64 16 + // WIN64-NEXT: store i8* %[[AP_NEXT3]], i8** %[[AP]] + // WIN64-NEXT: bitcast i8* %[[AP_CUR3]] to %[[STRUCT_FOO]]* + __builtin_va_list ap2; + __builtin_va_copy(ap2, ap); + // WIN64: call void @llvm.va_copy + __builtin_va_end(ap); + // WIN64: call void @llvm.va_end +} + +// Verify that using a Win64 va_list from a System V function works. +void __attribute__((sysv_abi)) f6(__builtin_ms_va_list ap) { + // FREEBSD-LABEL: define void @f6 + // FREEBSD: store i8* %ap, i8** %[[AP:.*]] + // WIN64-LABEL: define x86_64_sysvcc void @f6 + // WIN64: store i8* %ap, i8** %[[AP:.*]] + int b = __builtin_va_arg(ap, int); + // FREEBSD: %[[AP_CUR:.*]] = load i8*, i8** %[[AP]] + // FREEBSD-NEXT: %[[AP_NEXT:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR]], i64 8 + // FREEBSD-NEXT: store i8* %[[AP_NEXT]], i8** %[[AP]] + // FREEBSD-NEXT: bitcast i8* %[[AP_CUR]] to i32* + // WIN64: %[[AP_CUR:.*]] = load i8*, i8** %[[AP]] + // WIN64-NEXT: %[[AP_NEXT:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR]], i64 8 + // WIN64-NEXT: store i8* %[[AP_NEXT]], i8** %[[AP]] + // WIN64-NEXT: bitcast i8* %[[AP_CUR]] to i32* + double _Complex c = __builtin_va_arg(ap, double _Complex); + // FREEBSD: %[[AP_CUR2:.*]] = load i8*, i8** %[[AP]] + // FREEBSD-NEXT: %[[AP_NEXT2:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR2]], i64 16 + // FREEBSD-NEXT: store i8* %[[AP_NEXT2]], i8** %[[AP]] + // FREEBSD-NEXT: bitcast i8* %[[AP_CUR2]] to { double, double }* + // WIN64: %[[AP_CUR2:.*]] = load i8*, i8** %[[AP]] + // WIN64-NEXT: %[[AP_NEXT2:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR2]], i64 16 + // WIN64-NEXT: store i8* %[[AP_NEXT2]], i8** %[[AP]] + // WIN64-NEXT: bitcast i8* %[[AP_CUR2]] to { double, double }* + struct foo d = __builtin_va_arg(ap, struct foo); + // FREEBSD: %[[AP_CUR3:.*]] = load i8*, i8** %[[AP]] + // FREEBSD-NEXT: %[[AP_NEXT3:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR3]], i64 16 + // FREEBSD-NEXT: store i8* %[[AP_NEXT3]], i8** %[[AP]] + // FREEBSD-NEXT: bitcast i8* %[[AP_CUR3]] to %[[STRUCT_FOO]]* + // WIN64: %[[AP_CUR3:.*]] = load i8*, i8** %[[AP]] + // WIN64-NEXT: %[[AP_NEXT3:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR3]], i64 16 + // WIN64-NEXT: store i8* %[[AP_NEXT3]], i8** %[[AP]] + // WIN64-NEXT: bitcast i8* %[[AP_CUR3]] to %[[STRUCT_FOO]]* + __builtin_ms_va_list ap2; + __builtin_ms_va_copy(ap2, ap); + // FREEBSD: %[[AP_VAL:.*]] = load i8*, i8** %[[AP]] + // FREEBSD-NEXT: store i8* %[[AP_VAL]], i8** %[[AP2:.*]] + // WIN64: %[[AP_VAL:.*]] = load i8*, i8** %[[AP]] + // WIN64-NEXT: store i8* %[[AP_VAL]], i8** %[[AP2:.*]] +} diff --git a/clang/test/PCH/Inputs/va_arg.h b/clang/test/PCH/Inputs/va_arg.h index 1244e9faa36..132759ed027 100644 --- a/clang/test/PCH/Inputs/va_arg.h +++ b/clang/test/PCH/Inputs/va_arg.h @@ -1,2 +1,5 @@ #include <stdarg.h> +typedef __builtin_ms_va_list __ms_va_list; +#define __ms_va_start(ap, a) __builtin_ms_va_start(ap, a) +#define __ms_va_end(ap) __builtin_ms_va_end(ap) diff --git a/clang/test/PCH/va_arg.c b/clang/test/PCH/va_arg.c index dba9eea8de4..2bbf3c5ebd7 100644 --- a/clang/test/PCH/va_arg.c +++ b/clang/test/PCH/va_arg.c @@ -11,3 +11,9 @@ char *g0(char** argv, int argc) { return argv[argc]; } char *g(char **argv) { f(g0, argv, 1, 2, 3); } + +char *i0(char **argv, int argc) { return argv[argc]; } + +char *i(char **argv) { + h(i0, argv, 1, 2, 3); +} diff --git a/clang/test/PCH/va_arg.cpp b/clang/test/PCH/va_arg.cpp index 0b3c3b107c0..627ce23ad5d 100644 --- a/clang/test/PCH/va_arg.cpp +++ b/clang/test/PCH/va_arg.cpp @@ -10,8 +10,13 @@ typedef __SIZE_TYPE__ size_t; extern "C" { int vsnprintf(char * , size_t, const char * , va_list) ; +int __attribute__((ms_abi)) wvsprintfA(char *, const char *, __ms_va_list); } void f(char *buffer, unsigned count, const char* format, va_list argptr) { vsnprintf(buffer, count, format, argptr); } + +void g(char *buffer, const char *format, __ms_va_list argptr) { + wvsprintfA(buffer, format, argptr); +} diff --git a/clang/test/PCH/va_arg.h b/clang/test/PCH/va_arg.h index 4a8e5102bc6..255c6589a7e 100644 --- a/clang/test/PCH/va_arg.h +++ b/clang/test/PCH/va_arg.h @@ -6,3 +6,10 @@ char *f (char * (*g) (char **, int), char **p, ...) { va_list v; s = g (p, __builtin_va_arg(v, int)); } + +typedef __builtin_ms_va_list __ms_va_list; +char *__attribute__((ms_abi)) h(char *(*i)(char **, int), char **p, ...) { + char *s; + __ms_va_list v; + s = i(p, __builtin_va_arg(v, int)); +} diff --git a/clang/test/Sema/varargs-win64.c b/clang/test/Sema/varargs-win64.c new file mode 100644 index 00000000000..06d1c7f246b --- /dev/null +++ b/clang/test/Sema/varargs-win64.c @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -triple x86_64-pc-win32 + +void __attribute__((sysv_abi)) foo(int a, ...) { + __builtin_va_list ap; + __builtin_va_start(ap, a); // expected-error {{'va_start' used in System V ABI function}} +} diff --git a/clang/test/Sema/varargs-x86-32.c b/clang/test/Sema/varargs-x86-32.c new file mode 100644 index 00000000000..6f57022ffcb --- /dev/null +++ b/clang/test/Sema/varargs-x86-32.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -triple i386-apple-darwin9 + +void foo(int a, ...) { + __builtin_ms_va_start((void *)0, a); // expected-error {{this builtin is only available on x86-64 targets}} +} diff --git a/clang/test/Sema/varargs-x86-64.c b/clang/test/Sema/varargs-x86-64.c index 2fe9b10cf78..d50dd6a6fc1 100644 --- a/clang/test/Sema/varargs-x86-64.c +++ b/clang/test/Sema/varargs-x86-64.c @@ -6,3 +6,75 @@ void f1() { (void)__builtin_va_arg(args2, int); // expected-error {{first argument to 'va_arg' is of type 'const __builtin_va_list' and not 'va_list'}} } +void f2(int a, ...) { + __builtin_ms_va_list ap; + __builtin_ms_va_start(ap, a); // expected-error {{'__builtin_ms_va_start' used in System V ABI function}} +} + +void __attribute__((ms_abi)) g1(int a) { + __builtin_ms_va_list ap; + + __builtin_ms_va_start(ap, a, a); // expected-error {{too many arguments to function}} + __builtin_ms_va_start(ap, a); // expected-error {{'va_start' used in function with fixed args}} +} + +void __attribute__((ms_abi)) g2(int a, int b, ...) { + __builtin_ms_va_list ap; + + __builtin_ms_va_start(ap, 10); // expected-warning {{second parameter of 'va_start' not last named argument}} + __builtin_ms_va_start(ap, a); // expected-warning {{second parameter of 'va_start' not last named argument}} + __builtin_ms_va_start(ap, b); +} + +void __attribute__((ms_abi)) g3(float a, ...) { + __builtin_ms_va_list ap; + + __builtin_ms_va_start(ap, a); + __builtin_ms_va_start(ap, (a)); +} + +void __attribute__((ms_abi)) g5() { + __builtin_ms_va_list ap; + __builtin_ms_va_start(ap, ap); // expected-error {{'va_start' used in function with fixed args}} +} + +void __attribute__((ms_abi)) g6(int a, ...) { + __builtin_ms_va_list ap; + __builtin_ms_va_start(ap); // expected-error {{too few arguments to function}} +} + +void __attribute__((ms_abi)) +bar(__builtin_ms_va_list authors, ...) { + __builtin_ms_va_start(authors, authors); + (void)__builtin_va_arg(authors, int); + __builtin_ms_va_end(authors); +} + +void __attribute__((ms_abi)) g7(int a, ...) { + __builtin_ms_va_list ap; + __builtin_ms_va_start(ap, a); + // FIXME: This error message is sub-par. + __builtin_va_arg(ap, int) = 1; // expected-error {{expression is not assignable}} + int *x = &__builtin_va_arg(ap, int); // expected-error {{cannot take the address of an rvalue}} + __builtin_ms_va_end(ap); +} + +void __attribute__((ms_abi)) g8(int a, ...) { + __builtin_ms_va_list ap; + __builtin_ms_va_start(ap, a); + (void)__builtin_va_arg(ap, void); // expected-error {{second argument to 'va_arg' is of incomplete type 'void'}} + __builtin_ms_va_end(ap); +} + +enum E { x = -1, y = 2, z = 10000 }; +void __attribute__((ms_abi)) g9(__builtin_ms_va_list args) { + (void)__builtin_va_arg(args, float); // expected-warning {{second argument to 'va_arg' is of promotable type 'float'}} + (void)__builtin_va_arg(args, enum E); // no-warning + (void)__builtin_va_arg(args, short); // expected-warning {{second argument to 'va_arg' is of promotable type 'short'}} + (void)__builtin_va_arg(args, char); // expected-warning {{second argument to 'va_arg' is of promotable type 'char'}} +} + +void __attribute__((ms_abi)) g10(int a, ...) { + __builtin_va_list ap; + __builtin_va_start(ap, a); // expected-error {{'va_start' used in Win64 ABI function}} +} diff --git a/clang/test/SemaTemplate/instantiate-expr-3.cpp b/clang/test/SemaTemplate/instantiate-expr-3.cpp index ca88b00300d..90c322cbf37 100644 --- a/clang/test/SemaTemplate/instantiate-expr-3.cpp +++ b/clang/test/SemaTemplate/instantiate-expr-3.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify %s // --------------------------------------------------------------------- // Imaginary literals @@ -108,12 +108,41 @@ template<typename VaList, typename ArgType> struct VaArg1 { void f(int n, ...) { VaList va; - __builtin_va_start(va, n); // expected-error{{int}} + __builtin_va_start(va, n); // expected-error{{int}} expected-error{{char *}} for (int i = 0; i != n; ++i) (void)__builtin_va_arg(va, ArgType); // expected-error{{int}} - __builtin_va_end(va); // expected-error{{int}} + __builtin_va_end(va); // expected-error{{int}} expected-error{{char *}} } }; template struct VaArg1<__builtin_va_list, int>; +template struct VaArg1<__builtin_ms_va_list, int>; // expected-note{{instantiation}} template struct VaArg1<int, int>; // expected-note{{instantiation}} + +template<typename ArgType> +struct VaArg2 { + void __attribute__((ms_abi)) f(int n, ...) { + __builtin_ms_va_list va; + __builtin_ms_va_start(va, n); + for (int i = 0; i != n; ++i) + (void)__builtin_va_arg(va, ArgType); + __builtin_ms_va_end(va); + } +}; + +template struct VaArg2<int>; + +template<typename VaList, typename ArgType> +struct VaArg3 { + void __attribute__((ms_abi)) f(int n, ...) { + VaList va; + __builtin_ms_va_start(va, n); // expected-error{{int}} expected-error{{__va_list_tag}} + for (int i = 0; i != n; ++i) + (void)__builtin_va_arg(va, ArgType); // expected-error{{int}} + __builtin_ms_va_end(va); // expected-error{{int}} expected-error{{__va_list_tag}} + } +}; + +template struct VaArg3<__builtin_ms_va_list, int>; +template struct VaArg3<__builtin_va_list, int>; // expected-note{{instantiation}} +template struct VaArg3<int, int>; // expected-note{{instantiation}} |

