Add code generation and sema checking for __builtin_va_arg.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43006 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Sema/Sema.h b/Sema/Sema.h
index a7db5b9..c45bbf8 100644
--- a/Sema/Sema.h
+++ b/Sema/Sema.h
@@ -418,6 +418,11 @@
ExprTy *cond, ExprTy *expr1, ExprTy *expr2,
SourceLocation RPLoc);
+ // __builtin_va_arg(expr, type)
+ virtual ExprResult ActOnVAArg(SourceLocation BuiltinLoc,
+ ExprTy *expr, TypeTy *type,
+ SourceLocation RPLoc);
+
/// ActOnCXXCasts - Parse {dynamic,static,reinterpret,const}_cast's.
virtual ExprResult ActOnCXXCasts(SourceLocation OpLoc, tok::TokenKind Kind,
SourceLocation LAngleBracketLoc, TypeTy *Ty,
@@ -624,6 +629,8 @@
unsigned NewWidth, bool NewSign,
SourceLocation Loc, unsigned DiagID);
+ void InitBuiltinVaListType();
+
//===--------------------------------------------------------------------===//
// Extra semantic analysis beyond the C type system
private:
diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp
index 59a2d1d..62f3fab 100644
--- a/Sema/SemaDecl.cpp
+++ b/Sema/SemaDecl.cpp
@@ -146,23 +146,29 @@
return 0;
}
+void Sema::InitBuiltinVaListType()
+{
+ if (!Context.getBuiltinVaListType().isNull())
+ return;
+
+ IdentifierInfo *VaIdent = &Context.Idents.get("__builtin_va_list");
+ ScopedDecl *VaDecl = LookupScopedDecl(VaIdent, Decl::IDNS_Ordinary,
+ SourceLocation(), TUScope);
+ TypedefDecl *VaTypedef = cast<TypedefDecl>(VaDecl);
+ Context.setBuiltinVaListType(Context.getTypedefType(VaTypedef));
+}
+
/// LazilyCreateBuiltin - The specified Builtin-ID was first used at file scope.
/// lazily create a decl for it.
ScopedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
Scope *S) {
Builtin::ID BID = (Builtin::ID)bid;
- if ((BID == Builtin::BI__builtin_va_start ||
+ if (BID == Builtin::BI__builtin_va_start ||
BID == Builtin::BI__builtin_va_copy ||
- BID == Builtin::BI__builtin_va_end) &&
- Context.getBuiltinVaListType().isNull()) {
- IdentifierInfo *VaIdent = &Context.Idents.get("__builtin_va_list");
- ScopedDecl *VaDecl = LookupScopedDecl(VaIdent, Decl::IDNS_Ordinary,
- SourceLocation(), TUScope);
- TypedefDecl *VaTypedef = cast<TypedefDecl>(VaDecl);
- Context.setBuiltinVaListType(Context.getTypedefType(VaTypedef));
- }
-
+ BID == Builtin::BI__builtin_va_end)
+ InitBuiltinVaListType();
+
QualType R = Context.BuiltinInfo.GetBuiltinType(BID, Context);
FunctionDecl *New = new FunctionDecl(SourceLocation(), II, R,
FunctionDecl::Extern, false, 0);
diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp
index 471312b..9142a25 100644
--- a/Sema/SemaExpr.cpp
+++ b/Sema/SemaExpr.cpp
@@ -1859,6 +1859,30 @@
return new ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr, resType, RPLoc);
}
+Sema::ExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc,
+ ExprTy *expr, TypeTy *type,
+ SourceLocation RPLoc)
+{
+ Expr *E = static_cast<Expr*>(expr);
+ QualType T = QualType::getFromOpaquePtr(type);
+
+ InitBuiltinVaListType();
+
+ Sema::AssignmentCheckResult result;
+
+ result = CheckAssignmentConstraints(Context.getBuiltinVaListType(),
+ E->getType());
+ if (result != Compatible)
+ return Diag(E->getLocStart(),
+ diag::err_first_argument_to_va_arg_not_of_type_va_list,
+ E->getType().getAsString(),
+ E->getSourceRange());
+
+ // FIXME: Warn if a non-POD type is passed in.
+
+ return new VAArgExpr(BuiltinLoc, E, T, RPLoc);
+}
+
// TODO: Move this to SemaObjC.cpp
Sema::ExprResult Sema::ParseObjCStringLiteral(ExprTy *string) {
StringLiteral* S = static_cast<StringLiteral *>(string);