Submitted by:
Reviewed by:
-Converted the preprocessor to use NumericLiteralParser.
-Several minor changes to LiteralSupport interface/implementation.
-Added an error diagnostic for floating point usage in pp expr's.

llvm-svn: 39352
This commit is contained in:
Steve Naroff 2007-03-12 23:22:38 +00:00
parent 09ef474197
commit 451d8f1626
6 changed files with 68 additions and 36 deletions

View File

@ -305,11 +305,8 @@ Action::ExprResult Sema::ParseNumericConstant(const LexerToken &Tok) {
return ExprResult(new IntegerLiteral(atoi(ThisTokBegin)));
NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength,
Tok.getLocation(), PP, Context.Target);
if (Literal.hadError) {
return ExprResult(true);
}
Expr *literal_expr;
Tok.getLocation(), PP);
Expr *literal_expr = 0;
if (Literal.isIntegerLiteral()) {
TypeRef t;
@ -323,13 +320,14 @@ Action::ExprResult Sema::ParseNumericConstant(const LexerToken &Tok) {
} else {
t = Context.IntTy; // implicit type is "int"
}
intmax_t val;
if (Literal.GetValue(val)) {
uintmax_t val;
if (Literal.GetIntegerValue(val)) {
literal_expr = new IntegerLiteral(val, t);
}
} else if (Literal.isFloatingLiteral()) {
// TODO: add floating point processing...
}
return literal_expr ? ExprResult(literal_expr) : ExprResult(true);
}
Action::ExprResult Sema::ParseParenExpr(SourceLocation L, SourceLocation R,

View File

@ -60,8 +60,8 @@ using namespace clang;
NumericLiteralParser::
NumericLiteralParser(const char *begin, const char *end,
SourceLocation TokLoc, Preprocessor &pp, TargetInfo &t) :
PP(pp), Target(t), ThisTokBegin(begin), ThisTokEnd(end)
SourceLocation TokLoc, Preprocessor &pp) :
PP(pp), ThisTokBegin(begin), ThisTokEnd(end)
{
s = DigitsBegin = begin;
saw_exponent = false;
@ -216,13 +216,38 @@ NumericLiteralParser(const char *begin, const char *end,
}
}
bool NumericLiteralParser::GetValue(intmax_t &val) {
intmax_t cutoff = INTMAX_MAX;
int cutlim = cutoff % radix;
bool NumericLiteralParser::GetIntegerValue(uintmax_t &val) {
uintmax_t cutoff = UINTMAX_MAX / radix;
int cutlim = UINTMAX_MAX % radix;
char c;
val = 0;
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;
}
bool NumericLiteralParser::GetIntegerValue(int &val) {
intmax_t cutoff = INT_MAX / radix;
int cutlim = INT_MAX % radix;
char c;
val = 0;
cutoff /= radix;
s = DigitsBegin;
while (s < SuffixBegin) {
c = *s++;

View File

@ -13,7 +13,6 @@
//===----------------------------------------------------------------------===//
//
// FIXME: implement testing for asserts.
// FIXME: Parse integer constants correctly. Reject 123.0, etc.
// FIXME: Track signed/unsigned correctly.
// FIXME: Track and report integer overflow correctly.
//
@ -21,9 +20,11 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/ADT/SmallString.h"
using namespace llvm;
using namespace clang;
@ -144,10 +145,18 @@ static bool EvaluateValue(int &Result, LexerToken &PeekTok, DefinedTracker &DT,
PP.Diag(PeekTok, diag::err_pp_expected_value_in_expr);
return true;
case tok::numeric_constant: {
// FIXME: faster. FIXME: track signs.
std::string Spell = PP.getSpelling(PeekTok);
// FIXME: COMPUTE integer constants CORRECTLY.
Result = atoi(Spell.c_str());
// FIXME: track signs. ?? snaroff: talk to Chris...
SmallString<512> IntegerBuffer;
IntegerBuffer.resize(PeekTok.getLength());
const char *ThisTokBegin = &IntegerBuffer[0];
unsigned ActualLength = PP.getSpelling(PeekTok, ThisTokBegin);
NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength,
PeekTok.getLocation(), PP);
if (Literal.isIntegerLiteral()) {
Literal.GetIntegerValue(Result);
} else if (Literal.isFloatingLiteral()) {
PP.Diag(PeekTok, diag::err_pp_illegal_floating_literal);
}
PP.LexNonComment(PeekTok);
return false;
}

View File

@ -305,11 +305,8 @@ Action::ExprResult Sema::ParseNumericConstant(const LexerToken &Tok) {
return ExprResult(new IntegerLiteral(atoi(ThisTokBegin)));
NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength,
Tok.getLocation(), PP, Context.Target);
if (Literal.hadError) {
return ExprResult(true);
}
Expr *literal_expr;
Tok.getLocation(), PP);
Expr *literal_expr = 0;
if (Literal.isIntegerLiteral()) {
TypeRef t;
@ -323,13 +320,14 @@ Action::ExprResult Sema::ParseNumericConstant(const LexerToken &Tok) {
} else {
t = Context.IntTy; // implicit type is "int"
}
intmax_t val;
if (Literal.GetValue(val)) {
uintmax_t val;
if (Literal.GetIntegerValue(val)) {
literal_expr = new IntegerLiteral(val, t);
}
} else if (Literal.isFloatingLiteral()) {
// TODO: add floating point processing...
}
return literal_expr ? ExprResult(literal_expr) : ExprResult(true);
}
Action::ExprResult Sema::ParseParenExpr(SourceLocation L, SourceLocation R,

View File

@ -237,6 +237,8 @@ DIAG(err_pp_bad_paste, ERROR,
"pasting formed \"%s\", an invalid preprocessing token")
DIAG(err_pp_operator_used_as_macro_name, ERROR,
"C++ operator \"%s\" cannot be used as a macro name")
DIAG(err_pp_illegal_floating_literal, ERROR,
"floating point literal in preprocessor expression")
// Should be a sorry?
DIAG(err_pp_I_dash_not_supported, ERROR,

View File

@ -25,10 +25,9 @@ class TargetInfo;
struct NumericLiteralParser {
NumericLiteralParser(const char *begin, const char *end,
SourceLocation Loc, Preprocessor &PP, TargetInfo &T);
SourceLocation Loc, Preprocessor &PP);
private:
Preprocessor &PP; // needed for diagnostics
TargetInfo &Target; // needed to compute the size
const char *const ThisTokBegin;
const char *const ThisTokEnd;
@ -47,21 +46,22 @@ public:
bool isLongLong;
bool isIntegerLiteral() {
return !saw_period && !saw_exponent ? true : false;
return !saw_period && !saw_exponent && !hadError ? true : false;
}
bool isFloatingLiteral() {
return saw_period || saw_exponent ? true : false;
return saw_period || saw_exponent && !hadError ? 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);
/// getIntegerValue - 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. Sizing of the integer
/// type (int, unsigned, long, unsigned long, long long, unsigned long long)
/// will be done elsewhere - the computation is target dependent. We return
/// true if the value fit into uintmax_t, false otherwise.
bool GetIntegerValue(uintmax_t &val);
bool GetIntegerValue(int &val);
private:
void Diag(SourceLocation Loc, unsigned DiagID,