From: Reid Kleckner Date: Wed, 26 Mar 2014 15:38:33 +0000 (+0000) Subject: -fms-extensions: Add __va_start builtin, which is used for x64 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e1972b5edc56db7fe344a7a5da33025db4646563;p=clang -fms-extensions: Add __va_start builtin, which is used for x64 The main difference between __va_start and __builtin_va_start is that the address of the va_list has already been taken, and the va_list is always a char*. __va_end and __va_arg are not needed. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@204821 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 53bec2ab83..540ec25bad 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -681,6 +681,7 @@ LANGBUILTIN(_alloca, "v*z", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__assume, "vb", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__noop, "v.", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__debugbreak, "v", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(__va_start, "vc**.", "nt", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedCompareExchange, "LiLiD*LiLi", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedIncrement, "LiLiD*", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedDecrement, "LiLiD*", "n", ALL_MS_LANGUAGES) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index c105d80bf7..b0e63b647d 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -215,8 +215,11 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, return RValue::get(CGM.EmitConstantExpr(E, E->getType(), 0)); case Builtin::BI__builtin_stdarg_start: case Builtin::BI__builtin_va_start: + case Builtin::BI__va_start: case Builtin::BI__builtin_va_end: { - Value *ArgValue = EmitVAListRef(E->getArg(0)); + Value *ArgValue = (BuiltinID == Builtin::BI__va_start) + ? EmitScalarExpr(E->getArg(0)) + : EmitVAListRef(E->getArg(0)); llvm::Type *DestType = Int8PtrTy; if (ArgValue->getType() != DestType) ArgValue = Builder.CreateBitCast(ArgValue, DestType, diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 0285231305..f0e93a78f7 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -142,6 +142,7 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { break; case Builtin::BI__builtin_stdarg_start: case Builtin::BI__builtin_va_start: + case Builtin::BI__va_start: if (SemaBuiltinVAStart(TheCall)) return ExprError(); break; diff --git a/test/Sema/MicrosoftExtensions.c b/test/Sema/MicrosoftExtensions.c index 4441f17973..a4afcb1e64 100644 --- a/test/Sema/MicrosoftExtensions.c +++ b/test/Sema/MicrosoftExtensions.c @@ -131,3 +131,17 @@ int *(__ptr32 __sptr wrong9); // expected-error {{'__sptr' attribute only applie typedef int *T; T __ptr32 wrong10; // expected-error {{'__ptr32' attribute only applies to pointer arguments}} + +typedef char *my_va_list; +void __cdecl __va_start(my_va_list *ap, ...); // expected-note {{passing argument to parameter 'ap' here}} +void vmyprintf(const char *f, my_va_list ap); +void myprintf(const char *f, ...) { + my_va_list ap; + if (1) { + __va_start(&ap, f); + vmyprintf(f, ap); + ap = 0; + } else { + __va_start(ap, f); // expected-warning {{incompatible pointer types passing 'my_va_list'}} + } +}