//===- Preprocessor.cpp - C Language Family Preprocessor Implementation ---===//
//
// 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 interface.
//
//===----------------------------------------------------------------------===//
//
// Options to support:
//   -H       - Print the name of each header file used.
//   -d[DNI] - Dump various things.
//   -fworking-directory - #line's with preprocessor's working dir.
//   -fpreprocessed
//   -dependency-file,-M,-MM,-MF,-MG,-MP,-MT,-MQ,-MD,-MMD
//   -W*
//   -w
//
// Messages to emit:
//   "Multiple include guards may be useful for:\n"
//
//===----------------------------------------------------------------------===//

#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/CodeCompletionHandler.h"
#include "clang/Lex/DependencyDirectivesScanner.h"
#include "clang/Lex/ExternalPreprocessorSource.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/MacroArgs.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/ModuleLoader.h"
#include "clang/Lex/NoTrivialPPDirectiveTracer.h"
#include "clang/Lex/Pragma.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/PreprocessorLexer.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Lex/ScratchBuffer.h"
#include "clang/Lex/Token.h"
#include "clang/Lex/TokenLexer.h"
#include "clang/Support/Compiler.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Capacity.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/MemoryBufferRef.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

using namespace clang;

/// Minimum distance between two check points, in tokens.
static constexpr unsigned CheckPointStepSize = 1024;

LLVM_INSTANTIATE_REGISTRY_EX(CLANG_ABI_EXPORT, PragmaHandlerRegistry)

ExternalPreprocessorSource::~ExternalPreprocessorSource() = default;

Preprocessor::Preprocessor(const PreprocessorOptions &PPOpts,
                           DiagnosticsEngine &diags, const LangOptions &opts,
                           SourceManager &SM, HeaderSearch &Headers,
                           ModuleLoader &TheModuleLoader,
                           IdentifierInfoLookup *IILookup, bool OwnsHeaders,
                           TranslationUnitKind TUKind)
    : PPOpts(PPOpts), Diags(&diags), LangOpts(opts),
      FileMgr(Headers.getFileMgr()), SourceMgr(SM),
      ScratchBuf(new ScratchBuffer(SourceMgr)), HeaderInfo(Headers),
      TheModuleLoader(TheModuleLoader), ExternalSource(nullptr),
      // As the language options may have not been loaded yet (when
      // deserializing an ASTUnit), adding keywords to the identifier table is
      // deferred to Preprocessor::Initialize().
      Identifiers(IILookup), PragmaHandlers(new PragmaNamespace(StringRef())),
      TUKind(TUKind), SkipMainFilePreamble(0, true),
      CurSubmoduleState(&NullSubmoduleState) {
  OwnsHeaderSearch = OwnsHeaders;

  // Only record check points if we might highlight diagnostic snippets.
  RecordCheckPoints = getDiagnostics().getShowColors();

  // Default to discarding comments.
  KeepComments = false;
  KeepMacroComments = false;
  SuppressIncludeNotFoundError = false;

  // Macro expansion is enabled.
  DisableMacroExpansion = false;
  MacroExpansionInDirectivesOverride = false;
  InMacroArgs = false;
  ArgMacro = nullptr;
  InMacroArgPreExpansion = false;
  NumCachedTokenLexers = 0;
  PragmasEnabled = true;
  ParsingIfOrElifDirective = false;
  PreprocessedOutput = false;

  // We haven't read anything from the external source.
  ReadMacrosFromExternalSource = false;

  LastExportKeyword.startToken();

  BuiltinInfo = std::make_unique<Builtin::Context>();

  // "Poison" __VA_ARGS__, __VA_OPT__ which can only appear in the expansion of
  // a macro. They get unpoisoned where it is allowed.
  (Ident__VA_ARGS__ = getIdentifierInfo("__VA_ARGS__"))->setIsPoisoned();
  SetPoisonReason(Ident__VA_ARGS__,diag::ext_pp_bad_vaargs_use);
  (Ident__VA_OPT__ = getIdentifierInfo("__VA_OPT__"))->setIsPoisoned();
  SetPoisonReason(Ident__VA_OPT__,diag::ext_pp_bad_vaopt_use);

  // Initialize the pragma handlers.
  RegisterBuiltinPragmas();

  // Initialize builtin macros like __LINE__ and friends.
  RegisterBuiltinMacros();

  if(LangOpts.Borland) {
    Ident__exception_info        = getIdentifierInfo("_exception_info");
    Ident___exception_info       = getIdentifierInfo("__exception_info");
    Ident_GetExceptionInfo       = getIdentifierInfo("GetExceptionInformation");
    Ident__exception_code        = getIdentifierInfo("_exception_code");
    Ident___exception_code       = getIdentifierInfo("__exception_code");
    Ident_GetExceptionCode       = getIdentifierInfo("GetExceptionCode");
    Ident__abnormal_termination  = getIdentifierInfo("_abnormal_termination");
    Ident___abnormal_termination = getIdentifierInfo("__abnormal_termination");
    Ident_AbnormalTermination    = getIdentifierInfo("AbnormalTermination");
  } else {
    Ident__exception_info = Ident__exception_code = nullptr;
    Ident__abnormal_termination = Ident___exception_info = nullptr;
    Ident___exception_code = Ident___abnormal_termination = nullptr;
    Ident_GetExceptionInfo = Ident_GetExceptionCode = nullptr;
    Ident_AbnormalTermination = nullptr;
  }

  Ident__GLIBCXX__ = getIdentifierInfo("__GLIBCXX__");

  // Default incremental processing to -fincremental-extensions, clients can
  // override with `enableIncrementalProcessing` if desired.
  IncrementalProcessing = LangOpts.IncrementalExtensions;

  // If using a PCH where a #pragma hdrstop is expected, start skipping tokens.
  if (usingPCHWithPragmaHdrStop())
    SkippingUntilPragmaHdrStop = true;

  // If using a PCH with a through header, start skipping tokens.
  if (!this->PPOpts.PCHThroughHeader.empty() &&
      !this->PPOpts.ImplicitPCHInclude.empty())
    SkippingUntilPCHThroughHeader = true;

  if (this->PPOpts.GeneratePreamble)
    PreambleConditionalStack.startRecording();

  MaxTokens = LangOpts.MaxTokens;
}

Preprocessor::~Preprocessor() {
  assert(!isBacktrackEnabled() && "EnableBacktrack/Backtrack imbalance!");

  IncludeMacroStack.clear();

  // Free any cached macro expanders.
  // This populates MacroArgCache, so all TokenLexers need to be destroyed
  // before the code below that frees up the MacroArgCache list.
  std::fill(TokenLexerCache, TokenLexerCache + NumCachedTokenLexers, nullptr);
  CurTokenLexer.reset();

  // Free any cached MacroArgs.
  for (MacroArgs *ArgList = MacroArgCache; ArgList;)
    ArgList = ArgList->deallocate();

  // Delete the header search info, if we own it.
  if (OwnsHeaderSearch)
    delete &HeaderInfo;
}

void Preprocessor::Initialize(const TargetInfo &Target,
                              const TargetInfo *AuxTarget) {
  assert((!this->Target || this->Target == &Target) &&
         "Invalid override of target information");
  this->Target = &Target;

  assert((!this->AuxTarget || this->AuxTarget == AuxTarget) &&
         "Invalid override of aux target information.");
  this->AuxTarget = AuxTarget;

  // Initialize information about built-ins.
  BuiltinInfo->InitializeTarget(Target, AuxTarget);
  HeaderInfo.setTarget(Target);

  // Populate the identifier table with info about keywords for the current language.
  Identifiers.AddKeywords(LangOpts);

  // Initialize the __FTL_EVAL_METHOD__ macro to the TargetInfo.
  setTUFPEvalMethod(getTargetInfo().getFPEvalMethod());

  if (getLangOpts().getFPEvalMethod() == LangOptions::FEM_UnsetOnCommandLine)
    // Use setting from TargetInfo.
    setCurrentFPEvalMethod(SourceLocation(), Target.getFPEvalMethod());
  else
    // Set initial value of __FLT_EVAL_METHOD__ from the command line.
    setCurrentFPEvalMethod(SourceLocation(), getLangOpts().getFPEvalMethod());
}

void Preprocessor::InitializeForModelFile() {
  NumEnteredSourceFiles = 0;

  // Reset pragmas
  PragmaHandlersBackup = std::move(PragmaHandlers);
  PragmaHandlers = std::make_unique<PragmaNamespace>(StringRef());
  RegisterBuiltinPragmas();

  // Reset PredefinesFileID
  PredefinesFileID = FileID();
}

void Preprocessor::FinalizeForModelFile() {
  NumEnteredSourceFiles = 1;

  PragmaHandlers = std::move(PragmaHandlersBackup);
}

