expand casts to handle what isIntegerConstantExpr handles.
Casts from pointers remain a problem. :)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@53501 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 78e0470..6b33bb6 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -247,11 +247,11 @@
bool VisitBinaryOperator(const BinaryOperator *E);
bool VisitUnaryOperator(const UnaryOperator *E);
- bool VisitCastExpr(const CastExpr* E) {
- return HandleCast(E->getSubExpr(), E->getType());
+ bool VisitCastExpr(CastExpr* E) {
+ return HandleCast(E->getLParenLoc(), E->getSubExpr(), E->getType());
}
- bool VisitImplicitCastExpr(const ImplicitCastExpr* E) {
- return HandleCast(E->getSubExpr(), E->getType());
+ bool VisitImplicitCastExpr(ImplicitCastExpr* E) {
+ return HandleCast(E->getLocStart(), E->getSubExpr(), E->getType());
}
bool VisitSizeOfAlignOfTypeExpr(const SizeOfAlignOfTypeExpr *E) {
return EvaluateSizeAlignOf(E->isSizeOf(), E->getArgumentType(),
@@ -259,7 +259,7 @@
}
private:
- bool HandleCast(const Expr* SubExpr, QualType DestType);
+ bool HandleCast(SourceLocation CastLoc, Expr *SubExpr, QualType DestType);
bool EvaluateSizeAlignOf(bool isSizeOf, QualType SrcTy, QualType DstTy);
};
} // end anonymous namespace
@@ -467,12 +467,15 @@
return true;
}
-bool IntExprEvaluator::HandleCast(const Expr* SubExpr, QualType DestType) {
+/// HandleCast - This is used to evaluate implicit or explicit casts where the
+/// result type is integer.
+bool IntExprEvaluator::HandleCast(SourceLocation CastLoc,
+ Expr *SubExpr, QualType DestType) {
unsigned DestWidth = getIntTypeSizeInBits(DestType);
// Handle simple integer->integer casts.
if (SubExpr->getType()->isIntegerType()) {
- if (!EvaluateInteger(SubExpr, Result, Info))
+ if (!Visit(SubExpr))
return false;
// Figure out if this is a truncate, extend or noop cast.
@@ -483,7 +486,12 @@
Result.zextOrTrunc(DestWidth);
} else
Result.extOrTrunc(DestWidth);
- } else if (SubExpr->getType()->isPointerType()) {
+ Result.setIsUnsigned(DestType->isUnsignedIntegerType());
+ return true;
+ }
+
+ // FIXME: Clean this up!
+ if (SubExpr->getType()->isPointerType()) {
APValue LV;
if (!EvaluatePointer(SubExpr, LV, Info))
return false;
@@ -492,11 +500,44 @@
Result.extOrTrunc(DestWidth);
Result = LV.getLValueOffset();
- } else {
- assert(0 && "Unhandled cast!");
+ Result.setIsUnsigned(DestType->isUnsignedIntegerType());
+ return true;
}
- Result.setIsUnsigned(DestType->isUnsignedIntegerType());
+ if (!SubExpr->getType()->isRealFloatingType())
+ return Error(CastLoc, diag::err_expr_not_constant);
+
+ // FIXME: Generalize floating point constant folding! For now we just permit
+ // which is allowed by integer constant expressions.
+
+ // Allow floating constants that are the immediate operands of casts or that
+ // are parenthesized.
+ const Expr *Operand = SubExpr;
+ while (const ParenExpr *PE = dyn_cast<ParenExpr>(Operand))
+ Operand = PE->getSubExpr();
+
+ // If this isn't a floating literal, we can't handle it.
+ const FloatingLiteral *FL = dyn_cast<FloatingLiteral>(Operand);
+ if (!FL)
+ return Error(CastLoc, diag::err_expr_not_constant);
+
+ // If the destination is boolean, compare against zero.
+ if (DestType->isBooleanType()) {
+ Result = !FL->getValue().isZero();
+ Result.zextOrTrunc(DestWidth);
+ Result.setIsUnsigned(DestType->isUnsignedIntegerType());
+ return true;
+ }
+
+ // Determine whether we are converting to unsigned or signed.
+ bool DestSigned = DestType->isSignedIntegerType();
+
+ // FIXME: Warning for overflow.
+ uint64_t Space[4];
+ (void)FL->getValue().convertToInteger(Space, DestWidth, DestSigned,
+ llvm::APFloat::rmTowardZero);
+ Result = llvm::APInt(DestWidth, 4, Space);
+ Result.setIsUnsigned(!DestSigned);
return true;
}