Skip to content

Commit 4043331

Browse files
committed
[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
1 parent 0d09cdd commit 4043331

File tree

4 files changed

+68
-28
lines changed

4 files changed

+68
-28
lines changed

clang-tools-extra/test/pp-trace/pp-trace-include.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// CHECK-NEXT: Loc: "<built-in>:1:1"
1414
// CHECK-NEXT: Reason: EnterFile
1515
// CHECK-NEXT: FileType: C_User
16-
// CHECK-NEXT: PrevFID: (invalid)
16+
// CHECK-NEXT: PrevFID: "{{.*}}{{[/\\]}}pp-trace-include.cpp"
1717
// CHECK-NEXT: - Callback: FileChanged
1818
// CHECK-NEXT: Loc: "<built-in>:1:1"
1919
// CHECK-NEXT: Reason: RenameFile
@@ -63,7 +63,7 @@
6363
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}Inputs/Level1A.h:1:1"
6464
// CHECK-NEXT: Reason: EnterFile
6565
// CHECK-NEXT: FileType: C_User
66-
// CHECK-NEXT: PrevFID: (invalid)
66+
// CHECK-NEXT: PrevFID: "{{.*}}{{[/\\]}}pp-trace-include.cpp"
6767
// CHECK-NEXT: - Callback: InclusionDirective
6868
// CHECK-NEXT: IncludeTok: include
6969
// CHECK-NEXT: FileName: "Level2A.h"
@@ -77,7 +77,7 @@
7777
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}Inputs/Level2A.h:1:1"
7878
// CHECK-NEXT: Reason: EnterFile
7979
// CHECK-NEXT: FileType: C_User
80-
// CHECK-NEXT: PrevFID: (invalid)
80+
// CHECK-NEXT: PrevFID: "{{.*}}{{[/\\]}}Inputs/Level1A.h"
8181
// CHECK-NEXT: - Callback: MacroDefined
8282
// CHECK-NEXT: MacroNameTok: MACRO_2A
8383
// CHECK-NEXT: MacroDirective: MD_Define
@@ -107,7 +107,7 @@
107107
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}Inputs/Level1B.h:1:1"
108108
// CHECK-NEXT: Reason: EnterFile
109109
// CHECK-NEXT: FileType: C_User
110-
// CHECK-NEXT: PrevFID: (invalid)
110+
// CHECK-NEXT: PrevFID: "{{.*}}{{[/\\]}}pp-trace-include.cpp"
111111
// CHECK-NEXT: - Callback: InclusionDirective
112112
// CHECK-NEXT: IncludeTok: include
113113
// CHECK-NEXT: FileName: "Level2B.h"
@@ -121,7 +121,7 @@
121121
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}Inputs/Level2B.h:1:1"
122122
// CHECK-NEXT: Reason: EnterFile
123123
// CHECK-NEXT: FileType: C_User
124-
// CHECK-NEXT: PrevFID: (invalid)
124+
// CHECK-NEXT: PrevFID: "{{.*}}{{[/\\]}}Inputs/Level1B.h"
125125
// CHECK-NEXT: - Callback: MacroDefined
126126
// CHECK-NEXT: MacroNameTok: MACRO_2B
127127
// CHECK-NEXT: MacroDirective: MD_Define

clang/include/clang/Lex/PPCallbacks.h

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,34 @@ class PPCallbacks {
4343
/// Callback invoked whenever a source file is entered or exited.
4444
///
4545
/// \param Loc Indicates the new location.
46-
/// \param PrevFID the file that was exited if \p Reason is ExitFile.
46+
/// \param PrevFID the file that was exited if \p Reason is ExitFile or the
47+
/// the file before the new one entered for \p Reason EnterFile.
4748
virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
4849
SrcMgr::CharacteristicKind FileType,
4950
FileID PrevFID = FileID()) {
5051
}
5152