void Preprocessor::DumpToken(const Token &Tok, bool DumpFlags) const {
  std::string TokenStr;
  llvm::raw_string_ostream OS(TokenStr);

  // The alignment of 16 is chosen to comfortably fit most identifiers.
  OS << llvm::formatv("{0,-16} ", tok::getTokenName(Tok.getKind()));

  // Annotation tokens are just markers that don't have a spelling -- they
  // indicate where something expanded.
  if (!Tok.isAnnotation()) {
    OS << "'";
    // Escape string to prevent token spelling from spanning multiple lines.
    OS.write_escaped(getSpelling(Tok));
    OS << "'";
  }

  // The alignment of 48 (32 characters for the spelling + the 16 for
  // the identifier name) fits most variable names, keywords and annotations.
  llvm::errs() << llvm::formatv("{0,-48} ", OS.str());

  if (!DumpFlags) return;

  auto Loc = Tok.getLocation();
  llvm::errs() << "Loc=<";
  DumpLocation(Loc);
  llvm::errs() << ">";

  // If the token points directly to a file location (i.e. not a macro
  // expansion), then add additional padding so that trailing markers
  // align, provided the line/column numbers are reasonably sized.
  //
  // Otherwise, if it's a macro expansion, don't bother with alignment,
  // as the line will include multiple locations and be very long.
  //
  // NOTE: To keep this stateless, it doesn't account for filename
  // length, so when a header starts markers will be temporarily misaligned.
  if (Loc.isFileID()) {
    PresumedLoc PLoc = SourceMgr.getPresumedLoc(Loc);

    if (!PLoc.isInvalid()) {
      int LineWidth = llvm::utostr(PLoc.getLine()).size();
      int ColumnWidth = llvm::utostr(PLoc.getColumn()).size();

      // Reserve space for lines up to 9999 and columns up to 99,
      // which is 4 + 2 = 6 characters in total.
      const int ReservedSpace = 6;

      int LeftSpace = ReservedSpace - LineWidth - ColumnWidth;
      int Padding = std::max<int>(0, LeftSpace);

      llvm::errs().indent(Padding);
    }
  }

  if (Tok.isAtStartOfLine())
    llvm::errs() << " [StartOfLine]";
  if (Tok.hasLeadingSpace())
    llvm::errs() << " [LeadingSpace]";
  if (Tok.isExpandDisabled())
    llvm::errs() << " [ExpandDisabled]";
  if (Tok.needsCleaning()) {
    const char *Start = SourceMgr.getCharacterData(Tok.getLocation());
    llvm::errs() << " [UnClean='" << StringRef(Start, Tok.getLength()) << "']";
  }
}

void Preprocessor::DumpLocation(SourceLocation Loc) const {
  Loc.print(llvm::errs(), SourceMgr);
}

void Preprocessor::DumpMacro(const MacroInfo &MI) const {
  llvm::errs() << "MACRO: ";
  for (unsigned i = 0, e = MI.getNumTokens(); i != e; ++i) {
    DumpToken(MI.getReplacementToken(i));
    llvm::errs() << "  ";
  }
  llvm::errs() << "\n";
}

void Preprocessor::PrintStats() {
  llvm::errs() << "\n*** Preprocessor Stats:\n";
  llvm::errs() << NumDirectives << " directives found:\n";
  llvm::errs() << "  " << NumDefined << " #define.\n";
  llvm::errs() << "  " << NumUndefined << " #undef.\n";
  llvm::errs() << "  #include/#include_next/#import:\n";
  llvm::errs() << "    " << NumEnteredSourceFiles << " source files entered.\n";
  llvm::errs() << "    " << MaxIncludeStackDepth << " max include stack depth\n";
  llvm::errs() << "  " << NumIf << " #if/#ifndef/#ifdef.\n";
  llvm::errs() << "  " << NumElse << " #else/#elif/#elifdef/#elifndef.\n";
  llvm::errs() << "  " << NumEndif << " #endif.\n";
  llvm::errs() << "  " << NumPragma << " #pragma.\n";
  llvm::errs() << NumSkipped << " #if/#ifndef#ifdef regions skipped\n";

  llvm::errs() << NumMacroExpanded << "/" << NumFnMacroExpanded << "/"
             << NumBuiltinMacroExpanded << " obj/fn/builtin macros expanded, "
             << NumFastMacroExpanded << " on the fast path.\n";
  llvm::errs() << (NumFastTokenPaste+NumTokenPaste)
             << " token paste (##) operations performed, "
             << NumFastTokenPaste << " on the fast path.\n";

  llvm::errs() << "\nPreprocessor Memory: " << getTotalMemory() << "B total";

  llvm::errs() << "\n  BumpPtr: " << BP.getTotalMemory();
  llvm::errs() << "\n  Macro Expanded Tokens: "
               << llvm::capacity_in_bytes(MacroExpandedTokens);
  llvm::errs() << "\n  Predefines Buffer: " << Predefines.capacity();
  // FIXME: List information for all submodules.
  llvm::errs() << "\n  Macros: "
               << llvm::capacity_in_bytes(CurSubmoduleState->Macros);
  llvm::errs() << "\n  #pragma push_macro Info: "
               << llvm::capacity_in_bytes(PragmaPushMacroInfo);
  llvm::errs() << "\n  Poison Reasons: "
               << llvm::capacity_in_bytes(PoisonReasons);
  llvm::errs() << "\n  Comment Handlers: "
               << llvm::capacity_in_bytes(CommentHandlers) << "\n";
}

llvm::iterator_range<Preprocessor::macro_iterator>
Preprocessor::macros(bool IncludeExternalMacros) const {
  if (IncludeExternalMacros && ExternalSource &&
      !ReadMacrosFromExternalSource) {
    ReadMacrosFromExternalSource = true;
    ExternalSource->ReadDefinedMacros();
  }
  // Make sure we cover all macros in visible modules.
  for (const ModuleMacro &Macro : ModuleMacros)
    CurSubmoduleState->Macros.try_emplace(Macro.II);

  return CurSubmoduleState->Macros;
}

size_t Preprocessor::getTotalMemory() const {
  return BP.getTotalMemory()
    + llvm::capacity_in_bytes(MacroExpandedTokens)
    + Predefines.capacity() /* Predefines buffer. */
    // FIXME: Include sizes from all submodules, and include MacroInfo sizes,
    // and ModuleMacros.
    + llvm::capacity_in_bytes(CurSubmoduleState->Macros)
    + llvm::capacity_in_bytes(PragmaPushMacroInfo)
    + llvm::capacity_in_bytes(PoisonReasons)
    + llvm::capacity_in_bytes(CommentHandlers);
}

/// Compares macro tokens with a specified token value sequence.
static bool MacroDefinitionEquals(const MacroInfo *MI,
                                  ArrayRef<TokenValue> Tokens) {
  return Tokens.size() == MI->getNumTokens() &&
      std::equal(Tokens.begin(), Tokens.end(), MI->tokens_begin());
}

StringRef Preprocessor::getLastMacroWithSpelling(
                                    SourceLocation Loc,
                                    ArrayRef<TokenValue> Tokens) const {
  SourceLocation BestLocation;
  StringRef BestSpelling;
  for (const auto &M : macros()) {
    const MacroDirective::DefInfo Def =
        M.second.findDirectiveAtLoc(Loc, SourceMgr);
    if (!Def || !Def.getMacroInfo())
      continue;
    if (!Def.getMacroInfo()->isObjectLike())
      continue;
    if (!MacroDefinitionEquals(Def.getMacroInfo(), Tokens))
      continue;
    SourceLocation Location = Def.getLocation();
    // Choose the macro defined latest.
    if (BestLocation.isInvalid() ||
        (Location.isValid() &&
         SourceMgr.isBeforeInTranslationUnit(BestLocation, Location))) {
      BestLocation = Location;
      BestSpelling = M.first->getName();
    }
  }
  return BestSpelling;
}

void Preprocessor::recomputeCurLexerKind() {
  if (InCachingLexMode())
    CurLexerCallback = CLK_CachingLexer;
  else if (CurLexer)
    CurLexerCallback = CurLexer->isDependencyDirectivesLexer()
                           ? CLK_DependencyDirectivesLexer
                           : CLK_Lexer;
  else if (CurTokenLexer)
    CurLexerCallback = CLK_TokenLexer;
  else
    CurLexerCallback = CLK_Lexer;
}

bool Preprocessor::SetCodeCompletionPoint(FileEntryRef File,
                                          unsigned CompleteLine,
                                          unsigned CompleteColumn) {
  assert(CompleteLine && CompleteColumn && "Starts from 1:1");
  assert(!CodeCompletionFile && "Already set");

  // Load the actual file's contents.
  std::optional<llvm::MemoryBufferRef> Buffer =
      SourceMgr.getMemoryBufferForFileOrNone(File);
  if (!Buffer)
    return true;

  // Find the byte position of the truncation point.
  const char *Position = Buffer->getBufferStart();
  for (unsigned Line = 1; Line < CompleteLine; ++Line) {
    for (; *Position; ++Position) {
      if (*Position != '\r' && *Position != '\n')
        continue;

      // Eat \r\n or \n\r as a single line.
      if ((Position[1] == '\r' || Position[1] == '\n') &&
          Position[0] != Position[1])
        ++Position;
      ++Position;
      break;
    }
  }

  Position += CompleteColumn - 1;

  // If pointing inside the preamble, adjust the position at the beginning of
  // the file after the preamble.
  if (SkipMainFilePreamble.first &&
      SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()) == File) {
    if (Position - Buffer->getBufferStart() < SkipMainFilePreamble.first)
      Position = Buffer->getBufferStart() + SkipMainFilePreamble.first;
  }

  if (Position > Buffer->getBufferEnd())
    Position = Buffer->getBufferEnd();

  CodeCompletionFile = File;
  CodeCompletionOffset = Position - Buffer->getBufferStart();

  auto NewBuffer = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(
      Buffer->getBufferSize() + 1, Buffer->getBufferIdentifier());
  char *NewBuf = NewBuffer->getBufferStart();
  char *NewPos = std::copy(Buffer->getBufferStart(), Position, NewBuf);
  *NewPos = '\0';
  std::copy(Position, Buffer->getBufferEnd(), NewPos+1);
  SourceMgr.overrideFileContents(File, std::move(NewBuffer));

  return false;
}

