
Diagnostic pragmas are broken because we don't keep track of the diagnostic state changes and we only check the current/latest state. Problems manifest if a diagnostic is emitted for a source line that has different diagnostic state than the current state; this can affect a lot of places, like C++ inline methods, template instantiations, the lexer, etc. Fix the issue by having the Diagnostic object keep track of the source location of the pragmas so that it is able to know what is the diagnostic state at any given source location. Fixes rdar://8365684. llvm-svn: 121873
763 lines
27 KiB
C++
763 lines
27 KiB
C++
//===--- PPExpressions.cpp - Preprocessor Expression Evaluation -----------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the Preprocessor::EvaluateDirectiveExpression method,
|
|
// which parses and evaluates integer constant expressions for #if directives.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// FIXME: implement testing for #assert's.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "clang/Lex/Preprocessor.h"
|
|
#include "clang/Lex/MacroInfo.h"
|
|
#include "clang/Lex/LiteralSupport.h"
|
|
#include "clang/Lex/CodeCompletionHandler.h"
|
|
#include "clang/Basic/TargetInfo.h"
|
|
#include "clang/Lex/LexDiagnostic.h"
|
|
#include "llvm/ADT/APSInt.h"
|
|
using namespace clang;
|
|
|
|
namespace {
|
|
|
|
/// PPValue - Represents the value of a subexpression of a preprocessor
|
|
/// conditional and the source range covered by it.
|
|
class PPValue {
|
|
SourceRange Range;
|
|
public:
|
|
llvm::APSInt Val;
|
|
|
|
// Default ctor - Construct an 'invalid' PPValue.
|
|
PPValue(unsigned BitWidth) : Val(BitWidth) {}
|
|
|
|
unsigned getBitWidth() const { return Val.getBitWidth(); }
|
|
bool isUnsigned() const { return Val.isUnsigned(); }
|
|
|
|
const SourceRange &getRange() const { return Range; }
|
|
|
|
void setRange(SourceLocation L) { Range.setBegin(L); Range.setEnd(L); }
|
|
void setRange(SourceLocation B, SourceLocation E) {
|
|
Range.setBegin(B); Range.setEnd(E);
|
|
}
|
|
void setBegin(SourceLocation L) { Range.setBegin(L); }
|
|
void setEnd(SourceLocation L) { Range.setEnd(L); }
|
|
};
|
|
|
|
}
|
|
|
|
static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
|
|
Token &PeekTok, bool ValueLive,
|
|
Preprocessor &PP);
|
|
|
|
/// DefinedTracker - This struct is used while parsing expressions to keep track
|
|
/// of whether !defined(X) has been seen.
|
|
///
|
|
/// With this simple scheme, we handle the basic forms:
|
|
/// !defined(X) and !defined X
|
|
/// but we also trivially handle (silly) stuff like:
|
|
/// !!!defined(X) and +!defined(X) and !+!+!defined(X) and !(defined(X)).
|
|
struct DefinedTracker {
|
|
/// Each time a Value is evaluated, it returns information about whether the
|
|
/// parsed value is of the form defined(X), !defined(X) or is something else.
|
|
enum TrackerState {
|
|
DefinedMacro, // defined(X)
|
|
NotDefinedMacro, // !defined(X)
|
|
Unknown // Something else.
|
|
} State;
|
|
/// TheMacro - When the state is DefinedMacro or NotDefinedMacro, this
|
|
/// indicates the macro that was checked.
|
|
IdentifierInfo *TheMacro;
|
|
};
|
|
|
|
/// EvaluateDefined - Process a 'defined(sym)' expression.
|
|
static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
|
|
bool ValueLive, Preprocessor &PP) {
|
|
IdentifierInfo *II;
|
|
Result.setBegin(PeekTok.getLocation());
|
|
|
|
// Get the next token, don't expand it.
|
|
PP.LexUnexpandedToken(PeekTok);
|
|
|
|
// Two options, it can either be a pp-identifier or a (.
|
|
SourceLocation LParenLoc;
|
|
if (PeekTok.is(tok::l_paren)) {
|
|
// Found a paren, remember we saw it and skip it.
|
|
LParenLoc = PeekTok.getLocation();
|
|
PP.LexUnexpandedToken(PeekTok);
|
|
}
|
|
|
|
if (PeekTok.is(tok::code_completion)) {
|
|
if (PP.getCodeCompletionHandler())
|
|
PP.getCodeCompletionHandler()->CodeCompleteMacroName(false);
|
|
PP.LexUnexpandedToken(PeekTok);
|
|
}
|
|
|
|
// If we don't have a pp-identifier now, this is an error.
|
|
if ((II = PeekTok.getIdentifierInfo()) == 0) {
|
|
PP.Diag(PeekTok, diag::err_pp_defined_requires_identifier);
|
|
return true;
|
|
}
|
|
|
|
// Otherwise, we got an identifier, is it defined to something?
|
|
Result.Val = II->hasMacroDefinition();
|
|
Result.Val.setIsUnsigned(false); // Result is signed intmax_t.
|
|
|
|
// If there is a macro, mark it used.
|
|
if (Result.Val != 0 && ValueLive) {
|
|
MacroInfo *Macro = PP.getMacroInfo(II);
|
|
PP.markMacroAsUsed(Macro);
|
|
}
|
|
|
|
// Consume identifier.
|
|
Result.setEnd(PeekTok.getLocation());
|
|
PP.LexUnexpandedToken(PeekTok);
|
|
|
|
// If we are in parens, ensure we have a trailing ).
|
|
if (LParenLoc.isValid()) {
|
|
if (PeekTok.isNot(tok::r_paren)) {
|
|
PP.Diag(PeekTok.getLocation(), diag::err_pp_missing_rparen) << "defined";
|
|
PP.Diag(LParenLoc, diag::note_matching) << "(";
|
|
return true;
|
|
}
|
|
// Consume the ).
|
|
Result.setEnd(PeekTok.getLocation());
|
|
PP.LexNonComment(PeekTok);
|
|
}
|
|
|
|
// Success, remember that we saw defined(X).
|
|
DT.State = DefinedTracker::DefinedMacro;
|
|
DT.TheMacro = II;
|
|
return false;
|
|
}
|
|
|
|
/// EvaluateValue - Evaluate the token PeekTok (and any others needed) and
|
|
/// return the computed value in Result. Return true if there was an error
|
|
/// parsing. This function also returns information about the form of the
|
|
/// expression in DT. See above for information on what DT means.
|
|
///
|
|
/// If ValueLive is false, then this value is being evaluated in a context where
|
|
/// the result is not used. As such, avoid diagnostics that relate to
|
|
/// evaluation.
|
|
static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
|
|
bool ValueLive, Preprocessor &PP) {
|
|
DT.State = DefinedTracker::Unknown;
|
|
|
|
if (PeekTok.is(tok::code_completion)) {
|
|
if (PP.getCodeCompletionHandler())
|
|
PP.getCodeCompletionHandler()->CodeCompletePreprocessorExpression();
|
|
PP.LexUnexpandedToken(PeekTok);
|
|
}
|
|
|
|
// 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 (IdentifierInfo *II = PeekTok.getIdentifierInfo()) {
|
|
// Handle "defined X" and "defined(X)".
|
|
if (II->isStr("defined"))
|
|
return(EvaluateDefined(Result, PeekTok, DT, ValueLive, PP));
|
|
|
|
// If this identifier isn't 'defined' or one of the special
|
|
// preprocessor keywords and it wasn't macro expanded, it turns
|
|
// into a simple 0, unless it is the C++ keyword "true", in which case it
|
|
// turns into "1".
|
|
if (ValueLive)
|
|
PP.Diag(PeekTok, diag::warn_pp_undef_identifier) << II;
|
|
Result.Val = II->getTokenID() == tok::kw_true;
|
|
Result.Val.setIsUnsigned(false); // "0" is signed intmax_t 0.
|
|
Result.setRange(PeekTok.getLocation());
|
|
PP.LexNonComment(PeekTok);
|
|
return false;
|
|
}
|
|
|
|
switch (PeekTok.getKind()) {
|
|
default: // Non-value token.
|
|
PP.Diag(PeekTok, diag::err_pp_expr_bad_token_start_expr);
|
|
return true;
|
|
case tok::eom:
|
|
case tok::r_paren:
|
|
// If there is no expression, report and exit.
|
|
PP.Diag(PeekTok, diag::err_pp_expected_value_in_expr);
|
|
return true;
|
|
case tok::numeric_constant: {
|
|
llvm::SmallString<64> IntegerBuffer;
|
|
bool NumberInvalid = false;
|
|
llvm::StringRef Spelling = PP.getSpelling(PeekTok, IntegerBuffer,
|
|
&NumberInvalid);
|
|
if (NumberInvalid)
|
|
return true; // a diagnostic was already reported
|
|
|
|
NumericLiteralParser Literal(Spelling.begin(), Spelling.end(),
|
|
PeekTok.getLocation(), PP);
|
|
if (Literal.hadError)
|
|
return true; // a diagnostic was already reported.
|
|
|
|
if (Literal.isFloatingLiteral() || Literal.isImaginary) {
|
|
PP.Diag(PeekTok, diag::err_pp_illegal_floating_literal);
|
|
return true;
|
|
}
|
|
assert(Literal.isIntegerLiteral() && "Unknown ppnumber");
|
|
|
|
// long long is a C99 feature.
|
|
if (!PP.getLangOptions().C99 && !PP.getLangOptions().CPlusPlus0x
|
|
&& Literal.isLongLong)
|
|
PP.Diag(PeekTok, diag::ext_longlong);
|
|
|
|
// Parse the integer literal into Result.
|
|
if (Literal.GetIntegerValue(Result.Val)) {
|
|
// Overflow parsing integer literal.
|
|
if (ValueLive) PP.Diag(PeekTok, diag::warn_integer_too_large);
|
|
Result.Val.setIsUnsigned(true);
|
|
} else {
|
|
// Set the signedness of the result to match whether there was a U suffix
|
|
// or not.
|
|
Result.Val.setIsUnsigned(Literal.isUnsigned);
|
|
|
|
// Detect overflow based on whether the value is signed. If signed
|
|
// and if the value is too large, emit a warning "integer constant is so
|
|
// large that it is unsigned" e.g. on 12345678901234567890 where intmax_t
|
|
// is 64-bits.
|
|
if (!Literal.isUnsigned && Result.Val.isNegative()) {
|
|
// Don't warn for a hex literal: 0x8000..0 shouldn't warn.
|
|
if (ValueLive && Literal.getRadix() != 16)
|
|
PP.Diag(PeekTok, diag::warn_integer_too_large_for_signed);
|
|
Result.Val.setIsUnsigned(true);
|
|
}
|
|
}
|
|
|
|
// Consume the token.
|
|
Result.setRange(PeekTok.getLocation());
|
|
PP.LexNonComment(PeekTok);
|
|
return false;
|
|
}
|
|
case tok::char_constant: { // 'x'
|
|
llvm::SmallString<32> CharBuffer;
|
|
bool CharInvalid = false;
|
|
llvm::StringRef ThisTok = PP.getSpelling(PeekTok, CharBuffer, &CharInvalid);
|
|
if (CharInvalid)
|
|
return true;
|
|
|
|
CharLiteralParser Literal(ThisTok.begin(), ThisTok.end(),
|
|
PeekTok.getLocation(), PP);
|
|
if (Literal.hadError())
|
|
return true; // A diagnostic was already emitted.
|
|
|
|
// Character literals are always int or wchar_t, expand to intmax_t.
|
|
const TargetInfo &TI = PP.getTargetInfo();
|
|
unsigned NumBits;
|
|
if (Literal.isMultiChar())
|
|
NumBits = TI.getIntWidth();
|
|
else if (Literal.isWide())
|
|
NumBits = TI.getWCharWidth();
|
|
else
|
|
NumBits = TI.getCharWidth();
|
|
|
|
// Set the width.
|
|
llvm::APSInt Val(NumBits);
|
|
// Set the value.
|
|
Val = Literal.getValue();
|
|
// Set the signedness.
|
|
Val.setIsUnsigned(!PP.getLangOptions().CharIsSigned);
|
|
|
|
if (Result.Val.getBitWidth() > Val.getBitWidth()) {
|
|
Result.Val = Val.extend(Result.Val.getBitWidth());
|
|
} else {
|
|
assert(Result.Val.getBitWidth() == Val.getBitWidth() &&
|
|
"intmax_t smaller than char/wchar_t?");
|
|
Result.Val = Val;
|
|
}
|
|
|
|
// Consume the token.
|
|
Result.setRange(PeekTok.getLocation());
|
|
PP.LexNonComment(PeekTok);
|
|
return false;
|
|
}
|
|
case tok::l_paren: {
|
|
SourceLocation Start = PeekTok.getLocation();
|
|
PP.LexNonComment(PeekTok); // Eat the (.
|
|
// Parse the value and if there are any binary operators involved, parse
|
|
// them.
|
|
if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
|
|
|
|
// If this is a silly value like (X), which doesn't need parens, check for
|
|
// !(defined X).
|
|
if (PeekTok.is(tok::r_paren)) {
|
|
// Just use DT unmodified as our result.
|
|
} else {
|
|
// Otherwise, we have something like (x+y), and we consumed '(x'.
|
|
if (EvaluateDirectiveSubExpr(Result, 1, PeekTok, ValueLive, PP))
|
|
return true;
|
|
|
|
if (PeekTok.isNot(tok::r_paren)) {
|
|
PP.Diag(PeekTok.getLocation(), diag::err_pp_expected_rparen)
|
|
<< Result.getRange();
|
|
PP.Diag(Start, diag::note_matching) << "(";
|
|
return true;
|
|
}
|
|
DT.State = DefinedTracker::Unknown;
|
|
}
|
|
Result.setRange(Start, PeekTok.getLocation());
|
|
PP.LexNonComment(PeekTok); // Eat the ).
|
|
return false;
|
|
}
|
|
case tok::plus: {
|
|
SourceLocation Start = PeekTok.getLocation();
|
|
// Unary plus doesn't modify the value.
|
|
PP.LexNonComment(PeekTok);
|
|
if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
|
|
Result.setBegin(Start);
|
|
return false;
|
|
}
|
|
case tok::minus: {
|
|
SourceLocation Loc = PeekTok.getLocation();
|
|
PP.LexNonComment(PeekTok);
|
|
if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
|
|
Result.setBegin(Loc);
|
|
|
|
// C99 6.5.3.3p3: The sign of the result matches the sign of the operand.
|
|
Result.Val = -Result.Val;
|
|
|
|
// -MININT is the only thing that overflows. Unsigned never overflows.
|
|
bool Overflow = !Result.isUnsigned() && Result.Val.isMinSignedValue();
|
|
|
|
// If this operator is live and overflowed, report the issue.
|
|
if (Overflow && ValueLive)
|
|
PP.Diag(Loc, diag::warn_pp_expr_overflow) << Result.getRange();
|
|
|
|
DT.State = DefinedTracker::Unknown;
|
|
return false;
|
|
}
|
|
|
|
case tok::tilde: {
|
|
SourceLocation Start = PeekTok.getLocation();
|
|
PP.LexNonComment(PeekTok);
|
|
if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
|
|
Result.setBegin(Start);
|
|
|
|
// C99 6.5.3.3p4: The sign of the result matches the sign of the operand.
|
|
Result.Val = ~Result.Val;
|
|
DT.State = DefinedTracker::Unknown;
|
|
return false;
|
|
}
|
|
|
|
case tok::exclaim: {
|
|
SourceLocation Start = PeekTok.getLocation();
|
|
PP.LexNonComment(PeekTok);
|
|
if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
|
|
Result.setBegin(Start);
|
|
Result.Val = !Result.Val;
|
|
// C99 6.5.3.3p5: The sign of the result is 'int', aka it is signed.
|
|
Result.Val.setIsUnsigned(false);
|
|
|
|
if (DT.State == DefinedTracker::DefinedMacro)
|
|
DT.State = DefinedTracker::NotDefinedMacro;
|
|
else if (DT.State == DefinedTracker::NotDefinedMacro)
|
|
DT.State = DefinedTracker::DefinedMacro;
|
|
return false;
|
|
}
|
|
|
|
// FIXME: Handle #assert
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// getPrecedence - Return the precedence of the specified binary operator
|
|
/// token. This returns:
|
|
/// ~0 - Invalid token.
|
|
/// 14 -> 3 - various operators.
|
|
/// 0 - 'eom' or ')'
|
|
static unsigned getPrecedence(tok::TokenKind Kind) {
|
|
switch (Kind) {
|
|
default: return ~0U;
|
|
case tok::percent:
|
|
case tok::slash:
|
|
case tok::star: return 14;
|
|
case tok::plus:
|
|
case tok::minus: return 13;
|
|
case tok::lessless:
|
|
case tok::greatergreater: return 12;
|
|
case tok::lessequal:
|
|
case tok::less:
|
|
case tok::greaterequal:
|
|
case tok::greater: return 11;
|
|
case tok::exclaimequal:
|
|
case tok::equalequal: 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::comma: return 3;
|
|
case tok::colon: 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. This returns the result in LHS.
|
|
///
|
|
/// If ValueLive is false, then this value is being evaluated in a context where
|
|
/// the result is not used. As such, avoid diagnostics that relate to
|
|
/// evaluation, such as division by zero warnings.
|
|
static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
|
|
Token &PeekTok, bool ValueLive,
|
|
Preprocessor &PP) {
|
|
unsigned PeekPrec = getPrecedence(PeekTok.getKind());
|
|
// If this token isn't valid, report the error.
|
|
if (PeekPrec == ~0U) {
|
|
PP.Diag(PeekTok.getLocation(), diag::err_pp_expr_bad_token_binop)
|
|
<< LHS.getRange();
|
|
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();
|
|
|
|
// If this is a short-circuiting operator, see if the RHS of the operator is
|
|
// dead. Note that this cannot just clobber ValueLive. Consider
|
|
// "0 && 1 ? 4 : 1 / 0", which is parsed as "(0 && 1) ? 4 : (1 / 0)". In
|
|
// this example, the RHS of the && being dead does not make the rest of the
|
|
// expr dead.
|
|
bool RHSIsLive;
|
|
if (Operator == tok::ampamp && LHS.Val == 0)
|
|
RHSIsLive = false; // RHS of "0 && x" is dead.
|
|
else if (Operator == tok::pipepipe && LHS.Val != 0)
|
|
RHSIsLive = false; // RHS of "1 || x" is dead.
|
|
else if (Operator == tok::question && LHS.Val == 0)
|
|
RHSIsLive = false; // RHS (x) of "0 ? x : y" is dead.
|
|
else
|
|
RHSIsLive = ValueLive;
|
|
|
|
// Consume the operator, remembering the operator's location for reporting.
|
|
SourceLocation OpLoc = PeekTok.getLocation();
|
|
PP.LexNonComment(PeekTok);
|
|
|
|
PPValue RHS(LHS.getBitWidth());
|
|
// Parse the RHS of the operator.
|
|
DefinedTracker DT;
|
|
if (EvaluateValue(RHS, PeekTok, DT, RHSIsLive, PP)) 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) {
|
|
PP.Diag(PeekTok.getLocation(), diag::err_pp_expr_bad_token_binop)
|
|
<< RHS.getRange();
|
|
return true;
|
|
}
|
|
|
|
// Decide whether to include the next binop in this subexpression. For
|
|
// example, when parsing x+y*z and looking at '*', we want to recursively
|
|
// handle y*z as a single subexpression. We do this because the precedence
|
|
// of * is higher than that of +. The only strange case we have to handle
|
|
// here is for the ?: operator, where the precedence is actually lower than
|
|
// the LHS of the '?'. The grammar rule is:
|
|
//
|
|
// conditional-expression ::=
|
|
// logical-OR-expression ? expression : conditional-expression
|
|
// where 'expression' is actually comma-expression.
|
|
unsigned RHSPrec;
|
|
if (Operator == tok::question)
|
|
// The RHS of "?" should be maximally consumed as an expression.
|
|
RHSPrec = getPrecedence(tok::comma);
|
|
else // All others should munch while higher precedence.
|
|
RHSPrec = ThisPrec+1;
|
|
|
|
if (PeekPrec >= RHSPrec) {
|
|
if (EvaluateDirectiveSubExpr(RHS, RHSPrec, PeekTok, RHSIsLive, PP))
|
|
return true;
|
|
PeekPrec = getPrecedence(PeekTok.getKind());
|
|
}
|
|
assert(PeekPrec <= ThisPrec && "Recursion didn't work!");
|
|
|
|
// Usual arithmetic conversions (C99 6.3.1.8p1): result is unsigned if
|
|
// either operand is unsigned.
|
|
llvm::APSInt Res(LHS.getBitWidth());
|
|
switch (Operator) {
|
|
case tok::question: // No UAC for x and y in "x ? y : z".
|
|
case tok::lessless: // Shift amount doesn't UAC with shift value.
|
|
case tok::greatergreater: // Shift amount doesn't UAC with shift value.
|
|
case tok::comma: // Comma operands are not subject to UACs.
|
|
case tok::pipepipe: // Logical || does not do UACs.
|
|
case tok::ampamp: // Logical && does not do UACs.
|
|
break; // No UAC
|
|
default:
|
|
Res.setIsUnsigned(LHS.isUnsigned()|RHS.isUnsigned());
|
|
// If this just promoted something from signed to unsigned, and if the
|
|
// value was negative, warn about it.
|
|
if (ValueLive && Res.isUnsigned()) {
|
|
if (!LHS.isUnsigned() && LHS.Val.isNegative())
|
|
PP.Diag(OpLoc, diag::warn_pp_convert_lhs_to_positive)
|
|
<< LHS.Val.toString(10, true) + " to " +
|
|
LHS.Val.toString(10, false)
|
|
<< LHS.getRange() << RHS.getRange();
|
|
if (!RHS.isUnsigned() && RHS.Val.isNegative())
|
|
PP.Diag(OpLoc, diag::warn_pp_convert_rhs_to_positive)
|
|
<< RHS.Val.toString(10, true) + " to " +
|
|
RHS.Val.toString(10, false)
|
|
<< LHS.getRange() << RHS.getRange();
|
|
}
|
|
LHS.Val.setIsUnsigned(Res.isUnsigned());
|
|
RHS.Val.setIsUnsigned(Res.isUnsigned());
|
|
}
|
|
|
|
bool Overflow = false;
|
|
switch (Operator) {
|
|
default: assert(0 && "Unknown operator token!");
|
|
case tok::percent:
|
|
if (RHS.Val != 0)
|
|
Res = LHS.Val % RHS.Val;
|
|
else if (ValueLive) {
|
|
PP.Diag(OpLoc, diag::err_pp_remainder_by_zero)
|
|
<< LHS.getRange() << RHS.getRange();
|
|
return true;
|
|
}
|
|
break;
|
|
case tok::slash:
|
|
if (RHS.Val != 0) {
|
|
if (LHS.Val.isSigned())
|
|
Res = llvm::APSInt(LHS.Val.sdiv_ov(RHS.Val, Overflow), false);
|
|
else
|
|
Res = LHS.Val / RHS.Val;
|
|
} else if (ValueLive) {
|
|
PP.Diag(OpLoc, diag::err_pp_division_by_zero)
|
|
<< LHS.getRange() << RHS.getRange();
|
|
return true;
|
|
}
|
|
break;
|
|
|
|
case tok::star:
|
|
if (Res.isSigned())
|
|
Res = llvm::APSInt(LHS.Val.smul_ov(RHS.Val, Overflow), false);
|
|
else
|
|
Res = LHS.Val * RHS.Val;
|
|
break;
|
|
case tok::lessless: {
|
|
// Determine whether overflow is about to happen.
|
|
unsigned ShAmt = static_cast<unsigned>(RHS.Val.getLimitedValue());
|
|
if (LHS.isUnsigned()) {
|
|
Overflow = ShAmt >= LHS.Val.getBitWidth();
|
|
if (Overflow)
|
|
ShAmt = LHS.Val.getBitWidth()-1;
|
|
Res = LHS.Val << ShAmt;
|
|
} else {
|
|
Res = llvm::APSInt(LHS.Val.sshl_ov(ShAmt, Overflow), false);
|
|
}
|
|
break;
|
|
}
|
|
case tok::greatergreater: {
|
|
// Determine whether overflow is about to happen.
|
|
unsigned ShAmt = static_cast<unsigned>(RHS.Val.getLimitedValue());
|
|
if (ShAmt >= LHS.getBitWidth())
|
|
Overflow = true, ShAmt = LHS.getBitWidth()-1;
|
|
Res = LHS.Val >> ShAmt;
|
|
break;
|
|
}
|
|
case tok::plus:
|
|
if (LHS.isUnsigned())
|
|
Res = LHS.Val + RHS.Val;
|
|
else
|
|
Res = llvm::APSInt(LHS.Val.sadd_ov(RHS.Val, Overflow), false);
|
|
break;
|
|
case tok::minus:
|
|
if (LHS.isUnsigned())
|
|
Res = LHS.Val - RHS.Val;
|
|
else
|
|
Res = llvm::APSInt(LHS.Val.ssub_ov(RHS.Val, Overflow), false);
|
|
break;
|
|
case tok::lessequal:
|
|
Res = LHS.Val <= RHS.Val;
|
|
Res.setIsUnsigned(false); // C99 6.5.8p6, result is always int (signed)
|
|
break;
|
|
case tok::less:
|
|
Res = LHS.Val < RHS.Val;
|
|
Res.setIsUnsigned(false); // C99 6.5.8p6, result is always int (signed)
|
|
break;
|
|
case tok::greaterequal:
|
|
Res = LHS.Val >= RHS.Val;
|
|
Res.setIsUnsigned(false); // C99 6.5.8p6, result is always int (signed)
|
|
break;
|
|
case tok::greater:
|
|
Res = LHS.Val > RHS.Val;
|
|
Res.setIsUnsigned(false); // C99 6.5.8p6, result is always int (signed)
|
|
break;
|
|
case tok::exclaimequal:
|
|
Res = LHS.Val != RHS.Val;
|
|
Res.setIsUnsigned(false); // C99 6.5.9p3, result is always int (signed)
|
|
break;
|
|
case tok::equalequal:
|
|
Res = LHS.Val == RHS.Val;
|
|
Res.setIsUnsigned(false); // C99 6.5.9p3, result is always int (signed)
|
|
break;
|
|
case tok::amp:
|
|
Res = LHS.Val & RHS.Val;
|
|
break;
|
|
case tok::caret:
|
|
Res = LHS.Val ^ RHS.Val;
|
|
break;
|
|
case tok::pipe:
|
|
Res = LHS.Val | RHS.Val;
|
|
break;
|
|
case tok::ampamp:
|
|
Res = (LHS.Val != 0 && RHS.Val != 0);
|
|
Res.setIsUnsigned(false); // C99 6.5.13p3, result is always int (signed)
|
|
break;
|
|
case tok::pipepipe:
|
|
Res = (LHS.Val != 0 || RHS.Val != 0);
|
|
Res.setIsUnsigned(false); // C99 6.5.14p3, result is always int (signed)
|
|
break;
|
|
case tok::comma:
|
|
// Comma is invalid in pp expressions in c89/c++ mode, but is valid in C99
|
|
// if not being evaluated.
|
|
if (!PP.getLangOptions().C99 || ValueLive)
|
|
PP.Diag(OpLoc, diag::ext_pp_comma_expr)
|
|
<< LHS.getRange() << RHS.getRange();
|
|
Res = RHS.Val; // LHS = LHS,RHS -> RHS.
|
|
break;
|
|
case tok::question: {
|
|
// Parse the : part of the expression.
|
|
if (PeekTok.isNot(tok::colon)) {
|
|
PP.Diag(PeekTok.getLocation(), diag::err_expected_colon)
|
|
<< LHS.getRange(), RHS.getRange();
|
|
PP.Diag(OpLoc, diag::note_matching) << "?";
|
|
return true;
|
|
}
|
|
// Consume the :.
|
|
PP.LexNonComment(PeekTok);
|
|
|
|
// Evaluate the value after the :.
|
|
bool AfterColonLive = ValueLive && LHS.Val == 0;
|
|
PPValue AfterColonVal(LHS.getBitWidth());
|
|
DefinedTracker DT;
|
|
if (EvaluateValue(AfterColonVal, PeekTok, DT, AfterColonLive, PP))
|
|
return true;
|
|
|
|
// Parse anything after the : with the same precedence as ?. We allow
|
|
// things of equal precedence because ?: is right associative.
|
|
if (EvaluateDirectiveSubExpr(AfterColonVal, ThisPrec,
|
|
PeekTok, AfterColonLive, PP))
|
|
return true;
|
|
|
|
// Now that we have the condition, the LHS and the RHS of the :, evaluate.
|
|
Res = LHS.Val != 0 ? RHS.Val : AfterColonVal.Val;
|
|
RHS.setEnd(AfterColonVal.getRange().getEnd());
|
|
|
|
// Usual arithmetic conversions (C99 6.3.1.8p1): result is unsigned if
|
|
// either operand is unsigned.
|
|
Res.setIsUnsigned(RHS.isUnsigned() | AfterColonVal.isUnsigned());
|
|
|
|
// 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.
|
|
PP.Diag(OpLoc, diag::err_pp_colon_without_question)
|
|
<< LHS.getRange() << RHS.getRange();
|
|
return true;
|
|
}
|
|
|
|
// If this operator is live and overflowed, report the issue.
|
|
if (Overflow && ValueLive)
|
|
PP.Diag(OpLoc, diag::warn_pp_expr_overflow)
|
|
<< LHS.getRange() << RHS.getRange();
|
|
|
|
// Put the result back into 'LHS' for our next iteration.
|
|
LHS.Val = Res;
|
|
LHS.setEnd(RHS.getRange().getEnd());
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// EvaluateDirectiveExpression - Evaluate an integer constant expression that
|
|
/// may occur after a #if or #elif directive. If the expression is equivalent
|
|
/// to "!defined(X)" return X in IfNDefMacro.
|
|
bool Preprocessor::
|
|
EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) {
|
|
// Save the current state of 'DisableMacroExpansion' and reset it to false. If
|
|
// 'DisableMacroExpansion' is true, then we must be in a macro argument list
|
|
// in which case a directive is undefined behavior. We want macros to be able
|
|
// to recursively expand in order to get more gcc-list behavior, so we force
|
|
// DisableMacroExpansion to false and restore it when we're done parsing the
|
|
// expression.
|
|
bool DisableMacroExpansionAtStartOfDirective = DisableMacroExpansion;
|
|
DisableMacroExpansion = false;
|
|
|
|
// Peek ahead one token.
|
|
Token Tok;
|
|
Lex(Tok);
|
|
|
|
// C99 6.10.1p3 - All expressions are evaluated as intmax_t or uintmax_t.
|
|
unsigned BitWidth = getTargetInfo().getIntMaxTWidth();
|
|
|
|
PPValue ResVal(BitWidth);
|
|
DefinedTracker DT;
|
|
if (EvaluateValue(ResVal, Tok, DT, true, *this)) {
|
|
// Parse error, skip the rest of the macro line.
|
|
if (Tok.isNot(tok::eom))
|
|
DiscardUntilEndOfDirective();
|
|
|
|
// Restore 'DisableMacroExpansion'.
|
|
DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
|
|
return false;
|
|
}
|
|
|
|
// If we are at the end of the expression after just parsing a value, there
|
|
// must be no (unparenthesized) binary operators involved, so we can exit
|
|
// directly.
|
|
if (Tok.is(tok::eom)) {
|
|
// If the expression we parsed was of the form !defined(macro), return the
|
|
// macro in IfNDefMacro.
|
|
if (DT.State == DefinedTracker::NotDefinedMacro)
|
|
IfNDefMacro = DT.TheMacro;
|
|
|
|
// Restore 'DisableMacroExpansion'.
|
|
DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
|
|
return ResVal.Val != 0;
|
|
}
|
|
|
|
// Otherwise, we must have a binary operator (e.g. "#if 1 < 2"), so parse the
|
|
// operator and the stuff after it.
|
|
if (EvaluateDirectiveSubExpr(ResVal, getPrecedence(tok::question),
|
|
Tok, true, *this)) {
|
|
// Parse error, skip the rest of the macro line.
|
|
if (Tok.isNot(tok::eom))
|
|
DiscardUntilEndOfDirective();
|
|
|
|
// Restore 'DisableMacroExpansion'.
|
|
DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
|
|
return false;
|
|
}
|
|
|
|
// If we aren't at the tok::eom token, something bad happened, like an extra
|
|
// ')' token.
|
|
if (Tok.isNot(tok::eom)) {
|
|
Diag(Tok, diag::err_pp_expected_eol);
|
|
DiscardUntilEndOfDirective();
|
|
}
|
|
|
|
// Restore 'DisableMacroExpansion'.
|
|
DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
|
|
return ResVal.Val != 0;
|
|
}
|
|
|