//===--- PPExpressions.cpp - Preprocessor Expression Evaluation -----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// 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/Basic/IdentifierTable.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/CodeCompletionHandler.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/Token.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SaveAndRestore.h"
#include <cassert>

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;
  IdentifierInfo *II = nullptr;

public:
  llvm::APSInt Val;

  // Default ctor - Construct an 'invalid' PPValue.
  PPValue(unsigned BitWidth) : Val(BitWidth) {}

  // If this value was produced by directly evaluating an identifier, produce
  // that identifier.
  IdentifierInfo *getIdentifier() const { return II; }
  void setIdentifier(IdentifierInfo *II) { this->II = II; }

  unsigned getBitWidth() const { return Val.getBitWidth(); }
  bool isUnsigned() const { return Val.isUnsigned(); }

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

} // end anonymous namespace

static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
                                     Token &PeekTok, bool ValueLive,
                                     bool &IncludedUndefinedIds,
                                     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;
  bool IncludedUndefinedIds = false;
};

/// EvaluateDefined - Process a 'defined(sym)' expression.
static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
                            bool ValueLive, Preprocessor &PP) {
  SourceLocation beginLoc(PeekTok.getLocation());
  Result.setBegin(beginLoc);

  // Get the next token, don't expand it.
  PP.LexUnexpandedNonComment(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.LexUnexpandedNonComment(PeekTok);
  }

  if (PeekTok.is(tok::code_completion)) {
    if (PP.getCodeCompletionHandler())
      PP.getCodeCompletionHandler()->CodeCompleteMacroName(false);
    PP.setCodeCompletionReached();
    PP.LexUnexpandedNonComment(PeekTok);
  }

  // If we don't have a pp-identifier now, this is an error.
  if (PP.CheckMacroName(PeekTok, MU_Other))
    return true;

  // Otherwise, we got an identifier, is it defined to something?
  IdentifierInfo *II = PeekTok.getIdentifierInfo();
  MacroDefinition Macro = PP.getMacroDefinition(II);
  Result.Val = !!Macro;
  Result.Val.setIsUnsigned(false); // Result is signed intmax_t.
  DT.IncludedUndefinedIds = !Macro;

  PP.emitMacroExpansionWarnings(
      PeekTok,
      (II->getName() == "INFINITY" || II->getName() == "NAN") ? true : false);

  // If there is a macro, mark it used.
  if (Result.Val != 0 && ValueLive)
    PP.markMacroAsUsed(Macro.getMacroInfo());

  // Save macro token for callback.
  Token macroToken(PeekTok);

  // If we are in parens, ensure we have a trailing ).
  if (LParenLoc.isValid()) {
    // Consume identifier.
    Result.setEnd(PeekTok.getLocation());
    PP.LexUnexpandedNonComment(PeekTok);

    if (PeekTok.isNot(tok::r_paren)) {
      PP.Diag(PeekTok.getLocation(), diag::err_pp_expected_after)
          << "'defined'" << tok::r_paren;
      PP.Diag(LParenLoc, diag::note_matching) << tok::l_paren;
      return true;
    }
    // Consume the ).
    PP.LexNonComment(PeekTok);
    Result.setEnd(PeekTok.getLocation());
  } else {
    // Consume identifier.
    Result.setEnd(PeekTok.getLocation());
    PP.LexNonComment(PeekTok);
  }

  // [cpp.cond]p4:
  //   Prior to evaluation, macro invocations in the list of preprocessing
  //   tokens that will become the controlling constant expression are replaced
  //   (except for those macro names modified by the 'defined' unary operator),
  //   just as in normal text. If the token 'defined' is generated as a result
  //   of this replacement process or use of the 'defined' unary operator does
  //   not match one of the two specified forms prior to macro replacement, the
  //   behavior is undefined.
  // This isn't an idle threat, consider this program:
  //   #define FOO
  //   #define BAR defined(FOO)
  //   #if BAR
  //   ...
  //   #else
  //   ...
  //   #endif
  // clang and gcc will pick the #if branch while Visual Studio will take the
  // #else branch.  Emit a warning about this undefined behavior.
  if (beginLoc.isMacroID()) {
    bool IsFunctionTypeMacro =
        PP.getSourceManager()
            .getSLocEntry(PP.getSourceManager().getFileID(beginLoc))
            .getExpansion()
            .isFunctionMacroExpansion();
    // For object-type macros, it's easy to replace
    //   #define FOO defined(BAR)
    // with
    //   #if defined(BAR)
    //   #define FOO 1
    //   #else
    //   #define FOO 0
    //   #endif
    // and doing so makes sense since compilers handle this differently in
    // practice (see example further up).  But for function-type macros,
    // there is no good way to write
    //   # define FOO(x) (defined(M_ ## x) && M_ ## x)
    // in a different way, and compilers seem to agree on how to behave here.
    // So warn by default on object-type macros, but only warn in -pedantic
    // mode on function-type macros.
    if (IsFunctionTypeMacro)
      PP.Diag(beginLoc, diag::warn_defined_in_function_type_macro);
    else
      PP.Diag(beginLoc, diag::warn_defined_in_object_type_macro);
  }

  // Invoke the 'defined' callback.
  if (PPCallbacks *Callbacks = PP.getPPCallbacks()) {
    Callbacks->Defined(macroToken, Macro,
                       SourceRange(beginLoc, PeekTok.getLocation()));
  }

  // 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;

  Result.setIdentifier(nullptr);

  if (PeekTok.is(tok::code_completion)) {
    if (PP.getCodeCompletionHandler())
      PP.getCodeCompletionHandler()->CodeCompletePreprocessorExpression();
    PP.setCodeCompletionReached();
    PP.LexNonComment(PeekTok);
  }

  switch (PeekTok.getKind()) {
  default:
    // 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 (!II->isCPlusPlusOperatorKeyword()) {
        // 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
        if (ValueLive) {
          PP.Diag(PeekTok, diag::warn_pp_undef_identifier) << II;

          const DiagnosticsEngine &DiagEngine = PP.getDiagnostics();
          // If 'Wundef' is enabled, do not emit 'undef-prefix' diagnostics.
          if (DiagEngine.isIgnored(diag::warn_pp_undef_identifier,
                                   PeekTok.getLocation())) {
            const std::vector<std::string> UndefPrefixes =
                DiagEngine.getDiagnosticOptions().UndefPrefixes;
            const StringRef IdentifierName = II->getName();
            if (llvm::any_of(UndefPrefixes,
                             [&IdentifierName](const std::string &Prefix) {
                               return IdentifierName.starts_with(Prefix);
                             }))
              PP.Diag(PeekTok, diag::warn_pp_undef_prefix)
                  << AddFlagValue{llvm::join(UndefPrefixes, ",")} << II;
          }
        }
        Result.Val = 0;
        Result.Val.setIsUnsigned(false); // "0" is signed intmax_t 0.
        Result.setIdentifier(II);
        Result.setRange(PeekTok.getLocation());
        DT.IncludedUndefinedIds = true;
        PP.LexNonComment(PeekTok);
        return false;
      }
    }
    PP.Diag(PeekTok, diag::err_pp_expr_bad_token_start_expr);
    return true;
  case tok::eod:
  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: {
    SmallString<64> IntegerBuffer;
    bool NumberInvalid = false;
    StringRef Spelling = PP.getSpelling(PeekTok, IntegerBuffer,
                                              &NumberInvalid);
    if (NumberInvalid)
      return true; // a diagnostic was already reported

    NumericLiteralParser Literal(Spelling, PeekTok.getLocation(),
                                 PP.getSourceManager(), PP.getLangOpts(),
                                 PP.getTargetInfo(), PP.getDiagnostics());
    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");

    // Complain about, and drop, any ud-suffix.
    if (Literal.hasUDSuffix())
      PP.Diag(PeekTok, diag::err_pp_invalid_udl) << /*integer*/1;

    // 'long long' is a C99 or C++11 feature.
    if (!PP.getLangOpts().C99 && Literal.isLongLong) {
      if (PP.getLangOpts().CPlusPlus)
        PP.Diag(PeekTok,
             PP.getLangOpts().CPlusPlus11 ?
             diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong);
      else
        PP.Diag(PeekTok, diag::ext_c99_longlong);
    }

    // 'z/uz' literals are a C++23 feature.
    if (Literal.isSizeT)
      PP.Diag(PeekTok, PP.getLangOpts().CPlusPlus
                           ? PP.getLangOpts().CPlusPlus23
                                 ? diag::warn_cxx20_compat_size_t_suffix
                                 : diag::ext_cxx23_size_t_suffix
                           : diag::err_cxx23_size_t_suffix);

    // 'wb/uwb' literals are a C23 feature.
    // '__wb/__uwb' are a C++ extension.
    if (Literal.isBitInt)
      PP.Diag(PeekTok, PP.getLangOpts().CPlusPlus ? diag::ext_cxx_bitint_suffix
                       : PP.getLangOpts().C23
                           ? diag::warn_c23_compat_bitint_suffix
                           : diag::ext_c23_bitint_suffix);

    // Parse the integer literal into Result.
    if (Literal.GetIntegerValue(Result.Val)) {
      // Overflow parsing integer literal.
      if (ValueLive)
        PP.Diag(PeekTok, diag::err_integer_literal_too_large)
            << /* Unsigned */ 1;
      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()) {
        // Octal, hexadecimal, and binary literals are implicitly unsigned if
        // the value does not fit into a signed integer type.
        if (ValueLive && Literal.getRadix() == 10)
          PP.Diag(PeekTok, diag::ext_integer_literal_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'
  case tok::wide_char_constant:     // L'x'
  case tok::utf8_char_constant:     // u8'x'
  case tok::utf16_char_constant:    // u'x'
  case tok::utf32_char_constant: {  // U'x'
    // Complain about, and drop, any ud-suffix.
    if (PeekTok.hasUDSuffix())
      PP.Diag(PeekTok, diag::err_pp_invalid_udl) << /*character*/0;

    SmallString<32> CharBuffer;
    bool CharInvalid = false;
    StringRef ThisTok = PP.getSpelling(PeekTok, CharBuffer, &CharInvalid);
    if (CharInvalid)
      return true;

    CharLiteralParser Literal(ThisTok.begin(), ThisTok.end(),
                              PeekTok.getLocation(), PP, PeekTok.getKind());
    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 if (Literal.isUTF16())
      NumBits = TI.getChar16Width();
    else if (Literal.isUTF32())
      NumBits = TI.getChar32Width();
    else // char or char8_t
      NumBits = TI.getCharWidth();

    // Set the width.
    llvm::APSInt Val(NumBits);
    // Set the value.
    Val = Literal.getValue();
    // Set the signedness. UTF-16 and UTF-32 are always unsigned
    // UTF-8 is unsigned if -fchar8_t is specified.
    if (Literal.isWide())
      Val.setIsUnsigned(!TargetInfo::isTypeSigned(TI.getWCharType()));
    else if (Literal.isUTF16() || Literal.isUTF32())
      Val.setIsUnsigned(true);
    else if (Literal.isUTF8()) {
      if (PP.getLangOpts().CPlusPlus)
        Val.setIsUnsigned(
            PP.getLangOpts().Char8 ? true : !PP.getLangOpts().CharIsSigned);
      else
        Val.setIsUnsigned(true);
    } else
      Val.setIsUnsigned(!PP.getLangOpts().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,
                                   DT.IncludedUndefinedIds, 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) << tok::l_paren;
        return true;
      }
      DT.State = DefinedTracker::Unknown;
    }
    Result.setRange(Start, PeekTok.getLocation());
    Result.setIdentifier(nullptr);
    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);
    Result.setIdentifier(nullptr);
    return false;
  }
  case tok::minus: {
    SourceLocation Loc = PeekTok.getLocation();
    PP.LexNonComment(PeekTok);
    if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
    Result.setBegin(Loc);
    Result.setIdentifier(nullptr);

    // 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);
    Result.setIdentifier(nullptr);

    // 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);
    Result.setIdentifier(nullptr);

    if (DT.State == DefinedTracker::DefinedMacro)
      DT.State = DefinedTracker::NotDefinedMacro;
    else if (DT.State == DefinedTracker::NotDefinedMacro)
      DT.State = DefinedTracker::DefinedMacro;
    return false;
  }
  case tok::kw_true:
  case tok::kw_false:
    Result.Val = PeekTok.getKind() == tok::kw_true;
    Result.Val.setIsUnsigned(false); // "0" is signed intmax_t 0.
    Result.setIdentifier(PeekTok.getIdentifierInfo());
    Result.setRange(PeekTok.getLocation());
    PP.LexNonComment(PeekTok);
    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 - 'eod' 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::eod:                  return 0;// Lowest priority, end of directive.
  }
}

