[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