Skip to content

Commit

Permalink
[clang] Update ModuleMap::getModuleMapFile* to use FileEntryRef
Browse files Browse the repository at this point in the history
Update SourceManager::ContentCache::OrigEntry to keep the original
FileEntryRef, and use that to enable ModuleMap::getModuleMapFile* to
return the original FileEntryRef. This change should be NFC for
most users of SourceManager::ContentCache, but it could affect behaviour
for users of getNameAsRequested such as in compileModuleImpl. I have not
found a way to detect that difference without additional functional
changes, other than incidental cases like changes from / to \ on
Windows so there is no new test.

Differential Revision: https://reviews.llvm.org/D135220
  • Loading branch information
benlangmuir committed Oct 5, 2022
1 parent 1888dc9 commit 5ea78c4
Show file tree
Hide file tree
Showing 12 changed files with 85 additions and 61 deletions.
17 changes: 17 additions & 0 deletions clang/include/clang/Basic/FileEntry.h
Expand Up @@ -341,6 +341,23 @@ static_assert(
OptionalFileEntryRefDegradesToFileEntryPtr>::value,
"OptionalFileEntryRefDegradesToFileEntryPtr should be trivially copyable");

inline bool operator==(const FileEntry *LHS,
const Optional<FileEntryRef> &RHS) {
return LHS == (RHS ? &RHS->getFileEntry() : nullptr);
}
inline bool operator==(const Optional<FileEntryRef> &LHS,
const FileEntry *RHS) {
return (LHS ? &LHS->getFileEntry() : nullptr) == RHS;
}
inline bool operator!=(const FileEntry *LHS,
const Optional<FileEntryRef> &RHS) {
return !(LHS == RHS);
}
inline bool operator!=(const Optional<FileEntryRef> &LHS,
const FileEntry *RHS) {
return !(LHS == RHS);
}

