forked from OSchip/llvm-project
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; ^ llvm-svn: 41411
This commit is contained in:
parent
b620c34bb0
commit
f55ab18663
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue