Submitted by:
Reviewed by:
Moved numeric literal support from SemaExpr.cpp to LiteralSupport.[h,cpp]
in Lex. This will allow it to be used by both Sema and Preprocessor (and
should be the last major refactoring of this sub-system).. Over
time, it will be reused by anyone implementing an actions module (i.e.
any subclass of llvm::clang::Action. Minor changes to IntegerLiteral in Expr.h.
More to come...

llvm-svn: 39351
This commit is contained in:
Steve Naroff 2007-03-09 23:16:33 +00:00
parent cf30755a41
commit 09ef474197
6 changed files with 433 additions and 403 deletions

View File

@ -16,6 +16,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetInfo.h"
@ -24,7 +25,7 @@
using namespace llvm;
using namespace clang;
#include <iostream>
/// HexDigitValue - Return the value of the specified hex digit, or -1 if it's
/// not valid.
@ -285,68 +286,6 @@ Sema::ExprResult Sema::ParseSimplePrimaryExpr(SourceLocation Loc,
}
}
/// SkipHexDigits - Read and skip over any hex digits, up to End.
/// Return a pointer to the first non-hex digit or End.
static const char *SkipHexDigits(const char *ptr, const char *end) {
while (ptr != end && isxdigit(*ptr))
ptr++;
return ptr;
}
/// SkipOctalDigits - Read and skip over any octal digits, up to End.
/// Return a pointer to the first non-hex digit or End.
static const char *SkipOctalDigits(const char *ptr, const char *end) {
while (ptr != end && ((*ptr >= '0') && (*ptr <= '7')))
ptr++;
return ptr;
}
/// SkipDigits - Read and skip over any digits, up to End.
/// Return a pointer to the first non-hex digit or End.
static const char *SkipDigits(const char *ptr, const char *end) {
while (ptr != end && isdigit(*ptr))
ptr++;
return ptr;
}
/// 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());
@ -360,148 +299,37 @@ Action::ExprResult Sema::ParseNumericConstant(const LexerToken &Tok) {
// 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]) || s[1] == '.')) {
s++;
radix = 16;
s = SkipHexDigits(s, ThisTokEnd);
if (s == ThisTokEnd) {
} else if (*s == '.') {
s++;
saw_period = true;
s = SkipHexDigits(s, ThisTokEnd);
}
// A binary exponent can appear with or with a '.'. If dotted, the
// binary exponent is required.
if (*s == 'p' || *s == 'P') {
s++;
saw_exponent = true;
if (*s == '+' || *s == '-') s++; // sign
const char *first_non_digit = SkipDigits(s, ThisTokEnd);
if (first_non_digit == s) {
Diag(Tok, diag::err_exponent_has_no_digits);
return ExprResult(true);
} else {
s = first_non_digit;
}
} else if (saw_period) {
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;
s = SkipOctalDigits(s, ThisTokEnd);
if (s == ThisTokEnd) {
} else if (*s == '.') {
s++;
radix = 10;
saw_period = true;
s = SkipDigits(s, ThisTokEnd);
}
if (*s == 'e' || *s == 'E') { // exponent
s++;
radix = 10;
saw_exponent = true;
if (*s == '+' || *s == '-') s++; // sign
const char *first_non_digit = SkipDigits(s, ThisTokEnd);
if (first_non_digit == s) {
Diag(Tok, diag::err_exponent_has_no_digits);
return ExprResult(true);
} else {
s = first_non_digit;
}
}
}
} else { // the first digit is non-zero
radix = 10;
s = SkipDigits(s, ThisTokEnd);
if (s == ThisTokEnd) {
} else if (*s == '.') {
s++;
saw_period = true;
s = SkipDigits(s, ThisTokEnd);
}
if (*s == 'e' || *s == 'E') { // exponent
s++;
saw_exponent = true;
if (*s == '+' || *s == '-') s++; // sign
const char *first_non_digit = SkipDigits(s, ThisTokEnd);
if (first_non_digit == s) {
Diag(Tok, diag::err_exponent_has_no_digits);
return ExprResult(true);
} else {
s = first_non_digit;
}
}
}
const char *suffix_start = s;
if (saw_period || saw_exponent) {
bool saw_float_suffix = false, saw_long_suffix = false;
if (ActualLength == 1)
return ExprResult(new IntegerLiteral(atoi(ThisTokBegin)));
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') {
saw_long_suffix = true;
s++;
}
if (s != ThisTokEnd) {
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, saw_long = false, saw_longlong = false;
// 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) break; // only allowed to have one
saw_unsigned = true;
s++;
} else if (*s == 'l' || *s == 'L') {
if (saw_long || saw_longlong) break; // only allowed to have one
s++;
if (s < ThisTokEnd && (*s == *(s-1))) {
saw_longlong = true; // l's need to be adjacent and same case.
s++;
} else {
saw_long = true;
}
} else {
break;
}
}
if (s != ThisTokEnd) {
Diag(Tok, diag::err_invalid_suffix_integer_constant,
std::string(suffix_start, ThisTokEnd));
return ExprResult(true);
}
literal_expr = new IntegerLiteral();
NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength,
Tok.getLocation(), PP, Context.Target);
if (Literal.hadError) {
return ExprResult(true);
}
Expr *literal_expr;
if (Literal.isIntegerLiteral()) {
TypeRef t;
if (Literal.hasSuffix()) {
if (Literal.isLong)
t = Literal.isUnsigned ? Context.UnsignedLongTy : Context.LongTy;
else if (Literal.isLongLong)
t = Literal.isUnsigned ? Context.UnsignedLongLongTy : Context.LongLongTy;
else
t = Context.UnsignedIntTy;
} else {
t = Context.IntTy; // implicit type is "int"
}
intmax_t val;
if (Literal.GetValue(val)) {
literal_expr = new IntegerLiteral(val, t);
}
} else if (Literal.isFloatingLiteral()) {
// TODO: add floating point processing...
}
return ExprResult(literal_expr);
}
Action::ExprResult Sema::ParseParenExpr(SourceLocation L, SourceLocation R,

View File

@ -0,0 +1,244 @@
//===--- LiteralSupport.cpp - Code to parse and process literals-*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Steve Naroff and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the NumericLiteralParser interface.
//
//===----------------------------------------------------------------------===//
#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Diagnostic.h"
using namespace llvm;
using namespace clang;
/// 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...
///
NumericLiteralParser::
NumericLiteralParser(const char *begin, const char *end,
SourceLocation TokLoc, Preprocessor &pp, TargetInfo &t) :
PP(pp), Target(t), ThisTokBegin(begin), ThisTokEnd(end)
{
s = DigitsBegin = begin;
saw_exponent = false;
saw_period = false;
saw_float_suffix = false;
isLong = false;
isUnsigned = false;
isLongLong = false;
hadError = false;
if (*s == '0') { // parse radix
s++;
if ((*s == 'x' || *s == 'X') && (isxdigit(s[1]) || s[1] == '.')) {
s++;
radix = 16;
DigitsBegin = s;
s = SkipHexDigits(s);
if (s == ThisTokEnd) {
} else if (*s == '.') {
s++;
saw_period = true;
s = SkipHexDigits(s);
}
// A binary exponent can appear with or with a '.'. If dotted, the
// binary exponent is required.
if (*s == 'p' || *s == 'P') {
s++;
saw_exponent = true;
if (*s == '+' || *s == '-') s++; // sign
const char *first_non_digit = SkipDigits(s);
if (first_non_digit == s) {
Diag(TokLoc, diag::err_exponent_has_no_digits);
return;
} else {
s = first_non_digit;
}
} else if (saw_period) {
Diag(TokLoc, diag::err_hexconstant_requires_exponent);
return;
}
} 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;
DigitsBegin = s;
s = SkipOctalDigits(s);
if (s == ThisTokEnd) {
} else if (*s == '.') {
s++;
radix = 10;
saw_period = true;
s = SkipDigits(s);
}
if (*s == 'e' || *s == 'E') { // exponent
s++;
radix = 10;
saw_exponent = true;
if (*s == '+' || *s == '-') s++; // sign
const char *first_non_digit = SkipDigits(s);
if (first_non_digit == s) {
Diag(TokLoc, diag::err_exponent_has_no_digits);
return;
} else {
s = first_non_digit;
}
}
}
} else { // the first digit is non-zero
radix = 10;
s = SkipDigits(s);
if (s == ThisTokEnd) {
} else if (*s == '.') {
s++;
saw_period = true;
s = SkipDigits(s);
}
if (*s == 'e' || *s == 'E') { // exponent
s++;
saw_exponent = true;
if (*s == '+' || *s == '-') s++; // sign
const char *first_non_digit = SkipDigits(s);
if (first_non_digit == s) {
Diag(TokLoc, diag::err_exponent_has_no_digits);
return;
} else {
s = first_non_digit;
}
}
}
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') {
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;
}
}
}
}
bool NumericLiteralParser::GetValue(intmax_t &val) {
intmax_t cutoff = INTMAX_MAX;
int cutlim = cutoff % radix;
char c;
val = 0;
cutoff /= radix;
s = DigitsBegin;
while (s < SuffixBegin) {
c = *s++;
if (c >= '0' && c <= '9')
c -= '0';
else if (c >= 'A' && c <= 'F') // 10...15
c -= 'A' - 10;
else if (c >= 'a' && c <= 'f') // 10...15
c -= 'a' - 10;
if (val > cutoff || (val == cutoff && c > cutlim)) {
return false; // Overflow!
} else {
val *= radix;
val += c;
}
}
return true;
}