/// Cached information about one file (either on disk
/// or in the virtual file system).
///
Expand Down
22 changes: 13 additions & 9 deletions clang/include/clang/Basic/SourceManager.h
Expand Up @@ -139,8 +139,9 @@ class alignas(8) ContentCache {
/// It is possible for this to be NULL if the ContentCache encapsulates
/// an imaginary text buffer.
///
/// FIXME: Turn this into a FileEntryRef and remove Filename.
const FileEntry *OrigEntry;
/// FIXME: Make non-optional using a virtual file as needed, remove \c
/// Filename and use \c OrigEntry.getNameAsRequested() instead.
OptionalFileEntryRefDegradesToFileEntryPtr OrigEntry;

/// References the file which the contents were actually loaded from.
///
Expand Down Expand Up @@ -177,9 +178,13 @@ class alignas(8) ContentCache {

mutable unsigned IsBufferInvalid : 1;

ContentCache(const FileEntry *Ent = nullptr) : ContentCache(Ent, Ent) {}
ContentCache()
: OrigEntry(None), ContentsEntry(nullptr), BufferOverridden(false),
IsFileVolatile(false), IsTransient(false), IsBufferInvalid(false) {}

ContentCache(FileEntryRef Ent) : ContentCache(Ent, Ent) {}

ContentCache(const FileEntry *Ent, const FileEntry *contentEnt)
ContentCache(FileEntryRef Ent, const FileEntry *contentEnt)
: OrigEntry(Ent), ContentsEntry(contentEnt), BufferOverridden(false),
IsFileVolatile(false), IsTransient(false), IsBufferInvalid(false) {}

Expand Down Expand Up @@ -660,7 +665,7 @@ class SourceManager : public RefCountedBase<SourceManager> {
struct OverriddenFilesInfoTy {
/// Files that have been overridden with the contents from another
/// file.
llvm::DenseMap<const FileEntry *, const FileEntry *> OverriddenFiles;
llvm::DenseMap<const FileEntry *, FileEntryRef> OverriddenFiles;

/// Files that were overridden with a memory buffer.
llvm::DenseSet<const FileEntry *> OverriddenFilesWithBuffer;
Expand Down Expand Up @@ -978,8 +983,7 @@ class SourceManager : public RefCountedBase<SourceManager> {
///
/// \param NewFile the file whose contents will be used as the
/// data instead of the contents of the given source file.
void overrideFileContents(const FileEntry *SourceFile,
const FileEntry *NewFile);
void overrideFileContents(const FileEntry *SourceFile, FileEntryRef NewFile);

/// Returns true if the file contents have been overridden.
bool isFileOverridden(const FileEntry *File) const {
Expand Down Expand Up @@ -1044,8 +1048,8 @@ class SourceManager : public RefCountedBase<SourceManager> {

/// Returns the FileEntryRef for the provided FileID.
Optional<FileEntryRef> getFileEntryRefForID(FileID FID) const {
if (auto *Entry = getFileEntryForID(FID))
return Entry->getLastRef();
if (auto *Entry = getSLocEntryForFile(FID))
return Entry->getFile().getContentCache().OrigEntry;
return None;
}

Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Lex/ModuleMap.h
Expand Up @@ -607,7 +607,7 @@ class ModuleMap {
///
/// \returns The file entry for the module map file containing the given
/// module, or nullptr if the module definition was inferred.
const FileEntry *getContainingModuleMapFile(const Module *Module) const;
Optional<FileEntryRef> getContainingModuleMapFile(const Module *Module) const;

/// Get the module map file that (along with the module name) uniquely
/// identifies this module.
Expand All @@ -618,7 +618,7 @@ class ModuleMap {
/// of inferred modules, returns the module map that allowed the inference
/// (e.g. contained 'module *'). Otherwise, returns
/// getContainingModuleMapFile().
const FileEntry *getModuleMapFileForUniquing(const Module *M) const;
Optional<FileEntryRef> getModuleMapFileForUniquing(const Module *M) const;

void setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap);

Expand Down
13 changes: 8 additions & 5 deletions clang/lib/Basic/SourceManager.cpp
Expand Up @@ -399,8 +399,7 @@ ContentCache &SourceManager::getOrCreateContentCache(FileEntryRef FileEnt,
if (OverriddenFilesInfo) {
// If the file contents are overridden with contents from another file,
// pass that file to ContentCache.
llvm::DenseMap<const FileEntry *, const FileEntry *>::iterator
overI = OverriddenFilesInfo->OverriddenFiles.find(FileEnt);
auto overI = OverriddenFilesInfo->OverriddenFiles.find(FileEnt);
if (overI == OverriddenFilesInfo->OverriddenFiles.end())
new (Entry) ContentCache(FileEnt);
else
Expand Down Expand Up @@ -695,14 +694,18 @@ void SourceManager::overrideFileContents(
}

void SourceManager::overrideFileContents(const FileEntry *SourceFile,
const FileEntry *NewFile) {
assert(SourceFile->getSize() == NewFile->getSize() &&
FileEntryRef NewFile) {
assert(SourceFile->getSize() == NewFile.getSize() &&
"Different sizes, use the FileManager to create a virtual file with "
"the correct size");
assert(FileInfos.count(SourceFile) == 0 &&
"This function should be called at the initialization stage, before "
"any parsing occurs.");
getOverriddenFilesInfo().OverriddenFiles[SourceFile] = NewFile;
// FileEntryRef is not default-constructible.
auto Pair = getOverriddenFilesInfo().OverriddenFiles.insert(
std::make_pair(SourceFile, NewFile));
if (!Pair.second)
Pair.first->second = NewFile;
}

Optional<FileEntryRef>
Expand Down
31 changes: 13 additions & 18 deletions clang/lib/Frontend/CompilerInstance.cpp
Expand Up @@ -423,15 +423,15 @@ static void InitializeFileRemapping(DiagnosticsEngine &Diags,
// Remap files in the source manager (with other files).
for (const auto &RF : InitOpts.RemappedFiles) {
// Find the file that we're mapping to.
auto ToFile = FileMgr.getFile(RF.second);
Optional<FileEntryRef> ToFile = FileMgr.getOptionalFileRef(RF.second);
if (!ToFile) {
Diags.Report(diag::err_fe_remap_missing_to_file) << RF.first << RF.second;
continue;
}

// Create the file entry for the file that we're mapping from.
const FileEntry *FromFile =
FileMgr.getVirtualFile(RF.first, (*ToFile)->getSize(), 0);
FileMgr.getVirtualFile(RF.first, ToFile->getSize(), 0);
if (!FromFile) {
Diags.Report(diag::err_fe_remap_missing_from_file) << RF.first;
continue;
Expand Down Expand Up @@ -1278,19 +1278,17 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc,
Instance.getFrontendOpts().AllowPCMWithCompilerErrors;
}

static const FileEntry *getPublicModuleMap(const FileEntry *File,
FileManager &FileMgr) {
StringRef Filename = llvm::sys::path::filename(File->getName());
SmallString<128> PublicFilename(File->getDir()->getName());
static Optional<FileEntryRef> getPublicModuleMap(FileEntryRef File,
FileManager &FileMgr) {
StringRef Filename = llvm::sys::path::filename(File.getName());
SmallString<128> PublicFilename(File.getDir().getName());
if (Filename == "module_private.map")
llvm::sys::path::append(PublicFilename, "module.map");
else if (Filename == "module.private.modulemap")
llvm::sys::path::append(PublicFilename, "module.modulemap");
else
return nullptr;
if (auto FE = FileMgr.getFile(PublicFilename))
return *FE;
return nullptr;
return None;
return FileMgr.getOptionalFileRef(PublicFilename);
}

/// Compile a module file for the given module in a separate compiler instance,
Expand All @@ -1306,19 +1304,16 @@ static bool compileModule(CompilerInstance &ImportingInstance,
ModuleMap &ModMap
= ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap();
bool Result;
if (const FileEntry *ModuleMapFile =
if (Optional<FileEntryRef> ModuleMapFile =
ModMap.getContainingModuleMapFile(Module)) {
// Canonicalize compilation to start with the public module map. This is
// vital for submodules declarations in the private module maps to be
// correctly parsed when depending on a top level module in the public one.
if (const FileEntry *PublicMMFile = getPublicModuleMap(
ModuleMapFile, ImportingInstance.getFileManager()))
if (Optional<FileEntryRef> PublicMMFile = getPublicModuleMap(
*ModuleMapFile, ImportingInstance.getFileManager()))
ModuleMapFile = PublicMMFile;

// FIXME: Update header search to keep FileEntryRef rather than rely on
// getLastRef().
StringRef ModuleMapFilePath =
ModuleMapFile->getLastRef().getNameAsRequested();
StringRef ModuleMapFilePath = ModuleMapFile->getNameAsRequested();

// Use the module map where this module resides.
Result = compileModuleImpl(
Expand Down Expand Up @@ -1346,7 +1341,7 @@ static bool compileModule(CompilerInstance &ImportingInstance,
[&](CompilerInstance &Instance) {
std::unique_ptr<llvm::MemoryBuffer> ModuleMapBuffer =
llvm::MemoryBuffer::getMemBuffer(InferredModuleMapContent);
ModuleMapFile = Instance.getFileManager().getVirtualFile(
const FileEntry *ModuleMapFile = Instance.getFileManager().getVirtualFile(
FakeModuleMapFile, InferredModuleMapContent.size(), 0);
Instance.getSourceManager().overrideFileContents(
ModuleMapFile, std::move(ModuleMapBuffer));
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/Lex/HeaderSearch.cpp
Expand Up @@ -170,11 +170,11 @@ void HeaderSearch::getHeaderMapFileNames(
}

std::string HeaderSearch::getCachedModuleFileName(Module *Module) {
const FileEntry *ModuleMap =
Optional<FileEntryRef> ModuleMap =
getModuleMap().getModuleMapFileForUniquing(Module);
// The ModuleMap maybe a nullptr, when we load a cached C++ module without
// *.modulemap file. In this case, just return an empty string.
if (ModuleMap == nullptr)
if (!ModuleMap)
return {};
return getCachedModuleFileName(Module->Name, ModuleMap->getName());
}
Expand Down Expand Up @@ -211,7 +211,7 @@ std::string HeaderSearch::getPrebuiltModuleFileName(StringRef ModuleName,
}

std::string HeaderSearch::getPrebuiltImplicitModuleFileName(Module *Module) {
const FileEntry *ModuleMap =
Optional<FileEntryRef> ModuleMap =
getModuleMap().getModuleMapFileForUniquing(Module);
StringRef ModuleName = Module->Name;
StringRef ModuleMapPath = ModuleMap->getName();
Expand Down
24 changes: 14 additions & 10 deletions clang/lib/Lex/ModuleMap.cpp
Expand Up @@ -609,7 +609,7 @@ ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
UmbrellaModule = UmbrellaModule->Parent;

if (UmbrellaModule->InferSubmodules) {
const FileEntry *UmbrellaModuleMap =
OptionalFileEntryRefDegradesToFileEntryPtr UmbrellaModuleMap =
getModuleMapFileForUniquing(UmbrellaModule);

// Infer submodules for each of the directories we found between
Expand Down Expand Up @@ -1023,9 +1023,11 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
// If we're not allowed to infer a framework module, don't.
if (!canInfer)
return nullptr;
} else
ModuleMapFile = getModuleMapFileForUniquing(Parent);

} else {
OptionalFileEntryRefDegradesToFileEntryPtr ModuleMapRef =
getModuleMapFileForUniquing(Parent);
ModuleMapFile = ModuleMapRef;
}

// Look for an umbrella header.
SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
Expand Down Expand Up @@ -1277,19 +1279,21 @@ void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) {
Mod->Headers[Module::HK_Excluded].push_back(std::move(Header));
}

const FileEntry *
Optional<FileEntryRef>
ModuleMap::getContainingModuleMapFile(const Module *Module) const {
if (Module->DefinitionLoc.isInvalid())
return nullptr;
return None;

return SourceMgr.getFileEntryForID(
SourceMgr.getFileID(Module->DefinitionLoc));
return SourceMgr.getFileEntryRefForID(
SourceMgr.getFileID(Module->DefinitionLoc));
}

const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
Optional<FileEntryRef>
ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
if (M->IsInferred) {
assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
return InferredModuleAllowedBy.find(M)->second;
// FIXME: Update InferredModuleAllowedBy to use FileEntryRef.
return InferredModuleAllowedBy.find(M)->second->getLastRef();
}
return getContainingModuleMapFile(M);
}
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Serialization/ASTReader.cpp
Expand Up @@ -3919,7 +3919,8 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
Module *M =
PP.getHeaderSearchInfo().lookupModule(F.ModuleName, F.ImportLoc);
auto &Map = PP.getHeaderSearchInfo().getModuleMap();
const FileEntry *ModMap = M ? Map.getModuleMapFileForUniquing(M) : nullptr;
Optional<FileEntryRef> ModMap =
M ? Map.getModuleMapFileForUniquing(M) : None;
// Don't emit module relocation error if we have -fno-validate-pch
if (!bool(PP.getPreprocessorOpts().DisablePCHOrModuleValidation &
DisableValidationForModuleKind::Module) &&
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Serialization/ASTWriter.cpp
Expand Up @@ -193,13 +193,13 @@ std::set<const FileEntry *> GetAllModuleMaps(const HeaderSearch &HS,
auto *CurrentModule = ModulesToProcess.pop_back_val();
ProcessedModules.insert(CurrentModule);

auto *ModuleMapFile =
Optional<FileEntryRef> ModuleMapFile =
HS.getModuleMap().getModuleMapFileForUniquing(CurrentModule);
if (!ModuleMapFile) {
continue;
}

ModuleMaps.insert(ModuleMapFile);
ModuleMaps.insert(*ModuleMapFile);

for (auto *ImportedModule : (CurrentModule)->Imports) {
if (!ImportedModule ||
Expand Down
12 changes: 6 additions & 6 deletions clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
Expand Up @@ -227,7 +227,7 @@ void ModuleDepCollector::applyDiscoveredDependencies(CompilerInvocation &CI) {
if (llvm::any_of(CI.getFrontendOpts().Inputs, needsModules)) {
Preprocessor &PP = ScanInstance.getPreprocessor();
if (Module *CurrentModule = PP.getCurrentModuleImplementation())
if (const FileEntry *CurrentModuleMap =
if (Optional<FileEntryRef> CurrentModuleMap =
PP.getHeaderSearchInfo()
.getModuleMap()
.getModuleMapFileForUniquing(CurrentModule))
Expand Down Expand Up @@ -406,13 +406,13 @@ ModuleID ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
MD.ImplicitModulePCMPath = std::string(M->getASTFile()->getName());
MD.IsSystem = M->IsSystem;

const FileEntry *ModuleMap = MDC.ScanInstance.getPreprocessor()
.getHeaderSearchInfo()
.getModuleMap()
.getModuleMapFileForUniquing(M);
Optional<FileEntryRef> ModuleMap = MDC.ScanInstance.getPreprocessor()
.getHeaderSearchInfo()
.getModuleMap()
.getModuleMapFileForUniquing(M);

if (ModuleMap) {
StringRef Path = ModuleMap->tryGetRealPathName();
StringRef Path = ModuleMap->getFileEntry().tryGetRealPathName();
if (Path.empty())
Path = ModuleMap->getName();
MD.ClangModuleMapFile = std::string(Path);
Expand Down
6 changes: 3 additions & 3 deletions clang/test/Modules/malformed.cpp
Expand Up @@ -3,9 +3,9 @@
//
// RUN: rm -rf %t
// RUN: cd %S
// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I Inputs/malformed -DHEADER="a1.h" %s 2>&1 | FileCheck %s --check-prefix=CHECK-A
// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I Inputs/malformed -DHEADER="b1.h" %s 2>&1 | FileCheck %s --check-prefix=CHECK-B
// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I Inputs/malformed -DHEADER="c.h" malformed.cpp 2>&1 | FileCheck %s --check-prefix=CHECK-C
// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I Inputs/malformed -DHEADER="a1.h" %s 2>&1 | sed 's:\\\\\?:/:g' | FileCheck %s --check-prefix=CHECK-A
// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I Inputs/malformed -DHEADER="b1.h" %s 2>&1 | sed 's:\\\\\?:/:g' | FileCheck %s --check-prefix=CHECK-B
// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I Inputs/malformed -DHEADER="c.h" malformed.cpp 2>&1 | sed 's:\\\\\?:/:g' | FileCheck %s --check-prefix=CHECK-C

#define STR2(x) #x
#define STR(x) STR2(x)
Expand Down
4 changes: 2 additions & 2 deletions clang/tools/libclang/CIndexInclusionStack.cpp
Expand Up @@ -59,8 +59,8 @@ void getInclusions(bool IsLocal, unsigned n, CXTranslationUnit TU,

// Callback to the client.
// FIXME: We should have a function to construct CXFiles.
CB(static_cast<CXFile>(
const_cast<FileEntry *>(FI.getContentCache().OrigEntry)),
CB(static_cast<CXFile>(const_cast<FileEntry *>(
static_cast<const FileEntry *>(FI.getContentCache().OrigEntry))),
InclusionStack.data(), InclusionStack.size(), clientData);
}
}
Expand Down

0 comments on commit 5ea78c4

Please sign in to comment.