[Lex] Introduce PPCallbacks::LexedFileChanged()
preprocessor callback
This is a preprocessor callback focused on the lexed file changing, without conflating effects of line number directives and other pragmas. A client that only cares about what files the lexer processes, like dependency generation, can use this more straightforward callback instead of `PPCallbacks::FileChanged()`. Clients that want the pragma directive effects as well can keep using `FileChanged()`. A use case where `PPCallbacks::LexedFileChanged()` is particularly simpler to use than `FileChanged()` is in a situation where a client wants to keep track of lexed file changes that include changes from/to the predefines buffer, where it becomes unnecessary complicated trying to use `FileChanged()` while filtering out the pragma directives effects callbacks. Also take the opportunity to provide information about the prior `FileID` the `Lexer` moved from, even when entering a new file. Differential Revision: https://reviews.llvm.org/D128947
This commit is contained in:
parent
bcd153485e
commit
0d3a2b4c66
|
@ -13,7 +13,7 @@
|
||||||
// CHECK-NEXT: Loc: "<built-in>:1:1"
|
// CHECK-NEXT: Loc: "<built-in>:1:1"
|
||||||
// CHECK-NEXT: Reason: EnterFile
|
// CHECK-NEXT: Reason: EnterFile
|
||||||
// CHECK-NEXT: FileType: C_User
|
// CHECK-NEXT: FileType: C_User
|
||||||
// CHECK-NEXT: PrevFID: (invalid)
|
// CHECK-NEXT: PrevFID: "{{.*}}{{[/\\]}}pp-trace-include.cpp"
|
||||||
// CHECK-NEXT: - Callback: FileChanged
|
// CHECK-NEXT: - Callback: FileChanged
|
||||||
// CHECK-NEXT: Loc: "<built-in>:1:1"
|
// CHECK-NEXT: Loc: "<built-in>:1:1"
|
||||||
// CHECK-NEXT: Reason: RenameFile
|
// CHECK-NEXT: Reason: RenameFile
|
||||||
|
@ -64,7 +64,7 @@
|
||||||
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}Inputs/Level1A.h:1:1"
|
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}Inputs/Level1A.h:1:1"
|
||||||
// CHECK-NEXT: Reason: EnterFile
|
// CHECK-NEXT: Reason: EnterFile
|
||||||
// CHECK-NEXT: FileType: C_User
|
// CHECK-NEXT: FileType: C_User
|
||||||
// CHECK-NEXT: PrevFID: (invalid)
|
// CHECK-NEXT: PrevFID: "{{.*}}{{[/\\]}}pp-trace-include.cpp"
|
||||||
// CHECK-NEXT: - Callback: InclusionDirective
|
// CHECK-NEXT: - Callback: InclusionDirective
|
||||||
// CHECK-NEXT: HashLoc: "{{.*}}{{[/\\]}}Inputs/Level1A.h:1:1"
|
// CHECK-NEXT: HashLoc: "{{.*}}{{[/\\]}}Inputs/Level1A.h:1:1"
|
||||||
// CHECK-NEXT: IncludeTok: include
|
// CHECK-NEXT: IncludeTok: include
|
||||||
|
@ -79,7 +79,7 @@
|
||||||
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}Inputs/Level2A.h:1:1"
|
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}Inputs/Level2A.h:1:1"
|
||||||
// CHECK-NEXT: Reason: EnterFile
|
// CHECK-NEXT: Reason: EnterFile
|
||||||
// CHECK-NEXT: FileType: C_User
|
// CHECK-NEXT: FileType: C_User
|
||||||
// CHECK-NEXT: PrevFID: (invalid)
|
// CHECK-NEXT: PrevFID: "{{.*}}{{[/\\]}}Inputs/Level1A.h"
|
||||||
// CHECK-NEXT: - Callback: MacroDefined
|
// CHECK-NEXT: - Callback: MacroDefined
|
||||||
// CHECK-NEXT: MacroNameTok: MACRO_2A
|
// CHECK-NEXT: MacroNameTok: MACRO_2A
|
||||||
// CHECK-NEXT: MacroDirective: MD_Define
|
// CHECK-NEXT: MacroDirective: MD_Define
|
||||||
|
@ -110,7 +110,7 @@
|
||||||
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}Inputs/Level1B.h:1:1"
|
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}Inputs/Level1B.h:1:1"
|
||||||
// CHECK-NEXT: Reason: EnterFile
|
// CHECK-NEXT: Reason: EnterFile
|
||||||
// CHECK-NEXT: FileType: C_User
|
// CHECK-NEXT: FileType: C_User
|
||||||
// CHECK-NEXT: PrevFID: (invalid)
|
// CHECK-NEXT: PrevFID: "{{.*}}{{[/\\]}}pp-trace-include.cpp"
|
||||||
// CHECK-NEXT: - Callback: InclusionDirective
|
// CHECK-NEXT: - Callback: InclusionDirective
|
||||||
// CHECK-NEXT: HashLoc: "{{.*}}{{[/\\]}}Inputs/Level1B.h:1:1"
|
// CHECK-NEXT: HashLoc: "{{.*}}{{[/\\]}}Inputs/Level1B.h:1:1"
|
||||||
// CHECK-NEXT: IncludeTok: include
|
// CHECK-NEXT: IncludeTok: include
|
||||||
|
@ -125,7 +125,7 @@
|
||||||
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}Inputs/Level2B.h:1:1"
|
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}Inputs/Level2B.h:1:1"
|
||||||
// CHECK-NEXT: Reason: EnterFile
|
// CHECK-NEXT: Reason: EnterFile
|
||||||
// CHECK-NEXT: FileType: C_User
|
// CHECK-NEXT: FileType: C_User
|
||||||
// CHECK-NEXT: PrevFID: (invalid)
|
// CHECK-NEXT: PrevFID: "{{.*}}{{[/\\]}}Inputs/Level1B.h"
|
||||||
// CHECK-NEXT: - Callback: MacroDefined
|
// CHECK-NEXT: - Callback: MacroDefined
|
||||||
// CHECK-NEXT: MacroNameTok: MACRO_2B
|
// CHECK-NEXT: MacroNameTok: MACRO_2B
|
||||||
// CHECK-NEXT: MacroDirective: MD_Define
|
// CHECK-NEXT: MacroDirective: MD_Define
|
||||||
|
|
|
@ -43,12 +43,34 @@ public:
|
||||||
/// Callback invoked whenever a source file is entered or exited.
|
/// Callback invoked whenever a source file is entered or exited.
|
||||||
///
|
///
|
||||||
/// \param Loc Indicates the new location.
|
/// \param Loc Indicates the new location.
|
||||||
/// \param PrevFID the file that was exited if \p Reason is ExitFile.
|
/// \param PrevFID the file that was exited if \p Reason is ExitFile or the
|
||||||
|
/// the file before the new one entered for \p Reason EnterFile.
|
||||||
virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
|
virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
|
||||||
SrcMgr::CharacteristicKind FileType,
|
SrcMgr::CharacteristicKind FileType,
|
||||||
FileID PrevFID = FileID()) {
|
FileID PrevFID = FileID()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class LexedFileChangeReason { EnterFile, ExitFile };
|
||||||
|
|
||||||
|
/// Callback invoked whenever the \p Lexer moves to a different file for
|
||||||
|
/// lexing. Unlike \p FileChanged line number directives and other related
|
||||||
|
/// pragmas do not trigger callbacks to \p LexedFileChanged.
|
||||||
|
///
|
||||||
|
/// \param FID The \p FileID that the \p Lexer moved to.
|
||||||
|
///
|
||||||
|
/// \param Reason Whether the \p Lexer entered a new file or exited one.
|
||||||
|
///
|
||||||
|
/// \param FileType The \p CharacteristicKind of the file the \p Lexer moved
|
||||||
|
/// to.
|
||||||
|
///
|
||||||
|
/// \param PrevFID The \p FileID the \p Lexer was using before the change.
|
||||||
|
///
|
||||||
|
/// \param Loc The location where the \p Lexer entered a new file from or the
|
||||||
|
/// location that the \p Lexer moved into after exiting a file.
|
||||||
|
virtual void LexedFileChanged(FileID FID, LexedFileChangeReason Reason,
|
||||||
|
SrcMgr::CharacteristicKind FileType,
|
||||||
|
FileID PrevFID, SourceLocation Loc) {}
|
||||||
|
|
||||||
/// Callback invoked whenever a source file is skipped as the result
|
/// Callback invoked whenever a source file is skipped as the result
|
||||||
/// of header guard optimization.
|
/// of header guard optimization.
|
||||||
///
|
///
|
||||||
|
@ -420,6 +442,13 @@ public:
|
||||||
Second->FileChanged(Loc, Reason, FileType, PrevFID);
|
Second->FileChanged(Loc, Reason, FileType, PrevFID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LexedFileChanged(FileID FID, LexedFileChangeReason Reason,
|
||||||
|
SrcMgr::CharacteristicKind FileType, FileID PrevFID,
|
||||||
|
SourceLocation Loc) override {
|
||||||
|
First->LexedFileChanged(FID, Reason, FileType, PrevFID, Loc);
|
||||||
|
Second->LexedFileChanged(FID, Reason, FileType, PrevFID, Loc);
|
||||||
|
}
|
||||||
|
|
||||||
void FileSkipped(const FileEntryRef &SkippedFile, const Token &FilenameTok,
|
void FileSkipped(const FileEntryRef &SkippedFile, const Token &FilenameTok,
|
||||||
SrcMgr::CharacteristicKind FileType) override {
|
SrcMgr::CharacteristicKind FileType) override {
|
||||||
First->FileSkipped(SkippedFile, FilenameTok, FileType);
|
First->FileSkipped(SkippedFile, FilenameTok, FileType);
|
||||||
|
|
|
@ -31,23 +31,21 @@ using namespace clang;
|
||||||
namespace {
|
namespace {
|
||||||
struct DepCollectorPPCallbacks : public PPCallbacks {
|
struct DepCollectorPPCallbacks : public PPCallbacks {
|
||||||
DependencyCollector &DepCollector;
|
DependencyCollector &DepCollector;
|
||||||
SourceManager &SM;
|
Preprocessor &PP;
|
||||||
DiagnosticsEngine &Diags;
|
DepCollectorPPCallbacks(DependencyCollector &L, Preprocessor &PP)
|
||||||
DepCollectorPPCallbacks(DependencyCollector &L, SourceManager &SM,
|
: DepCollector(L), PP(PP) {}
|
||||||
DiagnosticsEngine &Diags)
|
|
||||||
: DepCollector(L), SM(SM), Diags(Diags) {}
|
|
||||||
|
|
||||||
void FileChanged(SourceLocation Loc, FileChangeReason Reason,
|
void LexedFileChanged(FileID FID, LexedFileChangeReason Reason,
|
||||||
SrcMgr::CharacteristicKind FileType,
|
SrcMgr::CharacteristicKind FileType, FileID PrevFID,
|
||||||
FileID PrevFID) override {
|
SourceLocation Loc) override {
|
||||||
if (Reason != PPCallbacks::EnterFile)
|
if (Reason != PPCallbacks::LexedFileChangeReason::EnterFile)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Dependency generation really does want to go all the way to the
|
// Dependency generation really does want to go all the way to the
|
||||||
// file entry for a source location to find out what is depended on.
|
// file entry for a source location to find out what is depended on.
|
||||||
// We do not want #line markers to affect dependency generation!
|
// We do not want #line markers to affect dependency generation!
|
||||||
if (Optional<StringRef> Filename = SM.getNonBuiltinFilenameForID(
|
if (Optional<StringRef> Filename =
|
||||||
SM.getFileID(SM.getExpansionLoc(Loc))))
|
PP.getSourceManager().getNonBuiltinFilenameForID(FID))
|
||||||
DepCollector.maybeAddDependency(
|
DepCollector.maybeAddDependency(
|
||||||
llvm::sys::path::remove_leading_dotslash(*Filename),
|
llvm::sys::path::remove_leading_dotslash(*Filename),
|
||||||
/*FromModule*/ false, isSystem(FileType), /*IsModuleFile*/ false,
|
/*FromModule*/ false, isSystem(FileType), /*IsModuleFile*/ false,
|
||||||
|
@ -90,7 +88,9 @@ struct DepCollectorPPCallbacks : public PPCallbacks {
|
||||||
/*IsMissing=*/false);
|
/*IsMissing=*/false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EndOfMainFile() override { DepCollector.finishedMainFile(Diags); }
|
void EndOfMainFile() override {
|
||||||
|
DepCollector.finishedMainFile(PP.getDiagnostics());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DepCollectorMMCallbacks : public ModuleMapCallbacks {
|
struct DepCollectorMMCallbacks : public ModuleMapCallbacks {
|
||||||
|
@ -175,8 +175,7 @@ bool DependencyCollector::sawDependency(StringRef Filename, bool FromModule,
|
||||||
|
|
||||||
DependencyCollector::~DependencyCollector() { }
|
DependencyCollector::~DependencyCollector() { }
|
||||||
void DependencyCollector::attachToPreprocessor(Preprocessor &PP) {
|
void DependencyCollector::attachToPreprocessor(Preprocessor &PP) {
|
||||||
PP.addPPCallbacks(std::make_unique<DepCollectorPPCallbacks>(
|
PP.addPPCallbacks(std::make_unique<DepCollectorPPCallbacks>(*this, PP));
|
||||||
*this, PP.getSourceManager(), PP.getDiagnostics()));
|
|
||||||
PP.getHeaderSearchInfo().getModuleMap().addModuleMapCallbacks(
|
PP.getHeaderSearchInfo().getModuleMap().addModuleMapCallbacks(
|
||||||
std::make_unique<DepCollectorMMCallbacks>(*this));
|
std::make_unique<DepCollectorMMCallbacks>(*this));
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,6 +111,7 @@ bool Preprocessor::EnterSourceFile(FileID FID, ConstSearchDirIterator CurDir,
|
||||||
/// and start lexing tokens from it instead of the current buffer.
|
/// and start lexing tokens from it instead of the current buffer.
|
||||||
void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer,
|
void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer,
|
||||||
ConstSearchDirIterator CurDir) {
|
ConstSearchDirIterator CurDir) {
|
||||||
|
PreprocessorLexer *PrevPPLexer = CurPPLexer;
|
||||||
|
|
||||||
// Add the current lexer to the include stack.
|
// Add the current lexer to the include stack.
|
||||||
if (CurPPLexer || CurTokenLexer)
|
if (CurPPLexer || CurTokenLexer)
|
||||||
|
@ -130,8 +131,17 @@ void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer,
|
||||||
SrcMgr::CharacteristicKind FileType =
|
SrcMgr::CharacteristicKind FileType =
|
||||||
SourceMgr.getFileCharacteristic(CurLexer->getFileLoc());
|
SourceMgr.getFileCharacteristic(CurLexer->getFileLoc());
|
||||||
|
|
||||||
Callbacks->FileChanged(CurLexer->getFileLoc(),
|
FileID PrevFID;
|
||||||
PPCallbacks::EnterFile, FileType);
|
SourceLocation EnterLoc;
|
||||||
|
if (PrevPPLexer) {
|
||||||
|
PrevFID = PrevPPLexer->getFileID();
|
||||||
|
EnterLoc = PrevPPLexer->getSourceLocation();
|
||||||
|
}
|
||||||
|
Callbacks->FileChanged(CurLexer->getFileLoc(), PPCallbacks::EnterFile,
|
||||||
|
FileType, PrevFID);
|
||||||
|
Callbacks->LexedFileChanged(CurLexer->getFileID(),
|
||||||
|
PPCallbacks::LexedFileChangeReason::EnterFile,
|
||||||
|
FileType, PrevFID, EnterLoc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,10 +496,13 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
|
||||||
|
|
||||||
// Notify the client, if desired, that we are in a new source file.
|
// Notify the client, if desired, that we are in a new source file.
|
||||||
if (Callbacks && !isEndOfMacro && CurPPLexer) {
|
if (Callbacks && !isEndOfMacro && CurPPLexer) {
|
||||||
|
SourceLocation Loc = CurPPLexer->getSourceLocation();
|
||||||
SrcMgr::CharacteristicKind FileType =
|
SrcMgr::CharacteristicKind FileType =
|
||||||
SourceMgr.getFileCharacteristic(CurPPLexer->getSourceLocation());
|
SourceMgr.getFileCharacteristic(Loc);
|
||||||
Callbacks->FileChanged(CurPPLexer->getSourceLocation(),
|
Callbacks->FileChanged(Loc, PPCallbacks::ExitFile, FileType, ExitedFID);
|
||||||
PPCallbacks::ExitFile, FileType, ExitedFID);
|
Callbacks->LexedFileChanged(CurPPLexer->getFileID(),
|
||||||
|
PPCallbacks::LexedFileChangeReason::ExitFile,
|
||||||
|
FileType, ExitedFID, Loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore conditional stack as well as the recorded
|
// Restore conditional stack as well as the recorded
|
||||||
|
|
Loading…
Reference in a new issue