void Preprocessor::CodeCompleteIncludedFile(llvm::StringRef Dir,
                                            bool IsAngled) {
  setCodeCompletionReached();
  if (CodeComplete)
    CodeComplete->CodeCompleteIncludedFile(Dir, IsAngled);
}

void Preprocessor::CodeCompleteNaturalLanguage() {
  setCodeCompletionReached();
  if (CodeComplete)
    CodeComplete->CodeCompleteNaturalLanguage();
}

/// getSpelling - This method is used to get the spelling of a token into a
/// SmallVector. Note that the returned StringRef may not point to the
/// supplied buffer if a copy can be avoided.
StringRef Preprocessor::getSpelling(const Token &Tok,
                                          SmallVectorImpl<char> &Buffer,
                                          bool *Invalid) const {
  // NOTE: this has to be checked *before* testing for an IdentifierInfo.
  if (Tok.isNot(tok::raw_identifier) && !Tok.hasUCN()) {
    // Try the fast path.
    if (const IdentifierInfo *II = Tok.getIdentifierInfo())
      return II->getName();
  }

  // Resize the buffer if we need to copy into it.
  if (Tok.needsCleaning())
    Buffer.resize(Tok.getLength());

  const char *Ptr = Buffer.data();
  unsigned Len = getSpelling(Tok, Ptr, Invalid);
  return StringRef(Ptr, Len);
}

/// CreateString - Plop the specified string into a scratch buffer and return a
/// location for it.  If specified, the source location provides a source
/// location for the token.
void Preprocessor::CreateString(StringRef Str, Token &Tok,
                                SourceLocation ExpansionLocStart,
                                SourceLocation ExpansionLocEnd) {
  Tok.setLength(Str.size());

  const char *DestPtr;
  SourceLocation Loc = ScratchBuf->getToken(Str.data(), Str.size(), DestPtr);

  if (ExpansionLocStart.isValid())
    Loc = SourceMgr.createExpansionLoc(Loc, ExpansionLocStart,
                                       ExpansionLocEnd, Str.size());
  Tok.setLocation(Loc);

  // If this is a raw identifier or a literal token, set the pointer data.
  if (Tok.is(tok::raw_identifier))
    Tok.setRawIdentifierData(DestPtr);
  else if (Tok.isLiteral())
    Tok.setLiteralData(DestPtr);
}

SourceLocation Preprocessor::SplitToken(SourceLocation Loc, unsigned Length) {
  auto &SM = getSourceManager();
  SourceLocation SpellingLoc = SM.getSpellingLoc(Loc);
  FileIDAndOffset LocInfo = SM.getDecomposedLoc(SpellingLoc);
  bool Invalid = false;
  StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid);
  if (Invalid)
    return SourceLocation();

  // FIXME: We could consider re-using spelling for tokens we see repeatedly.
  const char *DestPtr;
  SourceLocation Spelling =
      ScratchBuf->getToken(Buffer.data() + LocInfo.second, Length, DestPtr);
  return SM.createTokenSplitLoc(Spelling, Loc, Loc.getLocWithOffset(Length));
}

Module *Preprocessor::getCurrentModule() {
  if (!getLangOpts().isCompilingModule())
    return nullptr;

  return getHeaderSearchInfo().lookupModule(getLangOpts().CurrentModule);
}

Module *Preprocessor::getCurrentModuleImplementation() {
  if (!getLangOpts().isCompilingModuleImplementation())
    return nullptr;

  return getHeaderSearchInfo().lookupModule(getLangOpts().ModuleName);
}

//===----------------------------------------------------------------------===//
// Preprocessor Initialization Methods
//===----------------------------------------------------------------------===//

/// EnterMainSourceFile - Enter the specified FileID as the main source file,
/// which implicitly adds the builtin defines etc.
void Preprocessor::EnterMainSourceFile() {
  // We do not allow the preprocessor to reenter the main file.  Doing so will
  // cause FileID's to accumulate information from both runs (e.g. #line
  // information) and predefined macros aren't guaranteed to be set properly.
  assert(NumEnteredSourceFiles == 0 && "Cannot reenter the main file!");
  FileID MainFileID = SourceMgr.getMainFileID();

  // If MainFileID is loaded it means we loaded an AST file, no need to enter
  // a main file.
  if (!SourceMgr.isLoadedFileID(MainFileID)) {
    // Enter the main file source buffer.
    EnterSourceFile(MainFileID, nullptr, SourceLocation());

    // If we've been asked to skip bytes in the main file (e.g., as part of a
    // precompiled preamble), do so now.
    if (SkipMainFilePreamble.first > 0)
      CurLexer->SetByteOffset(SkipMainFilePreamble.first,
                              SkipMainFilePreamble.second);

    // Tell the header info that the main file was entered.  If the file is later
    // #imported, it won't be re-entered.
    if (OptionalFileEntryRef FE = SourceMgr.getFileEntryRefForID(MainFileID))
      markIncluded(*FE);

    // Record the first PP token in the main file. This is used to generate
    // better diagnostics for C++ modules.
    //
    // // This is a comment.
    // #define FOO int  // note: add 'module;' to the start of the file
    // ^ FirstPPToken   //       to introduce a global module fragment.
    //
    // export module M; // error: module declaration must occur
    //                  //        at the start of the translation unit.
    if (getLangOpts().CPlusPlusModules) {
      std::optional<StringRef> Input =
          getSourceManager().getBufferDataOrNone(MainFileID);
      if (!isPreprocessedModuleFile() && Input)
        MainFileIsPreprocessedModuleFile =
            clang::isPreprocessedModuleFile(*Input);
      auto Tracer = std::make_unique<NoTrivialPPDirectiveTracer>(*this);
      DirTracer = Tracer.get();
      addPPCallbacks(std::move(Tracer));
      std::optional<Token> FirstPPTok = CurLexer->peekNextPPToken();
      if (FirstPPTok)
        FirstPPTokenLoc = FirstPPTok->getLocation();
    }
  }

  // Preprocess Predefines to populate the initial preprocessor state.
  std::unique_ptr<llvm::MemoryBuffer> SB =
    llvm::MemoryBuffer::getMemBufferCopy(Predefines, "<built-in>");
  assert(SB && "Cannot create predefined source buffer");
  FileID FID = SourceMgr.createFileID(std::move(SB));
  assert(FID.isValid() && "Could not create FileID for predefines?");
  setPredefinesFileID(FID);

  // Start parsing the predefines.
  EnterSourceFile(FID, nullptr, SourceLocation());

  if (!PPOpts.PCHThroughHeader.empty()) {
    // Lookup and save the FileID for the through header. If it isn't found
    // in the search path, it's a fatal error.
    OptionalFileEntryRef File = LookupFile(
        SourceLocation(), PPOpts.PCHThroughHeader,
        /*isAngled=*/false, /*FromDir=*/nullptr, /*FromFile=*/nullptr,
        /*CurDir=*/nullptr, /*SearchPath=*/nullptr, /*RelativePath=*/nullptr,
        /*SuggestedModule=*/nullptr, /*IsMapped=*/nullptr,
        /*IsFrameworkFound=*/nullptr);
    if (!File) {
      Diag(SourceLocation(), diag::err_pp_through_header_not_found)
          << PPOpts.PCHThroughHeader;
      return;
    }
    setPCHThroughHeaderFileID(
        SourceMgr.createFileID(*File, SourceLocation(), SrcMgr::C_User));
  }

  // Skip tokens from the Predefines and if needed the main file.
  if ((usingPCHWithThroughHeader() && SkippingUntilPCHThroughHeader) ||
      (usingPCHWithPragmaHdrStop() && SkippingUntilPragmaHdrStop))
    SkipTokensWhileUsingPCH();
}

void Preprocessor::setPCHThroughHeaderFileID(FileID FID) {
  assert(PCHThroughHeaderFileID.isInvalid() &&
         "PCHThroughHeaderFileID already set!");
  PCHThroughHeaderFileID = FID;
}

bool Preprocessor::isPCHThroughHeader(const FileEntry *FE) {
  assert(PCHThroughHeaderFileID.isValid() &&
         "Invalid PCH through header FileID");
  return FE == SourceMgr.getFileEntryForID(PCHThroughHeaderFileID);
}

