From c6fdac260bc5890d78647615082e97263fd8a677 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Mon, 22 Sep 2008 23:53:24 +0000 Subject: [PATCH] Bug fix, result of isIntegerConstantExpr could be of incorrect width for type. - PR2817 llvm-svn: 56482 --- clang/lib/AST/Expr.cpp | 55 ++++++++++--------- .../test/CodeGen/2008-09-22-bad-switch-type.c | 34 ++++++++++++ 2 files changed, 63 insertions(+), 26 deletions(-) create mode 100644 clang/test/CodeGen/2008-09-22-bad-switch-type.c diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 8d49c8ef0ed2..9c3d623c1636 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -867,22 +867,25 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx, } case BinaryOperatorClass: { const BinaryOperator *Exp = cast(this); + llvm::APSInt LHS, RHS; + + // Initialize result to have correct signedness and width. + Result = llvm::APSInt(static_cast(Ctx.getTypeSize(getType())), + !getType()->isSignedIntegerType()); // The LHS of a constant expr is always evaluated and needed. - if (!Exp->getLHS()->isIntegerConstantExpr(Result, Ctx, Loc, isEvaluated)) + if (!Exp->getLHS()->isIntegerConstantExpr(LHS, Ctx, Loc, isEvaluated)) return false; - llvm::APSInt RHS(Result); - // The short-circuiting &&/|| operators don't necessarily evaluate their // RHS. Make sure to pass isEvaluated down correctly. if (Exp->isLogicalOp()) { bool RHSEval; if (Exp->getOpcode() == BinaryOperator::LAnd) - RHSEval = Result != 0; + RHSEval = LHS != 0; else { assert(Exp->getOpcode() == BinaryOperator::LOr &&"Unexpected logical"); - RHSEval = Result == 0; + RHSEval = LHS == 0; } if (!Exp->getRHS()->isIntegerConstantExpr(RHS, Ctx, Loc, @@ -898,7 +901,7 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx, if (Loc) *Loc = getLocStart(); return false; case BinaryOperator::Mul: - Result *= RHS; + Result = LHS * RHS; break; case BinaryOperator::Div: if (RHS == 0) { @@ -906,7 +909,7 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx, if (Loc) *Loc = getLocStart(); return false; } - Result /= RHS; + Result = LHS / RHS; break; case BinaryOperator::Rem: if (RHS == 0) { @@ -914,32 +917,32 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx, if (Loc) *Loc = getLocStart(); return false; } - Result %= RHS; + Result = LHS % RHS; break; - case BinaryOperator::Add: Result += RHS; break; - case BinaryOperator::Sub: Result -= RHS; break; + case BinaryOperator::Add: Result = LHS + RHS; break; + case BinaryOperator::Sub: Result = LHS - RHS; break; case BinaryOperator::Shl: - Result <<= - static_cast(RHS.getLimitedValue(Result.getBitWidth()-1)); - break; + Result = LHS << + static_cast(RHS.getLimitedValue(LHS.getBitWidth()-1)); + break; case BinaryOperator::Shr: - Result >>= - static_cast(RHS.getLimitedValue(Result.getBitWidth()-1)); + Result = LHS >> + static_cast(RHS.getLimitedValue(LHS.getBitWidth()-1)); break; - case BinaryOperator::LT: Result = Result < RHS; break; - case BinaryOperator::GT: Result = Result > RHS; break; - case BinaryOperator::LE: Result = Result <= RHS; break; - case BinaryOperator::GE: Result = Result >= RHS; break; - case BinaryOperator::EQ: Result = Result == RHS; break; - case BinaryOperator::NE: Result = Result != RHS; break; - case BinaryOperator::And: Result &= RHS; break; - case BinaryOperator::Xor: Result ^= RHS; break; - case BinaryOperator::Or: Result |= RHS; break; + case BinaryOperator::LT: Result = LHS < RHS; break; + case BinaryOperator::GT: Result = LHS > RHS; break; + case BinaryOperator::LE: Result = LHS <= RHS; break; + case BinaryOperator::GE: Result = LHS >= RHS; break; + case BinaryOperator::EQ: Result = LHS == RHS; break; + case BinaryOperator::NE: Result = LHS != RHS; break; + case BinaryOperator::And: Result = LHS & RHS; break; + case BinaryOperator::Xor: Result = LHS ^ RHS; break; + case BinaryOperator::Or: Result = LHS | RHS; break; case BinaryOperator::LAnd: - Result = Result != 0 && RHS != 0; + Result = LHS != 0 && RHS != 0; break; case BinaryOperator::LOr: - Result = Result != 0 || RHS != 0; + Result = LHS != 0 || RHS != 0; break; case BinaryOperator::Comma: diff --git a/clang/test/CodeGen/2008-09-22-bad-switch-type.c b/clang/test/CodeGen/2008-09-22-bad-switch-type.c new file mode 100644 index 000000000000..62a420eed3d4 --- /dev/null +++ b/clang/test/CodeGen/2008-09-22-bad-switch-type.c @@ -0,0 +1,34 @@ +// RUN: clang -emit-llvm -o %t %s +// PR2817 + +void f0(void) { + switch (0) { + case (unsigned long long) 0 < 0: + break; + } + + switch (0) { + case (unsigned long long) 0 > 0: + break; + } + + switch (0) { + case (unsigned long long) 0 <= 0: + break; + } + + switch (0) { + case (unsigned long long) 0 >= 0: + break; + } + + switch (0) { + case (unsigned long long) 0 == 0: + break; + } + + switch (0) { + case (unsigned long long) 0 != 0: + break; + } +}