//===--- 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/Basic/TargetInfo.h"
#include "clang/Lex/LexDiagnostic.h"
#include "llvm/ADT/APSInt.h"
using namespace clang;

/// 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 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);
    Macro->setIsUsed(true);
  }

  // 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 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;
    llvm::StringRef Spelling = PP.getSpelling(PeekTok, IntegerBuffer);
    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;
    llvm::StringRef ThisTok = PP.getSpelling(PeekTok, CharBuffer);

    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());
    }

    // FIXME: All of these should detect and report overflow??
    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) {
        Res = LHS.Val / RHS.Val;
        if (LHS.Val.isSigned())   // MININT/-1  -->  overflow.
          Overflow = LHS.Val.isMinSignedValue() && RHS.Val.isAllOnesValue();
      } else if (ValueLive) {
        PP.Diag(OpLoc, diag::err_pp_division_by_zero)
          << LHS.getRange() << RHS.getRange();
        return true;
      }
      break;

    case tok::star:
      Res = LHS.Val * RHS.Val;
      if (Res.isSigned() && LHS.Val != 0 && RHS.Val != 0)
        Overflow = Res/RHS.Val != LHS.Val || 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 (ShAmt >= LHS.Val.getBitWidth())
        Overflow = true, ShAmt = LHS.Val.getBitWidth()-1;
      else if (LHS.isUnsigned())
        Overflow = false;
      else if (LHS.Val.isNonNegative()) // Don't allow sign change.
        Overflow = ShAmt >= LHS.Val.countLeadingZeros();
      else
        Overflow = ShAmt >= LHS.Val.countLeadingOnes();

      Res = LHS.Val << ShAmt;
      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:
      Res = LHS.Val + RHS.Val;
      if (LHS.isUnsigned())
        Overflow = false;
      else if (LHS.Val.isNonNegative() == RHS.Val.isNonNegative() &&
               Res.isNonNegative() != LHS.Val.isNonNegative())
        Overflow = true;  // Overflow for signed addition.
      break;
    case tok::minus:
      Res = LHS.Val - RHS.Val;
      if (LHS.isUnsigned())
        Overflow = false;
      else if (LHS.Val.isNonNegative() != RHS.Val.isNonNegative() &&
               Res.isNonNegative() != LHS.Val.isNonNegative())
        Overflow = true;  // Overflow for signed subtraction.
      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;
}

