aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-11-12 07:43:42 +0000
committerChris Lattner <sabre@nondot.org>2008-11-12 07:43:42 +0000
commit32fea9d18cc3658a1b01df5ca6f2ac302625c61d (patch)
tree477bdc248666115f3bd74acfa3aaad85e94167eb /lib/AST/ExprConstant.cpp
parentc8cc9ccc7b87a7ed1749b074f6b670bcec49abc1 (diff)
fix a crash analyzing constants in 176.gcc/expr.c with my next patch. It was
crashing because we errors are ignored in subexpressions that are not evaluated, but we still evaluate the result of parents. This would cause an assertion because the erroneous subexpr didn't have its result value set to the right type. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59110 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r--lib/AST/ExprConstant.cpp50
1 files changed, 34 insertions, 16 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index e2be9f16e5..887a3aac5d 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -171,23 +171,36 @@ public:
return true; // still a constant.
}
- bool Error(SourceLocation L, diag::kind D) {
+ bool Error(SourceLocation L, diag::kind D, QualType ExprTy) {
// If this is in an unevaluated portion of the subexpression, ignore the
// error.
- if (!Info.isEvaluated)
+ if (!Info.isEvaluated) {
+ // If error is ignored because the value isn't evaluated, get the real
+ // type at least to prevent errors downstream.
+ Result.zextOrTrunc(getIntTypeSizeInBits(ExprTy));
+ Result.setIsUnsigned(ExprTy->isUnsignedIntegerType());
return true;
+ }
- Info.DiagLoc = L;
- Info.ICEDiag = D;
+ // Take the first error.
+ if (Info.ICEDiag == 0) {
+ Info.DiagLoc = L;
+ Info.ICEDiag = D;
+ }
return false;
}
//===--------------------------------------------------------------------===//
// Visitor Methods
//===--------------------------------------------------------------------===//
+
+ bool VisitStmt(Stmt *) {
+ assert(0 && "This should be called on integers, stmts are not integers");
+ return false;
+ }
- bool VisitStmt(Stmt *S) {
- return Error(S->getLocStart(), diag::err_expr_not_constant);
+ bool VisitExpr(Expr *E) {
+ return Error(E->getLocStart(), diag::err_expr_not_constant, E->getType());
}
bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
@@ -241,7 +254,7 @@ bool IntExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
}
// Otherwise, random variable references are not constants.
- return Error(E->getLocStart(), diag::err_expr_not_constant);
+ return Error(E->getLocStart(), diag::err_expr_not_constant, E->getType());
}
/// EvaluateBuiltinClassifyType - Evaluate __builtin_classify_type the same way
@@ -304,7 +317,7 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
switch (E->isBuiltinCall()) {
default:
- return Error(E->getLocStart(), diag::err_expr_not_constant);
+ return Error(E->getLocStart(), diag::err_expr_not_constant, E->getType());
case Builtin::BI__builtin_classify_type:
Result.setIsSigned(true);
Result = EvaluateBuiltinClassifyType(E);
@@ -340,6 +353,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
E->getOpcode() == BinaryOperator::LOr && RHS != 0) {
Result = RHS != 0;
Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
+ Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
return true;
}
@@ -364,7 +378,8 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
Info.isEvaluated = OldEval;
switch (E->getOpcode()) {
- default: return Error(E->getOperatorLoc(), diag::err_expr_not_constant);
+ default:
+ return Error(E->getOperatorLoc(), diag::err_expr_not_constant,E->getType());
case BinaryOperator::Mul: Result *= RHS; return true;
case BinaryOperator::Add: Result += RHS; return true;
case BinaryOperator::Sub: Result -= RHS; return true;
@@ -373,14 +388,16 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
case BinaryOperator::Or: Result |= RHS; return true;
case BinaryOperator::Div:
if (RHS == 0)
- return Error(E->getOperatorLoc(), diag::err_expr_divide_by_zero);
+ return Error(E->getOperatorLoc(), diag::err_expr_divide_by_zero,
+ E->getType());
Result /= RHS;
- return true;
+ break;
case BinaryOperator::Rem:
if (RHS == 0)
- return Error(E->getOperatorLoc(), diag::err_expr_divide_by_zero);
+ return Error(E->getOperatorLoc(), diag::err_expr_divide_by_zero,
+ E->getType());
Result %= RHS;
- return true;
+ break;
case BinaryOperator::Shl:
// FIXME: Warn about out of range shift amounts!
Result <<= (unsigned)RHS.getLimitedValue(Result.getBitWidth()-1);
@@ -498,7 +515,8 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
default:
// Address, indirect, pre/post inc/dec, etc are not valid constant exprs.
// See C99 6.6p3.
- return Error(E->getOperatorLoc(), diag::err_expr_not_constant);
+ return Error(E->getOperatorLoc(), diag::err_expr_not_constant,
+ E->getType());
case UnaryOperator::LNot: {
bool Val = Result == 0;
Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
@@ -561,11 +579,11 @@ bool IntExprEvaluator::HandleCast(SourceLocation CastLoc,
}
if (!SubExpr->getType()->isRealFloatingType())
- return Error(CastLoc, diag::err_expr_not_constant);
+ return Error(CastLoc, diag::err_expr_not_constant, DestType);
APFloat F(0.0);
if (!EvaluateFloat(SubExpr, F, Info))
- return Error(CastLoc, diag::err_expr_not_constant);
+ return Error(CastLoc, diag::err_expr_not_constant, DestType);
// If the destination is boolean, compare against zero.
if (DestType->isBooleanType()) {