From 6597f985156b3a24c0a9db1e01eeec85714c4a8d Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Tue, 20 Jan 2009 07:46:22 +0000 Subject: [PATCH] Fix for PR3350: add special-casing for "references" to va_lists in builtins. Also, a minor tweak to va_copy for consistency. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62574 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Builtins.def | 9 +++++---- include/clang/AST/Builtins.h | 2 +- lib/AST/Builtins.cpp | 17 +++++++++++++++++ lib/CodeGen/CGBuiltin.cpp | 6 +----- test/Sema/varargs.c | 9 +++++++++ 5 files changed, 33 insertions(+), 10 deletions(-) diff --git a/include/clang/AST/Builtins.def b/include/clang/AST/Builtins.def index ba20bbc463..07c751db3e 100644 --- a/include/clang/AST/Builtins.def +++ b/include/clang/AST/Builtins.def @@ -33,6 +33,7 @@ // z -> size_t // F -> constant CFString // a -> __builtin_va_list +// A -> "reference" to __builtin_va_list // V -> Vector, following num elements and a base type. // . -> "...". This may only occur at the end of the function list. // @@ -115,10 +116,10 @@ BUILTIN(__builtin_bswap64, "ULLiULLi", "nc") BUILTIN(__builtin_constant_p, "Us.", "nc") BUILTIN(__builtin_classify_type, "i.", "nc") BUILTIN(__builtin___CFStringMakeConstantString, "FC*cC*", "nc") -BUILTIN(__builtin_va_start, "va&.", "n") -BUILTIN(__builtin_va_end, "va&", "n") -BUILTIN(__builtin_va_copy, "va&a", "n") -BUILTIN(__builtin_stdarg_start, "va&.", "n") +BUILTIN(__builtin_va_start, "vA.", "n") +BUILTIN(__builtin_va_end, "vA", "n") +BUILTIN(__builtin_va_copy, "vAA", "n") +BUILTIN(__builtin_stdarg_start, "vA.", "n") BUILTIN(__builtin_bzero, "vv*z", "n") BUILTIN(__builtin_memcpy, "v*v*vC*z", "n") BUILTIN(__builtin_memmove, "v*v*vC*z", "n") diff --git a/include/clang/AST/Builtins.h b/include/clang/AST/Builtins.h index 7da9a5f26a..c1771924ba 100644 --- a/include/clang/AST/Builtins.h +++ b/include/clang/AST/Builtins.h @@ -81,7 +81,7 @@ public: /// hasVAListUse - Return true of the specified builtin uses __builtin_va_list /// as an operand or return type. bool hasVAListUse(unsigned ID) const { - return strchr(GetRecord(ID).Type, 'a') != 0; + return strpbrk(GetRecord(ID).Type, "Aa") != 0; } /// GetBuiltinType - Return the type for the specified builtin. diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp index a721c6ea8c..b675c72973 100644 --- a/lib/AST/Builtins.cpp +++ b/lib/AST/Builtins.cpp @@ -142,6 +142,23 @@ static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context, Type = Context.getBuiltinVaListType(); assert(!Type.isNull() && "builtin va list type not initialized!"); break; + case 'A': + // This is a "reference" to a va_list; however, what exactly + // this means depends on how va_list is defined. There are two + // different kinds of va_list: ones passed by value, and ones + // passed by reference. An example of a by-value va_list is + // x86, where va_list is a char*. An example of by-ref va_list + // is x86-64, where va_list is a __va_list_tag[1]. For x86, + // we want this argument to be a char*&; for x86-64, we want + // it to be a __va_list_tag*. + Type = Context.getBuiltinVaListType(); + assert(!Type.isNull() && "builtin va list type not initialized!"); + if (Type->isArrayType()) { + Type = Context.getArrayDecayedType(Type); + } else { + Type = Context.getReferenceType(Type); + } + break; case 'V': { char *End; diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 6e140da732..2d840ffd8d 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -67,11 +67,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { case Builtin::BI__builtin_va_copy: { // FIXME: This does not yet handle architectures where va_list is a struct. Value *DstPtr = EmitLValue(E->getArg(0)).getAddress(); - Value *SrcValue = EmitScalarExpr(E->getArg(1)); - - Value *SrcPtr = CreateTempAlloca(SrcValue->getType(), "dst_ptr"); - - Builder.CreateStore(SrcValue, SrcPtr, false); + Value *SrcPtr = EmitLValue(E->getArg(1)).getAddress(); const llvm::Type *Type = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); diff --git a/test/Sema/varargs.c b/test/Sema/varargs.c index 5e0f28b7c2..ae21c208eb 100644 --- a/test/Sema/varargs.c +++ b/test/Sema/varargs.c @@ -43,3 +43,12 @@ void f6(int a, ...) { __builtin_va_list ap; __builtin_va_start(ap); // expected-error {{too few arguments to function}} } + +// PR3350 +void +foo(__builtin_va_list authors, ...) { + __builtin_va_start (authors, authors); + (void)__builtin_va_arg(authors, int); + __builtin_va_end (authors); +} + -- 2.40.0