Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions clang/include/clang/Serialization/ModuleFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,20 @@ enum ModuleKind {

/// The input file info that has been loaded from an AST file.
struct InputFileInfo {
std::string FilenameAsRequested;
std::string Filename;
StringRef UnresolvedImportedFilenameAsRequested;
StringRef UnresolvedImportedFilename;

uint64_t ContentHash;
off_t StoredSize;
time_t StoredTime;
bool Overridden;
bool Transient;
bool TopLevel;
bool ModuleMap;

bool isValid() const {
return !UnresolvedImportedFilenameAsRequested.empty();
}
};

/// The input file that has been loaded from this AST file, along with
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,6 @@ struct ModuleDeps {
/// additionally appear in \c FileDeps as a dependency.
std::string ClangModuleMapFile;

/// A collection of absolute paths to files that this module directly depends
/// on, not including transitive dependencies.
llvm::StringSet<> FileDeps;

/// A collection of absolute paths to module map files that this module needs
/// to know about. The ordering is significant.
std::vector<std::string> ModuleMapFileDeps;
Expand All @@ -143,13 +139,25 @@ struct ModuleDeps {
/// an entity from this module is used.
llvm::SmallVector<Module::LinkLibrary, 2> LinkLibraries;

/// Invokes \c Cb for all file dependencies of this module. Each provided
/// \c StringRef is only valid within the individual callback invocation.
void forEachFileDep(llvm::function_ref<void(StringRef)> Cb) const;

/// Get (or compute) the compiler invocation that can be used to build this
/// module. Does not include argv[0].
const std::vector<std::string> &getBuildArguments();

private:
friend class ModuleDepCollector;
friend class ModuleDepCollectorPP;

/// The base directory for relative paths in \c FileDeps.
std::string FileDepsBaseDir;

/// A collection of paths to files that this module directly depends on, not
/// including transitive dependencies.
std::vector<std::string> FileDeps;

std::variant<std::monostate, CowCompilerInvocation, std::vector<std::string>>
BuildInfo;
};
Expand Down
41 changes: 17 additions & 24 deletions clang/lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2473,7 +2473,7 @@ InputFileInfo ASTReader::getInputFileInfo(ModuleFile &F, unsigned ID) {
return InputFileInfo();

// If we've already loaded this input file, return it.
if (!F.InputFileInfosLoaded[ID - 1].Filename.empty())
if (F.InputFileInfosLoaded[ID - 1].isValid())
return F.InputFileInfosLoaded[ID - 1];

// Go find this input file.
Expand Down Expand Up @@ -2510,21 +2510,11 @@ InputFileInfo ASTReader::getInputFileInfo(ModuleFile &F, unsigned ID) {
R.Transient = static_cast<bool>(Record[4]);
R.TopLevel = static_cast<bool>(Record[5]);
R.ModuleMap = static_cast<bool>(Record[6]);
std::tie(R.FilenameAsRequested, R.Filename) = [&]() {
uint16_t AsRequestedLength = Record[7];

StringRef NameAsRequestedRef = Blob.substr(0, AsRequestedLength);
StringRef NameRef = Blob.substr(AsRequestedLength);

std::string NameAsRequested =
ResolveImportedPathAndAllocate(PathBuf, NameAsRequestedRef, F);
std::string Name = ResolveImportedPathAndAllocate(PathBuf, NameRef, F);

if (Name.empty())
Name = NameAsRequested;

return std::make_pair(std::move(NameAsRequested), std::move(Name));
}();
uint16_t AsRequestedLength = Record[7];
R.UnresolvedImportedFilenameAsRequested = Blob.substr(0, AsRequestedLength);
R.UnresolvedImportedFilename = Blob.substr(AsRequestedLength);
if (R.UnresolvedImportedFilename.empty())
R.UnresolvedImportedFilename = R.UnresolvedImportedFilenameAsRequested;

Expected<llvm::BitstreamEntry> MaybeEntry = Cursor.advance();
if (!MaybeEntry) // FIXME this drops errors on the floor.
Expand Down Expand Up @@ -2576,7 +2566,8 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
time_t StoredTime = FI.StoredTime;
bool Overridden = FI.Overridden;
bool Transient = FI.Transient;
StringRef Filename = FI.FilenameAsRequested;
auto Filename =
ResolveImportedPath(PathBuf, FI.UnresolvedImportedFilenameAsRequested, F);
uint64_t StoredContentHash = FI.ContentHash;

// For standard C++ modules, we don't need to check the inputs.
Expand All @@ -2592,17 +2583,17 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
Overridden = false;
}

auto File = FileMgr.getOptionalFileRef(Filename, /*OpenFile=*/false);
auto File = FileMgr.getOptionalFileRef(*Filename, /*OpenFile=*/false);

// For an overridden file, create a virtual file with the stored
// size/timestamp.
if ((Overridden || Transient || SkipChecks) && !File)
File = FileMgr.getVirtualFileRef(Filename, StoredSize, StoredTime);
File = FileMgr.getVirtualFileRef(*Filename, StoredSize, StoredTime);

if (!File) {
if (Complain) {
std::string ErrorStr = "could not find file '";
ErrorStr += Filename;
ErrorStr += *Filename;
ErrorStr += "' referenced by AST file '";
ErrorStr += F.FileName;
ErrorStr += "'";
Expand All @@ -2622,7 +2613,7 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
if ((!Overridden && !Transient) && !SkipChecks &&
SM.isFileOverridden(*File)) {
if (Complain)
Error(diag::err_fe_pch_file_overridden, Filename);
Error(diag::err_fe_pch_file_overridden, *Filename);

// After emitting the diagnostic, bypass the overriding file to recover
// (this creates a separate FileEntry).
Expand Down Expand Up @@ -2714,7 +2705,7 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
// The top-level PCH is stale.
StringRef TopLevelPCHName(ImportStack.back()->FileName);
Diag(diag::err_fe_ast_file_modified)
<< Filename << moduleKindForDiagnostic(ImportStack.back()->Kind)
<< *Filename << moduleKindForDiagnostic(ImportStack.back()->Kind)
<< TopLevelPCHName << FileChange.Kind
<< (FileChange.Old && FileChange.New)
<< llvm::itostr(FileChange.Old.value_or(0))
Expand All @@ -2723,7 +2714,7 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
// Print the import stack.
if (ImportStack.size() > 1) {
Diag(diag::note_pch_required_by)
<< Filename << ImportStack[0]->FileName;
<< *Filename << ImportStack[0]->FileName;
for (unsigned I = 1; I < ImportStack.size(); ++I)
Diag(diag::note_pch_required_by)
<< ImportStack[I-1]->FileName << ImportStack[I]->FileName;
Expand Down Expand Up @@ -2971,8 +2962,10 @@ ASTReader::ReadControlBlock(ModuleFile &F,
for (unsigned I = 0; I < N; ++I) {
bool IsSystem = I >= NumUserInputs;
InputFileInfo FI = getInputFileInfo(F, I + 1);
auto FilenameAsRequested = ResolveImportedPath(
PathBuf, FI.UnresolvedImportedFilenameAsRequested, F);
Listener->visitInputFile(
FI.FilenameAsRequested, IsSystem, FI.Overridden,
*FilenameAsRequested, IsSystem, FI.Overridden,
F.Kind == MK_ExplicitModule || F.Kind == MK_PrebuiltModule);
}
}
Expand Down
41 changes: 25 additions & 16 deletions clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ using namespace clang;
using namespace tooling;
using namespace dependencies;

void ModuleDeps::forEachFileDep(llvm::function_ref<void(StringRef)> Cb) const {
SmallString<0> PathBuf;
PathBuf.reserve(256);
for (StringRef FileDep : FileDeps) {
auto ResolvedFileDep =
ASTReader::ResolveImportedPath(PathBuf, FileDep, FileDepsBaseDir);
Cb(*ResolvedFileDep);
}
}

const std::vector<std::string> &ModuleDeps::getBuildArguments() {
assert(!std::holds_alternative<std::monostate>(BuildInfo) &&
"Using uninitialized ModuleDeps");
Expand Down Expand Up @@ -596,6 +606,7 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
serialization::ModuleFile *MF =
MDC.ScanInstance.getASTReader()->getModuleManager().lookup(
*M->getASTFile());
MD.FileDepsBaseDir = MF->BaseDirectory;
MDC.ScanInstance.getASTReader()->visitInputFileInfos(
*MF, /*IncludeSystem=*/true,
[&](const serialization::InputFileInfo &IFI, bool IsSystem) {
Expand All @@ -604,25 +615,30 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
// actual on-disk module map file that allowed inferring the module,
// which is what we need for building the module explicitly
// Let's ignore this file.
if (StringRef(IFI.Filename).ends_with("__inferred_module.map"))
if (IFI.UnresolvedImportedFilename.ends_with("__inferred_module.map"))
return;
MDC.addFileDep(MD, IFI.Filename);
MDC.addFileDep(MD, IFI.UnresolvedImportedFilename);
});

llvm::DenseSet<const Module *> SeenDeps;
addAllSubmodulePrebuiltDeps(M, MD, SeenDeps);
addAllSubmoduleDeps(M, MD, SeenDeps);
addAllAffectingClangModules(M, MD, SeenDeps);

SmallString<0> PathBuf;
PathBuf.reserve(256);
MDC.ScanInstance.getASTReader()->visitInputFileInfos(
*MF, /*IncludeSystem=*/true,
[&](const serialization::InputFileInfo &IFI, bool IsSystem) {
if (!(IFI.TopLevel && IFI.ModuleMap))
return;
if (StringRef(IFI.FilenameAsRequested)
.ends_with("__inferred_module.map"))
if (IFI.UnresolvedImportedFilenameAsRequested.ends_with(
"__inferred_module.map"))
return;
MD.ModuleMapFileDeps.emplace_back(IFI.FilenameAsRequested);
auto ResolvedFilenameAsRequested = ASTReader::ResolveImportedPath(
PathBuf, IFI.UnresolvedImportedFilenameAsRequested,
MF->BaseDirectory);
MD.ModuleMapFileDeps.emplace_back(*ResolvedFilenameAsRequested);
});

CowCompilerInvocation CI =
Expand Down Expand Up @@ -779,23 +795,16 @@ static StringRef makeAbsoluteAndPreferred(CompilerInstance &CI, StringRef Path,
void ModuleDepCollector::addFileDep(StringRef Path) {
if (IsStdModuleP1689Format) {
// Within P1689 format, we don't want all the paths to be absolute path
// since it may violate the tranditional make style dependencies info.
FileDeps.push_back(std::string(Path));
// since it may violate the traditional make style dependencies info.
FileDeps.emplace_back(Path);
return;
}

llvm::SmallString<256> Storage;
Path = makeAbsoluteAndPreferred(ScanInstance, Path, Storage);
FileDeps.push_back(std::string(Path));
FileDeps.emplace_back(Path);
}

void ModuleDepCollector::addFileDep(ModuleDeps &MD, StringRef Path) {
if (IsStdModuleP1689Format) {
MD.FileDeps.insert(Path);
return;
}

llvm::SmallString<256> Storage;
Path = makeAbsoluteAndPreferred(ScanInstance, Path, Storage);
MD.FileDeps.insert(Path);
MD.FileDeps.emplace_back(Path);
}
2 changes: 1 addition & 1 deletion clang/test/ClangScanDeps/diagnostics.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ module mod { header "mod.h" }
// CHECK: ],
// CHECK-NEXT: "context-hash": "[[HASH_MOD:.*]]",
// CHECK-NEXT: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/module.modulemap",
// CHECK-NEXT: "[[PREFIX]]/mod.h"
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "mod"
Expand Down
18 changes: 9 additions & 9 deletions clang/test/ClangScanDeps/header-search-pruning-transitive.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ module X { header "X.h" }
// CHECK: ],
// CHECK-NEXT: "context-hash": "[[HASH_X:.*]]",
// CHECK-NEXT: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/X.h",
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: "[[PREFIX]]/module.modulemap",
// CHECK-NEXT: "[[PREFIX]]/X.h"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "X"
Expand All @@ -85,11 +85,11 @@ module X { header "X.h" }
// CHECK: ],
// CHECK-NEXT: "context-hash": "[[HASH_Y_WITH_A]]",
// CHECK-NEXT: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/module.modulemap",
// CHECK-NEXT: "[[PREFIX]]/Y.h",
// CHECK-NEXT: "[[PREFIX]]/a/a.h",
// CHECK-NEXT: "[[PREFIX]]/begin/begin.h",
// CHECK-NEXT: "[[PREFIX]]/end/end.h",
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: "[[PREFIX]]/a/a.h",
// CHECK-NEXT: "[[PREFIX]]/end/end.h"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "Y"
Expand Down Expand Up @@ -128,8 +128,8 @@ module X { header "X.h" }
// also has a different context hash from the first version of module X.
// CHECK-NOT: "context-hash": "[[HASH_X]]",
// CHECK: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/X.h",
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: "[[PREFIX]]/module.modulemap",
// CHECK-NEXT: "[[PREFIX]]/X.h"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "X"
Expand All @@ -141,10 +141,10 @@ module X { header "X.h" }
// CHECK: ],
// CHECK-NEXT: "context-hash": "[[HASH_Y_WITHOUT_A]]",
// CHECK-NEXT: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/module.modulemap",
// CHECK-NEXT: "[[PREFIX]]/Y.h",
// CHECK-NEXT: "[[PREFIX]]/begin/begin.h",
// CHECK-NEXT: "[[PREFIX]]/end/end.h",
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: "[[PREFIX]]/end/end.h"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "Y"
Expand Down
12 changes: 6 additions & 6 deletions clang/test/ClangScanDeps/link-libraries.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ module transitive {
// CHECK: ],
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/Inputs/frameworks/module.modulemap",
// CHECK-NEXT: "[[PREFIX]]/Inputs/frameworks/Framework.framework/Headers/Framework.h"
// CHECK-NEXT: "[[PREFIX]]/Inputs/frameworks/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [
// CHECK-NEXT: {
Expand All @@ -67,8 +67,8 @@ module transitive {
// CHECK: ],
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/module.modulemap",
// CHECK-NEXT: "[[PREFIX]]/direct.h"
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "direct"
Expand All @@ -89,10 +89,10 @@ module transitive {
// CHECK: ],
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/module.modulemap",
// CHECK-NEXT: "[[PREFIX]]/root.h",
// CHECK-NEXT: "[[PREFIX]]/root/textual.h",
// CHECK-NEXT: "[[PREFIX]]/Inputs/frameworks/module.modulemap"
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: "[[PREFIX]]/root.h"
// CHECK-NEXT: "[[PREFIX]]/root/textual.h"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "root"
Expand All @@ -104,7 +104,7 @@ module transitive {
// CHECK: ],
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: "[[PREFIX]]/module.modulemap",
// CHECK-NEXT: "[[PREFIX]]/transitive.h"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [
Expand Down
8 changes: 4 additions & 4 deletions clang/test/ClangScanDeps/modules-context-hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@
// CHECK: ],
// CHECK-NEXT: "context-hash": "[[HASH_MOD_A:.*]]",
// CHECK-NEXT: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/a/dep.h",
// CHECK-NEXT: "[[PREFIX]]/module.modulemap",
// CHECK-NEXT: "[[PREFIX]]/mod.h",
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: "[[PREFIX]]/a/dep.h"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "mod"
Expand Down Expand Up @@ -72,9 +72,9 @@
// CHECK: ],
// CHECK-NOT: "context-hash": "[[HASH_MOD_A]]",
// CHECK: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/b/dep.h",
// CHECK-NEXT: "[[PREFIX]]/module.modulemap",
// CHECK-NEXT: "[[PREFIX]]/mod.h",
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: "[[PREFIX]]/b/dep.h"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "mod"
Expand Down
4 changes: 2 additions & 2 deletions clang/test/ClangScanDeps/modules-dep-args.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ module Direct { header "direct.h" }
// CHECK: ],
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/direct.h",
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: "[[PREFIX]]/module.modulemap",
// CHECK-NEXT: "[[PREFIX]]/direct.h"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "Direct"
Expand Down
Loading
Loading