53+
enum class LexedFileChangeReason { EnterFile, ExitFile };
54+
55+
/// Callback invoked whenever the \p Lexer moves to a different file for
56+
/// lexing. Unlike \p FileChanged line number directives and other related
57+
/// pragmas do not trigger callbacks to \p LexedFileChanged.
58+
///
59+
/// \param FID The \p FileID that the \p Lexer moved to.
60+
///
61+
/// \param Reason Whether the \p Lexer entered a new file or exited one.
62+
///
63+
/// \param FileType The \p CharacteristicKind of the file the \p Lexer moved
64+
/// to.
65+
///
66+
/// \param PrevFID The \p FileID the \p Lexer was using before the change.
67+
///
68+
/// \param Loc The location where the \p Lexer entered a new file from or the
69+
/// location that the \p Lexer moved into after exiting a file.
70+
virtual void LexedFileChanged(FileID FID, LexedFileChangeReason Reason,
71+
SrcMgr::CharacteristicKind FileType,
72+
FileID PrevFID, SourceLocation Loc) {}
73+
5274
/// Callback invoked whenever a source file is skipped as the result
5375
/// of header guard optimization.
5476
///
@@ -420,6 +442,13 @@ class PPChainedCallbacks : public PPCallbacks {
420442
Second->FileChanged(Loc, Reason, FileType, PrevFID);
421443
}
422444

