From: Anders Carlsson Date: Mon, 24 Nov 2008 04:21:33 +0000 (+0000) Subject: Fix bug in the constant evaluator. Fixes PR3115. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4bbc0e05a714d4ee4918a92a4a7049dd6ef33ad0;p=clang Fix bug in the constant evaluator. Fixes PR3115. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59938 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 6fba884028..7b927f4628 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -505,14 +505,12 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { Result = EvaluateBuiltinClassifyType(E); return true; - case Builtin::BI__builtin_constant_p: { + case Builtin::BI__builtin_constant_p: // __builtin_constant_p always has one operand: it returns true if that // operand can be folded, false otherwise. - APValue Res; - Result = E->getArg(0)->Evaluate(Res, Info.Ctx); + Result = E->getArg(0)->isEvaluatable(Info.Ctx); return true; } - } } bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { @@ -537,43 +535,45 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { // These need to be handled specially because the operands aren't // necessarily integral bool bres; - bool isEvaluated = true; if (HandleConversionToBool(E->getLHS(), bres, Info)) { // We were able to evaluate the LHS, see if we can get away with not // evaluating the RHS: 0 && X -> 0, 1 || X -> 1 - } else { - // 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)) { - // We can't evaluate. - return false; + if (bres == (E->getOpcode() == BinaryOperator::LOr) || + !bres == (E->getOpcode() == BinaryOperator::LAnd)) { + Result.zextOrTrunc(getIntTypeSizeInBits(E->getType())); + Result.setIsUnsigned(E->getType()->isUnsignedIntegerType()); + Result = bres; + + return true; } - - // We did not evaluate the LHS - isEvaluated = false; - } - if (bres == (E->getOpcode() == BinaryOperator::LOr) || - !bres == (E->getOpcode() == BinaryOperator::LAnd)) { - Result.zextOrTrunc(getIntTypeSizeInBits(E->getType())); - Result.setIsUnsigned(E->getType()->isUnsignedIntegerType()); - Result = bres; - Info.isEvaluated = isEvaluated; - - return true; + 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; + } + } else { + if (HandleConversionToBool(E->getRHS(), bres, Info)) { + // We can't evaluate the LHS; however, sometimes the result + // is determined by the RHS: X && 0 -> 0, X || 1 -> 1. + if (bres == (E->getOpcode() == BinaryOperator::LOr) || + !bres == (E->getOpcode() == BinaryOperator::LAnd)) { + Result.zextOrTrunc(getIntTypeSizeInBits(E->getType())); + Result.setIsUnsigned(E->getType()->isUnsignedIntegerType()); + Result = bres; + Info.isEvaluated = false; + + return true; + } + } } - 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; } diff --git a/test/Sema/const-eval.c b/test/Sema/const-eval.c index 726b7cbb29..67c27d40f2 100644 --- a/test/Sema/const-eval.c +++ b/test/Sema/const-eval.c @@ -17,3 +17,6 @@ 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) + +unsigned int l_19 = 1; +EVAL_EXPR(14, (1 ^ l_19) && 1); // expected-error {{fields must have a constant size}}