//===--- PPLexerChange.cpp - Handle changing lexers in the preprocessor ---===//
//
// 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 pieces of the Preprocessor interface that manage the
// current lexer stack.
//
//===----------------------------------------------------------------------===//

#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/MemoryBufferRef.h"
#include "llvm/Support/Path.h"
#include <optional>

using namespace clang;

//===----------------------------------------------------------------------===//
// Miscellaneous Methods.
//===----------------------------------------------------------------------===//

/// isInPrimaryFile - Return true if we're in the top-level file, not in a
/// \#include.  This looks through macro expansions and active _Pragma lexers.
bool Preprocessor::isInPrimaryFile() const {
  if (IsFileLexer())
    return IncludeMacroStack.empty();

  // If there are any stacked lexers, we're in a #include.
  assert(IsFileLexer(IncludeMacroStack[0]) &&
         "Top level include stack isn't our primary lexer?");
  return llvm::none_of(
      llvm::drop_begin(IncludeMacroStack),
      [&](const IncludeStackInfo &ISI) -> bool { return IsFileLexer(ISI); });
}

/// getCurrentLexer - Return the current file lexer being lexed from.  Note
/// that this ignores any potentially active macro expansions and _Pragma
/// expansions going on at the time.
PreprocessorLexer *Preprocessor::getCurrentFileLexer() const {
  if (IsFileLexer())
    return CurPPLexer;

  // Look for a stacked lexer.
  for (const IncludeStackInfo &ISI : llvm::reverse(IncludeMacroStack)) {
    if (IsFileLexer(ISI))
      return ISI.ThePPLexer;
  }
  return nullptr;
}


//===----------------------------------------------------------------------===//
// Methods for Entering and Callbacks for leaving various contexts
//===----------------------------------------------------------------------===//

/// EnterSourceFile - Add a source file to the top of the include stack and
/// start lexing tokens from it instead of the current buffer.
bool Preprocessor::EnterSourceFile(FileID FID, ConstSearchDirIterator CurDir,
                                   SourceLocation Loc,
                                   bool IsFirstIncludeOfFile) {
  assert(!CurTokenLexer && "Cannot #include a file inside a macro!");
  ++NumEnteredSourceFiles;

  if (MaxIncludeStackDepth < IncludeMacroStack.size())
    MaxIncludeStackDepth = IncludeMacroStack.size();

  // Get the MemoryBuffer for this FID, if it fails, we fail.
  std::optional<llvm::MemoryBufferRef> InputFile =
      getSourceManager().getBufferOrNone(FID, Loc);
  if (!InputFile) {
    SourceLocation FileStart = SourceMgr.getLocForStartOfFile(FID);
    Diag(Loc, diag::err_pp_error_opening_file)
        << std::string(SourceMgr.getBufferName(FileStart)) << "";
    return true;
  }

  if (isCodeCompletionEnabled() &&
      SourceMgr.getFileEntryForID(FID) == CodeCompletionFile) {
    CodeCompletionFileLoc = SourceMgr.getLocForStartOfFile(FID);
    CodeCompletionLoc =
        CodeCompletionFileLoc.getLocWithOffset(CodeCompletionOffset);
  }

  Lexer *TheLexer = new Lexer(FID, *InputFile, *this, IsFirstIncludeOfFile);
  if (GetDependencyDirectives && FID != PredefinesFileID)
    if (OptionalFileEntryRef File = SourceMgr.getFileEntryRefForID(FID))
      if (auto MaybeDepDirectives = (*GetDependencyDirectives)(*File))
        TheLexer->DepDirectives = *MaybeDepDirectives;

  EnterSourceFileWithLexer(TheLexer, CurDir);
  return false;
}

/// EnterSourceFileWithLexer - Add a source file to the top of the include stack
///  and start lexing tokens from it instead of the current buffer.
void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer,
                                            ConstSearchDirIterator CurDir) {
  PreprocessorLexer *PrevPPLexer = CurPPLexer;

  // Add the current lexer to the include stack.
  if (CurPPLexer || CurTokenLexer)
    PushIncludeMacroStack();

  CurLexer.reset(TheLexer);
  CurPPLexer = TheLexer;
  CurDirLookup = CurDir;
  CurLexerSubmodule = nullptr;
  if (CurLexerCallback != CLK_LexAfterModuleImport)
    CurLexerCallback = TheLexer->isDependencyDirectivesLexer()
                           ? CLK_DependencyDirectivesLexer
                           : CLK_Lexer;

  // Notify the client, if desired, that we are in a new source file.
  if (Callbacks && !CurLexer->Is_PragmaLexer) {
    SrcMgr::CharacteristicKind FileType =
       SourceMgr.getFileCharacteristic(CurLexer->getFileLoc());

    FileID PrevFID;
    SourceLocation EnterLoc;
    if (PrevPPLexer) {
      PrevFID = PrevPPLexer->getFileID();
      EnterLoc = PrevPPLexer->getSourceLocation();
    }
    Callbacks->FileChanged(CurLexer->getFileLoc(), PPCallbacks::EnterFile,
                           FileType, PrevFID);
    Callbacks->LexedFileChanged(CurLexer->getFileID(),
                                PPCallbacks::LexedFileChangeReason::EnterFile,
                                FileType, PrevFID, EnterLoc);
  }
}

