зеркало из https://github.com/microsoft/clang-1.git
Change the pointer / lvalue constant evaluators to build into a target reference
and return a bool. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103296 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
fde75965ce
Коммит
efdb83e26f
|
@ -84,10 +84,22 @@ namespace {
|
|||
v = APValue(IntReal, IntImag);
|
||||
}
|
||||
};
|
||||
|
||||
struct LValue {
|
||||
Expr *Base;
|
||||
CharUnits Offset;
|
||||
|
||||
Expr *getLValueBase() { return Base; }
|
||||
CharUnits getLValueOffset() { return Offset; }
|
||||
|
||||
void moveInto(APValue &v) {
|
||||
v = APValue(Base, Offset);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static bool EvaluateLValue(const Expr *E, APValue &Result, EvalInfo &Info);
|
||||
static bool EvaluatePointer(const Expr *E, APValue &Result, EvalInfo &Info);
|
||||
static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info);
|
||||
static bool EvaluatePointer(const Expr *E, LValue &Result, EvalInfo &Info);
|
||||
static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info);
|
||||
static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result,
|
||||
EvalInfo &Info);
|
||||
|
@ -98,10 +110,10 @@ static bool EvaluateComplex(const Expr *E, ComplexValue &Res, EvalInfo &Info);
|
|||
// Misc utilities
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static bool EvalPointerValueAsBool(APValue& Value, bool& Result) {
|
||||
const Expr* Base = Value.getLValueBase();
|
||||
static bool EvalPointerValueAsBool(LValue& Value, bool& Result) {
|
||||
const Expr* Base = Value.Base;
|
||||
|
||||
Result = Base || !Value.getLValueOffset().isZero();
|
||||
Result = Base || !Value.Offset.isZero();
|
||||
|
||||
const DeclRefExpr* DeclRef = dyn_cast<DeclRefExpr>(Base);
|
||||
if (!DeclRef)
|
||||
|
@ -131,7 +143,7 @@ static bool HandleConversionToBool(const Expr* E, bool& Result,
|
|||
Result = !FloatResult.isZero();
|
||||
return true;
|
||||
} else if (E->getType()->hasPointerRepresentation()) {
|
||||
APValue PointerResult;
|
||||
LValue PointerResult;
|
||||
if (!EvaluatePointer(E, PointerResult, Info))
|
||||
return false;
|
||||
return EvalPointerValueAsBool(PointerResult, Result);
|
||||
|
@ -261,34 +273,42 @@ public:
|
|||
//===----------------------------------------------------------------------===//
|
||||
namespace {
|
||||
class LValueExprEvaluator
|
||||
: public StmtVisitor<LValueExprEvaluator, APValue> {
|
||||
: public StmtVisitor<LValueExprEvaluator, bool> {
|
||||
EvalInfo &Info;
|
||||
LValue &Result;
|
||||
|
||||
bool Success(Expr *E) {
|
||||
Result.Base = E;
|
||||
Result.Offset = CharUnits::Zero();
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
|
||||
LValueExprEvaluator(EvalInfo &info) : Info(info) {}
|
||||
LValueExprEvaluator(EvalInfo &info, LValue &Result) :
|
||||
Info(info), Result(Result) {}
|
||||
|
||||
APValue VisitStmt(Stmt *S) {
|
||||
return APValue();
|
||||
bool VisitStmt(Stmt *S) {
|
||||
return false;
|
||||
}
|
||||
|
||||
APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
|
||||
APValue VisitDeclRefExpr(DeclRefExpr *E);
|
||||
APValue VisitPredefinedExpr(PredefinedExpr *E) { return APValue(E); }
|
||||
APValue VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
|
||||
APValue VisitMemberExpr(MemberExpr *E);
|
||||
APValue VisitStringLiteral(StringLiteral *E) { return APValue(E); }
|
||||
APValue VisitObjCEncodeExpr(ObjCEncodeExpr *E) { return APValue(E); }
|
||||
APValue VisitArraySubscriptExpr(ArraySubscriptExpr *E);
|
||||
APValue VisitUnaryDeref(UnaryOperator *E);
|
||||
APValue VisitUnaryExtension(const UnaryOperator *E)
|
||||
bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
|
||||
bool VisitDeclRefExpr(DeclRefExpr *E);
|
||||
bool VisitPredefinedExpr(PredefinedExpr *E) { return Success(E); }
|
||||
bool VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
|
||||
bool VisitMemberExpr(MemberExpr *E);
|
||||
bool VisitStringLiteral(StringLiteral *E) { return Success(E); }
|
||||
bool VisitObjCEncodeExpr(ObjCEncodeExpr *E) { return Success(E); }
|
||||
bool VisitArraySubscriptExpr(ArraySubscriptExpr *E);
|
||||
bool VisitUnaryDeref(UnaryOperator *E);
|
||||
bool VisitUnaryExtension(const UnaryOperator *E)
|
||||
{ return Visit(E->getSubExpr()); }
|
||||
APValue VisitChooseExpr(const ChooseExpr *E)
|
||||
bool VisitChooseExpr(const ChooseExpr *E)
|
||||
{ return Visit(E->getChosenSubExpr(Info.Ctx)); }
|
||||
|
||||
APValue VisitCastExpr(CastExpr *E) {
|
||||
bool VisitCastExpr(CastExpr *E) {
|
||||
switch (E->getCastKind()) {
|
||||
default:
|
||||
return APValue();
|
||||
return false;
|
||||
|
||||
case CastExpr::CK_NoOp:
|
||||
return Visit(E->getSubExpr());
|
||||
|
@ -298,44 +318,41 @@ public:
|
|||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
static bool EvaluateLValue(const Expr* E, APValue& Result, EvalInfo &Info) {
|
||||
Result = LValueExprEvaluator(Info).Visit(const_cast<Expr*>(E));
|
||||
return Result.isLValue();
|
||||
static bool EvaluateLValue(const Expr* E, LValue& Result, EvalInfo &Info) {
|
||||
return LValueExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E));
|
||||
}
|
||||
|
||||
APValue LValueExprEvaluator::VisitDeclRefExpr(DeclRefExpr *E) {
|
||||
bool LValueExprEvaluator::VisitDeclRefExpr(DeclRefExpr *E) {
|
||||
if (isa<FunctionDecl>(E->getDecl())) {
|
||||
return APValue(E);
|
||||
return Success(E);
|
||||
} else if (VarDecl* VD = dyn_cast<VarDecl>(E->getDecl())) {
|
||||
if (!Info.AnyLValue && !VD->hasGlobalStorage())
|
||||
return APValue();
|
||||
return false;
|
||||
if (!VD->getType()->isReferenceType())
|
||||
return APValue(E);
|
||||
return Success(E);
|
||||
// FIXME: Check whether VD might be overridden!
|
||||
if (const Expr *Init = VD->getAnyInitializer())
|
||||
return Visit(const_cast<Expr *>(Init));
|
||||
}
|
||||
|
||||
return APValue();
|
||||
return false;
|
||||
}
|
||||
|
||||
APValue LValueExprEvaluator::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
|
||||
bool LValueExprEvaluator::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
|
||||
if (!Info.AnyLValue && !E->isFileScope())
|
||||
return APValue();
|
||||
return APValue(E);
|
||||
return false;
|
||||
return Success(E);
|
||||
}
|
||||
|
||||
APValue LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) {
|
||||
APValue result;
|
||||
bool LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) {
|
||||
QualType Ty;
|
||||
if (E->isArrow()) {
|
||||
if (!EvaluatePointer(E->getBase(), result, Info))
|
||||
return APValue();
|
||||
if (!EvaluatePointer(E->getBase(), Result, Info))
|
||||
return false;
|
||||
Ty = E->getBase()->getType()->getAs<PointerType>()->getPointeeType();
|
||||
} else {
|
||||
result = Visit(E->getBase());
|
||||
if (result.isUninit())
|
||||
return APValue();
|
||||
if (!Visit(E->getBase()))
|
||||
return false;
|
||||
Ty = E->getBase()->getType();
|
||||
}
|
||||
|
||||
|
@ -344,10 +361,10 @@ APValue LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) {
|
|||
|
||||
FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
|
||||
if (!FD) // FIXME: deal with other kinds of member expressions
|
||||
return APValue();
|
||||
return false;
|
||||
|
||||
if (FD->getType()->isReferenceType())
|
||||
return APValue();
|
||||
return false;
|
||||
|
||||
// FIXME: This is linear time.
|
||||
unsigned i = 0;
|
||||
|
@ -358,36 +375,25 @@ APValue LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) {
|
|||
break;
|
||||
}
|
||||
|
||||
result.setLValue(result.getLValueBase(),
|
||||
result.getLValueOffset() +
|
||||
CharUnits::fromQuantity(RL.getFieldOffset(i) / 8));
|
||||
|
||||
return result;
|
||||
Result.Offset += CharUnits::fromQuantity(RL.getFieldOffset(i) / 8);
|
||||
return true;
|
||||
}
|
||||
|
||||
APValue LValueExprEvaluator::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
|
||||
APValue Result;
|
||||
|
||||
bool LValueExprEvaluator::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
|
||||
if (!EvaluatePointer(E->getBase(), Result, Info))
|
||||
return APValue();
|
||||
return false;
|
||||
|
||||
APSInt Index;
|
||||
if (!EvaluateInteger(E->getIdx(), Index, Info))
|
||||
return APValue();
|
||||
return false;
|
||||
|
||||
CharUnits ElementSize = Info.Ctx.getTypeSizeInChars(E->getType());
|
||||
|
||||
CharUnits Offset = Index.getSExtValue() * ElementSize;
|
||||
Result.setLValue(Result.getLValueBase(),
|
||||
Result.getLValueOffset() + Offset);
|
||||
return Result;
|
||||
Result.Offset += Index.getSExtValue() * ElementSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
APValue LValueExprEvaluator::VisitUnaryDeref(UnaryOperator *E) {
|
||||
APValue Result;
|
||||
if (!EvaluatePointer(E->getSubExpr(), Result, Info))
|
||||
return APValue();
|
||||
return Result;
|
||||
bool LValueExprEvaluator::VisitUnaryDeref(UnaryOperator *E) {
|
||||
return EvaluatePointer(E->getSubExpr(), Result, Info);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -396,103 +402,103 @@ APValue LValueExprEvaluator::VisitUnaryDeref(UnaryOperator *E) {
|
|||
|
||||
namespace {
|
||||
class PointerExprEvaluator
|
||||
: public StmtVisitor<PointerExprEvaluator, APValue> {
|
||||
: public StmtVisitor<PointerExprEvaluator, bool> {
|
||||
EvalInfo &Info;
|
||||
LValue &Result;
|
||||
|
||||
bool Success(Expr *E) {
|
||||
Result.Base = E;
|
||||
Result.Offset = CharUnits::Zero();
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
|
||||
PointerExprEvaluator(EvalInfo &info) : Info(info) {}
|
||||
PointerExprEvaluator(EvalInfo &info, LValue &Result)
|
||||
: Info(info), Result(Result) {}
|
||||
|
||||
APValue VisitStmt(Stmt *S) {
|
||||
return APValue();
|
||||
bool VisitStmt(Stmt *S) {
|
||||
return false;
|
||||
}
|
||||
|
||||
APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
|
||||
bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
|
||||
|
||||
APValue VisitBinaryOperator(const BinaryOperator *E);
|
||||
APValue VisitCastExpr(CastExpr* E);
|
||||
APValue VisitUnaryExtension(const UnaryOperator *E)
|
||||
bool VisitBinaryOperator(const BinaryOperator *E);
|
||||
bool VisitCastExpr(CastExpr* E);
|
||||
bool VisitUnaryExtension(const UnaryOperator *E)
|
||||
{ return Visit(E->getSubExpr()); }
|
||||
APValue VisitUnaryAddrOf(const UnaryOperator *E);
|
||||
APValue VisitObjCStringLiteral(ObjCStringLiteral *E)
|
||||
{ return APValue(E); }
|
||||
APValue VisitAddrLabelExpr(AddrLabelExpr *E)
|
||||
{ return APValue(E); }
|
||||
APValue VisitCallExpr(CallExpr *E);
|
||||
APValue VisitBlockExpr(BlockExpr *E) {
|
||||
bool VisitUnaryAddrOf(const UnaryOperator *E);
|
||||
bool VisitObjCStringLiteral(ObjCStringLiteral *E)
|
||||
{ return Success(E); }
|
||||
bool VisitAddrLabelExpr(AddrLabelExpr *E)
|
||||
{ return Success(E); }
|
||||
bool VisitCallExpr(CallExpr *E);
|
||||
bool VisitBlockExpr(BlockExpr *E) {
|
||||
if (!E->hasBlockDeclRefExprs())
|
||||
return APValue(E);
|
||||
return APValue();
|
||||
return Success(E);
|
||||
return false;
|
||||
}
|
||||
APValue VisitImplicitValueInitExpr(ImplicitValueInitExpr *E)
|
||||
{ return APValue((Expr*)0); }
|
||||
APValue VisitConditionalOperator(ConditionalOperator *E);
|
||||
APValue VisitChooseExpr(ChooseExpr *E)
|
||||
bool VisitImplicitValueInitExpr(ImplicitValueInitExpr *E)
|
||||
{ return Success((Expr*)0); }
|
||||
bool VisitConditionalOperator(ConditionalOperator *E);
|
||||
bool VisitChooseExpr(ChooseExpr *E)
|
||||
{ return Visit(E->getChosenSubExpr(Info.Ctx)); }
|
||||
APValue VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E)
|
||||
{ return APValue((Expr*)0); }
|
||||
bool VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E)
|
||||
{ return Success((Expr*)0); }
|
||||
// FIXME: Missing: @protocol, @selector
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
static bool EvaluatePointer(const Expr* E, APValue& Result, EvalInfo &Info) {
|
||||
static bool EvaluatePointer(const Expr* E, LValue& Result, EvalInfo &Info) {
|
||||
assert(E->getType()->hasPointerRepresentation());
|
||||
Result = PointerExprEvaluator(Info).Visit(const_cast<Expr*>(E));
|
||||
return Result.isLValue();
|
||||
return PointerExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E));
|
||||
}
|
||||
|
||||
APValue PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
|
||||
bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
|
||||
if (E->getOpcode() != BinaryOperator::Add &&
|
||||
E->getOpcode() != BinaryOperator::Sub)
|
||||
return APValue();
|
||||
return false;
|
||||
|
||||
const Expr *PExp = E->getLHS();
|
||||
const Expr *IExp = E->getRHS();
|
||||
if (IExp->getType()->isPointerType())
|
||||
std::swap(PExp, IExp);
|
||||
|
||||
APValue ResultLValue;
|
||||
if (!EvaluatePointer(PExp, ResultLValue, Info))
|
||||
return APValue();
|
||||
if (!EvaluatePointer(PExp, Result, Info))
|
||||
return false;
|
||||
|
||||
llvm::APSInt AdditionalOffset;
|
||||
if (!EvaluateInteger(IExp, AdditionalOffset, Info))
|
||||
return APValue();
|
||||
llvm::APSInt Offset;
|
||||
if (!EvaluateInteger(IExp, Offset, Info))
|
||||
return false;
|
||||
int64_t AdditionalOffset
|
||||
= Offset.isSigned() ? Offset.getSExtValue()
|
||||
: static_cast<int64_t>(Offset.getZExtValue());
|
||||
|
||||
// Compute the new offset in the appropriate width.
|
||||
|
||||
QualType PointeeType =
|
||||
PExp->getType()->getAs<PointerType>()->getPointeeType();
|
||||
llvm::APSInt SizeOfPointee(AdditionalOffset);
|
||||
CharUnits SizeOfPointee;
|
||||
|
||||
// Explicitly handle GNU void* and function pointer arithmetic extensions.
|
||||
if (PointeeType->isVoidType() || PointeeType->isFunctionType())
|
||||
SizeOfPointee = 1;
|
||||
SizeOfPointee = CharUnits::One();
|
||||
else
|
||||
SizeOfPointee = Info.Ctx.getTypeSizeInChars(PointeeType).getQuantity();
|
||||
SizeOfPointee = Info.Ctx.getTypeSizeInChars(PointeeType);
|
||||
|
||||
llvm::APSInt Offset(AdditionalOffset);
|
||||
Offset = ResultLValue.getLValueOffset().getQuantity();
|
||||
if (E->getOpcode() == BinaryOperator::Add)
|
||||
Offset += AdditionalOffset * SizeOfPointee;
|
||||
Result.Offset += AdditionalOffset * SizeOfPointee;
|
||||
else
|
||||
Offset -= AdditionalOffset * SizeOfPointee;
|
||||
Result.Offset -= AdditionalOffset * SizeOfPointee;
|
||||
|
||||
// Sign extend prior to converting back to a char unit.
|
||||
if (Offset.getBitWidth() < 64)
|
||||
Offset.extend(64);
|
||||
return APValue(ResultLValue.getLValueBase(),
|
||||
CharUnits::fromQuantity(Offset.getLimitedValue()));
|
||||
return true;
|
||||
}
|
||||
|
||||
APValue PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) {
|
||||
APValue result;
|
||||
if (EvaluateLValue(E->getSubExpr(), result, Info))
|
||||
return result;
|
||||
return APValue();
|
||||
bool PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) {
|
||||
return EvaluateLValue(E->getSubExpr(), Result, Info);
|
||||
}
|
||||
|
||||
|
||||
APValue PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
|
||||
bool PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
|
||||
Expr* SubExpr = E->getSubExpr();
|
||||
|
||||
switch (E->getCastKind()) {
|
||||
|
@ -510,18 +516,20 @@ APValue PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
|
|||
return Visit(SubExpr);
|
||||
|
||||
if (SubExpr->getType()->isIntegralType()) {
|
||||
APValue Result;
|
||||
if (!EvaluateIntegerOrLValue(SubExpr, Result, Info))
|
||||
APValue Value;
|
||||
if (!EvaluateIntegerOrLValue(SubExpr, Value, Info))
|
||||
break;
|
||||
|
||||
if (Result.isInt()) {
|
||||
Result.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType()));
|
||||
return APValue(0,
|
||||
CharUnits::fromQuantity(Result.getInt().getZExtValue()));
|
||||
if (Value.isInt()) {
|
||||
Value.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType()));
|
||||
Result.Base = 0;
|
||||
Result.Offset = CharUnits::fromQuantity(Value.getInt().getZExtValue());
|
||||
return true;
|
||||
} else {
|
||||
Result.Base = Value.getLValueBase();
|
||||
Result.Offset = Value.getLValueOffset();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Cast is of an lvalue, no need to change value.
|
||||
return Result;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -533,51 +541,46 @@ APValue PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
|
|||
return Visit(SubExpr);
|
||||
|
||||
case CastExpr::CK_IntegralToPointer: {
|
||||
APValue Result;
|
||||
if (!EvaluateIntegerOrLValue(SubExpr, Result, Info))
|
||||
APValue Value;
|
||||
if (!EvaluateIntegerOrLValue(SubExpr, Value, Info))
|
||||
break;
|
||||
|
||||
if (Result.isInt()) {
|
||||
Result.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType()));
|
||||
return APValue(0,
|
||||
CharUnits::fromQuantity(Result.getInt().getZExtValue()));
|
||||
if (Value.isInt()) {
|
||||
Value.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType()));
|
||||
Result.Base = 0;
|
||||
Result.Offset = CharUnits::fromQuantity(Value.getInt().getZExtValue());
|
||||
return true;
|
||||
} else {
|
||||
// Cast is of an lvalue, no need to change value.
|
||||
Result.Base = Value.getLValueBase();
|
||||
Result.Offset = Value.getLValueOffset();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Cast is of an lvalue, no need to change value.
|
||||
return Result;
|
||||
}
|
||||
case CastExpr::CK_ArrayToPointerDecay:
|
||||
case CastExpr::CK_FunctionToPointerDecay: {
|
||||
APValue Result;
|
||||
if (EvaluateLValue(SubExpr, Result, Info))
|
||||
return Result;
|
||||
break;
|
||||
}
|
||||
case CastExpr::CK_FunctionToPointerDecay:
|
||||
return EvaluateLValue(SubExpr, Result, Info);
|
||||
}
|
||||
|
||||
return APValue();
|
||||
return false;
|
||||
}
|
||||
|
||||
APValue PointerExprEvaluator::VisitCallExpr(CallExpr *E) {
|
||||
bool PointerExprEvaluator::VisitCallExpr(CallExpr *E) {
|
||||
if (E->isBuiltinCall(Info.Ctx) ==
|
||||
Builtin::BI__builtin___CFStringMakeConstantString ||
|
||||
E->isBuiltinCall(Info.Ctx) ==
|
||||
Builtin::BI__builtin___NSStringMakeConstantString)
|
||||
return APValue(E);
|
||||
return APValue();
|
||||
return Success(E);
|
||||
return false;
|
||||
}
|
||||
|
||||
APValue PointerExprEvaluator::VisitConditionalOperator(ConditionalOperator *E) {
|
||||
bool PointerExprEvaluator::VisitConditionalOperator(ConditionalOperator *E) {
|
||||
bool BoolResult;
|
||||
if (!HandleConversionToBool(E->getCond(), BoolResult, Info))
|
||||
return APValue();
|
||||
return false;
|
||||
|
||||
Expr* EvalExpr = BoolResult ? E->getTrueExpr() : E->getFalseExpr();
|
||||
|
||||
APValue Result;
|
||||
if (EvaluatePointer(EvalExpr, Result, Info))
|
||||
return Result;
|
||||
return APValue();
|
||||
return Visit(EvalExpr);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -1212,11 +1215,11 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
|
|||
|
||||
if (LHSTy->isPointerType() && RHSTy->isPointerType()) {
|
||||
if (E->getOpcode() == BinaryOperator::Sub || E->isEqualityOp()) {
|
||||
APValue LHSValue;
|
||||
LValue LHSValue;
|
||||
if (!EvaluatePointer(E->getLHS(), LHSValue, Info))
|
||||
return false;
|
||||
|
||||
APValue RHSValue;
|
||||
LValue RHSValue;
|
||||
if (!EvaluatePointer(E->getRHS(), RHSValue, Info))
|
||||
return false;
|
||||
|
||||
|
@ -1502,7 +1505,7 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
|
|||
if (E->isOffsetOfOp()) {
|
||||
// The AST for offsetof is defined in such a way that we can just
|
||||
// directly Evaluate it as an l-value.
|
||||
APValue LV;
|
||||
LValue LV;
|
||||
if (!EvaluateLValue(E->getSubExpr(), LV, Info))
|
||||
return false;
|
||||
if (LV.getLValueBase())
|
||||
|
@ -1577,7 +1580,7 @@ bool IntExprEvaluator::VisitCastExpr(CastExpr *E) {
|
|||
|
||||
// FIXME: Clean this up!
|
||||
if (SrcType->isPointerType()) {
|
||||
APValue LV;
|
||||
LValue LV;
|
||||
if (!EvaluatePointer(SubExpr, LV, Info))
|
||||
return false;
|
||||
|
||||
|
@ -1586,7 +1589,7 @@ bool IntExprEvaluator::VisitCastExpr(CastExpr *E) {
|
|||
if (Info.Ctx.getTypeSize(DestType) != Info.Ctx.getTypeSize(SrcType))
|
||||
return false;
|
||||
|
||||
Result = LV;
|
||||
LV.moveInto(Result);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1598,14 +1601,14 @@ bool IntExprEvaluator::VisitCastExpr(CastExpr *E) {
|
|||
if (SrcType->isArrayType() || SrcType->isFunctionType()) {
|
||||
// This handles double-conversion cases, where there's both
|
||||
// an l-value promotion and an implicit conversion to int.
|
||||
APValue LV;
|
||||
LValue LV;
|
||||
if (!EvaluateLValue(SubExpr, LV, Info))
|
||||
return false;
|
||||
|
||||
if (Info.Ctx.getTypeSize(DestType) != Info.Ctx.getTypeSize(Info.Ctx.VoidPtrTy))
|
||||
return false;
|
||||
|
||||
Result = LV;
|
||||
LV.moveInto(Result);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2104,66 +2107,47 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
|
|||
// Top level Expr::Evaluate method.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Evaluate - Return true if this is a constant which we can fold using
|
||||
/// any crazy technique (that has nothing to do with language standards) that
|
||||
/// we want to. If this function returns true, it returns the folded constant
|
||||
/// in Result.
|
||||
bool Expr::Evaluate(EvalResult &Result, ASTContext &Ctx) const {
|
||||
EvalInfo Info(Ctx, Result);
|
||||
|
||||
if (getType()->isVectorType()) {
|
||||
if (!EvaluateVector(this, Result.Val, Info))
|
||||
static bool Evaluate(const Expr *E, EvalInfo &Info) {
|
||||
if (E->getType()->isVectorType()) {
|
||||
if (!EvaluateVector(E, Info.EvalResult.Val, Info))
|
||||
return false;
|
||||
} else if (getType()->isIntegerType()) {
|
||||
if (!IntExprEvaluator(Info, Result.Val).Visit(const_cast<Expr*>(this)))
|
||||
} else if (E->getType()->isIntegerType()) {
|
||||
if (!IntExprEvaluator(Info, Info.EvalResult.Val).Visit(const_cast<Expr*>(E)))
|
||||
return false;
|
||||
} else if (getType()->hasPointerRepresentation()) {
|
||||
if (!EvaluatePointer(this, Result.Val, Info))
|
||||
} else if (E->getType()->hasPointerRepresentation()) {
|
||||
LValue LV;
|
||||
if (!EvaluatePointer(E, LV, Info))
|
||||
return false;
|
||||
} else if (getType()->isRealFloatingType()) {
|
||||
llvm::APFloat f(0.0);
|
||||
if (!EvaluateFloat(this, f, Info))
|
||||
LV.moveInto(Info.EvalResult.Val);
|
||||
} else if (E->getType()->isRealFloatingType()) {
|
||||
llvm::APFloat F(0.0);
|
||||
if (!EvaluateFloat(E, F, Info))
|
||||
return false;
|
||||
|
||||
Result.Val = APValue(f);
|
||||
} else if (getType()->isAnyComplexType()) {
|
||||
ComplexValue c;
|
||||
if (!EvaluateComplex(this, c, Info))
|
||||
Info.EvalResult.Val = APValue(F);
|
||||
} else if (E->getType()->isAnyComplexType()) {
|
||||
ComplexValue C;
|
||||
if (!EvaluateComplex(E, C, Info))
|
||||
return false;
|
||||
c.moveInto(Result.Val);
|
||||
C.moveInto(Info.EvalResult.Val);
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Evaluate - Return true if this is a constant which we can fold using
|
||||
/// any crazy technique (that has nothing to do with language standards) that
|
||||
/// we want to. If this function returns true, it returns the folded constant
|
||||
/// in Result.
|
||||
bool Expr::Evaluate(EvalResult &Result, ASTContext &Ctx) const {
|
||||
EvalInfo Info(Ctx, Result);
|
||||
return ::Evaluate(this, Info);
|
||||
}
|
||||
|
||||
bool Expr::EvaluateAsAny(EvalResult &Result, ASTContext &Ctx) const {
|
||||
EvalInfo Info(Ctx, Result, true);
|
||||
|
||||
if (getType()->isVectorType()) {
|
||||
if (!EvaluateVector(this, Result.Val, Info))
|
||||
return false;
|
||||
} else if (getType()->isIntegerType()) {
|
||||
if (!IntExprEvaluator(Info, Result.Val).Visit(const_cast<Expr*>(this)))
|
||||
return false;
|
||||
} else if (getType()->hasPointerRepresentation()) {
|
||||
if (!EvaluatePointer(this, Result.Val, Info))
|
||||
return false;
|
||||
} else if (getType()->isRealFloatingType()) {
|
||||
llvm::APFloat f(0.0);
|
||||
if (!EvaluateFloat(this, f, Info))
|
||||
return false;
|
||||
|
||||
Result.Val = APValue(f);
|
||||
} else if (getType()->isAnyComplexType()) {
|
||||
ComplexValue c;
|
||||
if (!EvaluateComplex(this, c, Info))
|
||||
return false;
|
||||
c.moveInto(Result.Val);
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return ::Evaluate(this, Info);
|
||||
}
|
||||
|
||||
bool Expr::EvaluateAsBooleanCondition(bool &Result, ASTContext &Ctx) const {
|
||||
|
@ -2176,13 +2160,23 @@ bool Expr::EvaluateAsBooleanCondition(bool &Result, ASTContext &Ctx) const {
|
|||
bool Expr::EvaluateAsLValue(EvalResult &Result, ASTContext &Ctx) const {
|
||||
EvalInfo Info(Ctx, Result);
|
||||
|
||||
return EvaluateLValue(this, Result.Val, Info) && !Result.HasSideEffects;
|
||||
LValue LV;
|
||||
if (EvaluateLValue(this, LV, Info) && !Result.HasSideEffects) {
|
||||
LV.moveInto(Result.Val);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Expr::EvaluateAsAnyLValue(EvalResult &Result, ASTContext &Ctx) const {
|
||||
EvalInfo Info(Ctx, Result, true);
|
||||
|
||||
return EvaluateLValue(this, Result.Val, Info) && !Result.HasSideEffects;
|
||||
LValue LV;
|
||||
if (EvaluateLValue(this, LV, Info) && !Result.HasSideEffects) {
|
||||
LV.moveInto(Result.Val);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// isEvaluatable - Call Evaluate to see if this expression can be constant
|
||||
|
|
Загрузка…
Ссылка в новой задаче