[cfe-commits] r39473 - in /cfe/cfe/trunk: AST/SemaExpr.cpp Lex/LiteralSupport.cpp Sema/SemaExpr.cpp clang.xcodeproj/project.pbxproj include/clang/AST/Expr.h include/clang/Lex/LiteralSupport.h

clattner at cs.uiuc.edu clattner at cs.uiuc.edu
Wed Jul 11 09:44:46 PDT 2007


Author: clattner
Date: Wed Jul 11 11:44:46 2007
New Revision: 39473

URL: http://llvm.org/viewvc/llvm-project?rev=39473&view=rev
Log:
Implement Sema::ParseNumericConstant for integer constants in terms of APInt
and correctly in terms of C99 6.4.4.1p5.

Modified:
    cfe/cfe/trunk/AST/SemaExpr.cpp
    cfe/cfe/trunk/Lex/LiteralSupport.cpp
    cfe/cfe/trunk/Sema/SemaExpr.cpp
    cfe/cfe/trunk/clang.xcodeproj/project.pbxproj
    cfe/cfe/trunk/include/clang/AST/Expr.h
    cfe/cfe/trunk/include/clang/Lex/LiteralSupport.h

Modified: cfe/cfe/trunk/AST/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/SemaExpr.cpp?rev=39473&r1=39472&r2=39473&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/AST/SemaExpr.cpp Wed Jul 11 11:44:46 2007
@@ -117,42 +117,98 @@
   // cannot have a trigraph, escaped newline, radix prefix, or type suffix.
   if (Tok.getLength() == 1) {
     const char *t = PP.getSourceManager().getCharacterData(Tok.getLocation());
-    return ExprResult(new IntegerLiteral(*t-'0', Context.IntTy, 
+    
+    unsigned IntSize = Context.Target.getIntWidth(Tok.getLocation());
+    return ExprResult(new IntegerLiteral(APInt(IntSize, *t-'0'), Context.IntTy, 
                                          Tok.getLocation()));
   }
   SmallString<512> IntegerBuffer;
   IntegerBuffer.resize(Tok.getLength());
   const char *ThisTokBegin = &IntegerBuffer[0];
   
-  // Get the spelling of the token, which eliminates trigraphs, etc.  Notes:
-  // - We know that ThisTokBuf points to a buffer that is big enough for the 
-  //   whole token and 'spelled' tokens can only shrink.
-  // - In practice, the local buffer is only used when the spelling doesn't
-  //   match the original token (which is rare). The common case simply returns
-  //   a pointer to a *constant* buffer (avoiding a copy). 
-  
+  // Get the spelling of the token, which eliminates trigraphs, etc.
   unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin);
   NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength, 
                                Tok.getLocation(), PP);
   if (Literal.hadError)
     return ExprResult(true);
