The code for range-based for-loops makes a bad integer literal expression
which has a mis-match between the size of the literal and the integer type.
 This causes an assert to be thrown when IsIntegerConstant() is called on
it.
For this patch,

1) the assert that checks bit width is copied from IsIntegerConstant() into
the integer literal constructor.
2) a new static function was written so that it automatically selects the
correct size integer and returns a proper integer literal
3) the range-based for-loops now use the function in #2 to get the right
integer literal
Index: include/clang/AST/Expr.h
===================================================================
--- include/clang/AST/Expr.h	(revision 129825)
+++ include/clang/AST/Expr.h	(working copy)
@@ -977,13 +977,22 @@
            false),
       Loc(l) {
     assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
+    assert(V.getBitWidth() == C.getIntWidth(type) &&
+           "Integer type is not the correct size for constant.");
     setValue(C, V);
   }
 
-  // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
-  // or UnsignedLongLongTy
+  /// \brief Returns a new integer literal with value 'V' and type 'type'.
+  /// \param type - either IntTy, LongTy, LongLongTy, UnsignedIntTy,
+  /// UnsignedLongTy, or UnsignedLongLongTy which should match the size of V
+  /// \param V - the value that the returned integer literal contains.
   static IntegerLiteral *Create(ASTContext &C, const llvm::APInt &V,
                                 QualType type, SourceLocation l);
+  /// \brief Returns a new integer literal with value 'V' and proper type.
+  /// \param V - the value that the returned integer literal contains
+  static IntegerLiteral *Create(ASTContext &C, const llvm::APInt &V,
+                                SourceLocation l);
+  /// \brief Returns a new empty interger literal.
   static IntegerLiteral *Create(ASTContext &C, EmptyShell Empty);
 
   llvm::APInt getValue() const { return Num.getValue(); }
Index: lib/Sema/SemaStmt.cpp
===================================================================
--- lib/Sema/SemaStmt.cpp	(revision 129825)
+++ lib/Sema/SemaStmt.cpp	(working copy)
@@ -1257,7 +1257,7 @@
       ExprResult BoundExpr;
       if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(UnqAT))
         BoundExpr = Owned(IntegerLiteral::Create(Context, CAT->getSize(),
-                                                 Context.IntTy, RangeLoc));
+                                                 RangeLoc));
       else if (const VariableArrayType *VAT =
                dyn_cast<VariableArrayType>(UnqAT))
         BoundExpr = VAT->getSizeExpr();
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp	(revision 129825)
+++ lib/AST/Expr.cpp	(working copy)
@@ -481,6 +481,45 @@
 }
 
 IntegerLiteral *
+IntegerLiteral::Create(ASTContext &C, const llvm::APInt &V, SourceLocation l) {
+  // Pick the correct integer type for an integer literal.
+  // Possible types are:
+  // IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
+  // or UnsignedLongLongTy
+  bool NonNeg = V.isNonNegative();
+  unsigned UnsignedBitWidth = V.getActiveBits();
+  unsigned SignedBitWidth = V.getMinSignedBits();
+
+  unsigned TypeWidth = C.getIntWidth(C.IntTy);
+  if (SignedBitWidth <= TypeWidth)
+    return new (C) IntegerLiteral(C, V.trunc(TypeWidth), C.IntTy, l);
+
+  TypeWidth = C.getIntWidth(C.UnsignedIntTy);
+  if (NonNeg && UnsignedBitWidth <= TypeWidth)
+    return new (C) IntegerLiteral(C, V.trunc(TypeWidth), C.UnsignedIntTy, l);
+
+  TypeWidth = C.getIntWidth(C.LongTy);
+  if (SignedBitWidth <= TypeWidth)
+    return new (C) IntegerLiteral(C, V.trunc(TypeWidth), C.LongTy, l);
+
+  TypeWidth = C.getIntWidth(C.UnsignedLongTy);
+  if (NonNeg && UnsignedBitWidth <= TypeWidth)
+    return new (C) IntegerLiteral(C, V.trunc(TypeWidth), C.UnsignedLongTy, l);
+
+  TypeWidth = C.getIntWidth(C.LongLongTy);
+  if (SignedBitWidth <= TypeWidth)
+    return new (C) IntegerLiteral(C, V.trunc(TypeWidth), C.LongLongTy, l);
+
+  TypeWidth = C.getIntWidth(C.UnsignedLongLongTy);
+  if (NonNeg && UnsignedBitWidth <= TypeWidth)
+    return new (C) IntegerLiteral(C, V.trunc(TypeWidth), C.UnsignedLongLongTy, 
+                                  l);
+
+  // FIXME: Add support for 128-bit types.
+  assert(0 && "No integer type large enough to hold interger literal");
+}
+
+IntegerLiteral *
 IntegerLiteral::Create(ASTContext &C, EmptyShell Empty) {
   return new (C) IntegerLiteral(Empty);
 }
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to