summaryrefslogtreecommitdiffstats
path: root/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r--lib/AST/ExprConstant.cpp108
1 files changed, 62 insertions, 46 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 06afec7..dfff209 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -13,6 +13,7 @@
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/CharUnits.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/ASTDiagnostic.h"
@@ -69,11 +70,12 @@ static bool EvaluateComplex(const Expr *E, APValue &Result, EvalInfo &Info);
static bool EvalPointerValueAsBool(APValue& Value, bool& Result) {
// FIXME: Is this accurate for all kinds of bases? If not, what would
// the check look like?
- Result = Value.getLValueBase() || Value.getLValueOffset();
+ Result = Value.getLValueBase() || !Value.getLValueOffset().isZero();
return true;
}
-static bool HandleConversionToBool(Expr* E, bool& Result, EvalInfo &Info) {
+static bool HandleConversionToBool(const Expr* E, bool& Result,
+ EvalInfo &Info) {
if (E->getType()->isIntegralType()) {
APSInt IntResult;
if (!EvaluateInteger(E, IntResult, Info))
@@ -222,11 +224,11 @@ public:
APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
APValue VisitDeclRefExpr(DeclRefExpr *E);
- APValue VisitPredefinedExpr(PredefinedExpr *E) { return APValue(E, 0); }
+ APValue VisitPredefinedExpr(PredefinedExpr *E) { return APValue(E); }
APValue VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
APValue VisitMemberExpr(MemberExpr *E);
- APValue VisitStringLiteral(StringLiteral *E) { return APValue(E, 0); }
- APValue VisitObjCEncodeExpr(ObjCEncodeExpr *E) { return APValue(E, 0); }
+ 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)
@@ -254,12 +256,12 @@ static bool EvaluateLValue(const Expr* E, APValue& Result, EvalInfo &Info) {
APValue LValueExprEvaluator::VisitDeclRefExpr(DeclRefExpr *E) {
if (isa<FunctionDecl>(E->getDecl())) {
- return APValue(E, 0);
+ return APValue(E);
} else if (VarDecl* VD = dyn_cast<VarDecl>(E->getDecl())) {
if (!Info.AnyLValue && !VD->hasGlobalStorage())
return APValue();
if (!VD->getType()->isReferenceType())
- return APValue(E, 0);
+ return APValue(E);
// FIXME: Check whether VD might be overridden!
const VarDecl *Def = 0;
if (const Expr *Init = VD->getDefinition(Def))
@@ -272,7 +274,7 @@ APValue LValueExprEvaluator::VisitDeclRefExpr(DeclRefExpr *E) {
APValue LValueExprEvaluator::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
if (!Info.AnyLValue && !E->isFileScope())
return APValue();
- return APValue(E, 0);
+ return APValue(E);
}
APValue LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) {
@@ -309,7 +311,8 @@ APValue LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) {
}
result.setLValue(result.getLValueBase(),
- result.getLValueOffset() + RL.getFieldOffset(i) / 8);
+ result.getLValueOffset() +
+ CharUnits::fromQuantity(RL.getFieldOffset(i) / 8));
return result;
}
@@ -324,9 +327,9 @@ APValue LValueExprEvaluator::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
if (!EvaluateInteger(E->getIdx(), Index, Info))
return APValue();
- uint64_t ElementSize = Info.Ctx.getTypeSize(E->getType()) / 8;
+ CharUnits ElementSize = Info.Ctx.getTypeSizeInChars(E->getType());
- uint64_t Offset = Index.getSExtValue() * ElementSize;
+ CharUnits Offset = Index.getSExtValue() * ElementSize;
Result.setLValue(Result.getLValueBase(),
Result.getLValueOffset() + Offset);
return Result;
@@ -363,22 +366,22 @@ public:
{ return Visit(E->getSubExpr()); }
APValue VisitUnaryAddrOf(const UnaryOperator *E);
APValue VisitObjCStringLiteral(ObjCStringLiteral *E)
- { return APValue(E, 0); }
+ { return APValue(E); }
APValue VisitAddrLabelExpr(AddrLabelExpr *E)
- { return APValue(E, 0); }
+ { return APValue(E); }
APValue VisitCallExpr(CallExpr *E);
APValue VisitBlockExpr(BlockExpr *E) {
if (!E->hasBlockDeclRefExprs())
- return APValue(E, 0);
+ return APValue(E);
return APValue();
}
APValue VisitImplicitValueInitExpr(ImplicitValueInitExpr *E)
- { return APValue((Expr*)0, 0); }
+ { return APValue((Expr*)0); }
APValue VisitConditionalOperator(ConditionalOperator *E);
APValue VisitChooseExpr(ChooseExpr *E)
{ return Visit(E->getChosenSubExpr(Info.Ctx)); }
APValue VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E)
- { return APValue((Expr*)0, 0); }
+ { return APValue((Expr*)0); }
// FIXME: Missing: @protocol, @selector
};
} // end anonymous namespace
@@ -409,15 +412,15 @@ APValue PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
return APValue();
QualType PointeeType = PExp->getType()->getAs<PointerType>()->getPointeeType();
- uint64_t SizeOfPointee;
+ 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.getTypeSize(PointeeType) / 8;
+ SizeOfPointee = Info.Ctx.getTypeSizeInChars(PointeeType);
- uint64_t Offset = ResultLValue.getLValueOffset();
+ CharUnits Offset = ResultLValue.getLValueOffset();
if (E->getOpcode() == BinaryOperator::Add)
Offset += AdditionalOffset.getLimitedValue() * SizeOfPointee;
@@ -459,7 +462,8 @@ APValue PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
if (Result.isInt()) {
Result.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType()));
- return APValue(0, Result.getInt().getZExtValue());
+ return APValue(0,
+ CharUnits::fromQuantity(Result.getInt().getZExtValue()));
}
// Cast is of an lvalue, no need to change value.
@@ -481,7 +485,8 @@ APValue PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
if (Result.isInt()) {
Result.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType()));
- return APValue(0, Result.getInt().getZExtValue());
+ return APValue(0,
+ CharUnits::fromQuantity(Result.getInt().getZExtValue()));
}
// Cast is of an lvalue, no need to change value.
@@ -502,7 +507,7 @@ APValue PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
APValue PointerExprEvaluator::VisitCallExpr(CallExpr *E) {
if (E->isBuiltinCall(Info.Ctx) ==
Builtin::BI__builtin___CFStringMakeConstantString)
- return APValue(E, 0);
+ return APValue(E);
return APValue();
}
@@ -976,20 +981,20 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
&& VD->getType()->isObjectType()
&& !VD->getType()->isVariablyModifiedType()
&& !VD->getType()->isDependentType()) {
- uint64_t Size = Info.Ctx.getTypeSize(VD->getType()) / 8;
- uint64_t Offset = Base.Val.getLValueOffset();
- if (Offset <= Size)
- Size -= Base.Val.getLValueOffset();
+ CharUnits Size = Info.Ctx.getTypeSizeInChars(VD->getType());
+ CharUnits Offset = Base.Val.getLValueOffset();
+ if (!Offset.isNegative() && Offset <= Size)
+ Size -= Offset;
else
- Size = 0;
- return Success(Size, E);
+ Size = CharUnits::Zero();
+ return Success(Size.getQuantity(), E);
}
}
}
// TODO: Perhaps we should let LLVM lower this?
if (E->getArg(0)->HasSideEffects(Info.Ctx)) {
- if (E->getArg(1)->EvaluateAsInt(Info.Ctx).getZExtValue() == 0)
+ if (E->getArg(1)->EvaluateAsInt(Info.Ctx).getZExtValue() <= 1)
return Success(-1ULL, E);
return Success(0, E);
}
@@ -1151,7 +1156,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
if (LHSValue.getLValueBase()) {
if (!E->isEqualityOp())
return false;
- if (RHSValue.getLValueBase() || RHSValue.getLValueOffset())
+ if (RHSValue.getLValueBase() || !RHSValue.getLValueOffset().isZero())
return false;
bool bres;
if (!EvalPointerValueAsBool(LHSValue, bres))
@@ -1160,7 +1165,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
} else if (RHSValue.getLValueBase()) {
if (!E->isEqualityOp())
return false;
- if (LHSValue.getLValueBase() || LHSValue.getLValueOffset())
+ if (LHSValue.getLValueBase() || !LHSValue.getLValueOffset().isZero())
return false;
bool bres;
if (!EvalPointerValueAsBool(RHSValue, bres))
@@ -1172,11 +1177,13 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
const QualType Type = E->getLHS()->getType();
const QualType ElementType = Type->getAs<PointerType>()->getPointeeType();
- uint64_t D = LHSValue.getLValueOffset() - RHSValue.getLValueOffset();
+ CharUnits ElementSize = CharUnits::One();
if (!ElementType->isVoidType() && !ElementType->isFunctionType())
- D /= Info.Ctx.getTypeSize(ElementType) / 8;
+ ElementSize = Info.Ctx.getTypeSizeInChars(ElementType);
- return Success(D, E);
+ CharUnits Diff = LHSValue.getLValueOffset() -
+ RHSValue.getLValueOffset();
+ return Success(Diff / ElementSize, E);
}
bool Result;
if (E->getOpcode() == BinaryOperator::EQ) {
@@ -1204,21 +1211,23 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
// Handle cases like (unsigned long)&a + 4.
if (E->isAdditiveOp() && Result.isLValue() && RHSVal.isInt()) {
- uint64_t offset = Result.getLValueOffset();
+ CharUnits Offset = Result.getLValueOffset();
+ CharUnits AdditionalOffset = CharUnits::fromQuantity(
+ RHSVal.getInt().getZExtValue());
if (E->getOpcode() == BinaryOperator::Add)
- offset += RHSVal.getInt().getZExtValue();
+ Offset += AdditionalOffset;
else
- offset -= RHSVal.getInt().getZExtValue();
- Result = APValue(Result.getLValueBase(), offset);
+ Offset -= AdditionalOffset;
+ Result = APValue(Result.getLValueBase(), Offset);
return true;
}
// Handle cases like 4 + (unsigned long)&a
if (E->getOpcode() == BinaryOperator::Add &&
RHSVal.isLValue() && Result.isInt()) {
- uint64_t offset = RHSVal.getLValueOffset();
- offset += Result.getInt().getZExtValue();
- Result = APValue(RHSVal.getLValueBase(), offset);
+ CharUnits Offset = RHSVal.getLValueOffset();
+ Offset += CharUnits::fromQuantity(Result.getInt().getZExtValue());
+ Result = APValue(RHSVal.getLValueBase(), Offset);
return true;
}
@@ -1334,8 +1343,7 @@ bool IntExprEvaluator::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) {
return false;
// Get information about the size.
- unsigned BitWidth = Info.Ctx.getTypeSize(SrcTy);
- return Success(BitWidth / Info.Ctx.Target.getCharWidth(), E);
+ return Success(Info.Ctx.getTypeSizeInChars(SrcTy).getQuantity(), E);
}
bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
@@ -1349,7 +1357,7 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
return false;
if (LV.getLValueBase())
return false;
- return Success(LV.getLValueOffset(), E);
+ return Success(LV.getLValueOffset().getQuantity(), E);
}
if (E->getOpcode() == UnaryOperator::LNot) {
@@ -1432,7 +1440,8 @@ bool IntExprEvaluator::VisitCastExpr(CastExpr *E) {
return true;
}
- APSInt AsInt = Info.Ctx.MakeIntValue(LV.getLValueOffset(), SrcType);
+ APSInt AsInt = Info.Ctx.MakeIntValue(LV.getLValueOffset().getQuantity(),
+ SrcType);
return Success(HandleIntToIntCast(DestType, SrcType, AsInt, Info.Ctx), E);
}
@@ -1978,6 +1987,13 @@ bool Expr::EvaluateAsAny(EvalResult &Result, ASTContext &Ctx) const {
return true;
}
+bool Expr::EvaluateAsBooleanCondition(bool &Result, ASTContext &Ctx) const {
+ EvalResult Scratch;
+ EvalInfo Info(Ctx, Scratch);
+
+ return HandleConversionToBool(this, Result, Info);
+}
+
bool Expr::EvaluateAsLValue(EvalResult &Result, ASTContext &Ctx) const {
EvalInfo Info(Ctx, Result);
OpenPOWER on IntegriCloud