diff options
Diffstat (limited to 'lib/Lex/LiteralSupport.cpp')
-rw-r--r-- | lib/Lex/LiteralSupport.cpp | 157 |
1 files changed, 85 insertions, 72 deletions
diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp index 5b1c49344e8d..e68b82fb499a 100644 --- a/lib/Lex/LiteralSupport.cpp +++ b/lib/Lex/LiteralSupport.cpp @@ -522,8 +522,10 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, isLong = false; isUnsigned = false; isLongLong = false; + isHalf = false; isFloat = false; isImaginary = false; + isFloat128 = false; MicrosoftInteger = 0; hadError = false; @@ -536,34 +538,10 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, s = SkipDigits(s); if (s == ThisTokEnd) { // Done. - } else if (isHexDigit(*s) && !(*s == 'e' || *s == 'E')) { - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin), - diag::err_invalid_digit) << StringRef(s, 1) << 0; - hadError = true; - return; - } else if (*s == '.') { - checkSeparator(TokLoc, s, CSK_AfterDigits); - s++; - saw_period = true; - checkSeparator(TokLoc, s, CSK_BeforeDigits); - s = SkipDigits(s); - } - if ((*s == 'e' || *s == 'E')) { // exponent - checkSeparator(TokLoc, s, CSK_AfterDigits); - const char *Exponent = s; - s++; - saw_exponent = true; - if (*s == '+' || *s == '-') s++; // sign - checkSeparator(TokLoc, s, CSK_BeforeDigits); - const char *first_non_digit = SkipDigits(s); - if (first_non_digit != s) { - s = first_non_digit; - } else { - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent - ThisTokBegin), - diag::err_exponent_has_no_digits); - hadError = true; + } else { + ParseDecimalOrOctalCommon(TokLoc); + if (hadError) return; - } } } @@ -579,12 +557,28 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, // we break out of the loop. for (; s != ThisTokEnd; ++s) { switch (*s) { + case 'h': // FP Suffix for "half". + case 'H': + // OpenCL Extension v1.2 s9.5 - h or H suffix for half type. + if (!PP.getLangOpts().Half) break; + if (!isFPConstant) break; // Error for integer constant. + if (isHalf || isFloat || isLong) break; // HH, FH, LH invalid. + isHalf = true; + continue; // Success. case 'f': // FP Suffix for "float" case 'F': if (!isFPConstant) break; // Error for integer constant. - if (isFloat || isLong) break; // FF, LF invalid. + if (isHalf || isFloat || isLong || isFloat128) + break; // HF, FF, LF, QF invalid. isFloat = true; continue; // Success. + case 'q': // FP Suffix for "__float128" + case 'Q': + if (!isFPConstant) break; // Error for integer constant. + if (isHalf || isFloat || isLong || isFloat128) + break; // HQ, FQ, LQ, QQ invalid. + isFloat128 = true; + continue; // Success. case 'u': case 'U': if (isFPConstant) break; // Error for floating constant. @@ -594,7 +588,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, case 'l': case 'L': if (isLong || isLongLong) break; // Cannot be repeated. - if (isFloat) break; // LF invalid. + if (isHalf || isFloat || isFloat128) break; // LH, LF, LQ invalid. // Check for long long. The L's need to be adjacent and the same case. if (s[1] == s[0]) { @@ -671,6 +665,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, isUnsigned = false; isLongLong = false; isFloat = false; + isHalf = false; isImaginary = false; MicrosoftInteger = 0; @@ -693,6 +688,49 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, } } +/// ParseDecimalOrOctalCommon - This method is called for decimal or octal +/// numbers. It issues an error for illegal digits, and handles floating point +/// parsing. If it detects a floating point number, the radix is set to 10. +void NumericLiteralParser::ParseDecimalOrOctalCommon(SourceLocation TokLoc){ + assert((radix == 8 || radix == 10) && "Unexpected radix"); + + // If we have a hex digit other than 'e' (which denotes a FP exponent) then + // the code is using an incorrect base. + if (isHexDigit(*s) && *s != 'e' && *s != 'E') { + PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin), + diag::err_invalid_digit) << StringRef(s, 1) << (radix == 8 ? 1 : 0); + hadError = true; + return; + } + + if (*s == '.') { + checkSeparator(TokLoc, s, CSK_AfterDigits); + s++; + radix = 10; + saw_period = true; + checkSeparator(TokLoc, s, CSK_BeforeDigits); + s = SkipDigits(s); // Skip suffix. + } + if (*s == 'e' || *s == 'E') { // exponent + checkSeparator(TokLoc, s, CSK_AfterDigits); + const char *Exponent = s; + s++; + radix = 10; + saw_exponent = true; + if (*s == '+' || *s == '-') s++; // sign + const char *first_non_digit = SkipDigits(s); + if (containsDigits(s, first_non_digit)) { + checkSeparator(TokLoc, s, CSK_BeforeDigits); + s = first_non_digit; + } else { + PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin), + diag::err_exponent_has_no_digits); + hadError = true; + return; + } + } +} + /// Determine whether a suffix is a valid ud-suffix. We avoid treating reserved /// suffixes as ud-suffixes, because the diagnostic experience is better if we /// treat it as an invalid suffix. @@ -752,21 +790,24 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { radix = 16; DigitsBegin = s; s = SkipHexDigits(s); - bool noSignificand = (s == DigitsBegin); + bool HasSignificandDigits = containsDigits(DigitsBegin, s); if (s == ThisTokEnd) { // Done. } else if (*s == '.') { s++; saw_period = true; const char *floatDigitsBegin = s; - checkSeparator(TokLoc, s, CSK_BeforeDigits); s = SkipHexDigits(s); - noSignificand &= (floatDigitsBegin == s); + if (containsDigits(floatDigitsBegin, s)) + HasSignificandDigits = true; + if (HasSignificandDigits) + checkSeparator(TokLoc, floatDigitsBegin, CSK_BeforeDigits); } - if (noSignificand) { + if (!HasSignificandDigits) { PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin), - diag::err_hexconstant_requires) << 1; + diag::err_hex_constant_requires) + << PP.getLangOpts().CPlusPlus << 1; hadError = true; return; } @@ -780,7 +821,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { saw_exponent = true; if (*s == '+' || *s == '-') s++; // sign const char *first_non_digit = SkipDigits(s); - if (first_non_digit == s) { + if (!containsDigits(s, first_non_digit)) { PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin), diag::err_exponent_has_no_digits); hadError = true; @@ -790,10 +831,15 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { s = first_non_digit; if (!PP.getLangOpts().HexFloats) - PP.Diag(TokLoc, diag::ext_hexconstant_invalid); + PP.Diag(TokLoc, PP.getLangOpts().CPlusPlus + ? diag::ext_hex_literal_invalid + : diag::ext_hex_constant_invalid); + else if (PP.getLangOpts().CPlusPlus1z) + PP.Diag(TokLoc, diag::warn_cxx1z_hex_literal); } else if (saw_period) { - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin), - diag::err_hexconstant_requires) << 0; + PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin), + diag::err_hex_constant_requires) + << PP.getLangOpts().CPlusPlus << 0; hadError = true; } return; @@ -843,40 +889,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { } } - // If we have a hex digit other than 'e' (which denotes a FP exponent) then - // the code is using an incorrect base. - if (isHexDigit(*s) && *s != 'e' && *s != 'E') { - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin), - diag::err_invalid_digit) << StringRef(s, 1) << 1; - hadError = true; - return; - } - - if (*s == '.') { - s++; - radix = 10; - saw_period = true; - checkSeparator(TokLoc, s, CSK_BeforeDigits); - s = SkipDigits(s); // Skip suffix. - } - if (*s == 'e' || *s == 'E') { // exponent - checkSeparator(TokLoc, s, CSK_AfterDigits); - const char *Exponent = s; - s++; - radix = 10; - saw_exponent = true; - if (*s == '+' || *s == '-') s++; // sign - const char *first_non_digit = SkipDigits(s); - if (first_non_digit != s) { - checkSeparator(TokLoc, s, CSK_BeforeDigits); - s = first_non_digit; - } else { - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin), - diag::err_exponent_has_no_digits); - hadError = true; - return; - } - } + ParseDecimalOrOctalCommon(TokLoc); } static bool alwaysFitsInto64Bits(unsigned Radix, unsigned NumDigits) { |