-
+  
   if (Literal.isIntegerLiteral()) {
     QualType t;
-    if (Literal.hasSuffix()) {
-      if (Literal.isLong) 
-        t = Literal.isUnsigned ? Context.UnsignedLongTy : Context.LongTy;
-      else if (Literal.isLongLong) 
-        t = Literal.isUnsigned ? Context.UnsignedLongLongTy : Context.LongLongTy;
-      else 
-        t = Context.UnsignedIntTy;
+
+    // Get the value in the widest-possible width.
+    APInt ResultVal(Context.Target.getIntMaxTWidth(Tok.getLocation()), 0);
+   
+    if (Literal.GetIntegerValue(ResultVal)) {
+      // If this value didn't fit into uintmax_t, warn and force to ull.
+      Diag(Tok.getLocation(), diag::warn_integer_too_large);
+      t = Context.UnsignedLongLongTy;
+      assert(Context.getIntegerBitwidth(t, Tok.getLocation()) == 
+             ResultVal.getBitWidth() && "long long is not intmax_t?");
     } else {
-      t = Context.IntTy; // implicit type is "int"
+      // If this value fits into a ULL, try to figure out what else it fits into
+      // according to the rules of C99 6.4.4.1p5.
+      
+      // Octal, Hexadecimal, and integers with a U suffix are allowed to
+      // be an unsigned int.
+      bool AllowUnsigned = Literal.isUnsigned || Literal.getRadix() != 10;
+
+      // Check from smallest to largest, picking the smallest type we can.
+      if (!Literal.isLong) {  // Are int/unsigned possibilities?
+        unsigned IntSize = Context.Target.getIntWidth(Tok.getLocation());
+        // Does it fit in a unsigned int?
+        if (ResultVal.isIntN(IntSize)) {
+          // Does it fit in a signed int?
+          if (!Literal.isUnsigned && ResultVal[IntSize-1] == 0)
+            t = Context.IntTy;
+          else if (AllowUnsigned)
+            t = Context.UnsignedIntTy;
+        }
+        
+        if (!t.isNull())
+          ResultVal.trunc(IntSize);
+      }
+      
+      // Are long/unsigned long possibilities?
+      if (t.isNull() && !Literal.isLongLong) {
+        unsigned LongSize = Context.Target.getLongWidth(Tok.getLocation());
+     
+        // Does it fit in a unsigned long?
+        if (ResultVal.isIntN(LongSize)) {
+          // Does it fit in a signed long?
+          if (!Literal.isUnsigned && ResultVal[LongSize-1] == 0)
+            t = Context.LongTy;
+          else if (AllowUnsigned)
+            t = Context.UnsignedLongTy;
+        }
+        if (!t.isNull())
+          ResultVal.trunc(LongSize);
+      }      
+      
+      // Finally, check long long if needed.
+      if (t.isNull()) {
+        unsigned LongLongSize =
+          Context.Target.getLongLongWidth(Tok.getLocation());
+        
+        // Does it fit in a unsigned long long?
+        if (ResultVal.isIntN(LongLongSize)) {
+          // Does it fit in a signed long long?
+          if (!Literal.isUnsigned && ResultVal[LongLongSize-1] == 0)
+            t = Context.LongLongTy;
+          else if (AllowUnsigned)
+            t = Context.UnsignedLongLongTy;
+        }
+      }
+      
+      // If we still couldn't decide a type, we probably have something that
+      // does not fit in a signed long long, but has no U suffix.
+      if (t.isNull()) {
+        Diag(Tok.getLocation(), diag::warn_integer_too_large_for_signed);
+        t = Context.UnsignedLongLongTy;
+      }
     }
-    uintmax_t val;
-    if (Literal.GetIntegerValue(val)) {
-      return new IntegerLiteral(val, t, Tok.getLocation());
-    } 
+
+    return new IntegerLiteral(ResultVal, t, Tok.getLocation());
   } else if (Literal.isFloatingLiteral()) {
     // FIXME: fill in the value and compute the real type...
     return new FloatingLiteral(7.7, Context.FloatTy, Tok.getLocation());

Modified: cfe/cfe/trunk/Lex/LiteralSupport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Lex/LiteralSupport.cpp?rev=39473&r1=39472&r2=39473&view=diff

==============================================================================
--- cfe/cfe/trunk/Lex/LiteralSupport.cpp (original)
+++ cfe/cfe/trunk/Lex/LiteralSupport.cpp Wed Jul 11 11:44:46 2007
@@ -351,44 +351,6 @@
   }
 }
 
