[cfe-commits] r65053 - /cfe/trunk/lib/AST/ExprConstant.cpp

Daniel Dunbar daniel at zuster.org
Thu Feb 19 10:37:50 PST 2009


Author: ddunbar
Date: Thu Feb 19 12:37:50 2009
New Revision: 65053

URL: http://llvm.org/viewvc/llvm-project?rev=65053&view=rev
Log:
Add another IntExprEvaluator::Success overload to suck up remained of
manual setting of the Result.

 - Idiom now enforces that result will always have correct width and
   type; this exposed three new bugs:

    o Enum constant decl value can have different width than type
      (PR3173).

    o EvaluateInteger should not run an IntExprEvaluator over
      non-integral expressions.

    o FloatExprEvaluate was not handling casts correctly (it was
      evaluating the cast in the IntExprEvaluator!).

Modified:
    cfe/trunk/lib/AST/ExprConstant.cpp

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=65053&r1=65052&r2=65053&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Thu Feb 19 12:37:50 2009
@@ -469,9 +469,20 @@
     return true;  // still a constant.
   }
 
+  bool Success(const llvm::APSInt &SI, const Expr *E) {
+    Result = SI;
+    assert(Result.isSigned() == E->getType()->isSignedIntegerType() &&
+           "Invalid evaluation result.");
+    assert(Result.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) &&
+           "Invalid evaluation result.");
+    return true;
+  }
+
   bool Success(const llvm::APInt &I, const Expr *E) {
     Result = I;
     Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
+    assert(Result.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) &&
+           "Invalid evaluation result.");
     return true;
   }
 
@@ -561,17 +572,22 @@
 } // end anonymous namespace
 
 static bool EvaluateInteger(const Expr* E, APSInt &Result, EvalInfo &Info) {
+  if (!E->getType()->isIntegralType())
+    return false;
   return IntExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E));
 }
 
 bool IntExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
   // Enums are integer constant exprs.
   if (const EnumConstantDecl *D = dyn_cast<EnumConstantDecl>(E->getDecl())) {
-    Result = D->getInitVal();
     // FIXME: This is an ugly hack around the fact that enums don't set their
-    // signedness consistently; see PR3173
-    Result.setIsUnsigned(!E->getType()->isSignedIntegerType());
-    return true;
+    // signedness consistently; see PR3173.
+    APSInt SI = D->getInitVal();
+    SI.setIsUnsigned(!E->getType()->isSignedIntegerType());
+    // FIXME: This is an ugly hack around the fact that enums don't
+    // set their width (!?!) consistently; see PR3173.
+    SI.extOrTrunc(Info.Ctx.getIntWidth(E->getType()));
+    return Success(SI, E);
   }
 
   // In C++, const, non-volatile integers initialized with ICEs are ICEs.
