зеркало из https://github.com/microsoft/clang-1.git
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
This commit is contained in:
Родитель
be127ba477
Коммит
7c50aca2fe
|
@ -1054,6 +1054,15 @@ Stmt::child_iterator ChooseExpr::child_end() {
|
|||
return reinterpret_cast<Stmt**>(&SubExprs)+END_EXPR;
|
||||
}
|
||||
|
||||
// VAArgExpr
|
||||
Stmt::child_iterator VAArgExpr::child_begin() {
|
||||
return reinterpret_cast<Stmt**>(&Val);
|
||||
}
|
||||
|
||||
Stmt::child_iterator VAArgExpr::child_end() {
|
||||
return reinterpret_cast<Stmt**>(&Val)+1;
|
||||
}
|
||||
|
||||
// InitListExpr
|
||||
Stmt::child_iterator InitListExpr::child_begin() {
|
||||
return reinterpret_cast<Stmt**>(&InitExprs[0]);
|
||||
|
|
|
@ -587,6 +587,14 @@ void StmtPrinter::VisitInitListExpr(InitListExpr* Node) {
|
|||
OS << " }";
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitVAArgExpr(VAArgExpr *Node) {
|
||||
OS << "va_arg(";
|
||||
PrintExpr(Node->getSubExpr());
|
||||
OS << ", ";
|
||||
OS << Node->getType().getAsString();
|
||||
OS << ")";
|
||||
}
|
||||
|
||||
// C++
|
||||
|
||||
void StmtPrinter::VisitCXXCastExpr(CXXCastExpr *Node) {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "clang/AST/AST.h"
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/Intrinsics.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
using namespace clang;
|
||||
using namespace CodeGen;
|
||||
|
@ -241,6 +242,7 @@ public:
|
|||
// Other Operators.
|
||||
Value *VisitConditionalOperator(const ConditionalOperator *CO);
|
||||
Value *VisitChooseExpr(ChooseExpr *CE);
|
||||
Value *VisitVAArgExpr(VAArgExpr *VE);
|
||||
Value *VisitObjCStringLiteral(const ObjCStringLiteral *E) {
|
||||
return CGF.EmitObjCStringLiteral(E);
|
||||
}
|
||||
|
@ -892,6 +894,14 @@ Value *ScalarExprEmitter::VisitChooseExpr(ChooseExpr *E) {
|
|||
return Visit(CondVal != 0 ? E->getLHS() : E->getRHS());
|
||||
}
|
||||
|
||||
Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE)
|
||||
{
|
||||
llvm::Value *ArgValue = EmitLValue(VE->getSubExpr()).getAddress();
|
||||
|
||||
llvm::Value *V = Builder.CreateVAArg(ArgValue, ConvertType(VE->getType()));
|
||||
return V;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Entry Point into this File
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -793,9 +793,9 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
|
|||
|
||||
switch (T) {
|
||||
default: assert(0 && "Not a builtin primary expression!");
|
||||
case tok::kw___builtin_va_arg:
|
||||
Res = ParseAssignmentExpression();
|
||||
if (Res.isInvalid) {
|
||||
case tok::kw___builtin_va_arg: {
|
||||
ExprResult Expr = ParseAssignmentExpression();
|
||||
if (Expr.isInvalid) {
|
||||
SkipUntil(tok::r_paren);
|
||||
return Res;
|
||||
}
|
||||
|
@ -803,11 +803,15 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
|
|||
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
|
||||
return ExprResult(true);
|
||||
|
||||
ParseTypeName();
|
||||
TypeTy *Ty = ParseTypeName();
|
||||
|
||||
MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
||||
if (Tok.isNot(tok::r_paren)) {
|
||||
Diag(Tok, diag::err_expected_rparen);
|
||||
return ExprResult(true);
|
||||
}
|
||||
Res = Actions.ActOnVAArg(StartLoc, Expr.Val, Ty, ConsumeParen());
|
||||
break;
|
||||
|
||||
}
|
||||
case tok::kw___builtin_offsetof: {
|
||||
SourceLocation TypeLoc = Tok.getLocation();
|
||||
TypeTy *Ty = ParseTypeName();
|
||||
|
|
|
@ -418,6 +418,11 @@ public:
|
|||
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 @@ private:
|
|||
unsigned NewWidth, bool NewSign,
|
||||
SourceLocation Loc, unsigned DiagID);
|
||||
|
||||
void InitBuiltinVaListType();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Extra semantic analysis beyond the C type system
|
||||
private:
|
||||
|
|
|
@ -146,23 +146,29 @@ ScopedDecl *Sema::LookupScopedDecl(IdentifierInfo *II, unsigned NSI,
|
|||
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);
|
||||
|
|
|
@ -1859,6 +1859,30 @@ Sema::ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, ExprTy *cond,
|
|||
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);
|
||||
|
|
|
@ -976,6 +976,32 @@ public:
|
|||
virtual child_iterator child_end();
|
||||
};
|
||||
|
||||
/// VAArgExpr, used for the builtin function __builtin_va_start.
|
||||
class VAArgExpr : public Expr {
|
||||
Expr *Val;
|
||||
SourceLocation BuiltinLoc, RParenLoc;
|
||||
public:
|
||||
VAArgExpr(SourceLocation BLoc, Expr* e, QualType t, SourceLocation RPLoc)
|
||||
: Expr(VAArgExprClass, t),
|
||||
Val(e),
|
||||
BuiltinLoc(BLoc),
|
||||
RParenLoc(RPLoc) { }
|
||||
|
||||
const Expr *getSubExpr() const { return Val; }
|
||||
Expr *getSubExpr() { return Val; }
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SourceRange(BuiltinLoc, RParenLoc);
|
||||
}
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == VAArgExprClass;
|
||||
}
|
||||
static bool classof(const VAArgExpr *) { return true; }
|
||||
|
||||
// Iterators
|
||||
virtual child_iterator child_begin();
|
||||
virtual child_iterator child_end();
|
||||
};
|
||||
|
||||
/// InitListExpr, used for struct and array initializers.
|
||||
class InitListExpr : public Expr {
|
||||
Expr **InitExprs;
|
||||
|
|
|
@ -66,6 +66,7 @@ STMT(49, ImplicitCastExpr , Expr)
|
|||
STMT(50, CompoundLiteralExpr , Expr)
|
||||
STMT(51, OCUVectorElementExpr , Expr)
|
||||
STMT(52, InitListExpr , Expr)
|
||||
STMT(53, VAArgExpr , Expr)
|
||||
|
||||
// GNU Extensions.
|
||||
STMT(55, AddrLabelExpr , Expr)
|
||||
|
|
|
@ -863,7 +863,9 @@ DIAG(err_va_start_used_in_non_variadic_function, ERROR,
|
|||
"'va_start' used in function with fixed args")
|
||||
DIAG(warn_second_parameter_of_va_start_not_last_named_argument, WARNING,
|
||||
"second parameter of 'va_start' not last named argument")
|
||||
|
||||
DIAG(err_first_argument_to_va_arg_not_of_type_va_list, ERROR,
|
||||
"first argument to 'va_arg' is of type '%0' and not 'va_list'")
|
||||
|
||||
DIAG(warn_return_missing_expr, WARNING,
|
||||
"non-void function '%0' should return a value")
|
||||
DIAG(ext_return_missing_expr, EXTENSION,
|
||||
|
|
|
@ -425,6 +425,13 @@ public:
|
|||
return 0;
|
||||
}
|
||||
|
||||
// __builtin_va_arg(expr, type)
|
||||
virtual ExprResult ActOnVAArg(SourceLocation BuiltinLoc,
|
||||
ExprTy *expr, TypeTy *type,
|
||||
SourceLocation RPLoc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===------------------------- C++ Expressions --------------------------===//
|
||||
|
||||
/// ActOnCXXCasts - Parse {dynamic,static,reinterpret,const}_cast's.
|
||||
|
|
Загрузка…
Ссылка в новой задаче