summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTContext.cpp27
-rw-r--r--clang/lib/AST/ASTDiagnostic.cpp3
-rw-r--r--clang/lib/Basic/TargetInfo.cpp1
-rw-r--r--clang/lib/Basic/Targets.cpp3
-rw-r--r--clang/lib/CodeGen/ABIInfo.h6
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp54
-rw-r--r--clang/lib/CodeGen/CGCall.cpp8
-rw-r--r--clang/lib/CodeGen/CGExprAgg.cpp4
-rw-r--r--clang/lib/CodeGen/CGExprComplex.cpp4
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp5
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp4
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h23
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp15
-rw-r--r--clang/lib/Sema/Sema.cpp6
-rw-r--r--clang/lib/Sema/SemaChecking.cpp51
-rw-r--r--clang/lib/Sema/SemaExpr.cpp74
-rw-r--r--clang/lib/Serialization/ASTReader.cpp3
-rw-r--r--clang/lib/Serialization/ASTReaderStmt.cpp1
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp2
-rw-r--r--clang/lib/Serialization/ASTWriterStmt.cpp1
20 files changed, 233 insertions, 62 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index e5511cbd616..3e0d6d1144b 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -733,8 +733,9 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
SubstTemplateTemplateParmPacks(this_()),
GlobalNestedNameSpecifier(nullptr), Int128Decl(nullptr),
UInt128Decl(nullptr), Float128StubDecl(nullptr),
- BuiltinVaListDecl(nullptr), ObjCIdDecl(nullptr), ObjCSelDecl(nullptr),
- ObjCClassDecl(nullptr), ObjCProtocolClassDecl(nullptr), BOOLDecl(nullptr),
+ BuiltinVaListDecl(nullptr), BuiltinMSVaListDecl(nullptr),
+ ObjCIdDecl(nullptr), ObjCSelDecl(nullptr), ObjCClassDecl(nullptr),
+ ObjCProtocolClassDecl(nullptr), BOOLDecl(nullptr),
CFConstantStringTypeDecl(nullptr), ObjCInstanceTypeDecl(nullptr),
FILEDecl(nullptr), jmp_bufDecl(nullptr), sigjmp_bufDecl(nullptr),
ucontext_tDecl(nullptr), BlockDescriptorType(nullptr),
@@ -6039,10 +6040,19 @@ ObjCInterfaceDecl *ASTContext::getObjCProtocolDecl() const {
// __builtin_va_list Construction Functions
//===----------------------------------------------------------------------===//
-static TypedefDecl *CreateCharPtrBuiltinVaListDecl(const ASTContext *Context) {
- // typedef char* __builtin_va_list;
+static TypedefDecl *CreateCharPtrNamedVaListDecl(const ASTContext *Context,
+ StringRef Name) {
+ // typedef char* __builtin[_ms]_va_list;
QualType T = Context->getPointerType(Context->CharTy);
- return Context->buildImplicitTypedef(T, "__builtin_va_list");
+ return Context->buildImplicitTypedef(T, Name);
+}
+
+static TypedefDecl *CreateMSVaListDecl(const ASTContext *Context) {
+ return CreateCharPtrNamedVaListDecl(Context, "__builtin_ms_va_list");
+}
+
+static TypedefDecl *CreateCharPtrBuiltinVaListDecl(const ASTContext *Context) {
+ return CreateCharPtrNamedVaListDecl(Context, "__builtin_va_list");
}
static TypedefDecl *CreateVoidPtrBuiltinVaListDecl(const ASTContext *Context) {
@@ -6378,6 +6388,13 @@ Decl *ASTContext::getVaListTagDecl() const {
return VaListTagDecl;
}
+TypedefDecl *ASTContext::getBuiltinMSVaListDecl() const {
+ if (!BuiltinMSVaListDecl)
+ BuiltinMSVaListDecl = CreateMSVaListDecl(this);
+
+ return BuiltinMSVaListDecl;
+}
+
void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) {
assert(ObjCConstantStringType.isNull() &&
"'NSConstantString' type already set!");
diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp
index 0544ccbef7a..0ab1fa78860 100644
--- a/clang/lib/AST/ASTDiagnostic.cpp
+++ b/clang/lib/AST/ASTDiagnostic.cpp
@@ -132,7 +132,8 @@ static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) {
break;
// Don't desugar va_list.
- if (QualType(Ty,0) == Context.getBuiltinVaListType())
+ if (QualType(Ty, 0) == Context.getBuiltinVaListType() ||
+ QualType(Ty, 0) == Context.getBuiltinMSVaListType())
break;
// Otherwise, do a single-step desugar.
diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp
index aa7385eb005..7b52eb0f081 100644
--- a/clang/lib/Basic/TargetInfo.cpp
+++ b/clang/lib/Basic/TargetInfo.cpp
@@ -77,6 +77,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
RegParmMax = 0;
SSERegParmMax = 0;
HasAlignMac68kSupport = false;
+ HasBuiltinMSVaList = false;
// Default to no types using fpret.
RealTypeUsesObjCFPRet = 0;
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index 35d7030a250..b969f2a0797 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -3894,6 +3894,9 @@ public:
// Use fp2ret for _Complex long double.
ComplexLongDoubleUsesFP2Ret = true;
+ // Make __builtin_ms_va_list available.
+ HasBuiltinMSVaList = true;
+
// x86-64 has atomics up to 16 bytes.
MaxAtomicPromoteWidth = 128;
MaxAtomicInlineWidth = 128;
diff --git a/clang/lib/CodeGen/ABIInfo.h b/clang/lib/CodeGen/ABIInfo.h
index ece36e8879c..a65f2708561 100644
--- a/clang/lib/CodeGen/ABIInfo.h
+++ b/clang/lib/CodeGen/ABIInfo.h
@@ -85,6 +85,12 @@ namespace clang {
CodeGen::Address VAListAddr,
QualType Ty) const = 0;
+ /// Emit the target dependent code to load a value of
+ /// \arg Ty from the \c __builtin_ms_va_list pointed to by \arg VAListAddr.
+ virtual CodeGen::Address EmitMSVAArg(CodeGen::CodeGenFunction &CGF,
+ CodeGen::Address VAListAddr,
+ QualType Ty) const;
+
virtual bool isHomogeneousAggregateBaseType(QualType Ty) const;
virtual bool isHomogeneousAggregateSmallEnough(const Type *Base,
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 0cad469f782..91614a5a64b 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -278,6 +278,16 @@ static llvm::Value *EmitOverflowIntrinsic(CodeGenFunction &CGF,
return CGF.Builder.CreateExtractValue(Tmp, 0);
}
+Value *CodeGenFunction::EmitVAStartEnd(Value *ArgValue, bool IsStart) {
+ llvm::Type *DestType = Int8PtrTy;
+ if (ArgValue->getType() != DestType)
+ ArgValue =
+ Builder.CreateBitCast(ArgValue, DestType, ArgValue->getName().data());
+
+ Intrinsic::ID inst = IsStart ? Intrinsic::vastart : Intrinsic::vaend;
+ return Builder.CreateCall(CGM.getIntrinsic(inst), ArgValue);
+}
+
RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
unsigned BuiltinID, const CallExpr *E,
ReturnValueSlot ReturnValue) {
@@ -301,19 +311,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
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 = (BuiltinID == Builtin::BI__va_start)
- ? EmitScalarExpr(E->getArg(0))
- : EmitVAListRef(E->getArg(0)).getPointer();
- llvm::Type *DestType = Int8PtrTy;
- if (ArgValue->getType() != DestType)
- ArgValue = Builder.CreateBitCast(ArgValue, DestType,
- ArgValue->getName().data());
-
- Intrinsic::ID inst = (BuiltinID == Builtin::BI__builtin_va_end) ?
- Intrinsic::vaend : Intrinsic::vastart;
- return RValue::get(Builder.CreateCall(CGM.getIntrinsic(inst), ArgValue));
- }
+ case Builtin::BI__builtin_va_end:
+ return RValue::get(
+ EmitVAStartEnd(BuiltinID == Builtin::BI__va_start
+ ? EmitScalarExpr(E->getArg(0))
+ : EmitVAListRef(E->getArg(0)).getPointer(),
+ BuiltinID != Builtin::BI__builtin_va_end));
case Builtin::BI__builtin_va_copy: {
Value *DstPtr = EmitVAListRef(E->getArg(0)).getPointer();
Value *SrcPtr = EmitVAListRef(E->getArg(1)).getPointer();
@@ -5896,6 +5899,31 @@ BuildVector(ArrayRef<llvm::Value*> Ops) {
Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
const CallExpr *E) {
+ if (BuiltinID == X86::BI__builtin_ms_va_start ||
+ BuiltinID == X86::BI__builtin_ms_va_end)
+ return EmitVAStartEnd(EmitMSVAListRef(E->getArg(0)).getPointer(),
+ BuiltinID == X86::BI__builtin_ms_va_start);
+ if (BuiltinID == X86::BI__builtin_ms_va_copy) {
+ // Lower this manually. We can't reliably determine whether or not any
+ // given va_copy() is for a Win64 va_list from the calling convention
+ // alone, because it's legal to do this from a System V ABI function.
+ // With opaque pointer types, we won't have enough information in LLVM
+ // IR to determine this from the argument types, either. Best to do it
+ // now, while we have enough information.
+ Address DestAddr = EmitMSVAListRef(E->getArg(0));
+ Address SrcAddr = EmitMSVAListRef(E->getArg(1));
+
+ llvm::Type *BPP = Int8PtrPtrTy;
+
+ DestAddr = Address(Builder.CreateBitCast(DestAddr.getPointer(), BPP, "cp"),
+ DestAddr.getAlignment());
+ SrcAddr = Address(Builder.CreateBitCast(SrcAddr.getPointer(), BPP, "ap"),
+ SrcAddr.getAlignment());
+
+ Value *ArgPtr = Builder.CreateLoad(SrcAddr, "ap.val");
+ return Builder.CreateStore(ArgPtr, DestAddr);
+ }
+
SmallVector<Value*, 4> Ops;
// Find out if any arguments are required to be integer constant expressions.
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 1027661730a..f4cd314550b 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -3594,6 +3594,12 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
/* VarArg handling */
-Address CodeGenFunction::EmitVAArg(Address VAListAddr, QualType Ty) {
+Address CodeGenFunction::EmitVAArg(VAArgExpr *VE, Address &VAListAddr) {
+ VAListAddr = VE->isMicrosoftABI()
+ ? EmitMSVAListRef(VE->getSubExpr())
+ : EmitVAListRef(VE->getSubExpr());
+ QualType Ty = VE->getType();
+ if (VE->isMicrosoftABI())
+ return CGM.getTypes().getABIInfo().EmitMSVAArg(*this, VAListAddr, Ty);
return CGM.getTypes().getABIInfo().EmitVAArg(*this, VAListAddr, Ty);
}
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 1ab9e022c84..a229d94ad9e 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -960,8 +960,8 @@ void AggExprEmitter::VisitChooseExpr(const ChooseExpr *CE) {
}
void AggExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {
- Address ArgValue = CGF.EmitVAListRef(VE->getSubExpr());
- Address ArgPtr = CGF.EmitVAArg(ArgValue, VE->getType());
+ Address ArgValue = Address::invalid();
+ Address ArgPtr = CGF.EmitVAArg(VE, ArgValue);
if (!ArgPtr.isValid()) {
// If EmitVAArg fails, we fall back to the LLVM instruction.
diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp
index a2eba2b4cb1..2f9d0cab249 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -1011,8 +1011,8 @@ ComplexPairTy ComplexExprEmitter::VisitInitListExpr(InitListExpr *E) {
}
ComplexPairTy ComplexExprEmitter::VisitVAArgExpr(VAArgExpr *E) {
- Address ArgValue = CGF.EmitVAListRef(E->getSubExpr());
- Address ArgPtr = CGF.EmitVAArg(ArgValue, E->getType());
+ Address ArgValue = Address::invalid();
+ Address ArgPtr = CGF.EmitVAArg(E, ArgValue);
if (!ArgPtr.isValid()) {
CGF.ErrorUnsupported(E, "complex va_arg expression");
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 2bc264cfa12..7bf2cba5d8a 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -3357,8 +3357,9 @@ Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {
if (Ty->isVariablyModifiedType())
CGF.EmitVariablyModifiedType(Ty);
- Address ArgValue = CGF.EmitVAListRef(VE->getSubExpr());
- Address ArgPtr = CGF.EmitVAArg(ArgValue, VE->getType());
+ Address ArgValue = Address::invalid();
+ Address ArgPtr = CGF.EmitVAArg(VE, ArgValue);
+
llvm::Type *ArgTy = ConvertType(VE->getType());
// If EmitVAArg fails, we fall back to the LLVM instruction.
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index c948f8fdd9f..8801c3b3f25 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1718,6 +1718,10 @@ Address CodeGenFunction::EmitVAListRef(const Expr* E) {
return EmitLValue(E).getAddress();
}
+Address CodeGenFunction::EmitMSVAListRef(const Expr *E) {
+ return EmitLValue(E).getAddress();
+}
+
void CodeGenFunction::EmitDeclRefExprDbgValue(const DeclRefExpr *E,
llvm::Constant *Init) {
assert (Init && "Invalid DeclRefExpr initializer!");
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index cf045967722..8879169a0f5 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1655,6 +1655,11 @@ public:
// or the value of the expression, depending on how va_list is defined.
Address EmitVAListRef(const Expr *E);
+ /// Emit a "reference" to a __builtin_ms_va_list; this is
+ /// always the value of the expression, because a __builtin_ms_va_list is a
+ /// pointer to a char.
+ Address EmitMSVAListRef(const Expr *E);
+
/// EmitAnyExprToTemp - Similary to EmitAnyExpr(), however, the result will
/// always be accessible even if no aggregate location is provided.
RValue EmitAnyExprToTemp(const Expr *E);
@@ -1752,11 +1757,23 @@ public:
/// to -1 in accordance with the Itanium C++ ABI.
void EmitNullInitialization(Address DestPtr, QualType Ty);
- // EmitVAArg - Generate code to get an argument from the passed in pointer
- // and update it accordingly. The return value is a pointer to the argument.
+ /// Emits a call to an LLVM variable-argument intrinsic, either
+ /// \c llvm.va_start or \c llvm.va_end.
+ /// \param ArgValue A reference to the \c va_list as emitted by either
+ /// \c EmitVAListRef or \c EmitMSVAListRef.
+ /// \param IsStart If \c true, emits a call to \c llvm.va_start; otherwise,
+ /// calls \c llvm.va_end.
+ llvm::Value *EmitVAStartEnd(llvm::Value *ArgValue, bool IsStart);
+
+ /// Generate code to get an argument from the passed in pointer
+ /// and update it accordingly.
+ /// \param VE The \c VAArgExpr for which to generate code.
+ /// \param VAListAddr Receives a reference to the \c va_list as emitted by
+ /// either \c EmitVAListRef or \c EmitMSVAListRef.
+ /// \returns A pointer to the argument.
// FIXME: We should be able to get rid of this method and use the va_arg
// instruction in LLVM instead once it works well enough.
- Address EmitVAArg(Address VAListAddr, QualType Ty);
+ Address EmitVAArg(VAArgExpr *VE, Address &VAListAddr);
/// emitArrayLength - Compute the length of an array, even if it's a
/// VLA, and drill down to the base element type.
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index 201bebf9dbb..07c706b49a9 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -61,6 +61,11 @@ ABIInfo::getNaturalAlignIndirectInReg(QualType Ty, bool Realign) const {
/*ByRef*/ false, Realign);
}
+Address ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const {
+ return Address::invalid();
+}
+
ABIInfo::~ABIInfo() {}
static CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT,
@@ -1734,6 +1739,8 @@ public:
Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty) const override;
+ Address EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const override;
bool has64BitPointers() const {
return Has64BitPointers;
@@ -3266,6 +3273,14 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
return ResAddr;
}
+Address X86_64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const {
+ return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false,
+ CGF.getContext().getTypeInfoInChars(Ty),
+ CharUnits::fromQuantity(8),
+ /*allowHigherAlign*/ false);
+}
+
ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs,
bool IsReturnType) const {
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index b009123c8c7..cc509566bdd 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -249,6 +249,12 @@ void Sema::Initialize() {
}
}
+ if (PP.getTargetInfo().hasBuiltinMSVaList()) {
+ DeclarationName MSVaList = &Context.Idents.get("__builtin_ms_va_list");
+ if (IdResolver.begin(MSVaList) == IdResolver.end())
+ PushOnScopeChains(Context.getBuiltinMSVaListDecl(), TUScope);
+ }
+
DeclarationName BuiltinVaList = &Context.Idents.get("__builtin_va_list");
if (IdResolver.begin(BuiltinVaList) == IdResolver.end())
PushOnScopeChains(Context.getBuiltinVaListDecl(), TUScope);
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index c6a00b1dad1..f8e6c9d5ee4 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -1037,6 +1037,8 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
default: return false;
case X86::BI__builtin_cpu_supports:
return SemaBuiltinCpuSupports(TheCall);
+ case X86::BI__builtin_ms_va_start:
+ return SemaBuiltinMSVAStart(TheCall);
case X86::BI_mm_prefetch: i = 1; l = 0; u = 3; break;
case X86::BI__builtin_ia32_sha1rnds4: i = 2, l = 0; u = 3; break;
case X86::BI__builtin_ia32_vpermil2pd:
@@ -2317,9 +2319,10 @@ bool Sema::CheckObjCString(Expr *Arg) {
return false;
}
-/// SemaBuiltinVAStart - Check the arguments to __builtin_va_start for validity.
-/// Emit an error and return true on failure, return false on success.
-bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) {
+/// Check the arguments to '__builtin_va_start' or '__builtin_ms_va_start'
+/// for validity. Emit an error and return true on failure; return false
+/// on success.
+bool Sema::SemaBuiltinVAStartImpl(CallExpr *TheCall) {
Expr *Fn = TheCall->getCallee();
if (TheCall->getNumArgs() > 2) {
Diag(TheCall->getArg(2)->getLocStart(),
@@ -2397,6 +2400,48 @@ bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) {
return false;
}
+/// Check the arguments to '__builtin_va_start' for validity, and that
+/// it was called from a function of the native ABI.
+/// Emit an error and return true on failure; return false on success.
+bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) {
+ // On x86-64 Unix, don't allow this in Win64 ABI functions.
+ // On x64 Windows, don't allow this in System V ABI functions.
+ // (Yes, that means there's no corresponding way to support variadic
+ // System V ABI functions on Windows.)
+ if (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86_64) {
+ unsigned OS = Context.getTargetInfo().getTriple().getOS();
+ clang::CallingConv CC = CC_C;
+ if (const FunctionDecl *FD = getCurFunctionDecl())
+ CC = FD->getType()->getAs<FunctionType>()->getCallConv();
+ if ((OS == llvm::Triple::Win32 && CC == CC_X86_64SysV) ||
+ (OS != llvm::Triple::Win32 && CC == CC_X86_64Win64))
+ return Diag(TheCall->getCallee()->getLocStart(),
+ diag::err_va_start_used_in_wrong_abi_function)
+ << (OS != llvm::Triple::Win32);
+ }
+ return SemaBuiltinVAStartImpl(TheCall);
+}
+
+/// Check the arguments to '__builtin_ms_va_start' for validity, and that
+/// it was called from a Win64 ABI function.
+/// Emit an error and return true on failure; return false on success.
+bool Sema::SemaBuiltinMSVAStart(CallExpr *TheCall) {
+ // This only makes sense for x86-64.
+ const llvm::Triple &TT = Context.getTargetInfo().getTriple();
+ Expr *Callee = TheCall->getCallee();
+ if (TT.getArch() != llvm::Triple::x86_64)
+ return Diag(Callee->getLocStart(), diag::err_x86_builtin_32_bit_tgt);
+ // Don't allow this in System V ABI functions.
+ clang::CallingConv CC = CC_C;
+ if (const FunctionDecl *FD = getCurFunctionDecl())
+ CC = FD->getType()->getAs<FunctionType>()->getCallConv();
+ if (CC == CC_X86_64SysV ||
+ (TT.getOS() != llvm::Triple::Win32 && CC != CC_X86_64Win64))
+ return Diag(Callee->getLocStart(),
+ diag::err_ms_va_start_used_in_sysv_function);
+ return SemaBuiltinVAStartImpl(TheCall);
+}
+
bool Sema::SemaBuiltinVAStartARM(CallExpr *Call) {
// void __va_start(va_list *ap, const char *named_addr, size_t slot_size,
// const char *named_addr);
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 6b20f59046d..06b96aa0aca 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -11671,43 +11671,57 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
Expr *E, TypeSourceInfo *TInfo,
SourceLocation RPLoc) {
Expr *OrigExpr = E;
+ bool IsMS = false;
+
+ // It might be a __builtin_ms_va_list. (But don't ever mark a va_arg()
+ // as Microsoft ABI on an actual Microsoft platform, where
+ // __builtin_ms_va_list and __builtin_va_list are the same.)
+ if (!E->isTypeDependent() && Context.getTargetInfo().hasBuiltinMSVaList() &&
+ Context.getTargetInfo().getBuiltinVaListKind() != TargetInfo::CharPtrBuiltinVaList) {
+ QualType MSVaListType = Context.getBuiltinMSVaListType();
+ if (Context.hasSameType(MSVaListType, E->getType())) {
+ if (CheckForModifiableLvalue(E, BuiltinLoc, *this))
+ return ExprError();
+ IsMS = true;
+ }
+ }
// Get the va_list type
QualType VaListType = Context.getBuiltinVaListType();
- if (VaListType->isArrayType()) {
- // Deal with implicit array decay; for example, on x86-64,
- // va_list is an array, but it's supposed to decay to
- // a pointer for va_arg.
- VaListType = Context.getArrayDecayedType(VaListType);
- // Make sure the input expression also decays appropriately.
- ExprResult Result = UsualUnaryConversions(E);
- if (Result.isInvalid())
- return ExprError();
- E = Result.get();
- } else if (VaListType->isRecordType() && getLangOpts().CPlusPlus) {
- // If va_list is a record type and we are compiling in C++ mode,
- // check the argument using reference binding.
- InitializedEntity Entity
- = InitializedEntity::InitializeParameter(Context,
- Context.getLValueReferenceType(VaListType), false);
- ExprResult Init = PerformCopyInitialization(Entity, SourceLocation(), E);
- if (Init.isInvalid())
- return ExprError();
- E = Init.getAs<Expr>();
- } else {
- // Otherwise, the va_list argument must be an l-value because
- // it is modified by va_arg.
- if (!E->isTypeDependent() &&
- CheckForModifiableLvalue(E, BuiltinLoc, *this))
- return ExprError();
+ if (!IsMS) {
+ if (VaListType->isArrayType()) {
+ // Deal with implicit array decay; for example, on x86-64,
+ // va_list is an array, but it's supposed to decay to
+ // a pointer for va_arg.
+ VaListType = Context.getArrayDecayedType(VaListType);
+ // Make sure the input expression also decays appropriately.
+ ExprResult Result = UsualUnaryConversions(E);
+ if (Result.isInvalid())
+ return ExprError();
+ E = Result.get();
+ } else if (VaListType->isRecordType() && getLangOpts().CPlusPlus) {
+ // If va_list is a record type and we are compiling in C++ mode,
+ // check the argument using reference binding.
+ InitializedEntity Entity = InitializedEntity::InitializeParameter(
+ Context, Context.getLValueReferenceType(VaListType), false);
+ ExprResult Init = PerformCopyInitialization(Entity, SourceLocation(), E);
+ if (Init.isInvalid())
+ return ExprError();
+ E = Init.getAs<Expr>();
+ } else {
+ // Otherwise, the va_list argument must be an l-value because
+ // it is modified by va_arg.
+ if (!E->isTypeDependent() &&
+ CheckForModifiableLvalue(E, BuiltinLoc, *this))
+ return ExprError();
+ }
}
- if (!E->isTypeDependent() &&
- !Context.hasSameType(VaListType, E->getType())) {
+ if (!IsMS && !E->isTypeDependent() &&
+ !Context.hasSameType(VaListType, E->getType()))
return ExprError(Diag(E->getLocStart(),
diag::err_first_argument_to_va_arg_not_of_type_va_list)
<< OrigExpr->getType() << E->getSourceRange());
- }
if (!TInfo->getType()->isDependentType()) {
if (RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), TInfo->getType(),
@@ -11749,7 +11763,7 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
}
QualType T = TInfo->getType().getNonLValueExprType(Context);
- return new (Context) VAArgExpr(BuiltinLoc, E, TInfo, RPLoc, T);
+ return new (Context) VAArgExpr(BuiltinLoc, E, TInfo, RPLoc, T, IsMS);
}
ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) {
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 9c5586bbe10..45837285cda 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -6270,6 +6270,9 @@ static Decl *getPredefinedDecl(ASTContext &Context, PredefinedDeclIDs ID) {
case PREDEF_DECL_VA_LIST_TAG:
return Context.getVaListTagDecl();
+ case PREDEF_DECL_BUILTIN_MS_VA_LIST_ID:
+ return Context.getBuiltinMSVaListDecl();
+
case PREDEF_DECL_EXTERN_C_CONTEXT_ID:
return Context.getExternCContextDecl();
}
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 4501dd82b17..5322a406168 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -830,6 +830,7 @@ void ASTStmtReader::VisitVAArgExpr(VAArgExpr *E) {
E->setWrittenTypeInfo(GetTypeSourceInfo(Record, Idx));
E->setBuiltinLoc(ReadSourceLocation(Record, Idx));
E->setRParenLoc(ReadSourceLocation(Record, Idx));
+ E->setIsMicrosoftABI(Record[Idx++]);
}
void ASTStmtReader::VisitAddrLabelExpr(AddrLabelExpr *E) {
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 67a7eeaa59f..b582c3239d0 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -4084,6 +4084,8 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
PREDEF_DECL_OBJC_INSTANCETYPE_ID);
RegisterPredefDecl(Context.BuiltinVaListDecl, PREDEF_DECL_BUILTIN_VA_LIST_ID);
RegisterPredefDecl(Context.VaListTagDecl, PREDEF_DECL_VA_LIST_TAG);
+ RegisterPredefDecl(Context.BuiltinMSVaListDecl,
+ PREDEF_DECL_BUILTIN_MS_VA_LIST_ID);
RegisterPredefDecl(Context.ExternCContext, PREDEF_DECL_EXTERN_C_CONTEXT_ID);
// Build a record containing all of the tentative definitions in this file, in
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index be1c69bf08b..7c0424cc878 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -771,6 +771,7 @@ void ASTStmtWriter::VisitVAArgExpr(VAArgExpr *E) {
Writer.AddTypeSourceInfo(E->getWrittenTypeInfo(), Record);
Writer.AddSourceLocation(E->getBuiltinLoc(), Record);
Writer.AddSourceLocation(E->getRParenLoc(), Record);
+ Record.push_back(E->isMicrosoftABI());
Code = serialization::EXPR_VA_ARG;
}
OpenPOWER on IntegriCloud