445+
void LexedFileChanged(FileID FID, LexedFileChangeReason Reason,
446+
SrcMgr::CharacteristicKind FileType, FileID PrevFID,
447+
SourceLocation Loc) override {
448+
First->LexedFileChanged(FID, Reason, FileType, PrevFID, Loc);
449+
Second->LexedFileChanged(FID, Reason, FileType, PrevFID, Loc);
450+
}
451+
423452
void FileSkipped(const FileEntryRef &SkippedFile, const Token &FilenameTok,
424453
SrcMgr::CharacteristicKind FileType) override {
425454
First->FileSkipped(SkippedFile, FilenameTok, FileType);

clang/lib/Frontend/DependencyFile.cpp

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,21 @@ using namespace clang;
3232
namespace {
3333
struct DepCollectorPPCallbacks : public PPCallbacks {
3434
DependencyCollector &DepCollector;
35-
SourceManager &SM;
36-
DiagnosticsEngine &Diags;
37-
DepCollectorPPCallbacks(DependencyCollector &L, SourceManager &SM,
38-
DiagnosticsEngine &Diags)
39-
: DepCollector(L), SM(SM), Diags(Diags) {}
40-
41-
void FileChanged(SourceLocation Loc, FileChangeReason Reason,
42-
SrcMgr::CharacteristicKind FileType,
43-
FileID PrevFID) override {
44-
if (Reason != PPCallbacks::EnterFile)
35+
Preprocessor &PP;
36+
DepCollectorPPCallbacks(DependencyCollector &L, Preprocessor &PP)
37+
: DepCollector(L), PP(PP) {}
38+
39+
void LexedFileChanged(FileID FID, LexedFileChangeReason Reason,
40+
SrcMgr::CharacteristicKind FileType, FileID PrevFID,
41+
SourceLocation Loc) override {
42+
if (Reason != PPCallbacks::LexedFileChangeReason::EnterFile)
4543
return;
4644

4745
// Dependency generation really does want to go all the way to the
4846
// file entry for a source location to find out what is depended on.
4947
// We do not want #line markers to affect dependency generation!
50-
if (Optional<StringRef> Filename = SM.getNonBuiltinFilenameForID(
51-
SM.getFileID(SM.getExpansionLoc(Loc))))
48+
if (Optional<StringRef> Filename =
49+
PP.getSourceManager().getNonBuiltinFilenameForID(FID))
5250
DepCollector.maybeAddDependency(
5351
llvm::sys::path::remove_leading_dotslash(*Filename),
5452
/*FromModule*/ false, isSystem(FileType), /*IsModuleFile*/ false,
@@ -91,7 +89,9 @@ struct DepCollectorPPCallbacks : public PPCallbacks {
9189
/*IsMissing=*/false);
9290
}
9391

94-
void EndOfMainFile() override { DepCollector.finishedMainFile(Diags); }
92+
void EndOfMainFile() override {
93+
DepCollector.finishedMainFile(PP.getDiagnostics());
94+
}
9595
};
9696

9797
struct DepCollectorMMCallbacks : public ModuleMapCallbacks {
@@ -206,8 +206,7 @@ bool DependencyCollector::sawDependency(StringRef Filename, bool FromModule,
206206

207207
DependencyCollector::~DependencyCollector() { }
208208
void DependencyCollector::attachToPreprocessor(Preprocessor &PP) {
209-
PP.addPPCallbacks(std::make_unique<DepCollectorPPCallbacks>(
210-
*this, PP.getSourceManager(), PP.getDiagnostics()));
209+
PP.addPPCallbacks(std::make_unique<DepCollectorPPCallbacks>(*this, PP));
211210
PP.getHeaderSearchInfo().getModuleMap().addModuleMapCallbacks(
212211
std::make_unique<DepCollectorMMCallbacks>(*this));
213212
}
@@ -240,8 +239,7 @@ void DependencyFileGenerator::attachToPreprocessor(Preprocessor &PP) {
240239

241240
// FIXME: Restore the call to DependencyCollector::attachToPreprocessor(PP);
242241
// once the SkipUnusedModuleMaps is upstreamed.
243-
PP.addPPCallbacks(std::make_unique<DepCollectorPPCallbacks>(
244-
*this, PP.getSourceManager(), PP.getDiagnostics()));
242+
PP.addPPCallbacks(std::make_unique<DepCollectorPPCallbacks>(*this, PP));
245243
PP.getHeaderSearchInfo().getModuleMap().addModuleMapCallbacks(
246244
std::make_unique<DFGMMCallback>(*this, SkipUnusedModuleMaps));
247245
}

clang/lib/Lex/PPLexerChange.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ bool Preprocessor::EnterSourceFile(FileID FID, ConstSearchDirIterator CurDir,
112112
/// and start lexing tokens from it instead of the current buffer.
113113
void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer,
114114
ConstSearchDirIterator CurDir) {
115+
PreprocessorLexer *PrevPPLexer = CurPPLexer;
115116

116117
// Add the current lexer to the include stack.
117118
if (CurPPLexer || CurTokenLexer)
@@ -131,8 +132,17 @@ void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer,
131132
SrcMgr::CharacteristicKind FileType =
132133
SourceMgr.getFileCharacteristic(CurLexer->getFileLoc());
133134

134-
Callbacks->FileChanged(CurLexer->getFileLoc(),
135-
PPCallbacks::EnterFile, FileType);
135+
FileID PrevFID;
136+
SourceLocation EnterLoc;
137+
if (PrevPPLexer) {
138+
PrevFID = PrevPPLexer->getFileID();
139+
EnterLoc = PrevPPLexer->getSourceLocation();
140+
}
141+
Callbacks->FileChanged(CurLexer->getFileLoc(), PPCallbacks::EnterFile,
142+
FileType, PrevFID);
143+
Callbacks->LexedFileChanged(CurLexer->getFileID(),
144+
PPCallbacks::LexedFileChangeReason::EnterFile,
145+
FileType, PrevFID, EnterLoc);
136146
}
137147
}
138148

@@ -526,10 +536,13 @@ bool Preprocessor::HandleEndOfFile(Token &Result, SourceLocation EndLoc,
526536

527537
// Notify the client, if desired, that we are in a new source file.
528538
if (Callbacks && !isEndOfMacro && CurPPLexer) {
539+
SourceLocation Loc = CurPPLexer->getSourceLocation();
529540
SrcMgr::CharacteristicKind FileType =
530-
SourceMgr.getFileCharacteristic(CurPPLexer->getSourceLocation());
531-
Callbacks->FileChanged(CurPPLexer->getSourceLocation(),
532-
PPCallbacks::ExitFile, FileType, ExitedFID);
541+
SourceMgr.getFileCharacteristic(Loc);
542+
Callbacks->FileChanged(Loc, PPCallbacks::ExitFile, FileType, ExitedFID);
543+
Callbacks->LexedFileChanged(CurPPLexer->getFileID(),
544+
PPCallbacks::LexedFileChangeReason::ExitFile,
545+
FileType, ExitedFID, Loc);
533546
}
534547

535548
// Restore conditional stack as well as the recorded

0 commit comments

Comments
 (0)