/// EnterMacro - Add a Macro to the top of the include stack and start lexing
/// tokens from it instead of the current buffer.
void Preprocessor::EnterMacro(Token &Tok, SourceLocation ILEnd,
                              MacroInfo *Macro, MacroArgs *Args) {
  std::unique_ptr<TokenLexer> TokLexer;
  if (NumCachedTokenLexers == 0) {
    TokLexer = std::make_unique<TokenLexer>(Tok, ILEnd, Macro, Args, *this);
  } else {
    TokLexer = std::move(TokenLexerCache[--NumCachedTokenLexers]);
    TokLexer->Init(Tok, ILEnd, Macro, Args);
  }

  PushIncludeMacroStack();
  CurDirLookup = nullptr;
  CurTokenLexer = std::move(TokLexer);
  if (CurLexerCallback != CLK_LexAfterModuleImport)
    CurLexerCallback = CLK_TokenLexer;
}

/// EnterTokenStream - Add a "macro" context to the top of the include stack,
/// which will cause the lexer to start returning the specified tokens.
///
/// If DisableMacroExpansion is true, tokens lexed from the token stream will
/// not be subject to further macro expansion.  Otherwise, these tokens will
/// be re-macro-expanded when/if expansion is enabled.
///
/// If OwnsTokens is false, this method assumes that the specified stream of
/// tokens has a permanent owner somewhere, so they do not need to be copied.
/// If it is true, it assumes the array of tokens is allocated with new[] and
/// must be freed.
///
void Preprocessor::EnterTokenStream(const Token *Toks, unsigned NumToks,
                                    bool DisableMacroExpansion, bool OwnsTokens,
                                    bool IsReinject) {
  if (CurLexerCallback == CLK_CachingLexer) {
    if (CachedLexPos < CachedTokens.size()) {
      assert(IsReinject && "new tokens in the middle of cached stream");
      // We're entering tokens into the middle of our cached token stream. We
      // can't represent that, so just insert the tokens into the buffer.
      CachedTokens.insert(CachedTokens.begin() + CachedLexPos,
                          Toks, Toks + NumToks);
      if (OwnsTokens)
        delete [] Toks;
      return;
    }

    // New tokens are at the end of the cached token sequnece; insert the
    // token stream underneath the caching lexer.
    ExitCachingLexMode();
    EnterTokenStream(Toks, NumToks, DisableMacroExpansion, OwnsTokens,
                     IsReinject);
    EnterCachingLexMode();
    return;
  }

  // Create a macro expander to expand from the specified token stream.
  std::unique_ptr<TokenLexer> TokLexer;
  if (NumCachedTokenLexers == 0) {
    TokLexer = std::make_unique<TokenLexer>(
        Toks, NumToks, DisableMacroExpansion, OwnsTokens, IsReinject, *this);
  } else {
    TokLexer = std::move(TokenLexerCache[--NumCachedTokenLexers]);
    TokLexer->Init(Toks, NumToks, DisableMacroExpansion, OwnsTokens,
                   IsReinject);
  }

  // Save our current state.
  PushIncludeMacroStack();
  CurDirLookup = nullptr;
  CurTokenLexer = std::move(TokLexer);
  if (CurLexerCallback != CLK_LexAfterModuleImport)
    CurLexerCallback = CLK_TokenLexer;
}

/// Compute the relative path that names the given file relative to
/// the given directory.
static void computeRelativePath(FileManager &FM, const DirectoryEntry *Dir,
                                FileEntryRef File, SmallString<128> &Result) {
  Result.clear();

  StringRef FilePath = File.getDir().getName();
  StringRef Path = FilePath;
  while (!Path.empty()) {
    if (auto CurDir = FM.getOptionalDirectoryRef(Path)) {
      if (*CurDir == Dir) {
        Result = FilePath.substr(Path.size());
        llvm::sys::path::append(Result,
                                llvm::sys::path::filename(File.getName()));
        return;
      }
    }

    Path = llvm::sys::path::parent_path(Path);
  }

  Result = File.getName();
}

