[cfe-commits] r53490 - /cfe/trunk/lib/AST/ExprConstant.cpp
Chris Lattner
sabre at nondot.org
Fri Jul 11 15:52:42 PDT 2008
Author: lattner
Date: Fri Jul 11 17:52:41 2008
New Revision: 53490
URL: http://llvm.org/viewvc/llvm-project?rev=53490&view=rev
Log:
Provide a structure for passing down 'is evaluated' and passing up
diagnosic+loc info for i-c-e evaluation.
Modified:
cfe/trunk/lib/AST/ExprConstant.cpp
Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=53490&r1=53489&r2=53490&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Fri Jul 11 17:52:41 2008
@@ -51,8 +51,43 @@
return false;
}
-static bool EvaluatePointer(const Expr *E, APValue &Result, ASTContext &Ctx);
-static bool EvaluateInteger(const Expr *E, APSInt &Result, ASTContext &Ctx);
+/// EvalInfo - This is a private struct used by the evaluator to capture
+/// information about a subexpression as it is folded. It retains information
+/// about the AST context, but also maintains information about the folded
+/// expression.
+///
+/// If an expression could be evaluated, it is still possible it is not a C
+/// "integer constant expression" or constant expression. If not, this struct
+/// captures information about how and why not.
+///
+/// One bit of information passed *into* the request for constant folding
+/// indicates whether the subexpression is "evaluated" or not according to C
+/// rules. For example, the RHS of (0 && foo()) is not evaluated. We can
+/// evaluate the expression regardless of what the RHS is, but C only allows
+/// certain things in certain situations.
+struct EvalInfo {
+ ASTContext &Ctx;
+
+ /// isEvaluated - True if the subexpression is required to be evaluated, false
+ /// if it is short-circuited (according to C rules).
+ bool isEvaluated;
+
+ /// ICEDiag - If the expression is foldable, but the expression is not an
+ /// integer constant expression, this contains the extension diagnostic to
+ /// emit which describes why it isn't an integer constant expression. The
+ /// caller can choose to emit this or not, depending on whether they require
+ /// an i-c-e or not. DiagLoc indicates the caret position for the report.
+ ///
+ /// If ICEDiag is zero, then this expression is an i-c-e.
+ unsigned ICEDiag;
+ SourceLocation DiagLoc;
+
+ EvalInfo(ASTContext &ctx) : Ctx(ctx), isEvaluated(true), ICEDiag(0) {}
+};
+
+
+static bool EvaluatePointer(const Expr *E, APValue &Result, EvalInfo &Info);
+static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info);
//===----------------------------------------------------------------------===//
@@ -62,10 +97,10 @@
namespace {
class VISIBILITY_HIDDEN PointerExprEvaluator
: public StmtVisitor<PointerExprEvaluator, APValue> {
- ASTContext &Ctx;
+ EvalInfo &Info;
public:
- PointerExprEvaluator(ASTContext &ctx) : Ctx(ctx) {}
+ PointerExprEvaluator(EvalInfo &info) : Info(info) {}
APValue VisitStmt(Stmt *S) {
// FIXME: Remove this when we support more expressions.
@@ -81,10 +116,10 @@
};
} // end anonymous namespace
-static bool EvaluatePointer(const Expr* E, APValue& Result, ASTContext &Ctx) {
+static bool EvaluatePointer(const Expr* E, APValue& Result, EvalInfo &Info) {
if (!E->getType()->isPointerType())
return false;
- Result = PointerExprEvaluator(Ctx).Visit(const_cast<Expr*>(E));
+ Result = PointerExprEvaluator(Info).Visit(const_cast<Expr*>(E));
return Result.isLValue();
}
@@ -99,11 +134,11 @@
std::swap(PExp, IExp);
APValue ResultLValue;
- if (!EvaluatePointer(PExp, ResultLValue, Ctx))
+ if (!EvaluatePointer(PExp, ResultLValue, Info))
return APValue();
llvm::APSInt AdditionalOffset(32);
- if (!EvaluateInteger(IExp, AdditionalOffset, Ctx))
+ if (!EvaluateInteger(IExp, AdditionalOffset, Info))
return APValue();
uint64_t Offset = ResultLValue.getLValueOffset();
@@ -122,15 +157,15 @@
// Check for pointer->pointer cast
if (SubExpr->getType()->isPointerType()) {
APValue Result;
- if (EvaluatePointer(SubExpr, Result, Ctx))
+ if (EvaluatePointer(SubExpr, Result, Info))
return Result;
return APValue();
}
if (SubExpr->getType()->isArithmeticType()) {
llvm::APSInt Result(32);
- if (EvaluateInteger(SubExpr, Result, Ctx)) {
- Result.extOrTrunc(static_cast<uint32_t>(Ctx.getTypeSize(E->getType())));
+ if (EvaluateInteger(SubExpr, Result, Info)) {
+ Result.extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType()));
return APValue(0, Result.getZExtValue());
}
}
@@ -147,13 +182,14 @@
namespace {
class VISIBILITY_HIDDEN IntExprEvaluator
: public StmtVisitor<IntExprEvaluator, bool> {
- ASTContext &Ctx;
+ EvalInfo &Info;
APSInt &Result;
public:
- IntExprEvaluator(ASTContext &ctx, APSInt &result) : Ctx(ctx), Result(result){}
+ IntExprEvaluator(EvalInfo &info, APSInt &result)
+ : Info(info), Result(result) {}
unsigned getIntTypeSizeInBits(QualType T) const {
- return (unsigned)Ctx.getTypeSize(T);
+ return (unsigned)Info.Ctx.getTypeSize(T);
}
//===--------------------------------------------------------------------===//
@@ -193,15 +229,15 @@
};
} // end anonymous namespace
-static bool EvaluateInteger(const Expr* E, APSInt &Result, ASTContext &Ctx) {
- return IntExprEvaluator(Ctx, Result).Visit(const_cast<Expr*>(E));
+static bool EvaluateInteger(const Expr* E, APSInt &Result, EvalInfo &Info) {
+ return IntExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E));
}
bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
// The LHS of a constant expr is always evaluated and needed.
llvm::APSInt RHS(32);
- if (!Visit(E->getLHS()) || !EvaluateInteger(E->getRHS(), RHS, Ctx))
+ if (!Visit(E->getLHS()) || !EvaluateInteger(E->getRHS(), RHS, Info))
return false;
switch (E->getOpcode()) {
@@ -293,17 +329,17 @@
}
// Get information about the size or align.
- unsigned CharSize = Ctx.Target.getCharWidth();
+ unsigned CharSize = Info.Ctx.Target.getCharWidth();
if (isSizeOf)
Result = getIntTypeSizeInBits(SrcTy) / CharSize;
else
- Result = Ctx.getTypeAlign(SrcTy) / CharSize;
+ Result = Info.Ctx.getTypeAlign(SrcTy) / CharSize;
return true;
}
bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
if (E->isOffsetOfOp()) {
- Result = E->evaluateOffsetOf(Ctx);
+ Result = E->evaluateOffsetOf(Info.Ctx);
Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
return true;
}
@@ -312,8 +348,8 @@
return EvaluateSizeAlignOf(E->getOpcode() == UnaryOperator::SizeOf,
E->getSubExpr()->getType(), E->getType());
- // Get the operand value.
- if (!EvaluateInteger(E->getSubExpr(), Result, Ctx))
+ // Get the operand value into 'Result'.
+ if (!Visit(E->getSubExpr()))
return false;
switch (E->getOpcode()) {
@@ -348,7 +384,7 @@
// Handle simple integer->integer casts.
if (SubExpr->getType()->isIntegerType()) {
- if (!EvaluateInteger(SubExpr, Result, Ctx))
+ if (!EvaluateInteger(SubExpr, Result, Info))
return false;
// Figure out if this is a truncate, extend or noop cast.
@@ -361,7 +397,7 @@
Result.extOrTrunc(DestWidth);
} else if (SubExpr->getType()->isPointerType()) {
APValue LV;
- if (!EvaluatePointer(SubExpr, LV, Ctx))
+ if (!EvaluatePointer(SubExpr, LV, Info))
return false;
if (LV.getLValueBase())
return false;
@@ -383,8 +419,9 @@
bool Expr::tryEvaluate(APValue &Result, ASTContext &Ctx) const {
llvm::APSInt sInt(32);
#if USE_NEW_EVALUATOR
+ EvalInfo Info(Ctx);
if (getType()->isIntegerType()) {
- if (EvaluateInteger(this, sInt, Ctx)) {
+ if (EvaluateInteger(this, sInt, Info)) {
Result = APValue(sInt);
return true;
}
More information about the cfe-commits
mailing list