-bool NumericLiteralParser::GetIntegerValue(uintmax_t &val) {
-  uintmax_t max_value = UINTMAX_MAX / radix;
-  unsigned max_digit = UINTMAX_MAX % radix;
-  
-  val = 0;
-  s = DigitsBegin;
-  while (s < SuffixBegin) {
-    unsigned C = HexDigitValue(*s++);
-    
-    if (val > max_value || (val == max_value && C > max_digit)) {
-      return false; // Overflow!
-    } else {
-      val *= radix;
-      val += C;
-    }
-  }
-  return true;
-}
-
-bool NumericLiteralParser::GetIntegerValue(int &val) {
-  intmax_t max_value = INT_MAX / radix;
-  unsigned max_digit = INT_MAX % radix;
-  
-  val = 0;
-  s = DigitsBegin;
-  while (s < SuffixBegin) {
-    unsigned C = HexDigitValue(*s++);
-    
-    if (val > max_value || (val == max_value && C > max_digit)) {
-      return false; // Overflow!
-    } else {
-      val *= radix;
-      val += C;
-    }
-  }
-  return true;
-}
-
 /// GetIntegerValue - Convert this numeric literal value to an APInt that
 /// matches Val's input width.  If there is an overflow, set Val to the low bits
 /// of the result and return true.  Otherwise, return false.

Modified: cfe/cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaExpr.cpp?rev=39473&r1=39472&r2=39473&view=diff

==============================================================================
--- cfe/cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaExpr.cpp Wed Jul 11 11:44:46 2007
@@ -117,42 +117,98 @@
   // cannot have a trigraph, escaped newline, radix prefix, or type suffix.
   if (Tok.getLength() == 1) {
     const char *t = PP.getSourceManager().getCharacterData(Tok.getLocation());
-    return ExprResult(new IntegerLiteral(*t-'0', Context.IntTy, 
+    
+    unsigned IntSize = Context.Target.getIntWidth(Tok.getLocation());
+    return ExprResult(new IntegerLiteral(APInt(IntSize, *t-'0'), Context.IntTy, 
                                          Tok.getLocation()));
   }
   SmallString<512> IntegerBuffer;
   IntegerBuffer.resize(Tok.getLength());
   const char *ThisTokBegin = &IntegerBuffer[0];
   
-  // Get the spelling of the token, which eliminates trigraphs, etc.  Notes:
-  // - We know that ThisTokBuf points to a buffer that is big enough for the 
-  //   whole token and 'spelled' tokens can only shrink.
-  // - In practice, the local buffer is only used when the spelling doesn't
-  //   match the original token (which is rare). The common case simply returns
-  //   a pointer to a *constant* buffer (avoiding a copy). 
-  
+  // Get the spelling of the token, which eliminates trigraphs, etc.
   unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin);
   NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength, 
                                Tok.getLocation(), PP);
   if (Literal.hadError)
     return ExprResult(true);