void Preprocessor::PropagateLineStartLeadingSpaceInfo(Token &Result) {
  if (CurTokenLexer) {
    CurTokenLexer->PropagateLineStartLeadingSpaceInfo(Result);
    return;
  }
  if (CurLexer) {
    CurLexer->PropagateLineStartLeadingSpaceInfo(Result);
    return;
  }
  // FIXME: Handle other kinds of lexers?  It generally shouldn't matter,
  // but it might if they're empty?
}

/// Determine the location to use as the end of the buffer for a lexer.
///
/// If the file ends with a newline, form the EOF token on the newline itself,
/// rather than "on the line following it", which doesn't exist.  This makes
/// diagnostics relating to the end of file include the last file that the user
/// actually typed, which is goodness.
const char *Preprocessor::getCurLexerEndPos() {
  const char *EndPos = CurLexer->BufferEnd;
  if (EndPos != CurLexer->BufferStart &&
      (EndPos[-1] == '\n' || EndPos[-1] == '\r')) {
    --EndPos;

    // Handle \n\r and \r\n:
    if (EndPos != CurLexer->BufferStart &&
        (EndPos[-1] == '\n' || EndPos[-1] == '\r') &&
        EndPos[-1] != EndPos[0])
      --EndPos;
  }

  return EndPos;
}

static void collectAllSubModulesWithUmbrellaHeader(
    const Module &Mod, SmallVectorImpl<const Module *> &SubMods) {
  if (Mod.getUmbrellaHeaderAsWritten())
    SubMods.push_back(&Mod);
  for (auto *M : Mod.submodules())
    collectAllSubModulesWithUmbrellaHeader(*M, SubMods);
}

void Preprocessor::diagnoseMissingHeaderInUmbrellaDir(const Module &Mod) {
  std::optional<Module::Header> UmbrellaHeader =
      Mod.getUmbrellaHeaderAsWritten();
  assert(UmbrellaHeader && "Module must use umbrella header");
  const FileID &File = SourceMgr.translateFile(UmbrellaHeader->Entry);
  SourceLocation ExpectedHeadersLoc = SourceMgr.getLocForEndOfFile(File);
  if (getDiagnostics().isIgnored(diag::warn_uncovered_module_header,
                                 ExpectedHeadersLoc))
    return;

  ModuleMap &ModMap = getHeaderSearchInfo().getModuleMap();
  OptionalDirectoryEntryRef Dir = Mod.getEffectiveUmbrellaDir();
  llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
  std::error_code EC;
  for (llvm::vfs::recursive_directory_iterator Entry(FS, Dir->getName(), EC),
       End;
       Entry != End && !EC; Entry.increment(EC)) {
    using llvm::StringSwitch;

    // Check whether this entry has an extension typically associated with
    // headers.
    if (!StringSwitch<bool>(llvm::sys::path::extension(Entry->path()))
             .Cases({".h", ".H", ".hh", ".hpp"}, true)
             .Default(false))
      continue;

    if (auto Header = getFileManager().getOptionalFileRef(Entry->path()))
      if (!getSourceManager().hasFileInfo(*Header)) {
        if (!ModMap.isHeaderInUnavailableModule(*Header)) {
          // Find the relative path that would access this header.
          SmallString<128> RelativePath;
          computeRelativePath(FileMgr, *Dir, *Header, RelativePath);
          Diag(ExpectedHeadersLoc, diag::warn_uncovered_module_header)
              << Mod.getFullModuleName() << RelativePath;
        }
      }
  }
}

