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.cpp53
1 files changed, 28 insertions, 25 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index a20e1cc..13831dc 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -848,16 +848,8 @@ static bool EvaluateInteger(const Expr* E, APSInt &Result, EvalInfo &Info) {
bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) {
// Enums are integer constant exprs.
- if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D)) {
- // FIXME: This is an ugly hack around the fact that enums don't set their
- // signedness consistently; see PR3173.
- APSInt SI = ECD->getInitVal();
- SI.setIsUnsigned(!E->getType()->isSignedIntegerType());
- // FIXME: This is an ugly hack around the fact that enums don't
- // set their width (!?!) consistently; see PR3173.
- SI.extOrTrunc(Info.Ctx.getIntWidth(E->getType()));
- return Success(SI, E);
- }
+ if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D))
+ return Success(ECD->getInitVal(), E);
// In C++, const, non-volatile integers initialized with ICEs are ICEs.
// In C, they can also be folded, although they are not ICEs.
@@ -866,15 +858,24 @@ bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) {
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
const VarDecl *Def = 0;
if (const Expr *Init = VD->getDefinition(Def)) {
- if (APValue *V = VD->getEvaluatedValue())
- return Success(V->getInt(), E);
-
+ if (APValue *V = VD->getEvaluatedValue()) {
+ if (V->isInt())
+ return Success(V->getInt(), E);
+ return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
+ }
+
+ if (VD->isEvaluatingValue())
+ return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
+
+ VD->setEvaluatingValue();
+
if (Visit(const_cast<Expr*>(Init))) {
// Cache the evaluated value in the variable declaration.
- VD->setEvaluatedValue(Info.Ctx, Result);
+ VD->setEvaluatedValue(Result);
return true;
}
+ VD->setEvaluatedValue(APValue());
return false;
}
}
@@ -1506,6 +1507,7 @@ public:
bool VisitFloatingLiteral(const FloatingLiteral *E);
bool VisitCastExpr(CastExpr *E);
bool VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E);
+ bool VisitConditionalOperator(ConditionalOperator *E);
bool VisitChooseExpr(const ChooseExpr *E)
{ return Visit(E->getChosenSubExpr(Info.Ctx)); }
@@ -1513,8 +1515,7 @@ public:
{ return Visit(E->getSubExpr()); }
// FIXME: Missing: __real__/__imag__, array subscript of vector,
- // member of vector, ImplicitValueInitExpr,
- // conditional ?:
+ // member of vector, ImplicitValueInitExpr
};
} // end anonymous namespace
@@ -1547,16 +1548,10 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) {
if (!S->isWide()) {
const llvm::fltSemantics &Sem =
Info.Ctx.getFloatTypeSemantics(E->getType());
- llvm::SmallString<16> s;
- s.append(S->getStrData(), S->getStrData() + S->getByteLength());
- s += '\0';
- long l;
- char *endp;
- l = strtol(&s[0], &endp, 0);
- if (endp != s.end()-1)
+ unsigned Type = 0;
+ if (!S->getString().empty() && S->getString().getAsInteger(0, Type))
return false;
- unsigned type = (unsigned int)l;;
- Result = llvm::APFloat::getNaN(Sem, false, type);
+ Result = llvm::APFloat::getNaN(Sem, false, Type);
return true;
}
}
@@ -1673,6 +1668,14 @@ bool FloatExprEvaluator::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) {
return true;
}
+bool FloatExprEvaluator::VisitConditionalOperator(ConditionalOperator *E) {
+ bool Cond;
+ if (!HandleConversionToBool(E->getCond(), Cond, Info))
+ return false;
+
+ return Visit(Cond ? E->getTrueExpr() : E->getFalseExpr());
+}
+
//===----------------------------------------------------------------------===//
// Complex Evaluation (for float and integer)
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud