Index: include/clang/Lex/LiteralSupport.h =================================================================== --- include/clang/Lex/LiteralSupport.h +++ include/clang/Lex/LiteralSupport.h @@ -63,7 +63,7 @@ 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: lib/AST/StmtPrinter.cpp =================================================================== --- lib/AST/StmtPrinter.cpp +++ lib/AST/StmtPrinter.cpp @@ -899,11 +899,10 @@ // Emit suffixes. Integer literals are always a builtin integer type. switch (Node->getType()->getAs()->getKind()) { default: llvm_unreachable("Unexpected type for integer literal!"); - // 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: lib/Lex/LiteralSupport.cpp =================================================================== --- lib/Lex/LiteralSupport.cpp +++ lib/Lex/LiteralSupport.cpp @@ -522,7 +522,7 @@ isLongLong = false; isFloat = false; isImaginary = false; - isMicrosoftInteger = false; + MicrosoftInteger = 0; hadError = false; if (*s == '0') { // parse radix @@ -606,7 +606,8 @@ 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 @@ 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 @@ 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 @@ 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 @@ isLongLong = false; isFloat = false; isImaginary = false; - isMicrosoftInteger = false; + MicrosoftInteger = 0; saw_ud_suffix = true; return; Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -3186,7 +3186,7 @@ // 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 == 128 && MaxWidth < 128 && Context.getTargetInfo().hasInt128Type()) MaxWidth = 128; llvm::APInt ResultVal(MaxWidth, 0); @@ -3207,7 +3207,22 @@ // 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) { + if (Literal.MicrosoftInteger > MaxWidth) { + // If this target doesn't support __int128, error and force to ull. + Diag(Tok.getLocation(), diag::err_int128_unsupported); + Width = MaxWidth; + Ty = Context.getIntMaxType(); + } else { + Width = Literal.MicrosoftInteger; + Ty = Context.getIntTypeForBitwidth(Width, + /*Signed=*/!Literal.isUnsigned); + } + } + + if (Ty.isNull() && !Literal.isLong && !Literal.isLongLong) { // Are int/unsigned possibilities? unsigned IntSize = Context.getTargetInfo().getIntWidth(); @@ -3254,17 +3269,6 @@ 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. Index: test/SemaCXX/ms_integer_suffix.cpp =================================================================== --- /dev/null +++ test/SemaCXX/ms_integer_suffix.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fms-extensions -verify %s +// expected-no-diagnostics + +#ifdef __SIZEOF_INT8__ +static_assert(sizeof(0i8) == __SIZEOF_INT8__, ""); +#endif +#ifdef __SIZEOF_INT16__ +static_assert(sizeof(0i16) == __SIZEOF_INT16__, ""); +#endif +#ifdef __SIZEOF_INT32__ +static_assert(sizeof(0i32) == __SIZEOF_INT32__, ""); +#endif +#ifdef __SIZEOF_INT64__ +static_assert(sizeof(0i64) == __SIZEOF_INT64__, ""); +#endif +#ifdef __SIZEOF_INT128__ +static_assert(sizeof(0i128) == __SIZEOF_INT128__, ""); +#endif Index: unittests/AST/StmtPrinterTest.cpp =================================================================== --- unittests/AST/StmtPrinterTest.cpp +++ unittests/AST/StmtPrinterTest.cpp @@ -134,6 +134,8 @@ StringRef ContainingFunction, StringRef ExpectedPrinted) { std::vector 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 @@ " 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 }