static void diagnoseUnexpectedOperator(Preprocessor &PP, PPValue &LHS,
                                       Token &Tok) {
  if (Tok.is(tok::l_paren) && LHS.getIdentifier())
    PP.Diag(LHS.getRange().getBegin(), diag::err_pp_expr_bad_token_lparen)
        << LHS.getIdentifier();
  else
    PP.Diag(Tok.getLocation(), diag::err_pp_expr_bad_token_binop)
        << LHS.getRange();
}

/// 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,
                                     bool &IncludedUndefinedIds,
                                     Preprocessor &PP) {
  unsigned PeekPrec = getPrecedence(PeekTok.getKind());
  // If this token isn't valid, report the error.
  if (PeekPrec == ~0U) {
    diagnoseUnexpectedOperator(PP, LHS, PeekTok);
    return true;
  }

  while (true) {
    // 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;
    IncludedUndefinedIds = DT.IncludedUndefinedIds;

    // 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) {
      diagnoseUnexpectedOperator(PP, RHS, PeekTok);
      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,
                                   IncludedUndefinedIds, 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_to_positive) << 0
            << toString(LHS.Val, 10, true) + " to " +
               toString(LHS.Val, 10, false)
            << LHS.getRange() << RHS.getRange();
        if (!RHS.isUnsigned() && RHS.Val.isNegative())
          PP.Diag(OpLoc, diag::warn_pp_convert_to_positive) << 1
            << toString(RHS.Val, 10, true) + " to " +
               toString(RHS.Val, 10, false)
            << LHS.getRange() << RHS.getRange();
      }
      LHS.Val.setIsUnsigned(Res.isUnsigned());
      RHS.Val.setIsUnsigned(Res.isUnsigned());
    }

    bool Overflow = false;
    switch (Operator) {
    default: llvm_unreachable("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.
      if (LHS.isUnsigned())
        Res = LHS.Val.ushl_ov(RHS.Val, Overflow);
      else
        Res = llvm::APSInt(LHS.Val.sshl_ov(RHS.Val, 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.getLangOpts().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)
            << tok::colon << LHS.getRange() << RHS.getRange();
        PP.Diag(OpLoc, diag::note_matching) << tok::question;
        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,
                                   IncludedUndefinedIds, 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());
    RHS.setIdentifier(nullptr);
  }
}