/// HandleEndOfFile - This callback is invoked when the lexer hits the end of
/// the current file.  This either returns the EOF token or pops a level off
/// the include stack and keeps going.
bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
  assert(!CurTokenLexer &&
         "Ending a file when currently in a macro!");

  SourceLocation UnclosedSafeBufferOptOutLoc;

  if (IncludeMacroStack.empty() &&
      isPPInSafeBufferOptOutRegion(UnclosedSafeBufferOptOutLoc)) {
    // To warn if a "-Wunsafe-buffer-usage" opt-out region is still open by the
    // end of a file.
    Diag(UnclosedSafeBufferOptOutLoc,
         diag::err_pp_unclosed_pragma_unsafe_buffer_usage);
  }
  // If we have an unclosed module region from a pragma at the end of a
  // module, complain and close it now.
  const bool LeavingSubmodule = CurLexer && CurLexerSubmodule;
  if ((LeavingSubmodule || IncludeMacroStack.empty()) &&
      !BuildingSubmoduleStack.empty() &&
      BuildingSubmoduleStack.back().IsPragma) {
    Diag(BuildingSubmoduleStack.back().ImportLoc,
         diag::err_pp_module_begin_without_module_end);
    Module *M = LeaveSubmodule(/*ForPragma*/true);

    Result.startToken();
    const char *EndPos = getCurLexerEndPos();
    CurLexer->BufferPtr = EndPos;
    CurLexer->FormTokenWithChars(Result, EndPos, tok::annot_module_end);
    Result.setAnnotationEndLoc(Result.getLocation());
    Result.setAnnotationValue(M);
    return true;
  }

  // See if this file had a controlling macro.
  if (CurPPLexer) {  // Not ending a macro, ignore it.
    if (const IdentifierInfo *ControllingMacro =
          CurPPLexer->MIOpt.GetControllingMacroAtEndOfFile()) {
      // Okay, this has a controlling macro, remember in HeaderFileInfo.
      if (OptionalFileEntryRef FE = CurPPLexer->getFileEntry()) {
        HeaderInfo.SetFileControllingMacro(*FE, ControllingMacro);
        if (MacroInfo *MI = getMacroInfo(ControllingMacro))
          MI->setUsedForHeaderGuard(true);
        if (const IdentifierInfo *DefinedMacro =
              CurPPLexer->MIOpt.GetDefinedMacro()) {
          if (!isMacroDefined(ControllingMacro) &&
              DefinedMacro != ControllingMacro &&
              CurLexer->isFirstTimeLexingFile()) {

            // If the edit distance between the two macros is more than 50%,
            // DefinedMacro may not be header guard, or can be header guard of
            // another header file. Therefore, it maybe defining something
            // completely different. This can be observed in the wild when
            // handling feature macros or header guards in different files.

            const StringRef ControllingMacroName = ControllingMacro->getName();
            const StringRef DefinedMacroName = DefinedMacro->getName();
            const size_t MaxHalfLength = std::max(ControllingMacroName.size(),
                                                  DefinedMacroName.size()) / 2;
            const unsigned ED = ControllingMacroName.edit_distance(
                DefinedMacroName, true, MaxHalfLength);
            if (ED <= MaxHalfLength) {
              // Emit a warning for a bad header guard.
              Diag(CurPPLexer->MIOpt.GetMacroLocation(),
                   diag::warn_header_guard)
                  << CurPPLexer->MIOpt.GetMacroLocation() << ControllingMacro;
              Diag(CurPPLexer->MIOpt.GetDefinedLocation(),
                   diag::note_header_guard)
                  << CurPPLexer->MIOpt.GetDefinedLocation() << DefinedMacro
                  << ControllingMacro
                  << FixItHint::CreateReplacement(
                         CurPPLexer->MIOpt.GetDefinedLocation(),
                         ControllingMacro->getName());
            }
          }
        }
      }
    }
  }

  // Complain about reaching a true EOF within arc_cf_code_audited.
  // We don't want to complain about reaching the end of a macro
  // instantiation or a _Pragma.
  if (PragmaARCCFCodeAuditedInfo.getLoc().isValid() && !isEndOfMacro &&
      !(CurLexer && CurLexer->Is_PragmaLexer)) {
    Diag(PragmaARCCFCodeAuditedInfo.getLoc(),
         diag::err_pp_eof_in_arc_cf_code_audited);

    // Recover by leaving immediately.
    PragmaARCCFCodeAuditedInfo = IdentifierLoc();
  }

  // Complain about reaching a true EOF within assume_nonnull.
  // We don't want to complain about reaching the end of a macro
  // instantiation or a _Pragma.
  if (PragmaAssumeNonNullLoc.isValid() &&
      !isEndOfMacro && !(CurLexer && CurLexer->Is_PragmaLexer)) {
    // If we're at the end of generating a preamble, we should record the
    // unterminated \#pragma clang assume_nonnull so we can restore it later
    // when the preamble is loaded into the main file.
    if (isRecordingPreamble() && isInPrimaryFile())
      PreambleRecordedPragmaAssumeNonNullLoc = PragmaAssumeNonNullLoc;
    else
      Diag(PragmaAssumeNonNullLoc, diag::err_pp_eof_in_assume_nonnull);
    // Recover by leaving immediately.
    PragmaAssumeNonNullLoc = SourceLocation();
  }

  bool LeavingPCHThroughHeader = false;

  // If this is a #include'd file, pop it off the include stack and continue
  // lexing the #includer file.
  if (!IncludeMacroStack.empty()) {

    // If we lexed the code-completion file, act as if we reached EOF.
    if (isCodeCompletionEnabled() && CurPPLexer &&
        SourceMgr.getLocForStartOfFile(CurPPLexer->getFileID()) ==
            CodeCompletionFileLoc) {
      assert(CurLexer && "Got EOF but no current lexer set!");
      Result.startToken();
      CurLexer->FormTokenWithChars(Result, CurLexer->BufferEnd, tok::eof);
      CurLexer.reset();

      CurPPLexer = nullptr;
      recomputeCurLexerKind();
      return true;
    }

    if (!isEndOfMacro && CurPPLexer &&
        (SourceMgr.getIncludeLoc(CurPPLexer->getFileID()).isValid() ||
         // Predefines file doesn't have a valid include location.
         (PredefinesFileID.isValid() &&
          CurPPLexer->getFileID() == PredefinesFileID))) {
      // Notify SourceManager to record the number of FileIDs that were created
      // during lexing of the #include'd file.
      unsigned NumFIDs =
          SourceMgr.local_sloc_entry_size() -
          CurPPLexer->getInitialNumSLocEntries() + 1/*#include'd file*/;
      SourceMgr.setNumCreatedFIDsForFileID(CurPPLexer->getFileID(), NumFIDs);
    }

    bool ExitedFromPredefinesFile = false;
    FileID ExitedFID;
    if (!isEndOfMacro && CurPPLexer) {
      ExitedFID = CurPPLexer->getFileID();

      assert(PredefinesFileID.isValid() &&
             "HandleEndOfFile is called before PredefinesFileId is set");
      ExitedFromPredefinesFile = (PredefinesFileID == ExitedFID);
    }

    if (LeavingSubmodule) {
      // We're done with this submodule.
      Module *M = LeaveSubmodule(/*ForPragma*/false);

      // Notify the parser that we've left the module.
      const char *EndPos = getCurLexerEndPos();
      Result.startToken();
      CurLexer->BufferPtr = EndPos;
      CurLexer->FormTokenWithChars(Result, EndPos, tok::annot_module_end);
      Result.setAnnotationEndLoc(Result.getLocation());
      Result.setAnnotationValue(M);
    }

    bool FoundPCHThroughHeader = false;
    if (CurPPLexer && creatingPCHWithThroughHeader() &&
        isPCHThroughHeader(
            SourceMgr.getFileEntryForID(CurPPLexer->getFileID())))
      FoundPCHThroughHeader = true;

    // We're done with the #included file.
    RemoveTopOfLexerStack();

    // Propagate info about start-of-line/leading white-space/etc.
    PropagateLineStartLeadingSpaceInfo(Result);

    // Notify the client, if desired, that we are in a new source file.
    if (Callbacks && !isEndOfMacro && CurPPLexer) {
      SourceLocation Loc = CurPPLexer->getSourceLocation();
      SrcMgr::CharacteristicKind FileType =
          SourceMgr.getFileCharacteristic(Loc);
      Callbacks->FileChanged(Loc, PPCallbacks::ExitFile, FileType, ExitedFID);
      Callbacks->LexedFileChanged(CurPPLexer->getFileID(),
                                  PPCallbacks::LexedFileChangeReason::ExitFile,
                                  FileType, ExitedFID, Loc);
    }

    // Restore conditional stack as well as the recorded
    // \#pragma clang assume_nonnull from the preamble right after exiting
    // from the predefines file.
    if (ExitedFromPredefinesFile) {
      replayPreambleConditionalStack();
      if (PreambleRecordedPragmaAssumeNonNullLoc.isValid())
        PragmaAssumeNonNullLoc = PreambleRecordedPragmaAssumeNonNullLoc;
    }

    if (!isEndOfMacro && CurPPLexer && FoundPCHThroughHeader &&
        (isInPrimaryFile() ||
         CurPPLexer->getFileID() == getPredefinesFileID())) {
      // Leaving the through header. Continue directly to end of main file
      // processing.
      LeavingPCHThroughHeader = true;
    } else {
      // Client should lex another token unless we generated an EOM.
      return LeavingSubmodule;
    }
  }
  // If this is the end of the main file, form an EOF token.
  assert(CurLexer && "Got EOF but no current lexer set!");
  const char *EndPos = getCurLexerEndPos();
  Result.startToken();
  CurLexer->BufferPtr = EndPos;

  if (getLangOpts().IncrementalExtensions) {
    CurLexer->FormTokenWithChars(Result, EndPos, tok::annot_repl_input_end);
    Result.setAnnotationEndLoc(Result.getLocation());
    Result.setAnnotationValue(nullptr);
  } else {
    CurLexer->FormTokenWithChars(Result, EndPos, tok::eof);
  }

  if (isCodeCompletionEnabled()) {
    // Inserting the code-completion point increases the source buffer by 1,
    // but the main FileID was created before inserting the point.
    // Compensate by reducing the EOF location by 1, otherwise the location
    // will point to the next FileID.
    // FIXME: This is hacky, the code-completion point should probably be
    // inserted before the main FileID is created.
    if (CurLexer->getFileLoc() == CodeCompletionFileLoc)
      Result.setLocation(Result.getLocation().getLocWithOffset(-1));
  }

  if (creatingPCHWithThroughHeader() && !LeavingPCHThroughHeader) {
    // Reached the end of the compilation without finding the through header.
    Diag(CurLexer->getFileLoc(), diag::err_pp_through_header_not_seen)
        << PPOpts.PCHThroughHeader << 0;
  }

  if (!isIncrementalProcessingEnabled())
    // We're done with lexing.
    CurLexer.reset();

  if (!isIncrementalProcessingEnabled())
    CurPPLexer = nullptr;

  if (TUKind == TU_Complete) {
    // This is the end of the top-level file. 'WarnUnusedMacroLocs' has
    // collected all macro locations that we need to warn because they are not
    // used.
    for (WarnUnusedMacroLocsTy::iterator
           I=WarnUnusedMacroLocs.begin(), E=WarnUnusedMacroLocs.end();
           I!=E; ++I)
      Diag(*I, diag::pp_macro_not_used);
  }

  // If we are building a module that has an umbrella header, make sure that
  // each of the headers within the directory, including all submodules, is
  // covered by the umbrella header was actually included by the umbrella
  // header.
  if (Module *Mod = getCurrentModule()) {
    llvm::SmallVector<const Module *, 4> AllMods;
    collectAllSubModulesWithUmbrellaHeader(*Mod, AllMods);
    for (auto *M : AllMods)
      diagnoseMissingHeaderInUmbrellaDir(*M);
  }

  return true;
}

