From: Chris Lattner Date: Sun, 26 Aug 2007 01:58:14 +0000 (+0000) Subject: 1) refactor some code. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=506b8dec4ed3db3c60bf9e0dd37901f0cf3d6749;p=clang 1) refactor some code. 2) Add support for lexing imaginary constants (a GCC extension): t.c:5:10: warning: imaginary constants are an extension A = 1.0iF; ^ 3) Make the 'invalid suffix' diagnostic pointer more accurate: t.c:6:10: error: invalid suffix 'qF' on floating constant A = 1.0qF; ^ instead of: t.c:6:10: error: invalid suffix 'qF' on floating constant A = 1.0qF; ^ git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41411 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Lex/LiteralSupport.cpp b/Lex/LiteralSupport.cpp index 76a70ab7aa..82765522d7 100644 --- a/Lex/LiteralSupport.cpp +++ b/Lex/LiteralSupport.cpp @@ -206,6 +206,7 @@ NumericLiteralParser(const char *begin, const char *end, isLong = false; isUnsigned = false; isLongLong = false; + isImaginary = false; hadError = false; if (*s == '0') { // parse radix @@ -313,65 +314,62 @@ NumericLiteralParser(const char *begin, const char *end, } SuffixBegin = s; - - if (saw_period || saw_exponent) { - if (s < ThisTokEnd) { // parse size suffix (float, long double) - if (*s == 'f' || *s == 'F') { - saw_float_suffix = true; - s++; - } else if (*s == 'l' || *s == 'L') { + + // Parse the suffix. At this point we can classify whether we have an FP or + // integer constant. + bool isFPConstant = isFloatingLiteral(); + + // Loop over all of the characters of the suffix. If we see something bad, + // we break out of the loop. + for (; s != ThisTokEnd; ++s) { + switch (*s) { + case 'f': // FP Suffix for "float" + case 'F': + if (!isFPConstant) break; // Error for integer constant. + if (saw_float_suffix || isLong) break; // FF, LF invalid. + saw_float_suffix = true; + continue; // Success. + case 'u': + case 'U': + if (isFPConstant) break; // Error for floating constant. + if (isUnsigned) break; // Cannot be repeated. + isUnsigned = true; + continue; // Success. + case 'l': + case 'L': + if (isLong || isLongLong) break; // Cannot be repeated. + if (saw_float_suffix) break; // LF invalid. + + // Check for long long. The L's need to be adjacent and the same case. + if (s+1 != ThisTokEnd && s[1] == s[0]) { + if (isFPConstant) break; // long long invalid for floats. + isLongLong = true; + ++s; // Eat both of them. + } else { isLong = true; - s++; - } - if (s != ThisTokEnd) { - Diag(TokLoc, diag::err_invalid_suffix_float_constant, - std::string(SuffixBegin, ThisTokEnd)); - return; - } - } - } else { - if (s < ThisTokEnd) { - // parse int suffix - they can appear in any order ("ul", "lu", "llu"). - if (*s == 'u' || *s == 'U') { - s++; - isUnsigned = true; // unsigned - - if ((s < ThisTokEnd) && (*s == 'l' || *s == 'L')) { - s++; - // handle "long long" type - l's need to be adjacent and same case. - if ((s < ThisTokEnd) && (*s == *(s-1))) { - isLongLong = true; // unsigned long long - s++; - } else { - isLong = true; // unsigned long - } - } - } else if (*s == 'l' || *s == 'L') { - s++; - // handle "long long" types - l's need to be adjacent and same case. - if ((s < ThisTokEnd) && (*s == *(s-1))) { - s++; - if ((s < ThisTokEnd) && (*s == 'u' || *s == 'U')) { - isUnsigned = true; // unsigned long long - s++; - } else { - isLongLong = true; // long long - } - } else { // handle "long" types - if ((s < ThisTokEnd) && (*s == 'u' || *s == 'U')) { - isUnsigned = true; // unsigned long - s++; - } else { - isLong = true; // long - } - } - } - if (s != ThisTokEnd) { - Diag(TokLoc, diag::err_invalid_suffix_integer_constant, - std::string(SuffixBegin, ThisTokEnd)); - return; } + continue; // Success. + case 'i': + case 'I': + case 'j': + case 'J': + if (isImaginary) break; // Cannot be repeated. + PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-begin), + diag::ext_imaginary_constant); + isImaginary = true; + continue; // Success. } + // If we reached here, there was an error. + break; + } + + // Report an error if there are any. + if (s != ThisTokEnd) { + TokLoc = PP.AdvanceToTokenCharacter(TokLoc, s-begin); + Diag(TokLoc, isFPConstant ? diag::err_invalid_suffix_float_constant : + diag::err_invalid_suffix_integer_constant, + std::string(SuffixBegin, ThisTokEnd)); + return; } } diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index 00bdd3f44d..4835f0d508 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -570,6 +570,8 @@ DIAG(err_invalid_suffix_integer_constant, ERROR, "invalid suffix '%0' on integer constant") DIAG(err_invalid_suffix_float_constant, ERROR, "invalid suffix '%0' on floating constant") +DIAG(ext_imaginary_constant, EXTENSION, + "imaginary constants are an extension") DIAG(warn_integer_too_large, WARNING, "integer constant is too large for its type") DIAG(warn_integer_too_large_for_signed, WARNING, diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h index 7027fcd835..c667405235 100644 --- a/include/clang/Lex/LiteralSupport.h +++ b/include/clang/Lex/LiteralSupport.h @@ -44,21 +44,22 @@ class NumericLiteralParser { unsigned radix; bool saw_exponent, saw_period; - bool saw_float_suffix; + bool saw_float_suffix; // 1.0f public: NumericLiteralParser(const char *begin, const char *end, SourceLocation Loc, Preprocessor &PP); bool hadError; bool isUnsigned; - bool isLong; // This is also set for long long. + bool isLong; // This is *not* set for long long. bool isLongLong; + bool isImaginary; // 1.0i bool isIntegerLiteral() const { - return !saw_period && !saw_exponent ? true : false; + return !saw_period && !saw_exponent; } bool isFloatingLiteral() const { - return saw_period || saw_exponent ? true : false; + return saw_period || saw_exponent; } bool hasSuffix() const { return SuffixBegin != ThisTokEnd;