/// 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.
Preprocessor::DirectiveEvalResult
Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) {
  SaveAndRestore PPDir(ParsingIfOrElifDirective, true);
  // 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;
  LexNonComment(Tok);

  // C99 6.10.1p3 - All expressions are evaluated as intmax_t or uintmax_t.
  unsigned BitWidth = getTargetInfo().getIntMaxTWidth();

  PPValue ResVal(BitWidth);
  DefinedTracker DT;
  SourceLocation ExprStartLoc = SourceMgr.getExpansionLoc(Tok.getLocation());
  if (EvaluateValue(ResVal, Tok, DT, true, *this)) {
    // Parse error, skip the rest of the macro line.
    SourceRange ConditionRange = ExprStartLoc;
    if (Tok.isNot(tok::eod))
      ConditionRange = DiscardUntilEndOfDirective();

    // Restore 'DisableMacroExpansion'.
    DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;

    // We cannot trust the source range from the value because there was a
    // parse error. Track the range manually -- the end of the directive is the
    // end of the condition range.
    return {false,
            DT.IncludedUndefinedIds,
            {ExprStartLoc, ConditionRange.getEnd()}};
  }

  // 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::eod)) {
    // 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, DT.IncludedUndefinedIds, ResVal.getRange()};
  }

  // 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, DT.IncludedUndefinedIds, *this)) {
    // Parse error, skip the rest of the macro line.
    if (Tok.isNot(tok::eod))
      DiscardUntilEndOfDirective();

    // Restore 'DisableMacroExpansion'.
    DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
    return {false, DT.IncludedUndefinedIds, ResVal.getRange()};
  }

  // If we aren't at the tok::eod token, something bad happened, like an extra
  // ')' token.
  if (Tok.isNot(tok::eod)) {
    Diag(Tok, diag::err_pp_expected_eol);
    DiscardUntilEndOfDirective();
  }

  // Restore 'DisableMacroExpansion'.
  DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
  return {ResVal.Val != 0, DT.IncludedUndefinedIds, ResVal.getRange()};
}