bool Preprocessor::creatingPCHWithThroughHeader() {
  return TUKind == TU_Prefix && !PPOpts.PCHThroughHeader.empty() &&
         PCHThroughHeaderFileID.isValid();
}

bool Preprocessor::usingPCHWithThroughHeader() {
  return TUKind != TU_Prefix && !PPOpts.PCHThroughHeader.empty() &&
         PCHThroughHeaderFileID.isValid();
}

bool Preprocessor::creatingPCHWithPragmaHdrStop() {
  return TUKind == TU_Prefix && PPOpts.PCHWithHdrStop;
}

bool Preprocessor::usingPCHWithPragmaHdrStop() {
  return TUKind != TU_Prefix && PPOpts.PCHWithHdrStop;
}

/// Skip tokens until after the #include of the through header or
/// until after a #pragma hdrstop is seen. Tokens in the predefines file
/// and the main file may be skipped. If the end of the predefines file
/// is reached, skipping continues into the main file. If the end of the
/// main file is reached, it's a fatal error.
void Preprocessor::SkipTokensWhileUsingPCH() {
  bool ReachedMainFileEOF = false;
  bool UsingPCHThroughHeader = SkippingUntilPCHThroughHeader;
  bool UsingPragmaHdrStop = SkippingUntilPragmaHdrStop;
  Token Tok;
  while (true) {
    bool InPredefines =
        (CurLexer && CurLexer->getFileID() == getPredefinesFileID());
    CurLexerCallback(*this, Tok);
    if (Tok.is(tok::eof) && !InPredefines) {
      ReachedMainFileEOF = true;
      break;
    }
    if (UsingPCHThroughHeader && !SkippingUntilPCHThroughHeader)
      break;
    if (UsingPragmaHdrStop && !SkippingUntilPragmaHdrStop)
      break;
  }
  if (ReachedMainFileEOF) {
    if (UsingPCHThroughHeader)
      Diag(SourceLocation(), diag::err_pp_through_header_not_seen)
          << PPOpts.PCHThroughHeader << 1;
    else if (!PPOpts.PCHWithHdrStopCreate)
      Diag(SourceLocation(), diag::err_pp_pragma_hdrstop_not_seen);
  }
}

void Preprocessor::replayPreambleConditionalStack() {
  // Restore the conditional stack from the preamble, if there is one.
  if (PreambleConditionalStack.isReplaying()) {
    assert(CurPPLexer &&
           "CurPPLexer is null when calling replayPreambleConditionalStack.");
    CurPPLexer->setConditionalLevels(PreambleConditionalStack.getStack());
    PreambleConditionalStack.doneReplaying();
    if (PreambleConditionalStack.reachedEOFWhileSkipping())
      SkipExcludedConditionalBlock(
          PreambleConditionalStack.SkipInfo->HashTokenLoc,
          PreambleConditionalStack.SkipInfo->IfTokenLoc,
          PreambleConditionalStack.SkipInfo->FoundNonSkipPortion,
          PreambleConditionalStack.SkipInfo->FoundElse,
          PreambleConditionalStack.SkipInfo->ElseLoc);
  }
}

void Preprocessor::EndSourceFile() {
  // Notify the client that we reached the end of the source file.
  if (Callbacks)
    Callbacks->EndOfMainFile();
}

//===----------------------------------------------------------------------===//
// Lexer Event Handling.
//===----------------------------------------------------------------------===//

/// LookUpIdentifierInfo - Given a tok::raw_identifier token, look up the
/// identifier information for the token and install it into the token,
/// updating the token kind accordingly.
IdentifierInfo *Preprocessor::LookUpIdentifierInfo(Token &Identifier) const {
  assert(!Identifier.getRawIdentifier().empty() && "No raw identifier data!");

  // Look up this token, see if it is a macro, or if it is a language keyword.
  IdentifierInfo *II;
  if (!Identifier.needsCleaning() && !Identifier.hasUCN()) {
    // No cleaning needed, just use the characters from the lexed buffer.
    II = getIdentifierInfo(Identifier.getRawIdentifier());
  } else {
    // Cleaning needed, alloca a buffer, clean into it, then use the buffer.
    SmallString<64> IdentifierBuffer;
    StringRef CleanedStr = getSpelling(Identifier, IdentifierBuffer);

    if (Identifier.hasUCN()) {
      SmallString<64> UCNIdentifierBuffer;
      expandUCNs(UCNIdentifierBuffer, CleanedStr);
      II = getIdentifierInfo(UCNIdentifierBuffer);
    } else {
      II = getIdentifierInfo(CleanedStr);
    }
  }

  // Update the token info (identifier info and appropriate token kind).
  // FIXME: the raw_identifier may contain leading whitespace which is removed
  // from the cleaned identifier token. The SourceLocation should be updated to
  // refer to the non-whitespace character. For instance, the text "\\\nB" (a
  // line continuation before 'B') is parsed as a single tok::raw_identifier and
  // is cleaned to tok::identifier "B". After cleaning the token's length is
  // still 3 and the SourceLocation refers to the location of the backslash.
  Identifier.setIdentifierInfo(II);
  Identifier.setKind(II->getTokenID());

  return II;
}

void Preprocessor::SetPoisonReason(IdentifierInfo *II, unsigned DiagID) {
  PoisonReasons[II] = DiagID;
}

void Preprocessor::PoisonSEHIdentifiers(bool Poison) {
  assert(Ident__exception_code && Ident__exception_info);
  assert(Ident___exception_code && Ident___exception_info);
  Ident__exception_code->setIsPoisoned(Poison);
  Ident___exception_code->setIsPoisoned(Poison);
  Ident_GetExceptionCode->setIsPoisoned(Poison);
  Ident__exception_info->setIsPoisoned(Poison);
  Ident___exception_info->setIsPoisoned(Poison);
  Ident_GetExceptionInfo->setIsPoisoned(Poison);
  Ident__abnormal_termination->setIsPoisoned(Poison);
  Ident___abnormal_termination->setIsPoisoned(Poison);
  Ident_AbnormalTermination->setIsPoisoned(Poison);
}

void Preprocessor::HandlePoisonedIdentifier(Token & Identifier) {
  assert(Identifier.getIdentifierInfo() &&
         "Can't handle identifiers without identifier info!");
  llvm::DenseMap<IdentifierInfo*,unsigned>::const_iterator it =
    PoisonReasons.find(Identifier.getIdentifierInfo());
  if(it == PoisonReasons.end())
    Diag(Identifier, diag::err_pp_used_poisoned_id);
  else
    Diag(Identifier,it->second) << Identifier.getIdentifierInfo();
}

void Preprocessor::updateOutOfDateIdentifier(const IdentifierInfo &II) const {
  assert(II.isOutOfDate() && "not out of date");
  assert(getExternalSource() &&
         "getExternalSource() should not return nullptr");
  getExternalSource()->updateOutOfDateIdentifier(II);
}

/// HandleIdentifier - This callback is invoked when the lexer reads an
/// identifier.  This callback looks up the identifier in the map and/or
/// potentially macro expands it or turns it into a named token (like 'for').
///
/// Note that callers of this method are guarded by checking the
/// IdentifierInfo's 'isHandleIdentifierCase' bit.  If this method changes, the
/// IdentifierInfo methods that compute these properties will need to change to
/// match.
bool Preprocessor::HandleIdentifier(Token &Identifier) {
  assert(Identifier.getIdentifierInfo() &&
         "Can't handle identifiers without identifier info!");

  IdentifierInfo &II = *Identifier.getIdentifierInfo();

  // If the information about this identifier is out of date, update it from
  // the external source.
  // We have to treat __VA_ARGS__ in a special way, since it gets
  // serialized with isPoisoned = true, but our preprocessor may have
  // unpoisoned it if we're defining a C99 macro.
  if (II.isOutOfDate()) {
    bool CurrentIsPoisoned = false;
    const bool IsSpecialVariadicMacro =
        &II == Ident__VA_ARGS__ || &II == Ident__VA_OPT__;
    if (IsSpecialVariadicMacro)
      CurrentIsPoisoned = II.isPoisoned();

    updateOutOfDateIdentifier(II);
    Identifier.setKind(II.getTokenID());

    if (IsSpecialVariadicMacro)
      II.setIsPoisoned(CurrentIsPoisoned);
  }

  // If this identifier was poisoned, and if it was not produced from a macro
  // expansion, emit an error.
  if (II.isPoisoned() && CurPPLexer) {
    HandlePoisonedIdentifier(Identifier);
  }

  // If this is a macro to be expanded, do it.
  if (const MacroDefinition MD = getMacroDefinition(&II)) {
    const auto *MI = MD.getMacroInfo();
    assert(MI && "macro definition with no macro info?");
    if (!DisableMacroExpansion) {
      if (!Identifier.isExpandDisabled() && MI->isEnabled()) {
        // C99 6.10.3p10: If the preprocessing token immediately after the
        // macro name isn't a '(', this macro should not be expanded.
        if (!MI->isFunctionLike() || isNextPPTokenOneOf(tok::l_paren))
          return HandleMacroExpandedIdentifier(Identifier, MD);
      } else {
        // C99 6.10.3.4p2 says that a disabled macro may never again be
        // expanded, even if it's in a context where it could be expanded in the
        // future.
        Identifier.setFlag(Token::DisableExpand);
        if (MI->isObjectLike() || isNextPPTokenOneOf(tok::l_paren))
          Diag(Identifier, diag::pp_disabled_macro_expansion);
      }
    }
  }

  // If this identifier is a keyword in a newer Standard or proposed Standard,
  // produce a warning. Don't warn if we're not considering macro expansion,
  // since this identifier might be the name of a macro.
  // FIXME: This warning is disabled in cases where it shouldn't be, like
  //   "#define constexpr constexpr", "int constexpr;"
  if (II.isFutureCompatKeyword() && !DisableMacroExpansion) {
    Diag(Identifier, getIdentifierTable().getFutureCompatDiagKind(II, getLangOpts()))
        << II.getName();
    // Don't diagnose this keyword again in this translation unit.
    II.setIsFutureCompatKeyword(false);
  }

  // If this identifier would be a keyword in C++, diagnose as a compatibility
  // issue.
  if (II.IsKeywordInCPlusPlus() && !DisableMacroExpansion)
    Diag(Identifier, diag::warn_pp_identifier_is_cpp_keyword) << &II;

  // If this is an extension token, diagnose its use.
  // We avoid diagnosing tokens that originate from macro definitions.
  // FIXME: This warning is disabled in cases where it shouldn't be,
  // like "#define TY typeof", "TY(1) x".
  if (II.isExtensionToken() && !DisableMacroExpansion)
    Diag(Identifier, diag::ext_token_used);

  // Handle module contextual keywords.
  if (getLangOpts().CPlusPlusModules && CurLexer &&
      !CurLexer->isLexingRawMode() && !CurLexer->isPragmaLexer() &&
      !CurLexer->ParsingPreprocessorDirective &&
      Identifier.isModuleContextualKeyword() &&
      HandleModuleContextualKeyword(Identifier)) {
    HandleDirective(Identifier);
    // With a fatal failure in the module loader, we abort parsing.
    return hadModuleLoaderFatalFailure();
  }

  return true;
}

