Skip to content

Commit 062b023

Browse files
committed
[clang][cas] Factor IncludeTreeBuilder out of IncludeTreeActionConsumer
The IncludeTreeBuilder is responsible for building the include-tree for a specific TU. Factor it out of IncludeTreeActionConsumer to prepare for building modules, which require their own builder.
1 parent 0ae9977 commit 062b023

File tree

1 file changed

+132
-60
lines changed

1 file changed

+132
-60
lines changed

clang/lib/Tooling/DependencyScanning/IncludeTreeActionController.cpp

Lines changed: 132 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ using namespace dependencies;
2020
using llvm::Error;
2121

2222
namespace {
23+
class IncludeTreeBuilder;
24+
2325
class IncludeTreeActionController : public CallbackActionController {
2426
public:
2527
IncludeTreeActionController(cas::ObjectStore &DB,
@@ -47,21 +49,54 @@ class IncludeTreeActionController : public CallbackActionController {
4749
Error finalize(CompilerInstance &ScanInstance,
4850
CompilerInvocation &NewInvocation) override;
4951

50-
Expected<cas::ObjectRef> getObjectForFile(Preprocessor &PP, FileID FID);
51-
Expected<cas::ObjectRef>
52-
getObjectForFileNonCached(FileManager &FM, const SrcMgr::FileInfo &FI);
53-
Expected<cas::ObjectRef> getObjectForBuffer(const SrcMgr::FileInfo &FI);
54-
Expected<cas::ObjectRef> addToFileList(FileManager &FM, const FileEntry *FE);
52+
private:
53+
IncludeTreeBuilder &current() {
54+
assert(!BuilderStack.empty());
55+
return *BuilderStack.back();
56+
}
57+
58+
private:
59+
cas::ObjectStore &DB;
60+
CASOptions CASOpts;
61+
DepscanPrefixMapping PrefixMapping;
62+
llvm::PrefixMapper PrefixMapper;
63+
SmallVector<std::unique_ptr<IncludeTreeBuilder>> BuilderStack;
64+
std::optional<cas::IncludeTreeRoot> IncludeTreeResult;
65+
};
5566

67+
/// Callbacks for building an include-tree for a given translation unit or
68+
/// module. The \c IncludeTreeActionController is responsiblee for pushing and
69+
/// popping builders from the stack as modules are required.
70+
class IncludeTreeBuilder {
71+
public:
72+
IncludeTreeBuilder(cas::ObjectStore &DB, llvm::PrefixMapper &PrefixMapper)
73+
: DB(DB), PrefixMapper(PrefixMapper) {}
74+
75+
Expected<cas::IncludeTreeRoot>
76+
finishIncludeTree(CompilerInstance &ScanInstance,
77+
CompilerInvocation &NewInvocation);
78+
79+
void enteredInclude(Preprocessor &PP, FileID FID);
80+
81+
void exitedInclude(Preprocessor &PP, FileID IncludedBy, FileID Include,
82+
SourceLocation ExitLoc);
83+
84+
void handleHasIncludeCheck(Preprocessor &PP, bool Result);
85+
86+
private:
5687
struct FilePPState {
5788
SrcMgr::CharacteristicKind FileCharacteristic;
5889
cas::ObjectRef File;
5990
SmallVector<std::pair<cas::ObjectRef, uint32_t>, 6> Includes;
6091
llvm::SmallBitVector HasIncludeChecks;
6192
};
6293

94+
Expected<cas::ObjectRef> getObjectForFile(Preprocessor &PP, FileID FID);
95+
Expected<cas::ObjectRef>
96+
getObjectForFileNonCached(FileManager &FM, const SrcMgr::FileInfo &FI);
97+
Expected<cas::ObjectRef> getObjectForBuffer(const SrcMgr::FileInfo &FI);
98+
Expected<cas::ObjectRef> addToFileList(FileManager &FM, const FileEntry *FE);
6399
Expected<cas::IncludeTree> getCASTreeForFileIncludes(FilePPState &&PPState);
64-
65100
Expected<cas::IncludeFile> createIncludeFile(StringRef Filename,
66101
cas::ObjectRef Contents);
67102

@@ -75,10 +110,10 @@ class IncludeTreeActionController : public CallbackActionController {
75110
return *E;
76111
}
77112

113+
private:
78114
cas::ObjectStore &DB;
79-
CASOptions CASOpts;
80-
DepscanPrefixMapping PrefixMapping;
81-
llvm::PrefixMapper PrefixMapper;
115+
llvm::PrefixMapper &PrefixMapper;
116+
82117
std::optional<cas::ObjectRef> PCHRef;
83118
bool StartedEnteringIncludes = false;
84119
// When a PCH is used this lists the filenames of the included files as they
@@ -87,6 +122,10 @@ class IncludeTreeActionController : public CallbackActionController {
87122
llvm::BitVector SeenIncludeFiles;
88123
SmallVector<cas::IncludeFileList::FileEntry> IncludedFiles;
89124
std::optional<cas::ObjectRef> PredefinesBufferRef;
125+
std::optional<cas::ObjectRef> ModuleIncludesBufferRef;
126+
std::optional<cas::ObjectRef> ModuleMapFileRef;
127+
/// When the builder is created from an existing tree, the main include tree.
128+
std::optional<cas::ObjectRef> MainIncludeTreeRef;
90129
SmallVector<FilePPState> IncludeStack;
91130
llvm::DenseMap<const FileEntry *, std::optional<cas::ObjectRef>>
92131
ObjectForFile;
@@ -153,6 +192,13 @@ void dependencies::addReversePrefixMappingFileSystem(
153192
ScanInstance.getFileManager().setVirtualFileSystem(std::move(FS));
154193
}
155194

195+
Expected<cas::IncludeTreeRoot> IncludeTreeActionController::getIncludeTree() {
196+
if (IncludeTreeResult)
197+
return *IncludeTreeResult;
198+
return llvm::createStringError(llvm::inconvertibleErrorCode(),
199+
"failed to produce include-tree");
200+
}
201+
156202
Error IncludeTreeActionController::initialize(
157203
CompilerInstance &ScanInstance, CompilerInvocation &NewInvocation) {
158204
if (Error E =
@@ -185,10 +231,50 @@ Error IncludeTreeActionController::initialize(
185231

186232
CASOpts = ScanInstance.getCASOpts();
187233

234+
BuilderStack.push_back(
235+
std::make_unique<IncludeTreeBuilder>(DB, PrefixMapper));
236+
188237
return Error::success();
189238
}
190239

191240
void IncludeTreeActionController::enteredInclude(Preprocessor &PP, FileID FID) {
241+
current().enteredInclude(PP, FID);
242+
}
243+
244+
void IncludeTreeActionController::exitedInclude(Preprocessor &PP,
245+
FileID IncludedBy,
246+
FileID Include,
247+
SourceLocation ExitLoc) {
248+
current().exitedInclude(PP, IncludedBy, Include, ExitLoc);
249+
}
250+
251+
void IncludeTreeActionController::handleHasIncludeCheck(Preprocessor &PP,
252+
bool Result) {
253+
current().handleHasIncludeCheck(PP, Result);
254+
}
255+
256+
Error IncludeTreeActionController::finalize(CompilerInstance &ScanInstance,
257+
CompilerInvocation &NewInvocation) {
258+
assert(!IncludeTreeResult);
259+
assert(BuilderStack.size() == 1);
260+
auto Builder = BuilderStack.pop_back_val();
261+
Error E = Builder->finishIncludeTree(ScanInstance, NewInvocation)
262+
.moveInto(IncludeTreeResult);
263+
if (E)
264+
return E;
265+
266+
configureInvocationForCaching(NewInvocation, CASOpts,
267+
IncludeTreeResult->getID().toString(),
268+
// FIXME: working dir?
269+
/*CASFSWorkingDir=*/"",
270+
/*ProduceIncludeTree=*/true);
271+
272+
DepscanPrefixMapping::remapInvocationPaths(NewInvocation, PrefixMapper);
273+
274+
return Error::success();
275+
}
276+
277+
void IncludeTreeBuilder::enteredInclude(Preprocessor &PP, FileID FID) {
192278
if (hasErrorOccurred())
193279
return;
194280

@@ -213,10 +299,8 @@ void IncludeTreeActionController::enteredInclude(Preprocessor &PP, FileID FID) {
213299
IncludeStack.push_back({FI.getFileCharacteristic(), *FileRef, {}, {}});
214300
}
215301

216-
void IncludeTreeActionController::exitedInclude(Preprocessor &PP,
217-
FileID IncludedBy,
218-
FileID Include,
219-
SourceLocation ExitLoc) {
302+
void IncludeTreeBuilder::exitedInclude(Preprocessor &PP, FileID IncludedBy,
303+
FileID Include, SourceLocation ExitLoc) {
220304
if (hasErrorOccurred())
221305
return;
222306

@@ -232,16 +316,19 @@ void IncludeTreeActionController::exitedInclude(Preprocessor &PP,
232316
{IncludeTree->getRef(), LocInfo.second});
233317
}
234318

235-
void IncludeTreeActionController::handleHasIncludeCheck(Preprocessor &PP,
236-
bool Result) {
319+
void IncludeTreeBuilder::handleHasIncludeCheck(Preprocessor &PP, bool Result) {
237320
if (hasErrorOccurred())
238321
return;
239322

240323
IncludeStack.back().HasIncludeChecks.push_back(Result);
241324
}
242325

243-
Error IncludeTreeActionController::finalize(CompilerInstance &ScanInstance,
244-
CompilerInvocation &NewInvocation) {
326+
Expected<cas::IncludeTreeRoot>
327+
IncludeTreeBuilder::finishIncludeTree(CompilerInstance &ScanInstance,
328+
CompilerInvocation &NewInvocation) {
329+
if (ErrorToReport)
330+
return std::move(*ErrorToReport);
331+
245332
FileManager &FM = ScanInstance.getFileManager();
246333

247334
auto addFile = [&](StringRef FilePath,
@@ -258,21 +345,21 @@ Error IncludeTreeActionController::finalize(CompilerInstance &ScanInstance,
258345

259346
for (StringRef FilePath : NewInvocation.getLangOpts()->NoSanitizeFiles) {
260347
if (Error E = addFile(FilePath))
261-
return E;
348+
return std::move(E);
262349
}
263350
// Add profile files.
264351
// FIXME: Do not have the logic here to determine which path should be set
265352
// but ideally only the path needed for the compilation is set and we already
266353
// checked the file needed exists. Just try load and ignore errors.
267354
if (Error E = addFile(NewInvocation.getCodeGenOpts().ProfileInstrumentUsePath,
268355
/*IgnoreFileError=*/true))
269-
return E;
356+
return std::move(E);
270357
if (Error E = addFile(NewInvocation.getCodeGenOpts().SampleProfileFile,
271358
/*IgnoreFileError=*/true))
272-
return E;
359+
return std::move(E);
273360
if (Error E = addFile(NewInvocation.getCodeGenOpts().ProfileRemappingFile,
274361
/*IgnoreFileError=*/true))
275-
return E;
362+
return std::move(E);
276363

277364
StringRef Sysroot = NewInvocation.getHeaderSearchOpts().Sysroot;
278365
if (!Sysroot.empty()) {
@@ -281,7 +368,7 @@ Error IncludeTreeActionController::finalize(CompilerInstance &ScanInstance,
281368
llvm::SmallString<256> FilePath = Sysroot;
282369
llvm::sys::path::append(FilePath, "SDKSettings.json");
283370
if (Error E = addFile(FilePath, /*IgnoreFileError*/ true))
284-
return E;
371+
return std::move(E);
285372
}
286373

287374
auto FinishIncludeTree = [&]() -> Error {
@@ -320,24 +407,26 @@ Error IncludeTreeActionController::finalize(CompilerInstance &ScanInstance,
320407
};
321408

322409
if (Error E = FinishIncludeTree())
323-
return E;
324-
325-
auto IncludeTreeRoot = getIncludeTree();
326-
if (!IncludeTreeRoot)
327-
return IncludeTreeRoot.takeError();
410+
return std::move(E);
328411

329-
configureInvocationForCaching(NewInvocation, CASOpts,
330-
IncludeTreeRoot->getID().toString(),
331-
/*CASFSWorkingDir=*/"",
332-
/*ProduceIncludeTree=*/true);
412+
if (ErrorToReport)
413+
return std::move(*ErrorToReport);
333414

334-
DepscanPrefixMapping::remapInvocationPaths(NewInvocation, PrefixMapper);
415+
assert(IncludeStack.size() == 1);
416+
Expected<cas::IncludeTree> MainIncludeTree =
417+
getCASTreeForFileIncludes(IncludeStack.pop_back_val());
418+
if (!MainIncludeTree)
419+
return MainIncludeTree.takeError();
420+
auto FileList = cas::IncludeFileList::create(DB, IncludedFiles);
421+
if (!FileList)
422+
return FileList.takeError();
335423

336-
return Error::success();
424+
return cas::IncludeTreeRoot::create(DB, MainIncludeTree->getRef(),
425+
FileList->getRef(), PCHRef);
337426
}
338427

339-
Expected<cas::ObjectRef>
340-
IncludeTreeActionController::getObjectForFile(Preprocessor &PP, FileID FID) {
428+
Expected<cas::ObjectRef> IncludeTreeBuilder::getObjectForFile(Preprocessor &PP,
429+
FileID FID) {
341430
SourceManager &SM = PP.getSourceManager();
342431
const SrcMgr::FileInfo &FI = SM.getSLocEntry(FID).getFile();
343432
if (PP.getPredefinesFileID() == FID) {
@@ -360,8 +449,9 @@ IncludeTreeActionController::getObjectForFile(Preprocessor &PP, FileID FID) {
360449
return *FileRef;
361450
}
362451

363-
Expected<cas::ObjectRef> IncludeTreeActionController::getObjectForFileNonCached(
364-
FileManager &FM, const SrcMgr::FileInfo &FI) {
452+
Expected<cas::ObjectRef>
453+
IncludeTreeBuilder::getObjectForFileNonCached(FileManager &FM,
454+
const SrcMgr::FileInfo &FI) {
365455
const FileEntry *FE = FI.getContentCache().OrigEntry;
366456
assert(FE);
367457

@@ -374,7 +464,7 @@ Expected<cas::ObjectRef> IncludeTreeActionController::getObjectForFileNonCached(
374464
}
375465

376466
Expected<cas::ObjectRef>
377-
IncludeTreeActionController::getObjectForBuffer(const SrcMgr::FileInfo &FI) {
467+
IncludeTreeBuilder::getObjectForBuffer(const SrcMgr::FileInfo &FI) {
378468
// This is a non-file buffer, like the predefines.
379469
auto Ref = DB.storeFromString(
380470
{}, FI.getContentCache().getBufferIfLoaded()->getBuffer());
@@ -387,8 +477,7 @@ IncludeTreeActionController::getObjectForBuffer(const SrcMgr::FileInfo &FI) {
387477
}
388478

389479
Expected<cas::ObjectRef>
390-
IncludeTreeActionController::addToFileList(FileManager &FM,
391-
const FileEntry *FE) {
480+
IncludeTreeBuilder::addToFileList(FileManager &FM, const FileEntry *FE) {
392481
StringRef Filename = FE->getName();
393482
llvm::ErrorOr<std::optional<cas::ObjectRef>> CASContents =
394483
FM.getObjectRefForFileContent(Filename);
@@ -421,14 +510,14 @@ IncludeTreeActionController::addToFileList(FileManager &FM,
421510
}
422511

423512
Expected<cas::IncludeTree>
424-
IncludeTreeActionController::getCASTreeForFileIncludes(FilePPState &&PPState) {
513+
IncludeTreeBuilder::getCASTreeForFileIncludes(FilePPState &&PPState) {
425514
return cas::IncludeTree::create(DB, PPState.FileCharacteristic, PPState.File,
426515
PPState.Includes, PPState.HasIncludeChecks);
427516
}
428517

429518
Expected<cas::IncludeFile>
430-
IncludeTreeActionController::createIncludeFile(StringRef Filename,
431-
cas::ObjectRef Contents) {
519+
IncludeTreeBuilder::createIncludeFile(StringRef Filename,
520+
cas::ObjectRef Contents) {
432521
SmallString<256> MappedPath;
433522
if (!PrefixMapper.empty()) {
434523
PrefixMapper.map(Filename, MappedPath);
@@ -437,23 +526,6 @@ IncludeTreeActionController::createIncludeFile(StringRef Filename,
437526
return cas::IncludeFile::create(DB, Filename, std::move(Contents));
438527
}
439528

440-
Expected<cas::IncludeTreeRoot> IncludeTreeActionController::getIncludeTree() {
441-
if (ErrorToReport)
442-
return std::move(*ErrorToReport);
443-
444-
assert(IncludeStack.size() == 1);
445-
Expected<cas::IncludeTree> MainIncludeTree =
446-
getCASTreeForFileIncludes(IncludeStack.pop_back_val());
447-
if (!MainIncludeTree)
448-
return MainIncludeTree.takeError();
449-
auto FileList = cas::IncludeFileList::create(DB, IncludedFiles);
450-
if (!FileList)
451-
return FileList.takeError();
452-
453-
return cas::IncludeTreeRoot::create(DB, MainIncludeTree->getRef(),
454-
FileList->getRef(), PCHRef);
455-
}
456-
457529
std::unique_ptr<DependencyActionController>
458530
dependencies::createIncludeTreeActionController(
459531
cas::ObjectStore &DB, DepscanPrefixMapping PrefixMapping) {

0 commit comments

Comments
 (0)