Lex: Use the correct types for MS integer suffixes
authorDavid Majnemer <david.majnemer@gmail.com>
Sat, 21 Jun 2014 00:51:59 +0000 (00:51 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Sat, 21 Jun 2014 00:51:59 +0000 (00:51 +0000)
We didn't properly implement support for the sized integer suffixes.
Suffixes like i16 were essentially ignored instead of mapping them to
the appropriately sized integer type.

This fixes PR20008.

Differential Revision: http://reviews.llvm.org/D4132

llvm-svn: 211426

clang/include/clang/Lex/LiteralSupport.h
clang/lib/AST/StmtPrinter.cpp
clang/lib/Lex/LiteralSupport.cpp
clang/lib/Sema/SemaExpr.cpp
clang/test/SemaCXX/ms_integer_suffix.cpp [new file with mode: 0644]
clang/unittests/AST/StmtPrinterTest.cpp

index 2eb7751..acfd174 100644 (file)
@@ -63,7 +63,7 @@ public:
   bool isLongLong;
   bool isFloat;       // 1.0f
   bool isImaginary;   // 1.0i
-  bool isMicrosoftInteger;  // Microsoft suffix extension i8, i16, i32, or i64.
+  uint8_t MicrosoftInteger;  // Microsoft suffix extension i8, i16, i32, or i64.
 
   bool isIntegerLiteral() const {
     return !saw_period && !saw_exponent;
index 0f4fd55..5c92521 100644 (file)
@@ -947,8 +947,10 @@ void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) {
   // FIXME: The Short and UShort cases are to handle cases where a short
   // integeral literal is formed during template instantiation.  They should
   // be removed when template instantiation no longer needs integer literals.
-  case BuiltinType::Short:
-  case BuiltinType::UShort:
+  case BuiltinType::SChar:     OS << "i8"; break;
+  case BuiltinType::UChar:     OS << "Ui8"; break;
+  case BuiltinType::Short:     OS << "i16"; break;
+  case BuiltinType::UShort:    OS << "Ui16"; break;
   case BuiltinType::Int:       break; // no suffix.
   case BuiltinType::UInt:      OS << 'U'; break;
   case BuiltinType::Long:      OS << 'L'; break;
index 0103450..c55054b 100644 (file)
@@ -522,7 +522,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
   isLongLong = false;
   isFloat = false;
   isImaginary = false;
-  isMicrosoftInteger = false;
+  MicrosoftInteger = 0;
   hadError = false;
 
   if (*s == '0') { // parse radix
@@ -606,7 +606,8 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
     case 'i':
     case 'I':
       if (PP.getLangOpts().MicrosoftExt) {
-        if (isLong || isLongLong) break;
+        if (isLong || isLongLong || MicrosoftInteger)
+          break;
 
         // Allow i8, i16, i32, i64, and i128.
         if (s + 1 != ThisTokEnd) {
@@ -614,20 +615,20 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
             case '8':
               if (isFPConstant) break;
               s += 2; // i8 suffix
-              isMicrosoftInteger = true;
+              MicrosoftInteger = 8;
               break;
             case '1':
               if (isFPConstant) break;
               if (s + 2 == ThisTokEnd) break;
               if (s[2] == '6') {
                 s += 3; // i16 suffix
-                isMicrosoftInteger = true;
+                MicrosoftInteger = 16;
               }
               else if (s[2] == '2') {
                 if (s + 3 == ThisTokEnd) break;
                 if (s[3] == '8') {
                   s += 4; // i128 suffix
-                  isMicrosoftInteger = true;
+                  MicrosoftInteger = 128;
                 }
               }
               break;
@@ -636,8 +637,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
               if (s + 2 == ThisTokEnd) break;
               if (s[2] == '2') {
                 s += 3; // i32 suffix
-                isLong = true;
-                isMicrosoftInteger = true;
+                MicrosoftInteger = 32;
               }
               break;
             case '6':
@@ -645,14 +645,13 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
               if (s + 2 == ThisTokEnd) break;
               if (s[2] == '4') {
                 s += 3; // i64 suffix
-                isLongLong = true;
-                isMicrosoftInteger = true;
+                MicrosoftInteger = 64;
               }
               break;
             default:
               break;
           }
-          if (isMicrosoftInteger)
+          if (MicrosoftInteger)
             break;
         }
       }
@@ -682,7 +681,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
       isLongLong = false;
       isFloat = false;
       isImaginary = false;
-      isMicrosoftInteger = false;
+      MicrosoftInteger = 0;
 
       saw_ud_suffix = true;
       return;
index 2654c39..69cc8dc 100644 (file)
@@ -3190,7 +3190,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
     // may be wider than [u]intmax_t.
     // FIXME: Actually, they don't. We seem to have accidentally invented the
     //        i128 suffix.
-    if (Literal.isMicrosoftInteger && MaxWidth < 128 &&
+    if (Literal.MicrosoftInteger && MaxWidth < 128 &&
         Context.getTargetInfo().hasInt128Type())
       MaxWidth = 128;
     llvm::APInt ResultVal(MaxWidth, 0);
@@ -3211,7 +3211,18 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
 
       // Check from smallest to largest, picking the smallest type we can.
       unsigned Width = 0;
-      if (!Literal.isLong && !Literal.isLongLong) {
+
+      // Microsoft specific integer suffixes are explicitly sized.
+      if (Literal.MicrosoftInteger) {
+        Width = Literal.MicrosoftInteger;
+        if (Width < 128)
+          Ty = Context.getIntTypeForBitwidth(Width,
+                                             /*Signed=*/!Literal.isUnsigned);
+        else
+          Ty = Literal.isUnsigned ? Context.UnsignedInt128Ty : Context.Int128Ty;
+      }
+
+      if (Ty.isNull() && !Literal.isLong && !Literal.isLongLong) {
         // Are int/unsigned possibilities?
         unsigned IntSize = Context.getTargetInfo().getIntWidth();
 
@@ -3258,17 +3269,6 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
           Width = LongLongSize;
         }
       }
-        
-      // If it doesn't fit in unsigned long long, and we're using Microsoft
-      // extensions, then its a 128-bit integer literal.
-      if (Ty.isNull() && Literal.isMicrosoftInteger &&
-          Context.getTargetInfo().hasInt128Type()) {
-        if (Literal.isUnsigned)
-          Ty = Context.UnsignedInt128Ty;
-        else
-          Ty = Context.Int128Ty;
-        Width = 128;
-      }
 
       // 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.
diff --git a/clang/test/SemaCXX/ms_integer_suffix.cpp b/clang/test/SemaCXX/ms_integer_suffix.cpp
new file mode 100644 (file)
index 0000000..20cd5a6
--- /dev/null
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fms-compatibility -verify %s
+// expected-no-diagnostics
+
+static_assert(sizeof(0i8  ) == sizeof(__INT8_TYPE__ ), "");
+static_assert(sizeof(0i16 ) == sizeof(__INT16_TYPE__), "");
+static_assert(sizeof(0i32 ) == sizeof(__INT32_TYPE__), "");
+static_assert(sizeof(0i64 ) == sizeof(__INT64_TYPE__), "");
+static_assert(sizeof(0i128) >  sizeof(__INT64_TYPE__), "");
index c75cbde..541fb3d 100644 (file)
@@ -134,6 +134,8 @@ PrintedStmtCXX11Matches(StringRef Code, const StatementMatcher &NodeMatch,
                                               StringRef ContainingFunction,
                                               StringRef ExpectedPrinted) {
   std::vector<std::string> Args;
+  Args.push_back("-target");
+  Args.push_back("i686-pc-win32");
   Args.push_back("-std=c++98");
   Args.push_back("-fms-extensions");
   Args.push_back("-Wno-unused-value");
@@ -169,9 +171,9 @@ TEST(StmtPrinter, TestMSIntegerLiteral) {
     "  1i64, -1i64, 1ui64;"
     "}",
     "A",
+    "1i8 , -1i8 , 1Ui8 , "
+    "1i16 , -1i16 , 1Ui16 , "
     "1 , -1 , 1U , "
-    "1 , -1 , 1U , "
-    "1L , -1L , 1UL , "
     "1LL , -1LL , 1ULL"));
     // Should be: with semicolon
 }