View File

@ -16,6 +16,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetInfo.h"
@ -24,7 +25,7 @@
using namespace llvm;
using namespace clang;
#include <iostream>
/// HexDigitValue - Return the value of the specified hex digit, or -1 if it's
/// not valid.
@ -285,68 +286,6 @@ Sema::ExprResult Sema::ParseSimplePrimaryExpr(SourceLocation Loc,
}
}
/// SkipHexDigits - Read and skip over any hex digits, up to End.
/// Return a pointer to the first non-hex digit or End.
static const char *SkipHexDigits(const char *ptr, const char *end) {
while (ptr != end && isxdigit(*ptr))
ptr++;
return ptr;
}
/// SkipOctalDigits - Read and skip over any octal digits, up to End.
/// Return a pointer to the first non-hex digit or End.
static const char *SkipOctalDigits(const char *ptr, const char *end) {
while (ptr != end && ((*ptr >= '0') && (*ptr <= '7')))
ptr++;
return ptr;
}
/// SkipDigits - Read and skip over any digits, up to End.
/// Return a pointer to the first non-hex digit or End.
static const char *SkipDigits(const char *ptr, const char *end) {
while (ptr != end && isdigit(*ptr))
ptr++;
return ptr;
}
/// 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());
@ -360,148 +299,37 @@ Action::ExprResult Sema::ParseNumericConstant(const LexerToken &Tok) {
// 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]) || s[1] == '.')) {
s++;
radix = 16;
s = SkipHexDigits(s, ThisTokEnd);
if (s == ThisTokEnd) {
} else if (*s == '.') {
s++;
saw_period = true;
s = SkipHexDigits(s, ThisTokEnd);
}
// A binary exponent can appear with or with a '.'. If dotted, the
// binary exponent is required.
if (*s == 'p' || *s == 'P') {
s++;
saw_exponent = true;
if (*s == '+' || *s == '-') s++; // sign
const char *first_non_digit = SkipDigits(s, ThisTokEnd);
if (first_non_digit == s) {
Diag(Tok, diag::err_exponent_has_no_digits);
return ExprResult(true);
} else {
s = first_non_digit;
}
} else if (saw_period) {
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;
s = SkipOctalDigits(s, ThisTokEnd);
if (s == ThisTokEnd) {
} else if (*s == '.') {
s++;
radix = 10;
saw_period = true;
s = SkipDigits(s, ThisTokEnd);
}
if (*s == 'e' || *s == 'E') { // exponent
s++;
radix = 10;
saw_exponent = true;
if (*s == '+' || *s == '-') s++; // sign
const char *first_non_digit = SkipDigits(s, ThisTokEnd);
if (first_non_digit == s) {
Diag(Tok, diag::err_exponent_has_no_digits);
return ExprResult(true);
} else {
s = first_non_digit;
}
}
}
} else { // the first digit is non-zero
radix = 10;
s = SkipDigits(s, ThisTokEnd);
if (s == ThisTokEnd) {
} else if (*s == '.') {
s++;
saw_period = true;
s = SkipDigits(s, ThisTokEnd);
}
if (*s == 'e' || *s == 'E') { // exponent
s++;
saw_exponent = true;
if (*s == '+' || *s == '-') s++; // sign
const char *first_non_digit = SkipDigits(s, ThisTokEnd);
if (first_non_digit == s) {
Diag(Tok, diag::err_exponent_has_no_digits);
return ExprResult(true);
} else {
s = first_non_digit;
}
}
}
const char *suffix_start = s;
if (saw_period || saw_exponent) {
bool saw_float_suffix = false, saw_long_suffix = false;
if (ActualLength == 1)
return ExprResult(new IntegerLiteral(atoi(ThisTokBegin)));
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') {
saw_long_suffix = true;
s++;
}
if (s != ThisTokEnd) {
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, saw_long = false, saw_longlong = false;
// 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) break; // only allowed to have one
saw_unsigned = true;
s++;
} else if (*s == 'l' || *s == 'L') {
if (saw_long || saw_longlong) break; // only allowed to have one
s++;
if (s < ThisTokEnd && (*s == *(s-1))) {
saw_longlong = true; // l's need to be adjacent and same case.
s++;
} else {
saw_long = true;
}
} else {
break;
}
}
if (s != ThisTokEnd) {
Diag(Tok, diag::err_invalid_suffix_integer_constant,
std::string(suffix_start, ThisTokEnd));
return ExprResult(true);
}
literal_expr = new IntegerLiteral();
NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength,
Tok.getLocation(), PP, Context.Target);
if (Literal.hadError) {
return ExprResult(true);
}
Expr *literal_expr;
if (Literal.isIntegerLiteral()) {
TypeRef t;
if (Literal.hasSuffix()) {
if (Literal.isLong)
t = Literal.isUnsigned ? Context.UnsignedLongTy : Context.LongTy;
else if (Literal.isLongLong)
t = Literal.isUnsigned ? Context.UnsignedLongLongTy : Context.LongLongTy;
else
t = Context.UnsignedIntTy;
} else {
t = Context.IntTy; // implicit type is "int"
}
intmax_t val;
if (Literal.GetValue(val)) {
literal_expr = new IntegerLiteral(val, t);
}
} else if (Literal.isFloatingLiteral()) {
// TODO: add floating point processing...
}
return ExprResult(literal_expr);
}
Action::ExprResult Sema::ParseParenExpr(SourceLocation L, SourceLocation R,

View File

@ -8,6 +8,8 @@
/* Begin PBXBuildFile section */
1A30A9E90B93A4C800201A91 /* ExprCXX.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1A30A9E80B93A4C800201A91 /* ExprCXX.h */; };
1A869A700BA2164C008DA07A /* LiteralSupport.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1A869A6E0BA2164C008DA07A /* LiteralSupport.h */; };
1A869AA80BA21ABA008DA07A /* LiteralSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */; };
DE01DA490B12ADA300AC22CE /* PPCallbacks.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE01DA480B12ADA300AC22CE /* PPCallbacks.h */; };
DE06B73E0A8307640050E87E /* LangOptions.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE06B73D0A8307640050E87E /* LangOptions.h */; };
DE06BECB0A854E4B0050E87E /* Scope.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE06BECA0A854E4B0050E87E /* Scope.h */; };
@ -145,6 +147,7 @@
DED67AEE0B6DB92A00AAD4A3 /* X86Builtins.def in CopyFiles */,
DED67AF00B6DB92F00AAD4A3 /* PPCBuiltins.def in CopyFiles */,
1A30A9E90B93A4C800201A91 /* ExprCXX.h in CopyFiles */,
1A869A700BA2164C008DA07A /* LiteralSupport.h in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 1;
};
@ -152,6 +155,8 @@
/* Begin PBXFileReference section */
1A30A9E80B93A4C800201A91 /* ExprCXX.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ExprCXX.h; path = clang/AST/ExprCXX.h; sourceTree = "<group>"; };
1A869A6E0BA2164C008DA07A /* LiteralSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiteralSupport.h; sourceTree = "<group>"; };
1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LiteralSupport.cpp; sourceTree = "<group>"; };
8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = clang; sourceTree = BUILT_PRODUCTS_DIR; };
DE01DA480B12ADA300AC22CE /* PPCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PPCallbacks.h; sourceTree = "<group>"; };
DE06B73D0A8307640050E87E /* LangOptions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LangOptions.h; sourceTree = "<group>"; };
@ -415,6 +420,7 @@
DED7D73F0A524295003AD0FB /* Pragma.h */,
DED7D7400A524295003AD0FB /* Preprocessor.h */,
DED7D9170A52518C003AD0FB /* ScratchBuffer.h */,
1A869A6E0BA2164C008DA07A /* LiteralSupport.h */,
);
name = Lex;
path = clang/Lex;
@ -436,6 +442,7 @@
DED7D78C0A5242E6003AD0FB /* Lex */ = {
isa = PBXGroup;
children = (
1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */,
DE344B530AE5E46C00DBC861 /* HeaderSearch.cpp */,
DED7D79D0A5242E6003AD0FB /* IdentifierTable.cpp */,
DED7D79E0A5242E6003AD0FB /* Lexer.cpp */,
@ -534,6 +541,7 @@
DE17336E0B068DC20080B521 /* DeclSpec.cpp in Sources */,
DE1737A90B0847BC0080B521 /* SemaType.cpp in Sources */,
DED677C90B6C854100AAD4A3 /* Builtins.cpp in Sources */,
1A869AA80BA21ABA008DA07A /* LiteralSupport.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -60,9 +60,30 @@ public:
static bool classof(const DeclRefExpr *) { return true; }
};
// FIXME: The "type" will eventually be moved to Stmt.
class IntegerLiteral : public Expr {
TypeRef Type; // IntTy, LongTy, LongLongTy
// UnsignedIntTy, UnsignedLongTy, UnsignedLongLongTy
intmax_t Value;
public:
IntegerLiteral() : Expr(IntegerLiteralClass) {}
// FIXME: To satisfy some of the current adhoc usage...
IntegerLiteral() : Expr(IntegerLiteralClass),
Type(0), Value(0) {
}
// constructor for the single digit case
IntegerLiteral(intmax_t value) : Expr(IntegerLiteralClass),
Type(0), Value(value) {
}
IntegerLiteral(intmax_t value, TypeRef type)
: Expr(IntegerLiteralClass), Type(type), Value(value) {
#if 0
std::cout << "Value=" << Value;
std::cout << " Type= ";
std::cout << static_cast<BuiltinType *>(type.getTypePtr())->getName();
std::cout << "\n";
#endif
}
virtual void visit(StmtVisitor &Visitor);
static bool classof(const Stmt *T) {
return T->getStmtClass() == IntegerLiteralClass;

View File

@ -0,0 +1,101 @@
//===--- LiteralSupport.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Steve Naroff and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the NumericLiteralParser interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LITERALSUPPORT_H
#define LLVM_CLANG_LITERALSUPPORT_H
#include "clang/Lex/Preprocessor.h"
namespace llvm {
namespace clang {
class Diagnostic;
class Preprocessor;
class TargetInfo;
struct NumericLiteralParser {
NumericLiteralParser(const char *begin, const char *end,
SourceLocation Loc, Preprocessor &PP, TargetInfo &T);
private:
Preprocessor &PP; // needed for diagnostics
TargetInfo &Target; // needed to compute the size
const char *const ThisTokBegin;
const char *const ThisTokEnd;
const char *DigitsBegin, *SuffixBegin; // markers
const char *s; // cursor
unsigned int radix;
bool saw_exponent, saw_period;
bool saw_float_suffix;
public:
bool hadError;
bool isUnsigned;
bool isLong;
bool isLongLong;
bool isIntegerLiteral() {
return !saw_period && !saw_exponent ? true : false;
}
bool isFloatingLiteral() {
return saw_period || saw_exponent ? true : false;
}
bool hasSuffix() {
return SuffixBegin != ThisTokEnd;
}
/// getValue - Convert the string into a number. At this point, we know
/// the digit characters are valid (0...9, a...f, A...F). We don't know
/// how many bits are needed to store the number. We return true if the
/// value fit into intmax_t (typically 64-bit's), false otherwise. This
/// API will likely be replaced by sizing hooks and APInt. Nevertheless,
/// this provides basic conversion support for now.
bool GetValue(intmax_t &val);
private:
void Diag(SourceLocation Loc, unsigned DiagID,
const std::string &M = std::string()) {
PP.Diag(Loc, DiagID, M);
hadError = true;
}
/// SkipHexDigits - Read and skip over any hex digits, up to End.
/// Return a pointer to the first non-hex digit or End.
const char *SkipHexDigits(const char *ptr) {
while (ptr != ThisTokEnd && isxdigit(*ptr))
ptr++;
return ptr;
}
/// SkipOctalDigits - Read and skip over any octal digits, up to End.
/// Return a pointer to the first non-hex digit or End.
const char *SkipOctalDigits(const char *ptr) {
while (ptr != ThisTokEnd && ((*ptr >= '0') && (*ptr <= '7')))
ptr++;
return ptr;
}
/// SkipDigits - Read and skip over any digits, up to End.
/// Return a pointer to the first non-hex digit or End.
const char *SkipDigits(const char *ptr) {
while (ptr != ThisTokEnd && isdigit(*ptr))
ptr++;
return ptr;
}
};
} // end namespace clang
} // end namespace llvm
#endif