Lex: Use the correct types for MS integer suffixes

Something went wrong with r211426, it is an older version of this code
and should not have been committed.  It was reverted with r211434.

Original commit message:
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: 211441
This commit is contained in:
David Majnemer 2014-06-21 18:46:07 +00:00
parent 30d7731032
commit 65a407c2ce
6 changed files with 54 additions and 32 deletions

View 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;

View File

@ -944,11 +944,10 @@ void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) {
// Emit suffixes. Integer literals are always a builtin integer type.
switch (Node->getType()->getAs<BuiltinType>()->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;

View 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;

View 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 == 128 && MaxWidth < 128 &&
Context.getTargetInfo().hasInt128Type())
MaxWidth = 128;
llvm::APInt ResultVal(MaxWidth, 0);
@ -3211,7 +3211,22 @@ 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) {
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();
@ -3258,17 +3273,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.

View File

@ -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

View 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
}