void Preprocessor::Lex(Token &Result) {
  ++LexLevel;

  // We loop here until a lex function returns a token; this avoids recursion.
  while (!CurLexerCallback(*this, Result))
    ;

  if (Result.is(tok::unknown) && TheModuleLoader.HadFatalFailure)
    return;

  if (Result.is(tok::code_completion) && Result.getIdentifierInfo()) {
    // Remember the identifier before code completion token.
    setCodeCompletionIdentifierInfo(Result.getIdentifierInfo());
    setCodeCompletionTokenRange(Result.getLocation(), Result.getEndLoc());
    // Set IdenfitierInfo to null to avoid confusing code that handles both
    // identifiers and completion tokens.
    Result.setIdentifierInfo(nullptr);
  }

  // Update StdCXXImportSeqState to track our position within a C++20 import-seq
  // if this token is being produced as a result of phase 4 of translation.
  // Update TrackGMFState to decide if we are currently in a Global Module
  // Fragment. GMF state updates should precede StdCXXImportSeq ones, since GMF state
  // depends on the prevailing StdCXXImportSeq state in two cases.
  if (getLangOpts().CPlusPlusModules && LexLevel == 1 &&
      !Result.getFlag(Token::IsReinjected)) {
    switch (Result.getKind()) {
    case tok::l_paren: case tok::l_square: case tok::l_brace:
      StdCXXImportSeqState.handleOpenBracket();
      break;
    case tok::r_paren: case tok::r_square:
      StdCXXImportSeqState.handleCloseBracket();
      break;
    case tok::r_brace:
      StdCXXImportSeqState.handleCloseBrace();
      break;
#define PRAGMA_ANNOTATION(X) case tok::annot_##X:
// For `#pragma ...` mimic ';'.
#include "clang/Basic/TokenKinds.def"
#undef PRAGMA_ANNOTATION
    // This token is injected to represent the translation of '#include "a.h"'
    // into "import a.h;". Mimic the notional ';'.
    case tok::annot_module_include:
    case tok::annot_repl_input_end:
    case tok::semi:
      TrackGMFState.handleSemi();
      StdCXXImportSeqState.handleSemi();
      ModuleDeclState.handleSemi();
      break;
    case tok::header_name:
    case tok::annot_header_unit:
      StdCXXImportSeqState.handleHeaderName();
      break;
    case tok::kw_export:
      if (hasSeenNoTrivialPPDirective())
        Result.setFlag(Token::HasSeenNoTrivialPPDirective);
      TrackGMFState.handleExport();
      StdCXXImportSeqState.handleExport();
      ModuleDeclState.handleExport();
      break;
    case tok::colon:
      ModuleDeclState.handleColon();
      break;
    case tok::kw_import:
      if (StdCXXImportSeqState.atTopLevel()) {
        TrackGMFState.handleImport(StdCXXImportSeqState.afterTopLevelSeq());
        StdCXXImportSeqState.handleImport();
      }
      break;
    case tok::kw_module:
      if (StdCXXImportSeqState.atTopLevel()) {
        if (hasSeenNoTrivialPPDirective())
          Result.setFlag(Token::HasSeenNoTrivialPPDirective);
        TrackGMFState.handleModule(StdCXXImportSeqState.afterTopLevelSeq());
        ModuleDeclState.handleModule();
      }
      break;
    case tok::annot_module_name:
      ModuleDeclState.handleModuleName(
          static_cast<ModuleNameLoc *>(Result.getAnnotationValue()));
      if (ModuleDeclState.isModuleCandidate())
        break;
      [[fallthrough]];
    default:
      TrackGMFState.handleMisc();
      StdCXXImportSeqState.handleMisc();
      ModuleDeclState.handleMisc();
      break;
    }
  }

  if (RecordCheckPoints && CurLexer &&
      ++CheckPointCounter == CheckPointStepSize) {
    CheckPoints[CurLexer->getFileID()].push_back(CurLexer->BufferPtr);
    CheckPointCounter = 0;
  }

  if (Result.isNot(tok::kw_export))
    LastExportKeyword.startToken();

  --LexLevel;

  // Destroy any lexers that were deferred while we were in nested Lex calls.
  // This must happen after decrementing LexLevel but before any other
  // processing that might re-enter Lex.
  if (LexLevel == 0 && !PendingDestroyLexers.empty())
    PendingDestroyLexers.clear();

  if ((LexLevel == 0 || PreprocessToken) &&
      !Result.getFlag(Token::IsReinjected)) {
    if (LexLevel == 0)
      ++TokenCount;
    if (OnToken)
      OnToken(Result);
  }
}

void Preprocessor::LexTokensUntilEOF(std::vector<Token> *Tokens) {
  while (1) {
    Token Tok;
    Lex(Tok);
    if (Tok.isOneOf(tok::unknown, tok::eof, tok::eod,
                    tok::annot_repl_input_end))
      break;
    if (Tokens != nullptr)
      Tokens->push_back(Tok);
  }
}

