From 252cbe25cb7e02df422cc9f4ac0fdf235c6b2cd8 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Sat, 21 Jun 2014 00:51:59 +0000 Subject: [PATCH] Lex: Use the correct types for MS integer suffixes 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 | 2 +- clang/lib/AST/StmtPrinter.cpp | 6 ++++-- clang/lib/Lex/LiteralSupport.cpp | 21 ++++++++++----------- clang/lib/Sema/SemaExpr.cpp | 26 +++++++++++++------------- clang/test/SemaCXX/ms_integer_suffix.cpp | 8 ++++++++ clang/unittests/AST/StmtPrinterTest.cpp | 6 ++++-- 6 files changed, 40 insertions(+), 29 deletions(-) create mode 100644 clang/test/SemaCXX/ms_integer_suffix.cpp diff --git a/clang/include/clang/Lex/LiteralSupport.h b/clang/include/clang/Lex/LiteralSupport.h index 2eb7751f..acfd174 100644 --- a/clang/include/clang/Lex/LiteralSupport.h +++ b/clang/include/clang/Lex/LiteralSupport.h @@ -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; diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 0f4fd55..5c92521 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -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; diff --git a/clang/lib/Lex/LiteralSupport.cpp b/clang/lib/Lex/LiteralSupport.cpp index 0103450..c55054b 100644 --- a/clang/lib/Lex/LiteralSupport.cpp +++ b/clang/lib/Lex/LiteralSupport.cpp @@ -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; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 2654c39..69cc8dc 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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 index 0000000..20cd5a6 --- /dev/null +++ b/clang/test/SemaCXX/ms_integer_suffix.cpp @@ -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__), ""); diff --git a/clang/unittests/AST/StmtPrinterTest.cpp b/clang/unittests/AST/StmtPrinterTest.cpp index c75cbde..541fb3d 100644 --- a/clang/unittests/AST/StmtPrinterTest.cpp +++ b/clang/unittests/AST/StmtPrinterTest.cpp @@ -134,6 +134,8 @@ PrintedStmtCXX11Matches(StringRef Code, const StatementMatcher &NodeMatch, 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 @@ 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 } -- 2.7.4