/// HandleEndOfTokenLexer - This callback is invoked when the current TokenLexer
/// hits the end of its token stream.
bool Preprocessor::HandleEndOfTokenLexer(Token &Result) {
  assert(CurTokenLexer && !CurPPLexer &&
         "Ending a macro when currently in a #include file!");

  if (!MacroExpandingLexersStack.empty() &&
      MacroExpandingLexersStack.back().first == CurTokenLexer.get())
    removeCachedMacroExpandedTokensOfLastLexer();

  // Delete or cache the now-dead macro expander.
  if (NumCachedTokenLexers == TokenLexerCacheSize)
    CurTokenLexer.reset();
  else
    TokenLexerCache[NumCachedTokenLexers++] = std::move(CurTokenLexer);

  // Handle this like a #include file being popped off the stack.
  return HandleEndOfFile(Result, true);
}

/// RemoveTopOfLexerStack - Pop the current lexer/macro exp off the top of the
/// lexer stack.  This should only be used in situations where the current
/// state of the top-of-stack lexer is unknown.
void Preprocessor::RemoveTopOfLexerStack() {
  assert(!IncludeMacroStack.empty() && "Ran out of stack entries to load");

  if (CurTokenLexer) {
    // Delete or cache the now-dead macro expander.
    if (NumCachedTokenLexers == TokenLexerCacheSize)
      CurTokenLexer.reset();
    else
      TokenLexerCache[NumCachedTokenLexers++] = std::move(CurTokenLexer);
  }

  PopIncludeMacroStack();
}