/// Lex a header-name token (including one formed from header-name-tokens if
/// \p AllowMacroExpansion is \c true).
///
/// \param FilenameTok Filled in with the next token. On success, this will
///        be either a header_name token. On failure, it will be whatever other
///        token was found instead.
/// \param AllowMacroExpansion If \c true, allow the header name to be formed
///        by macro expansion (concatenating tokens as necessary if the first
///        token is a '<').
/// \return \c true if we reached EOD or EOF while looking for a > token in
///         a concatenated header name and diagnosed it. \c false otherwise.
bool Preprocessor::LexHeaderName(Token &FilenameTok, bool AllowMacroExpansion) {
  // Lex using header-name tokenization rules if tokens are being lexed from
  // a file. Just grab a token normally if we're in a macro expansion.
  if (CurPPLexer) {
    // Avoid nested header-name lexing when macro expansion recurses
    // __has_include(__has_include))
    if (CurPPLexer->ParsingFilename)
      LexUnexpandedToken(FilenameTok);
    else
      CurPPLexer->LexIncludeFilename(FilenameTok);
  } else {
    Lex(FilenameTok);
  }

  // This could be a <foo/bar.h> file coming from a macro expansion.  In this
  // case, glue the tokens together into an angle_string_literal token.
  SmallString<128> FilenameBuffer;
  if (FilenameTok.is(tok::less) && AllowMacroExpansion) {
    bool StartOfLine = FilenameTok.isAtStartOfLine();
    bool LeadingSpace = FilenameTok.hasLeadingSpace();
    bool LeadingEmptyMacro = FilenameTok.hasLeadingEmptyMacro();

    SourceLocation Start = FilenameTok.getLocation();
    SourceLocation End;
    FilenameBuffer.push_back('<');

    // Consume tokens until we find a '>'.
    // FIXME: A header-name could be formed starting or ending with an
    // alternative token. It's not clear whether that's ill-formed in all
    // cases.
    while (FilenameTok.isNot(tok::greater)) {
      Lex(FilenameTok);
      if (FilenameTok.isOneOf(tok::eod, tok::eof)) {
        Diag(FilenameTok.getLocation(), diag::err_expected) << tok::greater;
        Diag(Start, diag::note_matching) << tok::less;
        return true;
      }

      End = FilenameTok.getLocation();

      // FIXME: Provide code completion for #includes.
      if (FilenameTok.is(tok::code_completion)) {
        setCodeCompletionReached();
        Lex(FilenameTok);
        continue;
      }

      // Append the spelling of this token to the buffer. If there was a space
      // before it, add it now.
      if (FilenameTok.hasLeadingSpace())
        FilenameBuffer.push_back(' ');

      // Get the spelling of the token, directly into FilenameBuffer if
      // possible.
      size_t PreAppendSize = FilenameBuffer.size();
      FilenameBuffer.resize(PreAppendSize + FilenameTok.getLength());

      const char *BufPtr = &FilenameBuffer[PreAppendSize];
      unsigned ActualLen = getSpelling(FilenameTok, BufPtr);

      // If the token was spelled somewhere else, copy it into FilenameBuffer.
      if (BufPtr != &FilenameBuffer[PreAppendSize])
        memcpy(&FilenameBuffer[PreAppendSize], BufPtr, ActualLen);

      // Resize FilenameBuffer to the correct size.
      if (FilenameTok.getLength() != ActualLen)
        FilenameBuffer.resize(PreAppendSize + ActualLen);
    }

    FilenameTok.startToken();
    FilenameTok.setKind(tok::header_name);
    FilenameTok.setFlagValue(Token::StartOfLine, StartOfLine);
    FilenameTok.setFlagValue(Token::LeadingSpace, LeadingSpace);
    FilenameTok.setFlagValue(Token::LeadingEmptyMacro, LeadingEmptyMacro);
    CreateString(FilenameBuffer, FilenameTok, Start, End);
  } else if (FilenameTok.is(tok::string_literal) && AllowMacroExpansion) {
    // Convert a string-literal token of the form " h-char-sequence "
    // (produced by macro expansion) into a header-name token.
    //
    // The rules for header-names don't quite match the rules for
    // string-literals, but all the places where they differ result in
    // undefined behavior, so we can and do treat them the same.
    //
    // A string-literal with a prefix or suffix is not translated into a
    // header-name. This could theoretically be observable via the C++20
    // context-sensitive header-name formation rules.
    StringRef Str = getSpelling(FilenameTok, FilenameBuffer);
    if (Str.size() >= 2 && Str.front() == '"' && Str.back() == '"')
      FilenameTok.setKind(tok::header_name);
  }

  return false;
}

std::optional<Token> Preprocessor::peekNextPPToken() const {
  // Do some quick tests for rejection cases.
  std::optional<Token> Val;
  if (CurLexer)
    Val = CurLexer->peekNextPPToken();
  else
    Val = CurTokenLexer->peekNextPPToken();

  if (!Val) {
    // We have run off the end.  If it's a source file we don't
    // examine enclosing ones (C99 5.1.1.2p4).  Otherwise walk up the
    // macro stack.
    if (CurPPLexer)
      return std::nullopt;
    for (const IncludeStackInfo &Entry : llvm::reverse(IncludeMacroStack)) {
      if (Entry.TheLexer)
        Val = Entry.TheLexer->peekNextPPToken();
      else
        Val = Entry.TheTokenLexer->peekNextPPToken();

      if (Val)
        break;

      // Ran off the end of a source file?
      if (Entry.ThePPLexer)
        return std::nullopt;
    }
  }

  // Okay, we found the token and return.  Otherwise we found the end of the
  // translation unit.
  return Val;
}

// We represent the primary and partition names as 'Paths' which are sections
// of the hierarchical access path for a clang module.  However for C++20
// the periods in a name are just another character, and we will need to
// flatten them into a string.
std::string ModuleLoader::getFlatNameFromPath(ModuleIdPath Path) {
  std::string Name;
  if (Path.empty())
    return Name;

  for (auto &Piece : Path) {
    assert(Piece.getIdentifierInfo() && Piece.getLoc().isValid());
    if (!Name.empty())
      Name += ".";
    Name += Piece.getIdentifierInfo()->getName();
  }
  return Name;
}

ModuleNameLoc *ModuleNameLoc::Create(Preprocessor &PP, ModuleIdPath Path) {
  assert(!Path.empty() && "expect at least one identifier in a module name");
  void *Mem = PP.getPreprocessorAllocator().Allocate(
      totalSizeToAlloc<IdentifierLoc>(Path.size()), alignof(ModuleNameLoc));
  return new (Mem) ModuleNameLoc(Path);
}

bool Preprocessor::LexModuleNameContinue(Token &Tok, SourceLocation UseLoc,
                                         SmallVectorImpl<Token> &Suffix,
                                         SmallVectorImpl<IdentifierLoc> &Path,
                                         bool AllowMacroExpansion,
                                         bool IsPartition) {
  auto ConsumeToken = [&]() {
    if (AllowMacroExpansion)
      Lex(Tok);
    else
      LexUnexpandedToken(Tok);
    Suffix.push_back(Tok);
  };

  while (true) {
    if (Tok.isNot(tok::identifier)) {
      if (Tok.is(tok::code_completion)) {
        CurLexer->cutOffLexing();
        CodeComplete->CodeCompleteModuleImport(UseLoc, Path);
        return true;
      }

      Diag(Tok, diag::err_pp_module_expected_ident) << Path.empty();
      return true;
    }

    // [cpp.pre]/p2:
    // No identifier in the pp-module-name or pp-module-partition shall
    // currently be defined as an object-like macro.
    if (MacroInfo *MI = getMacroInfo(Tok.getIdentifierInfo());
        MI && MI->isObjectLike() && getLangOpts().CPlusPlus20 &&
        !AllowMacroExpansion) {
      Diag(Tok, diag::err_pp_module_name_is_macro)
          << IsPartition << Tok.getIdentifierInfo();
      Diag(MI->getDefinitionLoc(), diag::note_macro_here)
          << Tok.getIdentifierInfo();
    }

    // Record this part of the module path.
    Path.emplace_back(Tok.getLocation(), Tok.getIdentifierInfo());
    ConsumeToken();

    if (Tok.isNot(tok::period))
      return false;

    ConsumeToken();
  }
}

bool Preprocessor::HandleModuleName(StringRef DirType, SourceLocation UseLoc,
                                    Token &Tok,
                                    SmallVectorImpl<IdentifierLoc> &Path,
                                    SmallVectorImpl<Token> &DirToks,
                                    bool AllowMacroExpansion,
                                    bool IsPartition) {
  bool LeadingSpace = Tok.hasLeadingSpace();
  unsigned NumToksInDirective = DirToks.size();
  if (LexModuleNameContinue(Tok, UseLoc, DirToks, Path, AllowMacroExpansion,
                            IsPartition)) {
    if (Tok.isNot(tok::eod))
      CheckEndOfDirective(DirType,
                          /*EnableMacros=*/false, &DirToks);
    EnterModuleSuffixTokenStream(DirToks);
    return true;
  }

  // Clean the module-name tokens and replace these tokens with
  // annot_module_name.
  DirToks.resize(NumToksInDirective);
  ModuleNameLoc *NameLoc = ModuleNameLoc::Create(*this, Path);
  DirToks.emplace_back();
  DirToks.back().setKind(tok::annot_module_name);
  DirToks.back().setAnnotationRange(NameLoc->getRange());
  DirToks.back().setAnnotationValue(static_cast<void *>(NameLoc));
  DirToks.back().setFlagValue(Token::LeadingSpace, LeadingSpace);
  DirToks.push_back(Tok);
  return false;
}

