]> granicus.if.org Git - clang/commitdiff
Bug fix, result of isIntegerConstantExpr could be of incorrect width
authorDaniel Dunbar <daniel@zuster.org>
Mon, 22 Sep 2008 23:53:24 +0000 (23:53 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Mon, 22 Sep 2008 23:53:24 +0000 (23:53 +0000)
for type.
  - PR2817

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@56482 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/Expr.cpp
test/CodeGen/2008-09-22-bad-switch-type.c [new file with mode: 0644]

index 8d49c8ef0ed21903bf625cfe3e6d97efc86f7295..9c3d623c163670ed10dc1c55038648069402f6f0 100644 (file)
@@ -867,22 +867,25 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
   }
   case BinaryOperatorClass: {
     const BinaryOperator *Exp = cast<BinaryOperator>(this);
+    llvm::APSInt LHS, RHS;
+
+    // Initialize result to have correct signedness and width.
+    Result = llvm::APSInt(static_cast<uint32_t>(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<uint32_t>(RHS.getLimitedValue(Result.getBitWidth()-1));
-      break;
+      Result = LHS << 
+        static_cast<uint32_t>(RHS.getLimitedValue(LHS.getBitWidth()-1));
+    break;
     case BinaryOperator::Shr:
-      Result >>= 
-        static_cast<uint32_t>(RHS.getLimitedValue(Result.getBitWidth()-1));
+      Result = LHS >>
+        static_cast<uint32_t>(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/test/CodeGen/2008-09-22-bad-switch-type.c b/test/CodeGen/2008-09-22-bad-switch-type.c
new file mode 100644 (file)
index 0000000..62a420e
--- /dev/null
@@ -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;
+  }
+}