[cfe-commits] r59881 - in /cfe/trunk: include/clang/AST/Expr.h lib/AST/ExprConstant.cpp lib/CodeGen/CGStmt.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaStmt.cpp test/Sema/switch.c
Anders Carlsson
andersca at mac.com
Sat Nov 22 13:04:57 PST 2008
Author: andersca
Date: Sat Nov 22 15:04:56 2008
New Revision: 59881
URL: http://llvm.org/viewvc/llvm-project?rev=59881&view=rev
Log:
Use Expr::Evaluate for case statements. Fixes PR2525
Modified:
cfe/trunk/include/clang/AST/Expr.h
cfe/trunk/lib/AST/ExprConstant.cpp
cfe/trunk/lib/CodeGen/CGStmt.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaStmt.cpp
cfe/trunk/test/Sema/switch.c
Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=59881&r1=59880&r2=59881&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Sat Nov 22 15:04:56 2008
@@ -147,6 +147,10 @@
/// folded, but discard the result.
bool isEvaluatable(ASTContext &Ctx) const;
+ /// EvaluateAsInt - Call Evaluate and return the folded integer. This
+ /// must be called on an expression that constant folds to an integer.
+ llvm::APSInt EvaluateAsInt(ASTContext &Ctx) const;
+
/// hasGlobalStorage - Return true if this expression has static storage
/// duration. This means that the address of this expression is a link-time
/// constant.
Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=59881&r1=59880&r2=59881&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Sat Nov 22 15:04:56 2008
@@ -537,19 +537,28 @@
// These need to be handled specially because the operands aren't
// necessarily integral
bool bres;
- if (!HandleConversionToBool(E->getLHS(), bres, Info)) {
+
+ 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) &&
- bres == (E->getOpcode() == BinaryOperator::LOr)) {
- Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
- Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
- Result = bres;
- return true;
+ if (!HandleConversionToBool(E->getRHS(), bres, Info)) {
+ // We can't evaluate.
+ return false;
}
+ }
- // Really can't evaluate
- return false;
+ // FIXME: If we evaluate the RHS, we need to check if the LHS has
+ // any side effects.
+
+ 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;
}
bool bres2;
@@ -1176,3 +1185,12 @@
APValue V;
return Evaluate(V, Ctx);
}
+
+APSInt Expr::EvaluateAsInt(ASTContext &Ctx) const {
+ APValue V;
+ bool Result = Evaluate(V, Ctx);
+ assert(Result && "Could not evaluate expression");
+ assert(V.isInt() && "Expression did not evaluate to integer");
+
+ return V.getInt();
+}
Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=59881&r1=59880&r2=59881&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmt.cpp Sat Nov 22 15:04:56 2008
@@ -533,8 +533,8 @@
void CodeGenFunction::EmitCaseStmtRange(const CaseStmt &S) {
assert(S.getRHS() && "Expected RHS value in CaseStmt");
- llvm::APSInt LHS = S.getLHS()->getIntegerConstantExprValue(getContext());
- llvm::APSInt RHS = S.getRHS()->getIntegerConstantExprValue(getContext());
+ llvm::APSInt LHS = S.getLHS()->EvaluateAsInt(getContext());
+ llvm::APSInt RHS = S.getRHS()->EvaluateAsInt(getContext());
// Emit the code for this case. We do this first to make sure it is
// properly chained from our predecessor before generating the
@@ -594,7 +594,7 @@
EmitBlock(createBasicBlock("sw.bb"));
llvm::BasicBlock *CaseDest = Builder.GetInsertBlock();
- llvm::APSInt CaseVal = S.getLHS()->getIntegerConstantExprValue(getContext());
+ llvm::APSInt CaseVal = S.getLHS()->EvaluateAsInt(getContext());
SwitchInsn->addCase(llvm::ConstantInt::get(CaseVal), CaseDest);
EmitStmt(S.getSubStmt());
}
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=59881&r1=59880&r2=59881&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat Nov 22 15:04:56 2008
@@ -1488,7 +1488,7 @@
}
}
-bool Sema::CheckArithmeticConstantExpression(const Expr* Init) {
+bool Sema::CheckArithmeticConstantExpression(const Expr* Init) {
switch (Init->getStmtClass()) {
default:
InitializerElementNotConstant(Init);
Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=59881&r1=59880&r2=59881&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Sat Nov 22 15:04:56 2008
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
@@ -127,14 +128,22 @@
SourceLocation ExpLoc;
// C99 6.8.4.2p3: The expression shall be an integer constant.
- if (!LHSVal->isIntegerConstantExpr(Context, &ExpLoc)) {
+ // However, GCC allows any evaluatable integer expression.
+ // FIXME: Should we warn if this is evaluatable but not an I-C-E?
+ APValue Result;
+
+ if (!LHSVal->Evaluate(Result, Context) || !Result.isInt()) {
+ // FIXME: Evaluate doesn't return the SourceLocation that it failed to
+ // evaluate.
+ ExpLoc = LHSVal->getExprLoc();
Diag(ExpLoc, diag::err_case_label_not_integer_constant_expr)
<< LHSVal->getSourceRange();
return SubStmt;
}
// GCC extension: The expression shall be an integer constant.
- if (RHSVal && !RHSVal->isIntegerConstantExpr(Context, &ExpLoc)) {
+ if (RHSVal && !RHSVal->Evaluate(Result, Context) || !Result.isInt()) {
+ ExpLoc = RHSVal->getExprLoc();
Diag(ExpLoc, diag::err_case_label_not_integer_constant_expr)
<< RHSVal->getSourceRange();
RHSVal = 0; // Recover by just forgetting about it.
@@ -394,7 +403,7 @@
// We already verified that the expression has a i-c-e value (C99
// 6.8.4.2p3) - get that value now.
Expr *Lo = CS->getLHS();
- llvm::APSInt LoVal = Lo->getIntegerConstantExprValue(Context);
+ llvm::APSInt LoVal = Lo->EvaluateAsInt(Context);
// Convert the value to the same width/sign as the condition.
ConvertIntegerToTypeWarnOnOverflow(LoVal, CondWidth, CondIsSigned,
@@ -444,7 +453,7 @@
for (unsigned i = 0, e = CaseRanges.size(); i != e; ++i) {
CaseStmt *CR = CaseRanges[i].second;
Expr *Hi = CR->getRHS();
- llvm::APSInt HiVal = Hi->getIntegerConstantExprValue(Context);
+ llvm::APSInt HiVal = Hi->EvaluateAsInt(Context);
// Convert the value to the same width/sign as the condition.
ConvertIntegerToTypeWarnOnOverflow(HiVal, CondWidth, CondIsSigned,
Modified: cfe/trunk/test/Sema/switch.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/switch.c?rev=59881&r1=59880&r2=59881&view=diff
==============================================================================
--- cfe/trunk/test/Sema/switch.c (original)
+++ cfe/trunk/test/Sema/switch.c Sat Nov 22 15:04:56 2008
@@ -28,3 +28,25 @@
switch (0);
}
+extern int g();
+
+void test4()
+{
+ switch (1) {
+ case 0 && g():
+ case 1 || g():
+ break;
+ }
+
+ switch(1) {
+ case g(): // expected-error {{case label does not reduce to an integer constant}}
+ case 0 ... g(): // expected-error {{case label does not reduce to an integer constant}}
+ break;
+ }
+
+ switch (1) {
+ case 0 && g() ... 1 || g():
+ break;
+ }
+}
+
More information about the cfe-commits
mailing list