Now, instead of keeping a pointer to the start of the token in memory, we keep the start of the token as a SourceLocation node. This means that each LexerToken knows the full include stack it was created with, and means that the LexerToken isn't reliant on a "CurLexer" member to be around (lexer tokens would previously go out of scope when their lexers were deallocated). This simplifies several things, and forces good cleanup elsewhere. Now the Preprocessor is the one that knows how to dump tokens/macros and is the one that knows how to get the spelling of a token (it has all the context). llvm-svn: 38551
354 lines
11 KiB
C++
354 lines
11 KiB
C++
//===--- PPExpressions.cpp - Preprocessor Expression Evaluation -----------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file was developed by Chris Lattner and is distributed under
|
|
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the Preprocessor::EvaluateDirectiveExpression method.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "clang/Lex/Preprocessor.h"
|
|
#include "clang/Basic/TokenKinds.h"
|
|
#include "clang/Basic/Diagnostic.h"
|
|
using namespace llvm;
|
|
using namespace clang;
|
|
|
|
/// EvaluateDirectiveExpression - Evaluate an integer constant expression that
|
|
/// may occur after a #if or #elif directive. Sets Result to the result of
|
|
/// the expression. Returns false normally, true if lexing must be aborted.
|
|
///
|
|
/// MinPrec is the minimum precedence that this range of the expression is
|
|
/// allowed to include.
|
|
bool Preprocessor::EvaluateDirectiveExpression() {
|
|
// Peek ahead one token.
|
|
LexerToken Tok;
|
|
Lex(Tok);
|
|
|
|
int ResVal = 0;
|
|
if (EvaluateValue(ResVal, Tok) ||
|
|
EvaluateDirectiveSubExpr(ResVal, 1, Tok)) {
|
|
// Skip the rest of the macro line.
|
|
if (Tok.getKind() != tok::eom)
|
|
DiscardUntilEndOfDirective();
|
|
return false;
|
|
}
|
|
|
|
// If we aren't at the tok::eom token, something bad happened, like an extra
|
|
// ')' token.
|
|
if (Tok.getKind() != tok::eom) {
|
|
Diag(Tok, diag::err_pp_expected_eol);
|
|
DiscardUntilEndOfDirective();
|
|
}
|
|
|
|
return ResVal != 0;
|
|
}
|
|
|
|
/// EvaluateValue - Evaluate the token PeekTok (and any others needed) and
|
|
/// return the computed value in Result. Return true if there was an error
|
|
/// parsing.
|
|
bool Preprocessor::EvaluateValue(int &Result, LexerToken &PeekTok) {
|
|
Result = 0;
|
|
|
|
// If this token's spelling is a pp-identifier, check to see if it is
|
|
// 'defined' or if it is a macro. Note that we check here because many
|
|
// keywords are pp-identifiers, so we can't check the kind.
|
|
if (const IdentifierTokenInfo *II = PeekTok.getIdentifierInfo()) {
|
|
// If this identifier isn't 'defined' and it wasn't macro expanded, it turns
|
|
// into a simple 0.
|
|
if (strcmp(II->getName(), "defined")) {
|
|
Result = 0;
|
|
Lex(PeekTok);
|
|
return false;
|
|
}
|
|
|
|
// Handle "defined X" and "defined(X)".
|
|
assert(!DisableMacroExpansion &&
|
|
"How could macro exp already be disabled?");
|
|
// Turn off macro expansion.
|
|
DisableMacroExpansion = true;
|
|
|
|
// Get the next token.
|
|
Lex(PeekTok);
|
|
|
|
// Two options, it can either be a pp-identifier or a (.
|
|
bool InParens = false;
|
|
if (PeekTok.getKind() == tok::l_paren) {
|
|
// Found a paren, remember we saw it and skip it.
|
|
InParens = true;
|
|
Lex(PeekTok);
|
|
}
|
|
|
|
// If we don't have a pp-identifier now, this is an error.
|
|
if ((II = PeekTok.getIdentifierInfo()) == 0) {
|
|
DisableMacroExpansion = false;
|
|
Diag(PeekTok, diag::err_pp_defined_requires_identifier);
|
|
return true;
|
|
}
|
|
|
|
// Otherwise, we got an identifier, is it defined to something?
|
|
Result = II->getMacroInfo() != 0;
|
|
|
|
// Consume identifier.
|
|
Lex(PeekTok);
|
|
|
|
// If we are in parens, ensure we have a trailing ).
|
|
if (InParens) {
|
|
if (PeekTok.getKind() != tok::r_paren) {
|
|
Diag(PeekTok, diag::err_pp_missing_rparen);
|
|
return true;
|
|
}
|
|
// Consume the ).
|
|
Lex(PeekTok);
|
|
}
|
|
|
|
DisableMacroExpansion = false;
|
|
return false;
|
|
}
|
|
|
|
switch (PeekTok.getKind()) {
|
|
default: // Non-value token.
|
|
Diag(PeekTok, diag::err_pp_expr_bad_token);
|
|
return true;
|
|
case tok::eom:
|
|
case tok::r_paren:
|
|
// If there is no expression, report and exit.
|
|
Diag(PeekTok, diag::err_pp_expected_value_in_expr);
|
|
return true;
|
|
case tok::numeric_constant: {
|
|
// FIXME: faster. FIXME: track signs.
|
|
std::string Spell = getSpelling(PeekTok);
|
|
// FIXME: COMPUTE integer constants CORRECTLY.
|
|
Result = atoi(Spell.c_str());
|
|
Lex(PeekTok);
|
|
return false;
|
|
}
|
|
case tok::l_paren:
|
|
Lex(PeekTok); // Eat the (.
|
|
// Parse the value and if there are any binary operators involved, parse
|
|
// them.
|
|
if (EvaluateValue(Result, PeekTok) ||
|
|
EvaluateDirectiveSubExpr(Result, 1, PeekTok))
|
|
return true;
|
|
|
|
if (PeekTok.getKind() != tok::r_paren) {
|
|
Diag(PeekTok, diag::err_pp_expected_rparen);
|
|
return true;
|
|
}
|
|
Lex(PeekTok); // Eat the ).
|
|
return false;
|
|
|
|
case tok::plus:
|
|
// Unary plus doesn't modify the value.
|
|
Lex(PeekTok);
|
|
return EvaluateValue(Result, PeekTok);
|
|
case tok::minus:
|
|
Lex(PeekTok);
|
|
if (EvaluateValue(Result, PeekTok)) return true;
|
|
Result = -Result;
|
|
return false;
|
|
|
|
case tok::tilde:
|
|
Lex(PeekTok);
|
|
if (EvaluateValue(Result, PeekTok)) return true;
|
|
Result = ~Result;
|
|
return false;
|
|
|
|
case tok::exclaim:
|
|
Lex(PeekTok);
|
|
if (EvaluateValue(Result, PeekTok)) return true;
|
|
Result = !Result;
|
|
return false;
|
|
|
|
// FIXME: Handle #assert
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// getPrecedence - Return the precedence of the specified binary operator
|
|
/// token. This returns:
|
|
/// ~0 - Invalid token.
|
|
/// 15 - *,/,%
|
|
/// 14 - -,+
|
|
/// 13 - <<,>>
|
|
/// 12 - >=, <=, >, <
|
|
/// 11 - ==, !=
|
|
/// 10 - <?, >? min, max (GCC extensions)
|
|
/// 9 - &
|
|
/// 8 - ^
|
|
/// 7 - |
|
|
/// 6 - &&
|
|
/// 5 - ||
|
|
/// 4 - ?
|
|
/// 3 - :
|
|
/// 0 - eom, )
|
|
static unsigned getPrecedence(tok::TokenKind Kind) {
|
|
switch (Kind) {
|
|
default: return ~0U;
|
|
case tok::percent:
|
|
case tok::slash:
|
|
case tok::star: return 15;
|
|
case tok::plus:
|
|
case tok::minus: return 14;
|
|
case tok::lessless:
|
|
case tok::greatergreater: return 13;
|
|
case tok::lessequal:
|
|
case tok::less:
|
|
case tok::greaterequal:
|
|
case tok::greater: return 12;
|
|
case tok::exclaimequal:
|
|
case tok::equalequal: return 11;
|
|
case tok::lessquestion:
|
|
case tok::greaterquestion: return 10;
|
|
case tok::amp: return 9;
|
|
case tok::caret: return 8;
|
|
case tok::pipe: return 7;
|
|
case tok::ampamp: return 6;
|
|
case tok::pipepipe: return 5;
|
|
case tok::question: return 4;
|
|
case tok::colon: return 3;
|
|
case tok::comma: return 2;
|
|
case tok::r_paren: return 0; // Lowest priority, end of expr.
|
|
case tok::eom: return 0; // Lowest priority, end of macro.
|
|
}
|
|
}
|
|
|
|
|
|
/// EvaluateDirectiveSubExpr - Evaluate the subexpression whose first token is
|
|
/// PeekTok, and whose precedence is PeekPrec.
|
|
bool Preprocessor::EvaluateDirectiveSubExpr(int &LHS, unsigned MinPrec,
|
|
LexerToken &PeekTok) {
|
|
unsigned PeekPrec = getPrecedence(PeekTok.getKind());
|
|
// If this token isn't valid, report the error.
|
|
if (PeekPrec == ~0U) {
|
|
Diag(PeekTok, diag::err_pp_expr_bad_token);
|
|
return true;
|
|
}
|
|
|
|
while (1) {
|
|
// If this token has a lower precedence than we are allowed to parse, return
|
|
// it so that higher levels of the recursion can parse it.
|
|
if (PeekPrec < MinPrec)
|
|
return false;
|
|
|
|
tok::TokenKind Operator = PeekTok.getKind();
|
|
|
|
// Consume the operator, saving the operator token for error reporting.
|
|
LexerToken OpToken = PeekTok;
|
|
Lex(PeekTok);
|
|
|
|
int RHS;
|
|
// Parse the RHS of the operator.
|
|
if (EvaluateValue(RHS, PeekTok)) return true;
|
|
|
|
// Remember the precedence of this operator and get the precedence of the
|
|
// operator immediately to the right of the RHS.
|
|
unsigned ThisPrec = PeekPrec;
|
|
PeekPrec = getPrecedence(PeekTok.getKind());
|
|
|
|
// If this token isn't valid, report the error.
|
|
if (PeekPrec == ~0U) {
|
|
Diag(PeekTok, diag::err_pp_expr_bad_token);
|
|
return true;
|
|
}
|
|
|
|
bool isRightAssoc = Operator == tok::question;
|
|
|
|
// Get the precedence of the operator to the right of the RHS. If it binds
|
|
// more tightly with RHS than we do, evaluate it completely first.
|
|
if (ThisPrec < PeekPrec ||
|
|
(ThisPrec == PeekPrec && isRightAssoc)) {
|
|
if (EvaluateDirectiveSubExpr(RHS, ThisPrec+1, PeekTok))
|
|
return true;
|
|
PeekPrec = getPrecedence(PeekTok.getKind());
|
|
}
|
|
assert(PeekPrec <= ThisPrec && "Recursion didn't work!");
|
|
|
|
switch (Operator) {
|
|
default: assert(0 && "Unknown operator token!");
|
|
case tok::percent:
|
|
if (RHS == 0) {
|
|
Diag(OpToken, diag::err_pp_remainder_by_zero);
|
|
return true;
|
|
}
|
|
LHS %= RHS;
|
|
break;
|
|
case tok::slash:
|
|
if (RHS == 0) {
|
|
Diag(OpToken, diag::err_pp_division_by_zero);
|
|
return true;
|
|
}
|
|
LHS /= RHS;
|
|
break;
|
|
case tok::star : LHS *= RHS; break;
|
|
case tok::lessless: LHS << RHS; break; // FIXME: shift amt overflow?
|
|
case tok::greatergreater: LHS >> RHS; break; // FIXME: signed vs unsigned
|
|
case tok::plus : LHS += RHS; break;
|
|
case tok::minus: LHS -= RHS; break;
|
|
case tok::lessequal: LHS = LHS <= RHS; break;
|
|
case tok::less: LHS = LHS < RHS; break;
|
|
case tok::greaterequal: LHS = LHS >= RHS; break;
|
|
case tok::greater: LHS = LHS > RHS; break;
|
|
case tok::exclaimequal: LHS = LHS != RHS; break;
|
|
case tok::equalequal: LHS = LHS == RHS; break;
|
|
case tok::lessquestion: // Deprecation warning emitted by the lexer.
|
|
LHS = std::min(LHS, RHS);
|
|
break;
|
|
case tok::greaterquestion: // Deprecation warning emitted by the lexer.
|
|
LHS = std::max(LHS, RHS);
|
|
break;
|
|
case tok::amp: LHS &= RHS; break;
|
|
case tok::caret: LHS ^= RHS; break;
|
|
case tok::pipe: LHS |= RHS; break;
|
|
case tok::ampamp: LHS = LHS && RHS; break;
|
|
case tok::pipepipe: LHS = LHS || RHS; break;
|
|
case tok::comma:
|
|
Diag(OpToken, diag::ext_pp_comma_expr);
|
|
LHS = RHS; // LHS = LHS,RHS -> RHS.
|
|
break;
|
|
case tok::question: {
|
|
// Parse the : part of the expression.
|
|
if (PeekTok.getKind() != tok::colon) {
|
|
Diag(OpToken, diag::err_pp_question_without_colon);
|
|
return true;
|
|
}
|
|
// Consume the :.
|
|
Lex(PeekTok);
|
|
|
|
// Evaluate the value after the :.
|
|
int AfterColonVal = 0;
|
|
if (EvaluateValue(AfterColonVal, PeekTok)) return true;
|
|
|
|
// Parse anything after the : RHS that has a higher precedence than ?.
|
|
if (EvaluateDirectiveSubExpr(AfterColonVal, ThisPrec+1,
|
|
PeekTok))
|
|
return true;
|
|
|
|
// Now that we have the condition, the LHS and the RHS of the :, evaluate.
|
|
LHS = LHS ? RHS : AfterColonVal;
|
|
|
|
// Figure out the precedence of the token after the : part.
|
|
PeekPrec = getPrecedence(PeekTok.getKind());
|
|
break;
|
|
}
|
|
case tok::colon:
|
|
// Don't allow :'s to float around without being part of ?: exprs.
|
|
Diag(OpToken, diag::err_pp_colon_without_question);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|