/// [cpp.pre]/p2:
/// A preprocessing directive consists of a sequence of preprocessing tokens
/// that satisfies the following constraints: At the start of translation phase
/// 4, the first preprocessing token in the sequence, referred to as a
/// directive-introducing token, begins with the first character in the source
/// file (optionally after whitespace containing no new-line characters) or
/// follows whitespace containing at least one new-line character, and is:
///   - a # preprocessing token, or
///   - an import preprocessing token immediately followed on the same logical
///   source line by a header-name, <, identifier, or : preprocessing token, or
///   - a module preprocessing token immediately followed on the same logical
///   source line by an identifier, :, or ; preprocessing token, or
///   - an export preprocessing token immediately followed on the same logical
///   source line by one of the two preceding forms.
///
///
/// At the start of phase 4 an import or module token is treated as starting a
/// directive and are converted to their respective keywords iff:
///   - After skipping horizontal whitespace are
///     - at the start of a logical line, or
///     - preceded by an 'export' at the start of the logical line.
///   - Are followed by an identifier pp token (before macro expansion), or
///     - <, ", or : (but not ::) pp tokens for 'import', or
///     - ; for 'module'
/// Otherwise the token is treated as an identifier.
bool Preprocessor::HandleModuleContextualKeyword(Token &Result) {
  if (!getLangOpts().CPlusPlusModules || !Result.isModuleContextualKeyword())
    return false;

  if (Result.is(tok::kw_export)) {
    LastExportKeyword = Result;
    return false;
  }

  /// Trait 'module' and 'import' as a identifier when the main file is a
  /// preprocessed module file. We only allow '__preprocessed_module' and
  /// '__preprocessed_import' in this context.
  IdentifierInfo *II = Result.getIdentifierInfo();
  if (isPreprocessedModuleFile() &&
      (II->isStr(tok::getKeywordSpelling(tok::kw_import)) ||
       II->isStr(tok::getKeywordSpelling(tok::kw_module))))
    return false;

  if (LastExportKeyword.is(tok::kw_export)) {
    // The export keyword was not at the start of line, it's not a
    // directive-introducing token.
    if (!LastExportKeyword.isAtPhysicalStartOfLine())
      return false;
    // [cpp.pre]/1.4
    // export         // not a preprocessing directive
    // import foo;    // preprocessing directive (ill-formed at phase7)
    if (Result.isAtPhysicalStartOfLine())
      return false;
  } else if (!Result.isAtPhysicalStartOfLine())
    return false;

  assert(CurPPLexer && "CurPPLexer must not be null");

  llvm::SaveAndRestore<bool> SavedParsingPreprocessorDirective(
      CurPPLexer->ParsingPreprocessorDirective, true);

  // The next token may be an angled string literal after import keyword.
  llvm::SaveAndRestore<bool> SavedParsingFilemame(
      CurPPLexer->ParsingFilename,
      Result.getIdentifierInfo()->isImportKeyword());

  std::optional<Token> NextTok = peekNextPPToken();
  if (!NextTok)
    return false;

  if (NextTok->is(tok::raw_identifier))
    LookUpIdentifierInfo(*NextTok);

  if (Result.getIdentifierInfo()->isImportKeyword()) {
    if (NextTok->isOneOf(tok::identifier, tok::less, tok::colon,
                         tok::header_name)) {
      Result.setKind(tok::kw_import);
      ModuleImportLoc = Result.getLocation();
      return true;
    }
  }

  if (Result.getIdentifierInfo()->isModuleKeyword() &&
      NextTok->isOneOf(tok::identifier, tok::colon, tok::semi)) {
    Result.setKind(tok::kw_module);
    ModuleDeclLoc = Result.getLocation();
    return true;
  }

  // Ok, it's an identifier.
  return false;
}

bool Preprocessor::CollectPPImportSuffixAndEnterStream(
    SmallVectorImpl<Token> &Toks, bool StopUntilEOD) {
  CollectPPImportSuffix(Toks);
  EnterModuleSuffixTokenStream(Toks);
  return false;
}

/// Collect the tokens of a C++20 pp-import-suffix.
void Preprocessor::CollectPPImportSuffix(SmallVectorImpl<Token> &Toks,
                                         bool StopUntilEOD) {
  while (true) {
    Toks.emplace_back();
    Lex(Toks.back());

    switch (Toks.back().getKind()) {
    case tok::semi:
      if (!StopUntilEOD)
        return;
      [[fallthrough]];
    case tok::eod:
    case tok::eof:
      return;
    default:
      break;
    }
  }
}

// Allocate a holding buffer for a sequence of tokens and introduce it into
// the token stream.
void Preprocessor::EnterModuleSuffixTokenStream(ArrayRef<Token> Toks) {
  if (Toks.empty())
    return;
  auto ToksCopy = std::make_unique<Token[]>(Toks.size());
  std::copy(Toks.begin(), Toks.end(), ToksCopy.get());
  EnterTokenStream(std::move(ToksCopy), Toks.size(),
                   /*DisableMacroExpansion*/ false, /*IsReinject*/ false);
  assert(CurTokenLexer && "Must have a TokenLexer");
  CurTokenLexer->setLexingCXXModuleDirective();
}

void Preprocessor::makeModuleVisible(Module *M, SourceLocation Loc,
                                     bool IncludeExports) {
  CurSubmoduleState->VisibleModules.setVisible(
      M, Loc, IncludeExports, [](Module *) {},
      [&](ArrayRef<Module *> Path, Module *Conflict, StringRef Message) {
        // FIXME: Include the path in the diagnostic.
        // FIXME: Include the import location for the conflicting module.
        Diag(ModuleImportLoc, diag::warn_module_conflict)
            << Path[0]->getFullModuleName()
            << Conflict->getFullModuleName()
            << Message;
      });

  // Add this module to the imports list of the currently-built submodule.
  if (!BuildingSubmoduleStack.empty() && M != BuildingSubmoduleStack.back().M)
    BuildingSubmoduleStack.back().M->Imports.push_back(M);
}

bool Preprocessor::FinishLexStringLiteral(Token &Result, std::string &String,
                                          const char *DiagnosticTag,
                                          bool AllowMacroExpansion) {
  // We need at least one string literal.
  if (Result.isNot(tok::string_literal)) {
    Diag(Result, diag::err_expected_string_literal)
      << /*Source='in...'*/0 << DiagnosticTag;
    return false;
  }

  // Lex string literal tokens, optionally with macro expansion.
  SmallVector<Token, 4> StrToks;
  do {
    StrToks.push_back(Result);

    if (Result.hasUDSuffix())
      Diag(Result, diag::err_invalid_string_udl);

    if (AllowMacroExpansion)
      Lex(Result);
    else
      LexUnexpandedToken(Result);
  } while (Result.is(tok::string_literal));

  // Concatenate and parse the strings.
  StringLiteralParser Literal(StrToks, *this);
  assert(Literal.isOrdinary() && "Didn't allow wide strings in");

  if (Literal.hadError)
    return false;

  if (Literal.Pascal) {
    Diag(StrToks[0].getLocation(), diag::err_expected_string_literal)
      << /*Source='in...'*/0 << DiagnosticTag;
    return false;
  }

  String = std::string(Literal.GetString());
  return true;
}

bool Preprocessor::parseSimpleIntegerLiteral(Token &Tok, uint64_t &Value) {
  assert(Tok.is(tok::numeric_constant));
  SmallString<8> IntegerBuffer;
  bool NumberInvalid = false;
  StringRef Spelling = getSpelling(Tok, IntegerBuffer, &NumberInvalid);
  if (NumberInvalid)
    return false;
  NumericLiteralParser Literal(Spelling, Tok.getLocation(), getSourceManager(),
                               getLangOpts(), getTargetInfo(),
                               getDiagnostics());
  if (Literal.hadError || !Literal.isIntegerLiteral() || Literal.hasUDSuffix())
    return false;
  llvm::APInt APVal(64, 0);
  if (Literal.GetIntegerValue(APVal))
    return false;
  Lex(Tok);
  Value = APVal.getLimitedValue();
  return true;
}

void Preprocessor::addCommentHandler(CommentHandler *Handler) {
  assert(Handler && "NULL comment handler");
  assert(!llvm::is_contained(CommentHandlers, Handler) &&
         "Comment handler already registered");
  CommentHandlers.push_back(Handler);
}

void Preprocessor::removeCommentHandler(CommentHandler *Handler) {
  std::vector<CommentHandler *>::iterator Pos =
      llvm::find(CommentHandlers, Handler);
  assert(Pos != CommentHandlers.end() && "Comment handler not registered");
  CommentHandlers.erase(Pos);
}

bool Preprocessor::HandleComment(Token &result, SourceRange Comment) {
  bool AnyPendingTokens = false;
  for (CommentHandler *H : CommentHandlers) {
    if (H->HandleComment(*this, Comment))
      AnyPendingTokens = true;
  }
  if (!AnyPendingTokens || getCommentRetentionState())
    return false;
  Lex(result);
  return true;
}

void Preprocessor::emitMacroDeprecationWarning(const Token &Identifier) const {
  const MacroAnnotations &A =
      getMacroAnnotations(Identifier.getIdentifierInfo());
  assert(A.DeprecationInfo &&
         "Macro deprecation warning without recorded annotation!");
  const MacroAnnotationInfo &Info = *A.DeprecationInfo;
  if (Info.Message.empty())
    Diag(Identifier, diag::warn_pragma_deprecated_macro_use)
        << Identifier.getIdentifierInfo() << 0;
  else
    Diag(Identifier, diag::warn_pragma_deprecated_macro_use)
        << Identifier.getIdentifierInfo() << 1 << Info.Message;
  Diag(Info.Location, diag::note_pp_macro_annotation) << 0;
}

void Preprocessor::emitRestrictExpansionWarning(const Token &Identifier) const {
  const MacroAnnotations &A =
      getMacroAnnotations(Identifier.getIdentifierInfo());
  assert(A.RestrictExpansionInfo &&
         "Macro restricted expansion warning without recorded annotation!");
  const MacroAnnotationInfo &Info = *A.RestrictExpansionInfo;
  if (Info.Message.empty())
    Diag(Identifier, diag::warn_pragma_restrict_expansion_macro_use)
        << Identifier.getIdentifierInfo() << 0;
  else
    Diag(Identifier, diag::warn_pragma_restrict_expansion_macro_use)
        << Identifier.getIdentifierInfo() << 1 << Info.Message;
  Diag(Info.Location, diag::note_pp_macro_annotation) << 1;
}

