[cfe-commits] r59224 - in /cfe/trunk: lib/AST/Expr.cpp lib/AST/ExprConstant.cpp test/Sema/const-eval.c
Eli Friedman
eli.friedman at gmail.com
Wed Nov 12 22:09:17 PST 2008
Author: efriedma
Date: Thu Nov 13 00:09:17 2008
New Revision: 59224
URL: http://llvm.org/viewvc/llvm-project?rev=59224&view=rev
Log:
Fix for crash issues with comma operators with a void first operand, and
some more bullet-proofing/enhancements for tryEvaluate. This shouldn't
cause any behavior changes except for handling cases where we were
crashing before and being able to evaluate a few more cases in tryEvaluate.
This should settle the minor mess surrounding r59196.
Modified:
cfe/trunk/lib/AST/Expr.cpp
cfe/trunk/lib/AST/ExprConstant.cpp
cfe/trunk/test/Sema/const-eval.c
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=59224&r1=59223&r2=59224&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Thu Nov 13 00:09:17 2008
@@ -733,6 +733,12 @@
/// cast+dereference.
bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
SourceLocation *Loc, bool isEvaluated) const {
+ // Pretest for integral type; some parts of the code crash for types that
+ // can't be sized.
+ if (!getType()->isIntegralType()) {
+ if (Loc) *Loc = getLocStart();
+ return false;
+ }
switch (getStmtClass()) {
default:
if (Loc) *Loc = getLocStart();
Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=59224&r1=59223&r2=59224&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Thu Nov 13 00:09:17 2008
@@ -481,39 +481,67 @@
}
bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
- // The LHS of a constant expr is always evaluated and needed.
- llvm::APSInt RHS(32);
- if (!Visit(E->getLHS())) {
- // If the LHS is unfoldable, we generally can't fold this. However, if this
- // is a logical operator like &&/||, and if we know that the RHS determines
- // the outcome of the result (e.g. X && 0), return the outcome.
- if (!E->isLogicalOp())
- return false;
+ if (E->getOpcode() == BinaryOperator::Comma) {
+ // Evaluate the side that actually matters; this needs to be
+ // handled specially because calling Visit() on the LHS can
+ // have strange results when it doesn't have an integral type.
+ Visit(E->getRHS());
+
+ // Check for isEvaluated; the idea is that this might eventually
+ // be useful for isICE and other similar uses that care about
+ // whether a comma is evaluated. This isn't really used yet, though,
+ // and I'm not sure it really works as intended.
+ if (!Info.isEvaluated)
+ return true;
+
+ return Extension(E->getOperatorLoc(), diag::ext_comma_in_constant_expr);
+ }
+
+ if (E->isLogicalOp()) {
+ // These need to be handled specially because the operands aren't
+ // necessarily integral
+ bool bres;
+ if (!HandleConversionToBool(E->getLHS(), bres, Info)) {
+ // We can't evaluate the LHS; however, sometimes the result
+ // is determined by the RHS: X && 0 -> 0, X || 1 -> 1.
+ if (HandleConversionToBool(E->getRHS(), bres, Info) &&
+ bres == (E->getOpcode() == BinaryOperator::LOr)) {
+ Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
+ Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
+ Result = bres;
+ return true;
+ }
- // If this is a logical op, see if the RHS determines the outcome.
- EvalInfo Info2(Info.Ctx);
- if (!EvaluateInteger(E->getRHS(), RHS, Info2))
+ // Really can't evaluate
return false;
-
- // X && 0 -> 0, X || 1 -> 1.
- if ((E->getOpcode() == BinaryOperator::LAnd && RHS == 0) ||
- (E->getOpcode() == BinaryOperator::LOr && RHS != 0)) {
- Result = RHS != 0;
+ }
+
+ bool bres2;
+ if (HandleConversionToBool(E->getRHS(), bres2, Info)) {
Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
+ if (E->getOpcode() == BinaryOperator::LOr)
+ Result = bres || bres2;
+ else
+ Result = bres && bres2;
return true;
}
-
- return false; // error in subexpression.
+ return false;
}
-
- bool OldEval = Info.isEvaluated;
- // The short-circuiting &&/|| operators don't necessarily evaluate their
- // RHS. Make sure to pass isEvaluated down correctly.
- if ((E->getOpcode() == BinaryOperator::LAnd && Result == 0) ||
- (E->getOpcode() == BinaryOperator::LOr && Result != 0))
- Info.isEvaluated = false;
+ if (!E->getLHS()->getType()->isIntegralType() ||
+ !E->getRHS()->getType()->isIntegralType()) {
+ // We can't continue from here for non-integral types, and they
+ // could potentially confuse the following operations.
+ // FIXME: Deal with EQ and friends.
+ return false;
+ }
+
+ // The LHS of a constant expr is always evaluated and needed.
+ llvm::APSInt RHS(32);
+ if (!Visit(E->getLHS())) {
+ return false; // error in subexpression.
+ }
// FIXME: Handle pointer subtraction
@@ -522,8 +550,7 @@
// For example, see http://llvm.org/bugs/show_bug.cgi?id=2525
if (!EvaluateInteger(E->getRHS(), RHS, Info))
return false;
- Info.isEvaluated = OldEval;
-
+
switch (E->getOpcode()) {
default:
return Error(E->getOperatorLoc(), diag::err_expr_not_constant,E->getType());
@@ -585,21 +612,6 @@
Result = Result != 0 || RHS != 0;
Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
break;
-
-
- case BinaryOperator::Comma:
- // Result of the comma is just the result of the RHS.
- Result = RHS;
-
- // C99 6.6p3: "shall not contain assignment, ..., or comma operators,
- // *except* when they are contained within a subexpression that is not
- // evaluated". Note that Assignment can never happen due to constraints
- // on the LHS subexpr, so we don't need to check it here.
- if (!Info.isEvaluated)
- return true;
-
- // If the value is evaluated, we can accept it as an extension.
- return Extension(E->getOperatorLoc(), diag::ext_comma_in_constant_expr);
}
Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
@@ -656,7 +668,18 @@
Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
return true;
}
-
+
+ if (E->getOpcode() == UnaryOperator::LNot) {
+ // LNot's operand isn't necessarily an integer, so we handle it specially.
+ bool bres;
+ if (!HandleConversionToBool(E->getSubExpr(), bres, Info))
+ return false;
+ Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
+ Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
+ Result = !bres;
+ return true;
+ }
+
// Get the operand value into 'Result'.
if (!Visit(E->getSubExpr()))
return false;
@@ -667,12 +690,6 @@
// See C99 6.6p3.
return Error(E->getOperatorLoc(), diag::err_expr_not_constant,
E->getType());
- case UnaryOperator::LNot: {
- bool Val = Result == 0;
- Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
- Result = Val;
- break;
- }
case UnaryOperator::Extension:
// FIXME: Should extension allow i-c-e extension expressions in its scope?
// If so, we could clear the diagnostic ID.
@@ -708,7 +725,7 @@
}
// Handle simple integer->integer casts.
- if (SubExpr->getType()->isIntegerType()) {
+ if (SubExpr->getType()->isIntegralType()) {
if (!Visit(SubExpr))
return false;
Modified: cfe/trunk/test/Sema/const-eval.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/const-eval.c?rev=59224&r1=59223&r2=59224&view=diff
==============================================================================
--- cfe/trunk/test/Sema/const-eval.c (original)
+++ cfe/trunk/test/Sema/const-eval.c Thu Nov 13 00:09:17 2008
@@ -11,3 +11,9 @@
EVAL_EXPR(6, (int)(1+(struct y*)0))
EVAL_EXPR(7, (int)&((struct y*)0)->y)
EVAL_EXPR(8, (_Bool)"asdf")
+EVAL_EXPR(9, !!&x)
+EVAL_EXPR(10, ((void)1, 12))
+void g0(void);
+EVAL_EXPR(11, (g0(), 12)) // FIXME: This should give an error
+EVAL_EXPR(12, 1.0&&2.0)
+EVAL_EXPR(13, x || 3.0)
More information about the cfe-commits
mailing list