]> granicus.if.org Git - clang/commitdiff
Case values must be evaluated
authorAnders Carlsson <andersca@mac.com>
Sat, 22 Nov 2008 21:50:49 +0000 (21:50 +0000)
committerAnders Carlsson <andersca@mac.com>
Sat, 22 Nov 2008 21:50:49 +0000 (21:50 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59884 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Expr.h
lib/AST/ExprConstant.cpp
lib/Sema/SemaStmt.cpp
test/Sema/switch.c

index 77d6d5f86ddbde93428852ae4af0cee5764843fc..321dca5336585baf5959ee745bd78325b9bb07d3 100644 (file)
@@ -141,8 +141,9 @@ public:
   /// any crazy technique (that has nothing to do with language standards) that
   /// we want to.  If this function returns true, it returns the folded constant
   /// in Result.
-  bool Evaluate(APValue& Result, ASTContext &Ctx) const;
-  
+  // FIXME: We should come up with a better API for the isEvaluated case.
+  bool Evaluate(APValue& Result, ASTContext &Ctx, bool *isEvaluated = 0) const;
+
   /// isEvaluatable - Call Evaluate to see if this expression can be constant
   /// folded, but discard the result.
   bool isEvaluatable(ASTContext &Ctx) const;
index 35cec0f3442c7a19ab06fd05d6366cbe187368b0..5c5adb6a45e5beac0261a0f14c4b41bbfe6489b6 100644 (file)
@@ -537,6 +537,7 @@ 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
@@ -548,16 +549,18 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
         // We can't evaluate.
         return false;
       }
+      
+      // We did not evaluate the LHS
+      isEvaluated = 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;
+      Info.isEvaluated = isEvaluated;
+      
       return true;
     }
 
@@ -1153,30 +1156,31 @@ APValue ComplexFloatExprEvaluator::VisitBinaryOperator(const BinaryOperator *E)
 /// any crazy technique (that has nothing to do with language standards) that
 /// we want to.  If this function returns true, it returns the folded constant
 /// in Result.
-bool Expr::Evaluate(APValue &Result, ASTContext &Ctx) const {
+bool Expr::Evaluate(APValue &Result, ASTContext &Ctx, bool *isEvaluated) const {
   EvalInfo Info(Ctx);
   if (getType()->isIntegerType()) {
     llvm::APSInt sInt(32);
-    if (EvaluateInteger(this, sInt, Info)) {
-      Result = APValue(sInt);
-      return true;
-    }
+    if (!EvaluateInteger(this, sInt, Info))
+      return false;
+    
+    Result = APValue(sInt);
   } else if (getType()->isPointerType()) {
-    if (EvaluatePointer(this, Result, Info)) {
-      return true;
-    }
+    if (!EvaluatePointer(this, Result, Info))
+      return false;
   } else if (getType()->isRealFloatingType()) {
     llvm::APFloat f(0.0);
-    if (EvaluateFloat(this, f, Info)) {
-      Result = APValue(f);
-      return true;
-    }
+    if (!EvaluateFloat(this, f, Info))
+      return false;
+    
+    Result = APValue(f);
   } else if (getType()->isComplexType()) {
-    if (EvaluateComplexFloat(this, Result, Info))
-      return true;
+    if (!EvaluateComplexFloat(this, Result, Info))
+      return false;
   }    
-      
-  return false;
+
+  if (isEvaluated)
+    *isEvaluated = Info.isEvaluated;
+  return true;
 }
 
 /// isEvaluatable - Call Evaluate to see if this expression can be constant
index 6839310e0eca77ce6423be51b9fa34fbd28c6106..15d955cb7b4091c5c83f4a0f3339b44f554a2780 100644 (file)
@@ -131,8 +131,10 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, ExprTy *lhsval,
   // However, GCC allows any evaluatable integer expression. 
   // FIXME: Should we warn if this is evaluatable but not an I-C-E?
   APValue Result;
+  bool isEvaluated;
   
-  if (!LHSVal->Evaluate(Result, Context) || !Result.isInt()) {
+  if (!LHSVal->Evaluate(Result, Context, &isEvaluated) || !Result.isInt() ||
+      !isEvaluated) {
     // FIXME: Evaluate doesn't return the SourceLocation that it failed to
     // evaluate. 
     ExpLoc = LHSVal->getExprLoc();
@@ -142,7 +144,8 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, ExprTy *lhsval,
   }
 
   // GCC extension: The expression shall be an integer constant.
-  if (RHSVal && !RHSVal->Evaluate(Result, Context) || !Result.isInt()) {
+  if (RHSVal && !RHSVal->Evaluate(Result, Context, &isEvaluated) || 
+      !Result.isInt() || !isEvaluated) {
     ExpLoc = RHSVal->getExprLoc();
     Diag(ExpLoc, diag::err_case_label_not_integer_constant_expr)
       << RHSVal->getSourceRange();
index fd8e0464be6b3f4add5bfb41a07e7e5ff8944233..63e5fe33b7d6ec44ab6108978c24c645be5a6190 100644 (file)
@@ -48,5 +48,15 @@ void test4()
   case 0 && g() ... 1 || g():
     break;
   }
+  
+  switch (1) {
+  case g() && 0: // expected-error {{case label does not reduce to an integer constant}}
+    break;
+  }
+  
+  switch (1) {
+  case 0 ... g() || 1: // expected-error {{case label does not reduce to an integer constant}}
+    break;
+  }
 }