Repository: llvm/llvm-project
File: clang/lib/Serialization/ASTReader.cpp (C++)

Code before:
    }
  }
}

llvm::Error ASTReader::ReadASTBlock(ModuleFile &F,
                                    unsigned ClientLoadCapabilities) {
  BitstreamCursor &Stream = F.Stream;

  if (llvm::Error Err = Stream.EnterSubBlock(AST_BLOCK_ID))
    return Err;
  F.ASTBlockStartOffset = Stream.GetCurrentBitNo();

  // Read all of the records and blocks for the AST file.
  RecordData Record;
  while (true) {
    Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
    if (!MaybeEntry)
      return MaybeEntry.takeError();
    llvm::BitstreamEntry Entry = MaybeEntry.get();

    switch (Entry.Kind) {
    case llvm::BitstreamEntry::Error:
      return llvm::createStringError(
          std::errc::illegal_byte_sequence,
          "error at end of module block in AST file");
    case llvm::BitstreamEntry::EndBlock:
      // Outside of C++, we do not store a lookup map for the translation unit.
      // Instead, mark it as needing a lookup map to be built if this module
      // contains any declarations lexically within it (which it always does!).
      // This usually has no cost, since we very rarely need the lookup map for
      // the translation unit outside C++.
      if (ASTContext *Ctx = ContextObj) {
        DeclContext *DC = Ctx->getTranslationUnitDecl();
        if (DC->hasExternalLexicalStorage() && !Ctx->getLangOpts().CPlusPlus)
          DC->setMustBuildLookupTable();
      }

      return llvm::Error::success();
    case llvm::BitstreamEntry::SubBlock:
      switch (Entry.ID) {
      case DECLTYPES_BLOCK_ID:
        // We lazily load the decls block, but we want to set up the
        // DeclsCursor cursor to point into it.  Clone our current bitcode
        // cursor to it, enter the block and read the abbrevs in that block.
        // With the main cursor, we just skip over it.
        F.DeclsCursor = Stream;
        if (llvm::Error Err = Stream.SkipBlock())
          return Err;
        if (llvm::Error Err = ReadBlockAbbrevs(
                F.DeclsCursor, DECLTYPES_BLOCK_ID, &F.DeclsBlockStartOffset))
          return Err;

Review comment (suggestion):
I keep going back and forth on whether this should remain a remark or become an off-by-default warning that only we only attempt to emit in the `else` branch of the `if (!canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities))` below. I don't have a strong preference, so up to you.

Code after:
      F.BaseDirectory = std::string(Blob);

      auto [MaybeM, IgnoreError] =
          getModuleForRelocationChecks(F, /*DirectoryCheck=*/true);
      if (!MaybeM.has_value())
        break;

      Module *M = MaybeM.value();
      if (!M || !M->Directory)
        break;
      if (IgnoreError) {
        F.BaseDirectory = std::string(M->Directory->getName());
        break;
      }
      if ((F.Kind == MK_ExplicitModule) || (F.Kind == MK_PrebuiltModule))
        break;

      // If we're implicitly loading a module, the base directory can't
      // change between the build and use.
      auto BuildDir = PP.getFileManager().getOptionalDirectoryRef(Blob);
      if (BuildDir && (*BuildDir == M->Directory)) {
        F.BaseDirectory = std::string(M->Directory->getName());
        break;
      }
      Diag(diag::remark_module_relocated)
          << F.ModuleName << Blob << M->Directory->getName();

      if (!canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities))
        Diag(diag::err_imported_module_relocated)
            << F.ModuleName << Blob << M->Directory->getName();
      return OutOfDate;
    }

    case MODULE_MAP_FILE:
      if (ASTReadResult Result =
              ReadModuleMapFileBlock(Record, F, ImportedBy, ClientLoadCapabilities))
        return Result;
      break;

    case INPUT_FILE_OFFSETS:
      NumInputs = Record[0];
      NumUserInputs = Record[1];
      F.InputFileOffsets =
          (const llvm::support::unaligned_uint64_t *)Blob.data();
      F.InputFilesLoaded.resize(NumInputs);
      F.InputFileInfosLoaded.resize(NumInputs);
      F.NumUserInputFiles = NumUserInputs;
      break;
    }
  }
}