Skip to content

Commit 5f5d080

Browse files
committed
[𝘀𝗽𝗿] landed version
Created using spr 1.3.6-beta.1
2 parents d588ccd + 0428252 commit 5f5d080

File tree

10 files changed

+709
-116
lines changed

10 files changed

+709
-116
lines changed

clang/include/clang/Serialization/ASTReader.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,18 @@ class ASTReaderListener {
237237
return true;
238238
}
239239

240+
/// Overloaded member function of \c visitInputFile that should
241+
/// be defined when there is a distinction between
242+
/// the file name and name-as-requested. For example, when deserializing input
243+
/// files from precompiled AST files.
244+
///
245+
/// \returns true to continue receiving the next input file, false to stop.
246+
virtual bool visitInputFile(StringRef FilenameAsRequested, StringRef Filename,
247+
bool isSystem, bool isOverridden,
248+
bool isExplicitModule) {
249+
return true;
250+
}
251+
240252
/// Returns true if this \c ASTReaderListener wants to receive the
241253
/// imports of the AST file via \c visitImport, false otherwise.
242254
virtual bool needsImportVisitation() const { return false; }

clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ namespace dependencies {
3333

3434
class DependencyActionController;
3535
class DependencyConsumer;
36+
class PrebuiltModuleASTAttrs;
3637

3738
/// Modular dependency that has already been built prior to the dependency scan.
3839
struct PrebuiltModuleDep {
@@ -46,6 +47,47 @@ struct PrebuiltModuleDep {
4647
ModuleMapFile(M->PresumedModuleMapFile) {}
4748
};
4849

50+
/// Attributes loaded from AST files of prebuilt modules collected prior to
51+
/// ModuleDepCollector creation.
52+
using PrebuiltModulesAttrsMap = llvm::StringMap<PrebuiltModuleASTAttrs>;
53+
class PrebuiltModuleASTAttrs {
54+
public:
55+
/// When a module is discovered to not be in stable directories, traverse &
56+
/// update all modules that depend on it.
57+
void
58+
updateDependentsNotInStableDirs(PrebuiltModulesAttrsMap &PrebuiltModulesMap);
59+
60+
/// Read-only access to whether the module is made up of dependencies in
61+
/// stable directories.
62+
bool isInStableDir() const { return IsInStableDirs; }
63+
64+
/// Read-only access to vfs map files.
65+
const llvm::StringSet<> &getVFS() const { return VFSMap; }
66+
67+
/// Update the VFSMap to the one discovered from serializing the AST file.
68+
void setVFS(llvm::StringSet<> &&VFS) { VFSMap = std::move(VFS); }
69+
70+
/// Add a direct dependent module file, so it can be updated if the current
71+
/// module is from stable directores.
72+
void addDependent(StringRef ModuleFile) {
73+
ModuleFileDependents.insert(ModuleFile);
74+
}
75+
76+
/// Update whether the prebuilt module resolves entirely in a stable
77+
/// directories.
78+
void setInStableDir(bool V = false) {
79+
// Cannot reset attribute once it's false.
80+
if (!IsInStableDirs)
81+
return;
82+
IsInStableDirs = V;
83+
}
84+
85+
private:
86+
llvm::StringSet<> VFSMap;
87+
bool IsInStableDirs = true;
88+
std::set<StringRef> ModuleFileDependents;
89+
};
90+
4991
/// This is used to identify a specific module.
5092
struct ModuleID {
5193
/// The name of the module. This may include `:` for C++20 module partitions,
@@ -171,8 +213,6 @@ struct ModuleDeps {
171213
BuildInfo;
172214
};
173215

174-
using PrebuiltModuleVFSMapT = llvm::StringMap<llvm::StringSet<>>;
175-
176216
class ModuleDepCollector;
177217

178218
/// Callback that records textual includes and direct modular includes/imports
@@ -242,7 +282,7 @@ class ModuleDepCollector final : public DependencyCollector {
242282
CompilerInstance &ScanInstance, DependencyConsumer &C,
243283
DependencyActionController &Controller,
244284
CompilerInvocation OriginalCI,
245-
PrebuiltModuleVFSMapT PrebuiltModuleVFSMap);
285+
const PrebuiltModulesAttrsMap PrebuiltModulesASTMap);
246286

247287
void attachToPreprocessor(Preprocessor &PP) override;
248288
void attachToASTReader(ASTReader &R) override;
@@ -262,8 +302,9 @@ class ModuleDepCollector final : public DependencyCollector {
262302
DependencyConsumer &Consumer;
263303
/// Callbacks for computing dependency information.
264304
DependencyActionController &Controller;
265-
/// Mapping from prebuilt AST files to their sorted list of VFS overlay files.
266-
PrebuiltModuleVFSMapT PrebuiltModuleVFSMap;
305+
/// Mapping from prebuilt AST filepaths to their attributes referenced during
306+
/// dependency collecting.
307+
const PrebuiltModulesAttrsMap PrebuiltModulesASTMap;
267308
/// Path to the main source file.
268309
std::string MainFile;
269310
/// Hash identifying the compilation conditions of the current TU.
@@ -339,6 +380,14 @@ void resetBenignCodeGenOptions(frontend::ActionKind ProgramAction,
339380
bool isPathInStableDir(const ArrayRef<StringRef> Directories,
340381
const StringRef Input);
341382

383+
/// Determine if options collected from a module's
384+
/// compilation can safely be considered as stable.
385+
///
386+
/// \param Directories Paths known to be in a stable location. e.g. Sysroot.
387+
/// \param HSOpts Header search options derived from the compiler invocation.
388+
bool areOptionsInStableDir(const ArrayRef<StringRef> Directories,
389+
const HeaderSearchOptions &HSOpts);
390+
342391
} // end namespace dependencies
343392
} // end namespace tooling
344393
} // end namespace clang

clang/lib/Frontend/FrontendActions.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -777,10 +777,11 @@ namespace {
777777
/// Indicates that the AST file contains particular input file.
778778
///
779779
/// \returns true to continue receiving the next input file, false to stop.
780-
bool visitInputFile(StringRef Filename, bool isSystem,
781-
bool isOverridden, bool isExplicitModule) override {
780+
bool visitInputFile(StringRef FilenameAsRequested, StringRef Filename,
781+
bool isSystem, bool isOverridden,
782+
bool isExplicitModule) override {
782783

783-
Out.indent(2) << "Input file: " << Filename;
784+
Out.indent(2) << "Input file: " << FilenameAsRequested;
784785

785786
if (isSystem || isOverridden || isExplicitModule) {
786787
Out << " [";

clang/lib/Serialization/ASTReader.cpp

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2616,6 +2616,14 @@ bool ASTReader::shouldDisableValidationForFile(
26162616
return false;
26172617
}
26182618

2619+
static std::pair<StringRef, StringRef>
2620+
getUnresolvedInputFilenames(const ASTReader::RecordData &Record,
2621+
const StringRef InputBlob) {
2622+
uint16_t AsRequestedLength = Record[7];
2623+
return {InputBlob.substr(0, AsRequestedLength),
2624+
InputBlob.substr(AsRequestedLength)};
2625+
}
2626+
26192627
InputFileInfo ASTReader::getInputFileInfo(ModuleFile &F, unsigned ID) {
26202628
// If this ID is bogus, just return an empty input file.
26212629
if (ID == 0 || ID > F.InputFileInfosLoaded.size())
@@ -2659,11 +2667,12 @@ InputFileInfo ASTReader::getInputFileInfo(ModuleFile &F, unsigned ID) {
26592667
R.Transient = static_cast<bool>(Record[4]);
26602668
R.TopLevel = static_cast<bool>(Record[5]);
26612669
R.ModuleMap = static_cast<bool>(Record[6]);
2662-
uint16_t AsRequestedLength = Record[7];
2663-
R.UnresolvedImportedFilenameAsRequested = Blob.substr(0, AsRequestedLength);
2664-
R.UnresolvedImportedFilename = Blob.substr(AsRequestedLength);
2665-
if (R.UnresolvedImportedFilename.empty())
2666-
R.UnresolvedImportedFilename = R.UnresolvedImportedFilenameAsRequested;
2670+
auto [UnresolvedFilenameAsRequested, UnresolvedFilename] =
2671+
getUnresolvedInputFilenames(Record, Blob);
2672+
R.UnresolvedImportedFilenameAsRequested = UnresolvedFilenameAsRequested;
2673+
R.UnresolvedImportedFilename = UnresolvedFilename.empty()
2674+
? UnresolvedFilenameAsRequested
2675+
: UnresolvedFilename;
26672676

26682677
Expected<llvm::BitstreamEntry> MaybeEntry = Cursor.advance();
26692678
if (!MaybeEntry) // FIXME this drops errors on the floor.
@@ -5716,6 +5725,11 @@ bool ASTReader::readASTFileControlBlock(
57165725
bool DoneWithControlBlock = false;
57175726
SmallString<0> PathBuf;
57185727
PathBuf.reserve(256);
5728+
// Additional path buffer to use when multiple paths need to be resolved.
5729+
// For example, when deserializing input files that contains a path that was
5730+
// resolved from a vfs overlay and an external location.
5731+
SmallString<0> AdditionalPathBuf;
5732+
AdditionalPathBuf.reserve(256);
57195733
while (!DoneWithControlBlock) {
57205734
Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
57215735
if (!MaybeEntry) {
@@ -5847,9 +5861,21 @@ bool ASTReader::readASTFileControlBlock(
58475861
break;
58485862
case INPUT_FILE:
58495863
bool Overridden = static_cast<bool>(Record[3]);
5850-
auto Filename = ResolveImportedPath(PathBuf, Blob, ModuleDir);
5864+
auto [UnresolvedFilenameAsRequested, UnresolvedFilename] =
5865+
getUnresolvedInputFilenames(Record, Blob);
5866+
auto FilenameAsRequestedBuf = ResolveImportedPath(
5867+
PathBuf, UnresolvedFilenameAsRequested, ModuleDir);
5868+
StringRef Filename;
5869+
if (UnresolvedFilename.empty())
5870+
Filename = *FilenameAsRequestedBuf;
5871+
else {
5872+
auto FilenameBuf = ResolveImportedPath(
5873+
AdditionalPathBuf, UnresolvedFilename, ModuleDir);
5874+
Filename = *FilenameBuf;
5875+
}
58515876
shouldContinue = Listener.visitInputFile(
5852-
*Filename, isSystemFile, Overridden, /*IsExplicitModule=*/false);
5877+
*FilenameAsRequestedBuf, Filename, isSystemFile, Overridden,
5878+
/*IsExplicitModule=*/false);
58535879
break;
58545880
}
58555881
if (!shouldContinue)

clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp

Lines changed: 98 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -90,63 +90,140 @@ static bool checkHeaderSearchPaths(const HeaderSearchOptions &HSOpts,
9090

9191
using PrebuiltModuleFilesT = decltype(HeaderSearchOptions::PrebuiltModuleFiles);
9292

93-
/// A listener that collects the imported modules and optionally the input
94-
/// files.
93+
/// A listener that collects the imported modules and the input
94+
/// files. While visiting, collect vfsoverlays and file inputs that determine
95+
/// whether prebuilt modules fully resolve in stable directories.
9596
class PrebuiltModuleListener : public ASTReaderListener {
9697
public:
9798
PrebuiltModuleListener(PrebuiltModuleFilesT &PrebuiltModuleFiles,
9899
llvm::SmallVector<std::string> &NewModuleFiles,
99-
PrebuiltModuleVFSMapT &PrebuiltModuleVFSMap,
100+
PrebuiltModulesAttrsMap &PrebuiltModulesASTMap,
100101
const HeaderSearchOptions &HSOpts,
101-
const LangOptions &LangOpts, DiagnosticsEngine &Diags)
102+
const LangOptions &LangOpts, DiagnosticsEngine &Diags,
103+
const llvm::SmallVector<StringRef> &StableDirs)
102104
: PrebuiltModuleFiles(PrebuiltModuleFiles),
103105
NewModuleFiles(NewModuleFiles),
104-
PrebuiltModuleVFSMap(PrebuiltModuleVFSMap), ExistingHSOpts(HSOpts),
105-
ExistingLangOpts(LangOpts), Diags(Diags) {}
106+
PrebuiltModulesASTMap(PrebuiltModulesASTMap), ExistingHSOpts(HSOpts),
107+
ExistingLangOpts(LangOpts), Diags(Diags), StableDirs(StableDirs) {}
106108

107109
bool needsImportVisitation() const override { return true; }
110+
bool needsInputFileVisitation() override { return true; }
111+
bool needsSystemInputFileVisitation() override { return true; }
108112

113+
/// Accumulate the modules are transitively depended on by the initial
114+
/// prebuilt module.
109115
void visitImport(StringRef ModuleName, StringRef Filename) override {
110116
if (PrebuiltModuleFiles.insert({ModuleName.str(), Filename.str()}).second)
111117
NewModuleFiles.push_back(Filename.str());
118+
119+
auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(Filename);
120+
PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second;
121+
if (PrebuiltMapEntry.second)
122+
PrebuiltModule.setInStableDir(!StableDirs.empty());
123+
124+
if (auto It = PrebuiltModulesASTMap.find(CurrentFile);
125+
It != PrebuiltModulesASTMap.end() && CurrentFile != Filename)
126+
PrebuiltModule.addDependent(It->getKey());
127+
}
128+
129+
/// For each input file discovered, check whether it's external path is in a
130+
/// stable directory. Traversal is stopped if the current module is not
131+
/// considered stable.
132+
bool visitInputFile(StringRef FilenameAsRequested, StringRef Filename,
133+
bool isSystem, bool isOverridden,
134+
bool isExplicitModule) override {
135+
if (StableDirs.empty())
136+
return false;
137+
auto PrebuiltEntryIt = PrebuiltModulesASTMap.find(CurrentFile);
138+
if ((PrebuiltEntryIt == PrebuiltModulesASTMap.end()) ||
139+
(!PrebuiltEntryIt->second.isInStableDir()))
140+
return false;
141+
142+
PrebuiltEntryIt->second.setInStableDir(
143+
isPathInStableDir(StableDirs, Filename));
144+
return PrebuiltEntryIt->second.isInStableDir();
112145
}
113146

147+
/// Update which module that is being actively traversed.
114148
void visitModuleFile(StringRef Filename,
115149
serialization::ModuleKind Kind) override {
150+
// If the CurrentFile is not
151+
// considered stable, update any of it's transitive dependents.
152+
auto PrebuiltEntryIt = PrebuiltModulesASTMap.find(CurrentFile);
153+
if ((PrebuiltEntryIt != PrebuiltModulesASTMap.end()) &&
154+
!PrebuiltEntryIt->second.isInStableDir())
155+
PrebuiltEntryIt->second.updateDependentsNotInStableDirs(
156+
PrebuiltModulesASTMap);
116157
CurrentFile = Filename;
117158
}
118159

160+
/// Check the header search options for a given module when considering
161+
/// if the module comes from stable directories.
162+
bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
163+
StringRef ModuleFilename,
164+
StringRef SpecificModuleCachePath,
165+
bool Complain) override {
166+
167+
auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(CurrentFile);
168+
PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second;
169+
if (PrebuiltMapEntry.second)
170+
PrebuiltModule.setInStableDir(!StableDirs.empty());
171+
172+
if (PrebuiltModule.isInStableDir())
173+
PrebuiltModule.setInStableDir(areOptionsInStableDir(StableDirs, HSOpts));
174+
175+
return false;
176+
}
177+
178+
/// Accumulate vfsoverlays used to build these prebuilt modules.
119179
bool ReadHeaderSearchPaths(const HeaderSearchOptions &HSOpts,
120180
bool Complain) override {
121-
std::vector<std::string> VFSOverlayFiles = HSOpts.VFSOverlayFiles;
122-
PrebuiltModuleVFSMap.try_emplace(CurrentFile, llvm::from_range,
123-
VFSOverlayFiles);
181+
182+
auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(CurrentFile);
183+
PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first->second;
184+
if (PrebuiltMapEntry.second)
185+
PrebuiltModule.setInStableDir(!StableDirs.empty());
186+
187+
PrebuiltModule.setVFS(
188+
llvm::StringSet<>(llvm::from_range, HSOpts.VFSOverlayFiles));
189+
124190
return checkHeaderSearchPaths(
125191
HSOpts, ExistingHSOpts, Complain ? &Diags : nullptr, ExistingLangOpts);
126192
}
127193

128194
private:
129195
PrebuiltModuleFilesT &PrebuiltModuleFiles;
130196
llvm::SmallVector<std::string> &NewModuleFiles;
131-
PrebuiltModuleVFSMapT &PrebuiltModuleVFSMap;
197+
PrebuiltModulesAttrsMap &PrebuiltModulesASTMap;
132198
const HeaderSearchOptions &ExistingHSOpts;
133199
const LangOptions &ExistingLangOpts;
134200
DiagnosticsEngine &Diags;
135201
std::string CurrentFile;
202+
const llvm::SmallVector<StringRef> &StableDirs;
136203
};
137204

138205
/// Visit the given prebuilt module and collect all of the modules it
139206
/// transitively imports and contributing input files.
140207
static bool visitPrebuiltModule(StringRef PrebuiltModuleFilename,
141208
CompilerInstance &CI,
142209
PrebuiltModuleFilesT &ModuleFiles,
143-
PrebuiltModuleVFSMapT &PrebuiltModuleVFSMap,
210+
PrebuiltModulesAttrsMap &PrebuiltModulesASTMap,
144211
DiagnosticsEngine &Diags) {
212+
213+
// Gather the set of stable directories to use as transitive dependencies are
214+
// discovered.
215+
llvm::SmallVector<StringRef> StableDirs;
216+
std::string SysrootToUse(CI.getHeaderSearchOpts().Sysroot);
217+
if (!SysrootToUse.empty() &&
218+
(llvm::sys::path::root_directory(SysrootToUse) != SysrootToUse))
219+
StableDirs = {SysrootToUse, CI.getHeaderSearchOpts().ResourceDir};
220+
145221
// List of module files to be processed.
146222
llvm::SmallVector<std::string> Worklist;
147-
PrebuiltModuleListener Listener(ModuleFiles, Worklist, PrebuiltModuleVFSMap,
223+
224+
PrebuiltModuleListener Listener(ModuleFiles, Worklist, PrebuiltModulesASTMap,
148225
CI.getHeaderSearchOpts(), CI.getLangOpts(),
149-
Diags);
226+
Diags, StableDirs);
150227

151228
Listener.visitModuleFile(PrebuiltModuleFilename,
152229
serialization::MK_ExplicitModule);
@@ -371,16 +448,18 @@ class DependencyScanningAction : public tooling::ToolAction {
371448
auto *FileMgr = ScanInstance.createFileManager(FS);
372449
ScanInstance.createSourceManager(*FileMgr);
373450

374-
// Store the list of prebuilt module files into header search options. This
375-
// will prevent the implicit build to create duplicate modules and will
376-
// force reuse of the existing prebuilt module files instead.
377-
PrebuiltModuleVFSMapT PrebuiltModuleVFSMap;
451+
// Store a mapping of prebuilt module files and their properties like header
452+
// search options. This will prevent the implicit build to create duplicate
453+
// modules and will force reuse of the existing prebuilt module files
454+
// instead.
455+
PrebuiltModulesAttrsMap PrebuiltModulesASTMap;
456+
378457
if (!ScanInstance.getPreprocessorOpts().ImplicitPCHInclude.empty())
379458
if (visitPrebuiltModule(
380459
ScanInstance.getPreprocessorOpts().ImplicitPCHInclude,
381460
ScanInstance,
382461
ScanInstance.getHeaderSearchOpts().PrebuiltModuleFiles,
383-
PrebuiltModuleVFSMap, ScanInstance.getDiagnostics()))
462+
PrebuiltModulesASTMap, ScanInstance.getDiagnostics()))
384463
return false;
385464

386465
// Create the dependency collector that will collect the produced
@@ -410,7 +489,7 @@ class DependencyScanningAction : public tooling::ToolAction {
410489
case ScanningOutputFormat::Full:
411490
MDC = std::make_shared<ModuleDepCollector>(
412491
Service, std::move(Opts), ScanInstance, Consumer, Controller,
413-
OriginalInvocation, std::move(PrebuiltModuleVFSMap));
492+
OriginalInvocation, std::move(PrebuiltModulesASTMap));
414493
ScanInstance.addDependencyCollector(MDC);
415494
break;
416495
}

0 commit comments

Comments
 (0)