@@ -683,18 +699,16 @@
       // evaluating the RHS: 0 && X -> 0, 1 || X -> 1
       if (lhsResult == (E->getOpcode() == BinaryOperator::LOr) || 
           !lhsResult == (E->getOpcode() == BinaryOperator::LAnd)) {
-        Result = Info.Ctx.MakeIntValue(lhsResult, E->getType());
-        
         Info.ShortCircuit++;
         bool rhsEvaluated = HandleConversionToBool(E->getRHS(), rhsResult, Info);
         Info.ShortCircuit--;
         
-        if (rhsEvaluated)
-          return true;
-        
         // FIXME: Return an extension warning saying that the RHS could not be
         // evaluated.
-        return true;
+        // if (!rhsEvaluated) ...
+        (void) rhsEvaluated;
+        
+        return Success(lhsResult, E);
       }
 
       if (HandleConversionToBool(E->getRHS(), rhsResult, Info)) {
@@ -839,29 +853,29 @@
   switch (E->getOpcode()) {
   default:
     return Error(E->getOperatorLoc(), diag::note_invalid_subexpr_in_ice, E);
-  case BinaryOperator::Mul: Result *= RHS; return true;
-  case BinaryOperator::Add: Result += RHS; return true;
-  case BinaryOperator::Sub: Result -= RHS; return true;
-  case BinaryOperator::And: Result &= RHS; return true;
-  case BinaryOperator::Xor: Result ^= RHS; return true;
-  case BinaryOperator::Or:  Result |= RHS; return true;
+  case BinaryOperator::Mul: return Success(Result * RHS, E);
+  case BinaryOperator::Add: return Success(Result + RHS, E);
+  case BinaryOperator::Sub: return Success(Result - RHS, E);
+  case BinaryOperator::And: return Success(Result & RHS, E);
+  case BinaryOperator::Xor: return Success(Result ^ RHS, E);
+  case BinaryOperator::Or:  return Success(Result | RHS, E);
   case BinaryOperator::Div:
     if (RHS == 0)
       return Error(E->getOperatorLoc(), diag::note_expr_divide_by_zero, E);
-    Result /= RHS;
-    break;
+    return Success(Result / RHS, E);
   case BinaryOperator::Rem:
     if (RHS == 0)
       return Error(E->getOperatorLoc(), diag::note_expr_divide_by_zero, E);
-    Result %= RHS;
-    break;
-  case BinaryOperator::Shl:
+    return Success(Result % RHS, E);
+  case BinaryOperator::Shl: {
     // FIXME: Warn about out of range shift amounts!
-    Result <<= (unsigned)RHS.getLimitedValue(Result.getBitWidth()-1);
-    break;
-  case BinaryOperator::Shr:
-    Result >>= (unsigned)RHS.getLimitedValue(Result.getBitWidth()-1);
-    break;
+    unsigned SA = (unsigned) RHS.getLimitedValue(Result.getBitWidth()-1);
+    return Success(Result << SA, E);
+  }
+  case BinaryOperator::Shr: {
+    unsigned SA = (unsigned) RHS.getLimitedValue(Result.getBitWidth()-1);
+    return Success(Result >> SA, E);
+  }
       
   case BinaryOperator::LT: return Success(Result < RHS, E);
   case BinaryOperator::GT: return Success(Result > RHS, E);
@@ -870,9 +884,6 @@
   case BinaryOperator::EQ: return Success(Result == RHS, E);
   case BinaryOperator::NE: return Success(Result != RHS, E);
   }
-
-  Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
-  return true;
 }
 
 bool IntExprEvaluator::VisitConditionalOperator(const ConditionalOperator *E) {
@@ -991,20 +1002,15 @@
   case UnaryOperator::Extension:
     // FIXME: Should extension allow i-c-e extension expressions in its scope?
     // If so, we could clear the diagnostic ID.
-    break;
+    return true;
   case UnaryOperator::Plus:
     // The result is always just the subexpr. 
-    break;
+    return true;
   case UnaryOperator::Minus:
-    Result = -Result;
-    break;
+    return Success(-Result, E);
   case UnaryOperator::Not:
-    Result = ~Result;
-    break;
+    return Success(~Result, E);
   }
-
-  Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
-  return true;
 }
   
 /// HandleCast - This is used to evaluate implicit or explicit casts where the
@@ -1025,8 +1031,8 @@
     if (!Visit(SubExpr))
       return false;
 
-    Result = HandleIntToIntCast(DestType, SubExpr->getType(), Result, Info.Ctx);
-    return true;
+    return Success(HandleIntToIntCast(DestType, SubExpr->getType(), 
+                                      Result, Info.Ctx), E);
   }
   
   // FIXME: Clean this up!
@@ -1048,8 +1054,8 @@
   if (!EvaluateFloat(SubExpr, F, Info))
     return Error(E->getExprLoc(), diag::note_invalid_subexpr_in_ice, E);
   
-  Result = HandleFloatToIntCast(DestType, SubExpr->getType(), F, Info.Ctx);
-  return true;
+  return Success(HandleFloatToIntCast(DestType, SubExpr->getType(), 
+                                      F, Info.Ctx), E);
 }
 
 //===----------------------------------------------------------------------===//
@@ -1194,7 +1200,7 @@
   
   if (SubExpr->getType()->isIntegralType()) {
     APSInt IntResult;
-    if (!EvaluateInteger(E, IntResult, Info))
+    if (!EvaluateInteger(SubExpr, IntResult, Info))
       return false;
     Result = HandleIntToFloatCast(E->getType(), SubExpr->getType(), 
                                   IntResult, Info.Ctx);





More information about the cfe-commits mailing list