/// HandleMicrosoftCommentPaste - When the macro expander pastes together a
/// comment (/##/) in microsoft mode, this method handles updating the current
/// state, returning the token on the next source line.
void Preprocessor::HandleMicrosoftCommentPaste(Token &Tok) {
  assert(CurTokenLexer && !CurPPLexer &&
         "Pasted comment can only be formed from macro");
  // We handle this by scanning for the closest real lexer, switching it to
  // raw mode and preprocessor mode.  This will cause it to return \n as an
  // explicit EOD token.
  PreprocessorLexer *FoundLexer = nullptr;
  bool LexerWasInPPMode = false;
  for (const IncludeStackInfo &ISI : llvm::reverse(IncludeMacroStack)) {
    if (ISI.ThePPLexer == nullptr) continue;  // Scan for a real lexer.

    // Once we find a real lexer, mark it as raw mode (disabling macro
    // expansions) and preprocessor mode (return EOD).  We know that the lexer
    // was *not* in raw mode before, because the macro that the comment came
    // from was expanded.  However, it could have already been in preprocessor
    // mode (#if COMMENT) in which case we have to return it to that mode and
    // return EOD.
    FoundLexer = ISI.ThePPLexer;
    FoundLexer->LexingRawMode = true;
    LexerWasInPPMode = FoundLexer->ParsingPreprocessorDirective;
    FoundLexer->ParsingPreprocessorDirective = true;
    break;
  }

  // Okay, we either found and switched over the lexer, or we didn't find a
  // lexer.  In either case, finish off the macro the comment came from, getting
  // the next token.
  if (!HandleEndOfTokenLexer(Tok)) Lex(Tok);

  // Discarding comments as long as we don't have EOF or EOD.  This 'comments
  // out' the rest of the line, including any tokens that came from other macros
  // that were active, as in:
  //  #define submacro a COMMENT b
  //    submacro c
  // which should lex to 'a' only: 'b' and 'c' should be removed.
  while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof))
    Lex(Tok);

  // If we got an eod token, then we successfully found the end of the line.
  if (Tok.is(tok::eod)) {
    assert(FoundLexer && "Can't get end of line without an active lexer");
    // Restore the lexer back to normal mode instead of raw mode.
    FoundLexer->LexingRawMode = false;

    // If the lexer was already in preprocessor mode, just return the EOD token
    // to finish the preprocessor line.
    if (LexerWasInPPMode) return;

    // Otherwise, switch out of PP mode and return the next lexed token.
    FoundLexer->ParsingPreprocessorDirective = false;
    return Lex(Tok);
  }

  // If we got an EOF token, then we reached the end of the token stream but
  // didn't find an explicit \n.  This can only happen if there was no lexer
  // active (an active lexer would return EOD at EOF if there was no \n in
  // preprocessor directive mode), so just return EOF as our token.
  assert(!FoundLexer && "Lexer should return EOD before EOF in PP mode");
}

