diff options
author | Anders Carlsson <andersca@mac.com> | 2008-07-08 14:30:00 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2008-07-08 14:30:00 +0000 |
commit | 2bad1687fe6f00e10767a691a33b070b151902b6 (patch) | |
tree | a215e96d58309cf5aced0c25fc680ccceca5a790 /lib/AST/ExprConstant.cpp | |
parent | 0fe52e1bcaa69ba127f1bda036f057fec1f478de (diff) |
More work.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@53233 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r-- | lib/AST/ExprConstant.cpp | 79 |
1 files changed, 78 insertions, 1 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 3be2f94f23..5307a56fab 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -52,6 +52,32 @@ static bool CalcFakeICEVal(const Expr* Expr, } namespace { +class VISIBILITY_HIDDEN PointerExprEvaluator + : public StmtVisitor<PointerExprEvaluator, APValue> { + ASTContext &Ctx; + + PointerExprEvaluator(ASTContext &ctx) + : Ctx(ctx) {} + +public: + static bool Evaluate(const Expr* E, APValue& Result, ASTContext &Ctx) { + Result = PointerExprEvaluator(Ctx).Visit(const_cast<Expr*>(E)); + return Result.isLValue(); + } + + APValue VisitStmt(Stmt *S) { + // FIXME: Remove this when we support more expressions. + printf("Unhandled statement\n"); + S->dump(); + return APValue(); + } + + APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } + +}; +} + +namespace { class VISIBILITY_HIDDEN IntExprEvaluator : public StmtVisitor<IntExprEvaluator, APValue> { ASTContext &Ctx; @@ -84,7 +110,7 @@ public: APValue VisitBinaryOperator(const BinaryOperator *E) { // The LHS of a constant expr is always evaluated and needed. llvm::APSInt Result(32); - if (!Evaluate(E->getRHS(), Result, Ctx)) + if (!Evaluate(E->getLHS(), Result, Ctx)) return APValue(); llvm::APSInt RHS(32); @@ -209,6 +235,57 @@ public: Result.setIsUnsigned(E->getType()->isUnsignedIntegerType()); return APValue(Result); } + + APValue HandleCast(const Expr* SubExpr, QualType DestType) { + llvm::APSInt Result(32); + + uint32_t DestWidth = static_cast<uint32_t>(Ctx.getTypeSize(DestType)); + + // Handle simple integer->integer casts. + if (SubExpr->getType()->isIntegerType()) { + if (!Evaluate(SubExpr, Result, Ctx)) + return APValue(); + + // Figure out if this is a truncate, extend or noop cast. + // If the input is signed, do a sign extend, noop, or truncate. + if (DestType->isBooleanType()) { + // Conversion to bool compares against zero. + Result = Result != 0; + Result.zextOrTrunc(DestWidth); + } + else + Result.extOrTrunc(DestWidth); + } else if (SubExpr->getType()->isPointerType()) { + APValue LV; + if (!PointerExprEvaluator::Evaluate(SubExpr, LV, Ctx)) + return APValue(); + if (LV.getLValueBase()) + return APValue(); + + Result = llvm::APSInt(DestWidth, LV.getLValueOffset()); + } else { + assert(0 && "Unhandled cast!"); + } + + Result.setIsUnsigned(DestType->isUnsignedIntegerType()); + return APValue(Result); + } + + APValue VisitImplicitCastExpr(const ImplicitCastExpr *E) { + return HandleCast(E->getSubExpr(), E->getType()); + } + + APValue VisitCastExpr(const CastExpr *E) { + return HandleCast(E->getSubExpr(), E->getType()); + } + + APValue VisitIntegerLiteral(const IntegerLiteral *E) { + llvm::APSInt Result(Ctx.getTypeSize(E->getType())); + + Result = E->getValue(); + return APValue(Result); + } + }; } |