Bug #:
Submitted by: Reviewed by: More code to parse numeric constants. This checkin includes: - Feedback from Chris. - Support for parsing floating point constants. - Moved the code to "Sema". Changed API in Action. - More/better error diagnostics. At this point, the parsing support should be largely complete. Next step is to work on filling in sensible values (in IntegerLiteral/FloatLiteral). llvm-svn: 39349
This commit is contained in:
parent
1fb30c5e99
commit
8160ea2072
|
@ -30,6 +30,10 @@ void Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg) {
|
|||
PP.Diag(Loc, DiagID, Msg);
|
||||
}
|
||||
|
||||
void Sema::Diag(const LexerToken &Tok, unsigned DiagID, const std::string &M) {
|
||||
Diag(Tok.getLocation(), DiagID, M);
|
||||
}
|
||||
|
||||
const LangOptions &Sema::getLangOptions() const {
|
||||
return PP.getLangOptions();
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace clang {
|
|||
class TypeRef;
|
||||
class LangOptions;
|
||||
class DeclaratorChunk;
|
||||
class LexerToken;
|
||||
|
||||
/// Sema - This implements semantic analysis and AST building for C.
|
||||
class Sema : public Action {
|
||||
|
@ -53,6 +54,8 @@ public:
|
|||
|
||||
void Diag(SourceLocation Loc, unsigned DiagID,
|
||||
const std::string &Msg = std::string());
|
||||
void Diag(const LexerToken &Tok, unsigned DiagID,
|
||||
const std::string &M = std::string());
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Type Analysis / Processing: SemaType.cpp.
|
||||
|
@ -155,8 +158,7 @@ public:
|
|||
bool HasTrailingLParen);
|
||||
virtual ExprResult ParseSimplePrimaryExpr(SourceLocation Loc,
|
||||
tok::TokenKind Kind);
|
||||
virtual ExprResult ParseIntegerLiteral(SourceLocation Loc);
|
||||
virtual ExprResult ParseFloatingLiteral(SourceLocation Loc);
|
||||
virtual ExprResult ParseNumericConstant(const LexerToken &);
|
||||
virtual ExprResult ParseParenExpr(SourceLocation L, SourceLocation R,
|
||||
ExprTy *Val);
|
||||
|
||||
|
|
|
@ -285,11 +285,234 @@ Sema::ExprResult Sema::ParseSimplePrimaryExpr(SourceLocation Loc,
|
|||
}
|
||||
}
|
||||
|
||||
Sema::ExprResult Sema::ParseIntegerLiteral(SourceLocation Loc) {
|
||||
return new IntegerLiteral();
|
||||
}
|
||||
Sema::ExprResult Sema::ParseFloatingLiteral(SourceLocation Loc) {
|
||||
return new FloatingLiteral();
|
||||
/// integer-constant: [C99 6.4.4.1]
|
||||
/// decimal-constant integer-suffix
|
||||
/// octal-constant integer-suffix
|
||||
/// hexadecimal-constant integer-suffix
|
||||
/// decimal-constant:
|
||||
/// nonzero-digit
|
||||
/// decimal-constant digit
|
||||
/// octal-constant:
|
||||
/// 0
|
||||
/// octal-constant octal-digit
|
||||
/// hexadecimal-constant:
|
||||
/// hexadecimal-prefix hexadecimal-digit
|
||||
/// hexadecimal-constant hexadecimal-digit
|
||||
/// hexadecimal-prefix: one of
|
||||
/// 0x 0X
|
||||
/// integer-suffix:
|
||||
/// unsigned-suffix [long-suffix]
|
||||
/// unsigned-suffix [long-long-suffix]
|
||||
/// long-suffix [unsigned-suffix]
|
||||
/// long-long-suffix [unsigned-sufix]
|
||||
/// nonzero-digit:
|
||||
/// 1 2 3 4 5 6 7 8 9
|
||||
/// octal-digit:
|
||||
/// 0 1 2 3 4 5 6 7
|
||||
/// hexadecimal-digit:
|
||||
/// 0 1 2 3 4 5 6 7 8 9
|
||||
/// a b c d e f
|
||||
/// A B C D E F
|
||||
/// unsigned-suffix: one of
|
||||
/// u U
|
||||
/// long-suffix: one of
|
||||
/// l L
|
||||
/// long-long-suffix: one of
|
||||
/// ll LL
|
||||
///
|
||||
/// floating-constant: [C99 6.4.4.2]
|
||||
/// TODO: add rules...
|
||||
///
|
||||
Action::ExprResult Sema::ParseNumericConstant(const LexerToken &Tok) {
|
||||
SmallString<512> IntegerBuffer;
|
||||
IntegerBuffer.resize(Tok.getLength());
|
||||
const char *ThisTokBegin = &IntegerBuffer[0];
|
||||
|
||||
// Get the spelling of the token, which eliminates trigraphs, etc. Notes:
|
||||
// - We know that ThisTokBuf points to a buffer that is big enough for the
|
||||
// whole token and 'spelled' tokens can only shrink.
|
||||
// - In practice, the local buffer is only used when the spelling doesn't
|
||||
// match the original token (which is rare). The common case simply returns
|
||||
// a pointer to a *constant* buffer (avoiding a copy).
|
||||
|
||||
unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin);
|
||||
ExprResult Res;
|
||||
|
||||
// This is an optimization for single digits (which are very common).
|
||||
if (ActualLength == 1) {
|
||||
return ExprResult(new IntegerLiteral());
|
||||
}
|
||||
const char *ThisTokEnd = ThisTokBegin+ActualLength;
|
||||
const char *s = ThisTokBegin;
|
||||
unsigned int radix;
|
||||
bool saw_exponent = false, saw_period = false;
|
||||
Expr *literal_expr = 0;
|
||||
|
||||
if (*s == '0') { // parse radix
|
||||
s++;
|
||||
if ((*s == 'x' || *s == 'X') && isxdigit(s[1])) { // need 1 digit
|
||||
s++;
|
||||
radix = 16;
|
||||
while (s < ThisTokEnd) {
|
||||
if (isxdigit(*s)) {
|
||||
s++;
|
||||
} else if (*s == '.') {
|
||||
s++;
|
||||
if (saw_period) {
|
||||
Diag(Tok, diag::err_too_many_decimal_points);
|
||||
return ExprResult(true);
|
||||
} else
|
||||
saw_period = true;
|
||||
} else if (*s == 'p' || *s == 'P') { // binary exponent
|
||||
saw_exponent = true;
|
||||
s++;
|
||||
if (*s == '+' || *s == '-') s++; // sign is optional
|
||||
if (isdigit(*s)) {
|
||||
do { s++; } while (isdigit(*s)); // a decimal integer
|
||||
} else {
|
||||
Diag(Tok, diag::err_exponent_has_no_digits);
|
||||
return ExprResult(true);
|
||||
}
|
||||
break;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
if (saw_period && !saw_exponent) {
|
||||
Diag(Tok, diag::err_hexconstant_requires_exponent);
|
||||
return ExprResult(true);
|
||||
}
|
||||
} else {
|
||||
// For now, the radix is set to 8. If we discover that we have a
|
||||
// floating point constant, the radix will change to 10. Octal floating
|
||||
// point constants are not permitted (only decimal and hexadecimal).
|
||||
radix = 8;
|
||||
while (s < ThisTokEnd) {
|
||||
if ((*s >= '0') && (*s <= '7')) {
|
||||
s++;
|
||||
} else if (*s == '.') {
|
||||
s++;
|
||||
if (saw_period) {
|
||||
Diag(Tok, diag::err_too_many_decimal_points);
|
||||
return ExprResult(true);
|
||||
}
|
||||
saw_period = true;
|
||||
radix = 10;
|
||||
} else if (*s == 'e' || *s == 'E') { // exponent
|
||||
saw_exponent = true;
|
||||
s++;
|
||||
if (*s == '+' || *s == '-') s++; // sign
|
||||
if (isdigit(*s)) {
|
||||
do { s++; } while (isdigit(*s)); // a decimal integer
|
||||
} else {
|
||||
Diag(Tok, diag::err_exponent_has_no_digits);
|
||||
return ExprResult(true);
|
||||
}
|
||||
radix = 10;
|
||||
break;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else { // the first digit is non-zero
|
||||
radix = 10;
|
||||
while (s < ThisTokEnd) {
|
||||
if (isdigit(*s)) {
|
||||
s++;
|
||||
} else if (*s == '.') {
|
||||
s++;
|
||||
if (saw_period) {
|
||||
Diag(Tok, diag::err_too_many_decimal_points);
|
||||
return ExprResult(true);
|
||||
} else
|
||||
saw_period = true;
|
||||
} else if (*s == 'e' || *s == 'E') { // exponent
|
||||
saw_exponent = true;
|
||||
s++;
|
||||
if (*s == '+' || *s == '-') s++; // sign
|
||||
if (isdigit(*s)) {
|
||||
do { s++; } while (isdigit(*s)); // a decimal integer
|
||||
} else {
|
||||
Diag(Tok, diag::err_exponent_has_no_digits);
|
||||
return ExprResult(true);
|
||||
}
|
||||
break;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const char *suffix_start = s;
|
||||
bool invalid_suffix = false;
|
||||
|
||||
if (saw_period || saw_exponent) {
|
||||
bool saw_float_suffix = false, saw_long_suffix = false;
|
||||
|
||||
while (s < ThisTokEnd) {
|
||||
// parse float suffix - they can appear in any order.
|
||||
if (*s == 'f' || *s == 'F') {
|
||||
if (saw_float_suffix) {
|
||||
invalid_suffix = true;
|
||||
break;
|
||||
} else {
|
||||
saw_float_suffix = true;
|
||||
s++;
|
||||
}
|
||||
} else if (*s == 'l' || *s == 'L') {
|
||||
if (saw_long_suffix) {
|
||||
invalid_suffix = true;
|
||||
break;
|
||||
} else {
|
||||
saw_long_suffix = true;
|
||||
s++;
|
||||
}
|
||||
} else {
|
||||
invalid_suffix = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (invalid_suffix) {
|
||||
Diag(Tok, diag::err_invalid_suffix_float_constant,
|
||||
std::string(suffix_start, ThisTokEnd));
|
||||
return ExprResult(true);
|
||||
}
|
||||
literal_expr = new FloatingLiteral();
|
||||
} else {
|
||||
bool saw_unsigned = false;
|
||||
int long_cnt = 0;
|
||||
|
||||
// if there is no suffix, this loop won't be executed (s == ThisTokEnd)
|
||||
while (s < ThisTokEnd) {
|
||||
// parse int suffix - they can appear in any order ("ul", "lu", "llu").
|
||||
if (*s == 'u' || *s == 'U') {
|
||||
if (saw_unsigned) {
|
||||
invalid_suffix = true;
|
||||
break;
|
||||
} else {
|
||||
saw_unsigned = true;
|
||||
s++;
|
||||
}
|
||||
} else if (*s == 'l' || *s == 'L') {
|
||||
long_cnt++;
|
||||
// l's need to be adjacent and the same case.
|
||||
if ((long_cnt == 2 && (*s != *(s-1))) || long_cnt == 3) {
|
||||
invalid_suffix = true;
|
||||
break;
|
||||
} else {
|
||||
s++;
|
||||
}
|
||||
} else {
|
||||
invalid_suffix = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (invalid_suffix) {
|
||||
Diag(Tok, diag::err_invalid_suffix_integer_constant,
|
||||
std::string(suffix_start, ThisTokEnd));
|
||||
return ExprResult(true);
|
||||
}
|
||||
literal_expr = new IntegerLiteral();
|
||||
}
|
||||
return ExprResult(literal_expr);
|
||||
}
|
||||
|
||||
Action::ExprResult Sema::ParseParenExpr(SourceLocation L, SourceLocation R,
|
||||
|
|
|
@ -473,7 +473,7 @@ Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) {
|
|||
// constant: integer-constant
|
||||
// constant: floating-constant
|
||||
|
||||
ParseNumericConstant();
|
||||
Actions.ParseNumericConstant(Tok);
|
||||
ConsumeToken();
|
||||
|
||||
// These can be followed by postfix-expr pieces.
|
||||
|
@ -925,114 +925,3 @@ Parser::ExprResult Parser::ParseStringLiteralExpression() {
|
|||
// Pass the set of string tokens, ready for concatenation, to the actions.
|
||||
return Actions.ParseStringLiteral(&StringToks[0], StringToks.size());
|
||||
}
|
||||
|
||||
/// integer-constant: [C99 6.4.4.1]
|
||||
/// decimal-constant integer-suffix
|
||||
/// octal-constant integer-suffix
|
||||
/// hexidecimal-constant integer-suffix
|
||||
/// decimal-constant:
|
||||
/// nonzero-digit
|
||||
/// decimal-constant digit
|
||||
/// octal-constant:
|
||||
/// 0
|
||||
/// octal-constant octal-digit
|
||||
/// hexidecimal-constant:
|
||||
/// hexidecimal-prefix hexidecimal-digit
|
||||
/// hexidecimal-constant hexidecimal-digit
|
||||
/// hexidecimal-prefix: one of
|
||||
/// 0x 0X
|
||||
/// integer-suffix:
|
||||
/// unsigned-suffix [long-suffix]
|
||||
/// unsigned-suffix [long-long-suffix]
|
||||
/// long-suffix [unsigned-suffix]
|
||||
/// long-long-suffix [unsigned-sufix]
|
||||
/// nonzero-digit:
|
||||
/// 1 2 3 4 5 6 7 8 9
|
||||
/// octal-digit:
|
||||
/// 0 1 2 3 4 5 6 7
|
||||
/// hexadecimal-digit:
|
||||
/// 0 1 2 3 4 5 6 7 8 9
|
||||
/// a b c d e f
|
||||
/// A B C D E F
|
||||
/// unsigned-suffix: one of
|
||||
/// u U
|
||||
/// long-suffix: one of
|
||||
/// l L
|
||||
/// long-long-suffix: one of
|
||||
/// ll LL
|
||||
///
|
||||
/// floating-constant: [C99 6.4.4.2]
|
||||
///
|
||||
Parser::ExprResult Parser::ParseNumericConstant() {
|
||||
SmallString<512> IntegerBuffer;
|
||||
IntegerBuffer.resize(Tok.getLength());
|
||||
const char *ThisTokBegin = &IntegerBuffer[0];
|
||||
|
||||
// Get the spelling of the token, which eliminates trigraphs, etc. Notes:
|
||||
// - We know that ThisTokBuf points to a buffer that is big enough for the
|
||||
// whole token and 'spelled' tokens can only shrink.
|
||||
// - In practice, the local buffer is only used when the spelling doesn't
|
||||
// match the original token (which is rare). The common case simply returns
|
||||
// a pointer to a *constant* buffer (avoiding a copy).
|
||||
|
||||
unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin);
|
||||
ExprResult Res;
|
||||
|
||||
if (ActualLength == 1) {
|
||||
// need to change interface...just a placeholder
|
||||
Res = Actions.ParseIntegerLiteral(Tok.getLocation());
|
||||
} else if (ActualLength > 1) {
|
||||
const char *ThisTokEnd = ThisTokBegin+ActualLength;
|
||||
const char *s = ThisTokBegin;
|
||||
unsigned int radix;
|
||||
|
||||
if (*s == '0') { // parse radix
|
||||
s++;
|
||||
if (*s == 'x' || *s == 'X') {
|
||||
s++;
|
||||
radix = 16;
|
||||
while (s < ThisTokEnd && isxdigit(*s)) *s++;
|
||||
} else {
|
||||
radix = 8;
|
||||
while (s < ThisTokEnd && ((*s >= '0') && (*s <= '7'))) *s++;
|
||||
}
|
||||
} else { // the first digit is non-zero
|
||||
radix = 10;
|
||||
while (s < ThisTokEnd && isdigit(*s)) *s++;
|
||||
}
|
||||
|
||||
if (*s == '.') { // TODO: Parse Floats...
|
||||
Res = Actions.ParseFloatingLiteral(Tok.getLocation());
|
||||
} else {
|
||||
int unsigned_cnt = 0, long_cnt = 0, invalid_suffix = 0;
|
||||
|
||||
// if there is no suffix, this loop won't be executed (s == ThisTokEnd)
|
||||
while (s < ThisTokEnd && !invalid_suffix) {
|
||||
// parse type suffix - they can appear in any order "ul", "lu", "llu"
|
||||
if (*s == 'u' || *s == 'U') {
|
||||
unsigned_cnt++;
|
||||
if (unsigned_cnt == 2)
|
||||
invalid_suffix = 1;
|
||||
else
|
||||
s++;
|
||||
} else if (*s == 'l' || *s == 'L') {
|
||||
long_cnt++;
|
||||
// l's need to be adjacent and the same case
|
||||
if ((long_cnt == 2 && (*s != *(s-1))) || long_cnt == 3)
|
||||
invalid_suffix = 1;
|
||||
else
|
||||
s++;
|
||||
} else {
|
||||
invalid_suffix = 1;
|
||||
}
|
||||
}
|
||||
if (invalid_suffix) {
|
||||
Diag(Tok, diag::err_invalid_suffix_integer_constant);
|
||||
return ExprResult(true);
|
||||
} else {
|
||||
// need to change interface...just a placeholder
|
||||
Res = Actions.ParseIntegerLiteral(Tok.getLocation());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,10 @@ void Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg) {
|
|||
PP.Diag(Loc, DiagID, Msg);
|
||||
}
|
||||
|
||||
void Sema::Diag(const LexerToken &Tok, unsigned DiagID, const std::string &M) {
|
||||
Diag(Tok.getLocation(), DiagID, M);
|
||||
}
|
||||
|
||||
const LangOptions &Sema::getLangOptions() const {
|
||||
return PP.getLangOptions();
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace clang {
|
|||
class TypeRef;
|
||||
class LangOptions;
|
||||
class DeclaratorChunk;
|
||||
class LexerToken;
|
||||
|
||||
/// Sema - This implements semantic analysis and AST building for C.
|
||||
class Sema : public Action {
|
||||
|
@ -53,6 +54,8 @@ public:
|
|||
|
||||
void Diag(SourceLocation Loc, unsigned DiagID,
|
||||
const std::string &Msg = std::string());
|
||||
void Diag(const LexerToken &Tok, unsigned DiagID,
|
||||
const std::string &M = std::string());
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Type Analysis / Processing: SemaType.cpp.
|
||||
|
@ -155,8 +158,7 @@ public:
|
|||
bool HasTrailingLParen);
|
||||
virtual ExprResult ParseSimplePrimaryExpr(SourceLocation Loc,
|
||||
tok::TokenKind Kind);
|
||||
virtual ExprResult ParseIntegerLiteral(SourceLocation Loc);
|
||||
virtual ExprResult ParseFloatingLiteral(SourceLocation Loc);
|
||||
virtual ExprResult ParseNumericConstant(const LexerToken &);
|
||||
virtual ExprResult ParseParenExpr(SourceLocation L, SourceLocation R,
|
||||
ExprTy *Val);
|
||||
|
||||
|
|
|
@ -285,11 +285,234 @@ Sema::ExprResult Sema::ParseSimplePrimaryExpr(SourceLocation Loc,
|
|||
}
|
||||
}
|
||||
|
||||
Sema::ExprResult Sema::ParseIntegerLiteral(SourceLocation Loc) {
|
||||
return new IntegerLiteral();
|
||||
}
|
||||
Sema::ExprResult Sema::ParseFloatingLiteral(SourceLocation Loc) {
|
||||
return new FloatingLiteral();
|
||||
/// integer-constant: [C99 6.4.4.1]
|
||||
/// decimal-constant integer-suffix
|
||||
/// octal-constant integer-suffix
|
||||
/// hexadecimal-constant integer-suffix
|
||||
/// decimal-constant:
|
||||
/// nonzero-digit
|
||||
/// decimal-constant digit
|
||||
/// octal-constant:
|
||||
/// 0
|
||||
/// octal-constant octal-digit
|
||||
/// hexadecimal-constant:
|
||||
/// hexadecimal-prefix hexadecimal-digit
|
||||
/// hexadecimal-constant hexadecimal-digit
|
||||
/// hexadecimal-prefix: one of
|
||||
/// 0x 0X
|
||||
/// integer-suffix:
|
||||
/// unsigned-suffix [long-suffix]
|
||||
/// unsigned-suffix [long-long-suffix]
|
||||
/// long-suffix [unsigned-suffix]
|
||||
/// long-long-suffix [unsigned-sufix]
|
||||
/// nonzero-digit:
|
||||
/// 1 2 3 4 5 6 7 8 9
|
||||
/// octal-digit:
|
||||
/// 0 1 2 3 4 5 6 7
|
||||
/// hexadecimal-digit:
|
||||
/// 0 1 2 3 4 5 6 7 8 9
|
||||
/// a b c d e f
|
||||
/// A B C D E F
|
||||
/// unsigned-suffix: one of
|
||||
/// u U
|
||||
/// long-suffix: one of
|
||||
/// l L
|
||||
/// long-long-suffix: one of
|
||||
/// ll LL
|
||||
///
|
||||
/// floating-constant: [C99 6.4.4.2]
|
||||
/// TODO: add rules...
|
||||
///
|
||||
Action::ExprResult Sema::ParseNumericConstant(const LexerToken &Tok) {
|
||||
SmallString<512> IntegerBuffer;
|
||||
IntegerBuffer.resize(Tok.getLength());
|
||||
const char *ThisTokBegin = &IntegerBuffer[0];
|
||||
|
||||
// Get the spelling of the token, which eliminates trigraphs, etc. Notes:
|
||||
// - We know that ThisTokBuf points to a buffer that is big enough for the
|
||||
// whole token and 'spelled' tokens can only shrink.
|
||||
// - In practice, the local buffer is only used when the spelling doesn't
|
||||
// match the original token (which is rare). The common case simply returns
|
||||
// a pointer to a *constant* buffer (avoiding a copy).
|
||||
|
||||
unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin);
|
||||
ExprResult Res;
|
||||
|
||||
// This is an optimization for single digits (which are very common).
|
||||
if (ActualLength == 1) {
|
||||
return ExprResult(new IntegerLiteral());
|
||||
}
|
||||
const char *ThisTokEnd = ThisTokBegin+ActualLength;
|
||||
const char *s = ThisTokBegin;
|
||||
unsigned int radix;
|
||||
bool saw_exponent = false, saw_period = false;
|
||||
Expr *literal_expr = 0;
|
||||
|
||||
if (*s == '0') { // parse radix
|
||||
s++;
|
||||
if ((*s == 'x' || *s == 'X') && isxdigit(s[1])) { // need 1 digit
|
||||
s++;
|
||||
radix = 16;
|
||||
while (s < ThisTokEnd) {
|
||||
if (isxdigit(*s)) {
|
||||
s++;
|
||||
} else if (*s == '.') {
|
||||
s++;
|
||||
if (saw_period) {
|
||||
Diag(Tok, diag::err_too_many_decimal_points);
|
||||
return ExprResult(true);
|
||||
} else
|
||||
saw_period = true;
|
||||
} else if (*s == 'p' || *s == 'P') { // binary exponent
|
||||
saw_exponent = true;
|
||||
s++;
|
||||
if (*s == '+' || *s == '-') s++; // sign is optional
|
||||
if (isdigit(*s)) {
|
||||
do { s++; } while (isdigit(*s)); // a decimal integer
|
||||
} else {
|
||||
Diag(Tok, diag::err_exponent_has_no_digits);
|
||||
return ExprResult(true);
|
||||
}
|
||||
break;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
if (saw_period && !saw_exponent) {
|
||||
Diag(Tok, diag::err_hexconstant_requires_exponent);
|
||||
return ExprResult(true);
|
||||
}
|
||||
} else {
|
||||
// For now, the radix is set to 8. If we discover that we have a
|
||||
// floating point constant, the radix will change to 10. Octal floating
|
||||
// point constants are not permitted (only decimal and hexadecimal).
|
||||
radix = 8;
|
||||
while (s < ThisTokEnd) {
|
||||
if ((*s >= '0') && (*s <= '7')) {
|
||||
s++;
|
||||
} else if (*s == '.') {
|
||||
s++;
|
||||
if (saw_period) {
|
||||
Diag(Tok, diag::err_too_many_decimal_points);
|
||||
return ExprResult(true);
|
||||
}
|
||||
saw_period = true;
|
||||
radix = 10;
|
||||
} else if (*s == 'e' || *s == 'E') { // exponent
|
||||
saw_exponent = true;
|
||||
s++;
|
||||
if (*s == '+' || *s == '-') s++; // sign
|
||||
if (isdigit(*s)) {
|
||||
do { s++; } while (isdigit(*s)); // a decimal integer
|
||||
} else {
|
||||
Diag(Tok, diag::err_exponent_has_no_digits);
|
||||
return ExprResult(true);
|
||||
}
|
||||
radix = 10;
|
||||
break;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else { // the first digit is non-zero
|
||||
radix = 10;
|
||||
while (s < ThisTokEnd) {
|
||||
if (isdigit(*s)) {
|
||||
s++;
|
||||
} else if (*s == '.') {
|
||||
s++;
|
||||
if (saw_period) {
|
||||
Diag(Tok, diag::err_too_many_decimal_points);
|
||||
return ExprResult(true);
|
||||
} else
|
||||
saw_period = true;
|
||||
} else if (*s == 'e' || *s == 'E') { // exponent
|
||||
saw_exponent = true;
|
||||
s++;
|
||||
if (*s == '+' || *s == '-') s++; // sign
|
||||
if (isdigit(*s)) {
|
||||
do { s++; } while (isdigit(*s)); // a decimal integer
|
||||
} else {
|
||||
Diag(Tok, diag::err_exponent_has_no_digits);
|
||||
return ExprResult(true);
|
||||
}
|
||||
break;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const char *suffix_start = s;
|
||||
bool invalid_suffix = false;
|
||||
|
||||
if (saw_period || saw_exponent) {
|
||||
bool saw_float_suffix = false, saw_long_suffix = false;
|
||||
|
||||
while (s < ThisTokEnd) {
|
||||
// parse float suffix - they can appear in any order.
|
||||
if (*s == 'f' || *s == 'F') {
|
||||
if (saw_float_suffix) {
|
||||
invalid_suffix = true;
|
||||
break;
|
||||
} else {
|
||||
saw_float_suffix = true;
|
||||
s++;
|
||||
}
|
||||
} else if (*s == 'l' || *s == 'L') {
|
||||
if (saw_long_suffix) {
|
||||
invalid_suffix = true;
|
||||
break;
|
||||
} else {
|
||||
saw_long_suffix = true;
|
||||
s++;
|
||||
}
|
||||
} else {
|
||||
invalid_suffix = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (invalid_suffix) {
|
||||
Diag(Tok, diag::err_invalid_suffix_float_constant,
|
||||
std::string(suffix_start, ThisTokEnd));
|
||||
return ExprResult(true);
|
||||
}
|
||||
literal_expr = new FloatingLiteral();
|
||||
} else {
|
||||
bool saw_unsigned = false;
|
||||
int long_cnt = 0;
|
||||
|
||||
// if there is no suffix, this loop won't be executed (s == ThisTokEnd)
|
||||
while (s < ThisTokEnd) {
|
||||
// parse int suffix - they can appear in any order ("ul", "lu", "llu").
|
||||
if (*s == 'u' || *s == 'U') {
|
||||
if (saw_unsigned) {
|
||||
invalid_suffix = true;
|
||||
break;
|
||||
} else {
|
||||
saw_unsigned = true;
|
||||
s++;
|
||||
}
|
||||
} else if (*s == 'l' || *s == 'L') {
|
||||
long_cnt++;
|
||||
// l's need to be adjacent and the same case.
|
||||
if ((long_cnt == 2 && (*s != *(s-1))) || long_cnt == 3) {
|
||||
invalid_suffix = true;
|
||||
break;
|
||||
} else {
|
||||
s++;
|
||||
}
|
||||
} else {
|
||||
invalid_suffix = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (invalid_suffix) {
|
||||
Diag(Tok, diag::err_invalid_suffix_integer_constant,
|
||||
std::string(suffix_start, ThisTokEnd));
|
||||
return ExprResult(true);
|
||||
}
|
||||
literal_expr = new IntegerLiteral();
|
||||
}
|
||||
return ExprResult(literal_expr);
|
||||
}
|
||||
|
||||
Action::ExprResult Sema::ParseParenExpr(SourceLocation L, SourceLocation R,
|
||||
|
|
|
@ -94,23 +94,6 @@
|
|||
DED7D9E50A5257F6003AD0FB /* ScratchBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED7D9E40A5257F6003AD0FB /* ScratchBuffer.cpp */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXBuildStyle section */
|
||||
842065AF0B98D65200CA7A69 /* Development */ = {
|
||||
isa = PBXBuildStyle;
|
||||
buildSettings = {
|
||||
COPY_PHASE_STRIP = NO;
|
||||
};
|
||||
name = Development;
|
||||
};
|
||||
842065B00B98D65200CA7A69 /* Deployment */ = {
|
||||
isa = PBXBuildStyle;
|
||||
buildSettings = {
|
||||
COPY_PHASE_STRIP = YES;
|
||||
};
|
||||
name = Deployment;
|
||||
};
|
||||
/* End PBXBuildStyle section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
8DD76F690486A84900D96B5E /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
|
@ -493,15 +476,12 @@
|
|||
08FB7793FE84155DC02AAC07 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
|
||||
buildSettings = {
|
||||
};
|
||||
buildStyles = (
|
||||
842065AF0B98D65200CA7A69 /* Development */,
|
||||
842065B00B98D65200CA7A69 /* Deployment */,
|
||||
);
|
||||
compatibilityVersion = "Xcode 2.4";
|
||||
hasScannedForEncodings = 1;
|
||||
mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
shouldCheckCompatibility = 1;
|
||||
targets = (
|
||||
8DD76F620486A84900D96B5E /* clang */,
|
||||
);
|
||||
|
|
|
@ -471,7 +471,15 @@ DIAG(err_sizeof_incomplete_type, ERROR,
|
|||
DIAG(err_alignof_incomplete_type, ERROR,
|
||||
"invalid application of '__alignof' to an incomplete type '%s'")
|
||||
DIAG(err_invalid_suffix_integer_constant, ERROR,
|
||||
"invalid suffix on integer constant")
|
||||
"invalid suffix '%s' on integer constant")
|
||||
DIAG(err_invalid_suffix_float_constant, ERROR,
|
||||
"invalid suffix '%s' on floating constant")
|
||||
DIAG(err_exponent_has_no_digits, ERROR,
|
||||
"exponent has no digits")
|
||||
DIAG(err_too_many_decimal_points, ERROR,
|
||||
"too many decimal points in number")
|
||||
DIAG(err_hexconstant_requires_exponent, ERROR,
|
||||
"hexadecimal floating constants require an exponent")
|
||||
|
||||
// Statements.
|
||||
DIAG(err_continue_not_in_loop, ERROR,
|
||||
|
|
|
@ -263,8 +263,7 @@ public:
|
|||
tok::TokenKind Kind) {
|
||||
return 0;
|
||||
}
|
||||
virtual ExprResult ParseIntegerLiteral(SourceLocation Loc) { return 0; }
|
||||
virtual ExprResult ParseFloatingLiteral(SourceLocation Loc) { return 0; }
|
||||
virtual ExprResult ParseNumericConstant(const LexerToken &) { return 0; }
|
||||
|
||||
/// ParseStringLiteral - The specified tokens were lexed as pasted string
|
||||
/// fragments (e.g. "foo" "bar" L"baz").
|
||||
|
|
|
@ -291,7 +291,6 @@ private:
|
|||
return ParseParenExpression(Op, CastTy, RParenLoc);
|
||||
}
|
||||
ExprResult ParseStringLiteralExpression();
|
||||
ExprResult ParseNumericConstant();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// C++ 5.2p1: C++ Casts
|
||||
|
|
Loading…
Reference in New Issue