void Preprocessor::EnterSubmodule(Module *M, SourceLocation ImportLoc,
                                  bool ForPragma) {
  if (!getLangOpts().ModulesLocalVisibility) {
    // Just track that we entered this submodule.
    BuildingSubmoduleStack.push_back(
        BuildingSubmoduleInfo(M, ImportLoc, ForPragma, CurSubmoduleState,
                              PendingModuleMacroNames.size()));
    if (Callbacks)
      Callbacks->EnteredSubmodule(M, ImportLoc, ForPragma);
    return;
  }

  // Resolve as much of the module definition as we can now, before we enter
  // one of its headers.
  // FIXME: Can we enable Complain here?
  // FIXME: Can we do this when local visibility is disabled?
  ModuleMap &ModMap = getHeaderSearchInfo().getModuleMap();
  ModMap.resolveExports(M, /*Complain=*/false);
  ModMap.resolveUses(M, /*Complain=*/false);
  ModMap.resolveConflicts(M, /*Complain=*/false);

  // If this is the first time we've entered this module, set up its state.
  auto R = Submodules.try_emplace(M);
  auto &State = R.first->second;
  bool FirstTime = R.second;
  if (FirstTime) {
    // Determine the set of starting macros for this submodule; take these
    // from the "null" module (the predefines buffer).
    //
    // FIXME: If we have local visibility but not modules enabled, the
    // NullSubmoduleState is polluted by #defines in the top-level source
    // file.
    auto &StartingMacros = NullSubmoduleState.Macros;

    // Restore to the starting state.
    // FIXME: Do this lazily, when each macro name is first referenced.
    for (auto &Macro : StartingMacros) {
      // Skip uninteresting macros.
      if (!Macro.second.getLatest() &&
          Macro.second.getOverriddenMacros().empty())
        continue;

      MacroState MS(Macro.second.getLatest());
      MS.setOverriddenMacros(*this, Macro.second.getOverriddenMacros());
      State.Macros.insert(std::make_pair(Macro.first, std::move(MS)));
    }
  }

  // Track that we entered this module.
  BuildingSubmoduleStack.push_back(
      BuildingSubmoduleInfo(M, ImportLoc, ForPragma, CurSubmoduleState,
                            PendingModuleMacroNames.size()));

  if (Callbacks)
    Callbacks->EnteredSubmodule(M, ImportLoc, ForPragma);

  // Switch to this submodule as the current submodule.
  CurSubmoduleState = &State;

  // This module is visible to itself, but exports should not be made visible
  // until they are imported.
  if (FirstTime)
    makeModuleVisible(M, ImportLoc, /*IncludeExports=*/false);
}

bool Preprocessor::needModuleMacros() const {
  // If we're not within a submodule, we never need to create ModuleMacros.
  if (BuildingSubmoduleStack.empty())
    return false;
  // If we are tracking module macro visibility even for textually-included
  // headers, we need ModuleMacros.
  if (getLangOpts().ModulesLocalVisibility)
    return true;
  // Otherwise, we only need module macros if we're actually compiling a module
  // interface.
  return getLangOpts().isCompilingModule();
}