-
+  
   if (Literal.isIntegerLiteral()) {
     QualType t;
-    if (Literal.hasSuffix()) {
-      if (Literal.isLong) 
-        t = Literal.isUnsigned ? Context.UnsignedLongTy : Context.LongTy;
-      else if (Literal.isLongLong) 
-        t = Literal.isUnsigned ? Context.UnsignedLongLongTy : Context.LongLongTy;
-      else 
-        t = Context.UnsignedIntTy;
+
+    // Get the value in the widest-possible width.
+    APInt ResultVal(Context.Target.getIntMaxTWidth(Tok.getLocation()), 0);
+   
+    if (Literal.GetIntegerValue(ResultVal)) {
+      // If this value didn't fit into uintmax_t, warn and force to ull.
+      Diag(Tok.getLocation(), diag::warn_integer_too_large);
+      t = Context.UnsignedLongLongTy;
+      assert(Context.getIntegerBitwidth(t, Tok.getLocation()) == 
+             ResultVal.getBitWidth() && "long long is not intmax_t?");
     } else {
-      t = Context.IntTy; // implicit type is "int"
+      // If this value fits into a ULL, try to figure out what else it fits into
+      // according to the rules of C99 6.4.4.1p5.
+      
+      // Octal, Hexadecimal, and integers with a U suffix are allowed to
+      // be an unsigned int.
+      bool AllowUnsigned = Literal.isUnsigned || Literal.getRadix() != 10;
+
+      // Check from smallest to largest, picking the smallest type we can.
+      if (!Literal.isLong) {  // Are int/unsigned possibilities?
+        unsigned IntSize = Context.Target.getIntWidth(Tok.getLocation());
+        // Does it fit in a unsigned int?
+        if (ResultVal.isIntN(IntSize)) {
+          // Does it fit in a signed int?
+          if (!Literal.isUnsigned && ResultVal[IntSize-1] == 0)
+            t = Context.IntTy;
+          else if (AllowUnsigned)
+            t = Context.UnsignedIntTy;
+        }
+        
+        if (!t.isNull())
+          ResultVal.trunc(IntSize);
+      }
+      
+      // Are long/unsigned long possibilities?
+      if (t.isNull() && !Literal.isLongLong) {
+        unsigned LongSize = Context.Target.getLongWidth(Tok.getLocation());
+     
+        // Does it fit in a unsigned long?
+        if (ResultVal.isIntN(LongSize)) {
+          // Does it fit in a signed long?
+          if (!Literal.isUnsigned && ResultVal[LongSize-1] == 0)
+            t = Context.LongTy;
+          else if (AllowUnsigned)
+            t = Context.UnsignedLongTy;
+        }
+        if (!t.isNull())
+          ResultVal.trunc(LongSize);
+      }      
+      
+      // Finally, check long long if needed.
+      if (t.isNull()) {
+        unsigned LongLongSize =
+          Context.Target.getLongLongWidth(Tok.getLocation());
+        
+        // Does it fit in a unsigned long long?
+        if (ResultVal.isIntN(LongLongSize)) {
+          // Does it fit in a signed long long?
+          if (!Literal.isUnsigned && ResultVal[LongLongSize-1] == 0)
+            t = Context.LongLongTy;
+          else if (AllowUnsigned)
+            t = Context.UnsignedLongLongTy;
+        }
+      }
+      
+      // If we still couldn't decide a type, we probably have something that
+      // does not fit in a signed long long, but has no U suffix.
+      if (t.isNull()) {
+        Diag(Tok.getLocation(), diag::warn_integer_too_large_for_signed);
+        t = Context.UnsignedLongLongTy;
+      }
     }
-    uintmax_t val;
-    if (Literal.GetIntegerValue(val)) {
-      return new IntegerLiteral(val, t, Tok.getLocation());
-    } 
+
+    return new IntegerLiteral(ResultVal, t, Tok.getLocation());
   } else if (Literal.isFloatingLiteral()) {
     // FIXME: fill in the value and compute the real type...
     return new FloatingLiteral(7.7, Context.FloatTy, Tok.getLocation());

Modified: cfe/cfe/trunk/clang.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/clang.xcodeproj/project.pbxproj?rev=39473&r1=39472&r2=39473&view=diff

==============================================================================
--- cfe/cfe/trunk/clang.xcodeproj/project.pbxproj (original)
+++ cfe/cfe/trunk/clang.xcodeproj/project.pbxproj Wed Jul 11 11:44:46 2007
@@ -94,23 +94,6 @@
 		DED7D9E50A5257F6003AD0FB /* ScratchBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED7D9E40A5257F6003AD0FB /* ScratchBuffer.cpp */; };
 /* End PBXBuildFile section */
 
-/* Begin PBXBuildStyle section */
-		84DE4C220BFFB2D9009E9268 /* Development */ = {
-			isa = PBXBuildStyle;
-			buildSettings = {
-				COPY_PHASE_STRIP = NO;
-			};
-			name = Development;
-		};
-		84DE4C230BFFB2D9009E9268 /* Deployment */ = {
-			isa = PBXBuildStyle;
-			buildSettings = {
-				COPY_PHASE_STRIP = YES;
-			};
-			name = Deployment;
-		};
-/* End PBXBuildStyle section */
-
 /* Begin PBXCopyFilesBuildPhase section */
 		8DD76F690486A84900D96B5E /* CopyFiles */ = {
 			isa = PBXCopyFilesBuildPhase;
@@ -493,12 +476,6 @@
 		08FB7793FE84155DC02AAC07 /* Project object */ = {
 			isa = PBXProject;
 			buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
-			buildSettings = {
-			};
-			buildStyles = (
-				84DE4C220BFFB2D9009E9268 /* Development */,
-				84DE4C230BFFB2D9009E9268 /* Deployment */,
-			);
 			hasScannedForEncodings = 1;
 			mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
 			projectDirPath = "";

Modified: cfe/cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/AST/Expr.h?rev=39473&r1=39472&r2=39473&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Expr.h Wed Jul 11 11:44:46 2007
@@ -17,6 +17,7 @@
 #include "clang/AST/Stmt.h"
 #include "clang/AST/Type.h"
 #include "clang/AST/Decl.h"
+#include "llvm/ADT/APInt.h"
 
 namespace llvm {
 namespace clang {
@@ -102,16 +103,16 @@
 };
 
 class IntegerLiteral : public Expr {
-  intmax_t Value;
+  APInt Value;
   SourceLocation Loc;
 public:
   // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy, 
   // or UnsignedLongLongTy
-  IntegerLiteral(intmax_t value, QualType type, SourceLocation l)
-    : Expr(IntegerLiteralClass, type), Value(value), Loc(l) {
+  IntegerLiteral(const APInt &V, QualType type, SourceLocation l)
+    : Expr(IntegerLiteralClass, type), Value(V), Loc(l) {
     assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
   }
-  intmax_t getValue() const { return Value; }
+  const APInt &getValue() const { return Value; }
   virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
 
   virtual void visit(StmtVisitor &Visitor);

Modified: cfe/cfe/trunk/include/clang/Lex/LiteralSupport.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Lex/LiteralSupport.h?rev=39473&r1=39472&r2=39473&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Lex/LiteralSupport.h (original)
+++ cfe/cfe/trunk/include/clang/Lex/LiteralSupport.h Wed Jul 11 11:44:46 2007
@@ -39,7 +39,7 @@
   const char *DigitsBegin, *SuffixBegin; // markers
   const char *s; // cursor
   
-  unsigned int radix;
+  unsigned radix;
   
   bool saw_exponent, saw_period;
   bool saw_float_suffix;
@@ -49,7 +49,7 @@
                        SourceLocation Loc, Preprocessor &PP);
   bool hadError;
   bool isUnsigned;
-  bool isLong;
+  bool isLong;       // This is also set for long long.
   bool isLongLong;
   
   bool isIntegerLiteral() const { 
@@ -61,19 +61,12 @@
   bool hasSuffix() const {
     return SuffixBegin != ThisTokEnd;
   }
-  /// getIntegerValue - Convert the string into a number. At this point, we 
-  /// know the digit characters are valid (0...9, a...f, A...F). We don't know
-  /// how many bits are needed to store the number. Sizing of the integer
-  /// type (int, unsigned, long, unsigned long, long long, unsigned long long) 
-  /// will be done elsewhere - the size computation is target dependent. We  
-  /// return true if the value fit into "val", false otherwise. 
-  /// NOTE: The api of these returns an inverted value for 'overflow' than the
-  /// version below does.
-  bool GetIntegerValue(uintmax_t &val);
-  bool GetIntegerValue(int &val);
+  
+  unsigned getRadix() const { return radix; }
   
   /// GetIntegerValue - Convert this numeric literal value to an APInt that
-  /// matches Val's input width.  If there is an overflow, set Val to the low
+  /// matches Val's input width.  If there is an overflow (i.e., if the unsigned
+  /// value read is larger than the APInt's bits will hold), set Val to the low
   /// bits of the result and return true.  Otherwise, return false.
   bool GetIntegerValue(APInt &Val);
 





More information about the cfe-commits mailing list