void Preprocessor::emitRestrictInfNaNWarning(const Token &Identifier,
                                             unsigned DiagSelection) const {
  Diag(Identifier, diag::warn_fp_nan_inf_when_disabled) << DiagSelection << 1;
}

void Preprocessor::emitFinalMacroWarning(const Token &Identifier,
                                         bool IsUndef) const {
  const MacroAnnotations &A =
      getMacroAnnotations(Identifier.getIdentifierInfo());
  assert(A.FinalAnnotationLoc &&
         "Final macro warning without recorded annotation!");

  Diag(Identifier, diag::warn_pragma_final_macro)
      << Identifier.getIdentifierInfo() << (IsUndef ? 0 : 1);
  Diag(*A.FinalAnnotationLoc, diag::note_pp_macro_annotation) << 2;
}

bool Preprocessor::isSafeBufferOptOut(const SourceManager &SourceMgr,
                                      const SourceLocation &Loc) const {
  // The lambda that tests if a `Loc` is in an opt-out region given one opt-out
  // region map:
  auto TestInMap = [&SourceMgr](const SafeBufferOptOutRegionsTy &Map,
                                const SourceLocation &Loc) -> bool {
    // Try to find a region in `SafeBufferOptOutMap` where `Loc` is in:
    auto FirstRegionEndingAfterLoc = llvm::partition_point(
        Map, [&SourceMgr,
              &Loc](const std::pair<SourceLocation, SourceLocation> &Region) {
          return SourceMgr.isBeforeInTranslationUnit(Region.second, Loc);
        });

    if (FirstRegionEndingAfterLoc != Map.end()) {
      // To test if the start location of the found region precedes `Loc`:
      return SourceMgr.isBeforeInTranslationUnit(
          FirstRegionEndingAfterLoc->first, Loc);
    }
    // If we do not find a region whose end location passes `Loc`, we want to
    // check if the current region is still open:
    if (!Map.empty() && Map.back().first == Map.back().second)
      return SourceMgr.isBeforeInTranslationUnit(Map.back().first, Loc);
    return false;
  };

  // What the following does:
  //
  // If `Loc` belongs to the local TU, we just look up `SafeBufferOptOutMap`.
  // Otherwise, `Loc` is from a loaded AST.  We look up the
  // `LoadedSafeBufferOptOutMap` first to get the opt-out region map of the
  // loaded AST where `Loc` is at.  Then we find if `Loc` is in an opt-out
  // region w.r.t. the region map.  If the region map is absent, it means there
  // is no opt-out pragma in that loaded AST.
  //
  // Opt-out pragmas in the local TU or a loaded AST is not visible to another
  // one of them.  That means if you put the pragmas around a `#include
  // "module.h"`, where module.h is a module, it is not actually suppressing
  // warnings in module.h.  This is fine because warnings in module.h will be
  // reported when module.h is compiled in isolation and nothing in module.h
  // will be analyzed ever again.  So you will not see warnings from the file
  // that imports module.h anyway. And you can't even do the same thing for PCHs
  //  because they can only be included from the command line.

  if (SourceMgr.isLocalSourceLocation(Loc))
    return TestInMap(SafeBufferOptOutMap, Loc);

  const SafeBufferOptOutRegionsTy *LoadedRegions =
      LoadedSafeBufferOptOutMap.lookupLoadedOptOutMap(Loc, SourceMgr);

  if (LoadedRegions)
    return TestInMap(*LoadedRegions, Loc);
  return false;
}

bool Preprocessor::enterOrExitSafeBufferOptOutRegion(
    bool isEnter, const SourceLocation &Loc) {
  if (isEnter) {
    if (isPPInSafeBufferOptOutRegion())
      return true; // invalid enter action
    InSafeBufferOptOutRegion = true;
    CurrentSafeBufferOptOutStart = Loc;

    // To set the start location of a new region:

    if (!SafeBufferOptOutMap.empty()) {
      [[maybe_unused]] auto *PrevRegion = &SafeBufferOptOutMap.back();
      assert(PrevRegion->first != PrevRegion->second &&
             "Shall not begin a safe buffer opt-out region before closing the "
             "previous one.");
    }
    // If the start location equals to the end location, we call the region a
    // open region or a unclosed region (i.e., end location has not been set
    // yet).
    SafeBufferOptOutMap.emplace_back(Loc, Loc);
  } else {
    if (!isPPInSafeBufferOptOutRegion())
      return true; // invalid enter action
    InSafeBufferOptOutRegion = false;

    // To set the end location of the current open region:

    assert(!SafeBufferOptOutMap.empty() &&
           "Misordered safe buffer opt-out regions");
    auto *CurrRegion = &SafeBufferOptOutMap.back();
    assert(CurrRegion->first == CurrRegion->second &&
           "Set end location to a closed safe buffer opt-out region");
    CurrRegion->second = Loc;
  }
  return false;
}

bool Preprocessor::isPPInSafeBufferOptOutRegion() {
  return InSafeBufferOptOutRegion;
}
bool Preprocessor::isPPInSafeBufferOptOutRegion(SourceLocation &StartLoc) {
  StartLoc = CurrentSafeBufferOptOutStart;
  return InSafeBufferOptOutRegion;
}

SmallVector<SourceLocation, 64>
Preprocessor::serializeSafeBufferOptOutMap() const {
  assert(!InSafeBufferOptOutRegion &&
         "Attempt to serialize safe buffer opt-out regions before file being "
         "completely preprocessed");

  SmallVector<SourceLocation, 64> SrcSeq;

  for (const auto &[begin, end] : SafeBufferOptOutMap) {
    SrcSeq.push_back(begin);
    SrcSeq.push_back(end);
  }
  // Only `SafeBufferOptOutMap` gets serialized. No need to serialize
  // `LoadedSafeBufferOptOutMap` because if this TU loads a pch/module, every
  // pch/module in the pch-chain/module-DAG will be loaded one by one in order.
  // It means that for each loading pch/module m, it just needs to load m's own
  // `SafeBufferOptOutMap`.
  return SrcSeq;
}

bool Preprocessor::setDeserializedSafeBufferOptOutMap(
    const SmallVectorImpl<SourceLocation> &SourceLocations) {
  if (SourceLocations.size() == 0)
    return false;

  assert(SourceLocations.size() % 2 == 0 &&
         "ill-formed SourceLocation sequence");

  auto It = SourceLocations.begin();
  SafeBufferOptOutRegionsTy &Regions =
      LoadedSafeBufferOptOutMap.findAndConsLoadedOptOutMap(*It, SourceMgr);

  do {
    SourceLocation Begin = *It++;
    SourceLocation End = *It++;

    Regions.emplace_back(Begin, End);
  } while (It != SourceLocations.end());
  return true;
}

ModuleLoader::~ModuleLoader() = default;

CommentHandler::~CommentHandler() = default;

EmptylineHandler::~EmptylineHandler() = default;

CodeCompletionHandler::~CodeCompletionHandler() = default;

void Preprocessor::createPreprocessingRecord() {
  if (Record)
    return;

  Record = new PreprocessingRecord(getSourceManager());
  addPPCallbacks(std::unique_ptr<PPCallbacks>(Record));
}

void Preprocessor::removePPCallbacks() {
  auto IsPreserved = [&](PPCallbacks *C) {
    return C == Record || C == DirTracer;
  };
  SmallVector<PPCallbacks *, 2> Released;
  PPCallbacks::releaseIfPreserved(Callbacks, IsPreserved, Released);
  Callbacks.reset();
  for (auto *P : Released)
    addPPCallbacks(std::unique_ptr<PPCallbacks>(P));
}

const char *Preprocessor::getCheckPoint(FileID FID, const char *Start) const {
  if (auto It = CheckPoints.find(FID); It != CheckPoints.end()) {
    const SmallVector<const char *> &FileCheckPoints = It->second;
    auto P = llvm::upper_bound(FileCheckPoints, Start);
    if (P == FileCheckPoints.begin())
      return nullptr;
    return *std::prev(P);
  }
  return nullptr;
}

bool Preprocessor::hasSeenNoTrivialPPDirective() const {
  return DirTracer && DirTracer->hasSeenNoTrivialPPDirective();
}

bool NoTrivialPPDirectiveTracer::hasSeenNoTrivialPPDirective() const {
  return SeenNoTrivialPPDirective;
}

void NoTrivialPPDirectiveTracer::setSeenNoTrivialPPDirective() {
  if (InMainFile && !SeenNoTrivialPPDirective)
    SeenNoTrivialPPDirective = true;
}

void NoTrivialPPDirectiveTracer::LexedFileChanged(
    FileID FID, LexedFileChangeReason Reason,
    SrcMgr::CharacteristicKind FileType, FileID PrevFID, SourceLocation Loc) {
  InMainFile = (FID == PP.getSourceManager().getMainFileID());
}

void NoTrivialPPDirectiveTracer::MacroExpands(const Token &MacroNameTok,
                                              const MacroDefinition &MD,
                                              SourceRange Range,
                                              const MacroArgs *Args) {
  // FIXME: Does only enable builtin macro expansion make sense?
  if (!MD.getMacroInfo()->isBuiltinMacro())
    setSeenNoTrivialPPDirective();
}