Module *Preprocessor::LeaveSubmodule(bool ForPragma) {
  if (BuildingSubmoduleStack.empty() ||
      BuildingSubmoduleStack.back().IsPragma != ForPragma) {
    assert(ForPragma && "non-pragma module enter/leave mismatch");
    return nullptr;
  }

  auto &Info = BuildingSubmoduleStack.back();

  Module *LeavingMod = Info.M;
  SourceLocation ImportLoc = Info.ImportLoc;

  if (!needModuleMacros() ||
      (!getLangOpts().ModulesLocalVisibility &&
       LeavingMod->getTopLevelModuleName() != getLangOpts().CurrentModule)) {
    // If we don't need module macros, or this is not a module for which we
    // are tracking macro visibility, don't build any, and preserve the list
    // of pending names for the surrounding submodule.
    BuildingSubmoduleStack.pop_back();

    if (Callbacks)
      Callbacks->LeftSubmodule(LeavingMod, ImportLoc, ForPragma);

    makeModuleVisible(LeavingMod, ImportLoc);
    return LeavingMod;
  }

  // Create ModuleMacros for any macros defined in this submodule.
  llvm::SmallPtrSet<const IdentifierInfo*, 8> VisitedMacros;
  for (unsigned I = Info.OuterPendingModuleMacroNames;
       I != PendingModuleMacroNames.size(); ++I) {
    auto *II = PendingModuleMacroNames[I];
    if (!VisitedMacros.insert(II).second)
      continue;

    auto MacroIt = CurSubmoduleState->Macros.find(II);
    if (MacroIt == CurSubmoduleState->Macros.end())
      continue;
    auto &Macro = MacroIt->second;

    // Find the starting point for the MacroDirective chain in this submodule.
    MacroDirective *OldMD = nullptr;
    auto *OldState = Info.OuterSubmoduleState;
    if (getLangOpts().ModulesLocalVisibility)
      OldState = &NullSubmoduleState;
    if (OldState && OldState != CurSubmoduleState) {
      // FIXME: It'd be better to start at the state from when we most recently
      // entered this submodule, but it doesn't really matter.
      auto &OldMacros = OldState->Macros;
      auto OldMacroIt = OldMacros.find(II);
      if (OldMacroIt == OldMacros.end())
        OldMD = nullptr;
      else
        OldMD = OldMacroIt->second.getLatest();
    }

    // This module may have exported a new macro. If so, create a ModuleMacro
    // representing that fact.
    bool ExplicitlyPublic = false;
    for (auto *MD = Macro.getLatest(); MD != OldMD; MD = MD->getPrevious()) {
      assert(MD && "broken macro directive chain");

      if (auto *VisMD = dyn_cast<VisibilityMacroDirective>(MD)) {
        // The latest visibility directive for a name in a submodule affects
        // all the directives that come before it.
        if (VisMD->isPublic())
          ExplicitlyPublic = true;
        else if (!ExplicitlyPublic)
          // Private with no following public directive: not exported.
          break;
      } else {
        MacroInfo *Def = nullptr;
        if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD))
          Def = DefMD->getInfo();

        // FIXME: Issue a warning if multiple headers for the same submodule
        // define a macro, rather than silently ignoring all but the first.
        bool IsNew;
        // Don't bother creating a module macro if it would represent a #undef
        // that doesn't override anything.
        if (Def || !Macro.getOverriddenMacros().empty())
          addModuleMacro(LeavingMod, II, Def, Macro.getOverriddenMacros(),
                         IsNew);

        if (!getLangOpts().ModulesLocalVisibility) {
          // This macro is exposed to the rest of this compilation as a
          // ModuleMacro; we don't need to track its MacroDirective any more.
          Macro.setLatest(nullptr);
          Macro.setOverriddenMacros(*this, {});
        }
        break;
      }
    }
  }
  PendingModuleMacroNames.resize(Info.OuterPendingModuleMacroNames);

  // FIXME: Before we leave this submodule, we should parse all the other
  // headers within it. Otherwise, we're left with an inconsistent state
  // where we've made the module visible but don't yet have its complete
  // contents.

  // Put back the outer module's state, if we're tracking it.
  if (getLangOpts().ModulesLocalVisibility)
    CurSubmoduleState = Info.OuterSubmoduleState;

  BuildingSubmoduleStack.pop_back();

  if (Callbacks)
    Callbacks->LeftSubmodule(LeavingMod, ImportLoc, ForPragma);

  // A nested #include makes the included submodule visible.
  makeModuleVisible(LeavingMod, ImportLoc);
  return LeavingMod;
}
