Skip to content

Commit 110d422

Browse files
authored
Merge pull request #5085 from akyrtzi/pr/stable-picks-lex-pp
[Lex & PP] Cherry-picks from upstream llvm.org, related to lexer and preprocessor
2 parents f59b1b5 + 4043331 commit 110d422

File tree

10 files changed

+232
-31
lines changed

10 files changed

+232
-31
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/include/clang/Lex/Preprocessor.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,18 @@ class Preprocessor {
946946
/// of that list.
947947
MacroInfoChain *MIChainHead = nullptr;
948948

949+
/// True if \p Preprocessor::SkipExcludedConditionalBlock() is running.
950+
/// This is used to guard against calling this function recursively.
951+
///
952+
/// See comments at the use-site for more context about why it is needed.
953+
bool SkippingExcludedConditionalBlock = false;
954+
955+
/// Keeps track of skipped range mappings that were recorded while skipping
956+
/// excluded conditional directives. It maps the source buffer pointer at
957+
/// the beginning of a skipped block, to the number of bytes that should be
958+
/// skipped.
959+
llvm::DenseMap<const char *, unsigned> RecordedSkippedRanges;
960+
949961
void updateOutOfDateIdentifier(IdentifierInfo &II) const;
950962

951963
public:

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/Lexer.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4165,6 +4165,10 @@ bool Lexer::LexDependencyDirectiveToken(Token &Result) {
41654165

41664166
const dependency_directives_scan::Token &DDTok =
41674167
DepDirectives.front().Tokens[NextDepDirectiveTokenIndex++];
4168+
if (NextDepDirectiveTokenIndex > 1 || DDTok.Kind != tok::hash) {
4169+
// Read something other than a preprocessor directive hash.
4170+
MIOpt.ReadToken();
4171+
}
41684172

41694173
const char *TokPtr = convertDependencyDirectiveToken(DDTok, Result);
41704174

@@ -4252,6 +4256,7 @@ bool Lexer::LexDependencyDirectiveTokenWhileSkipping(Token &Result) {
42524256
}
42534257
break;
42544258
case pp_eof:
4259+
NextDepDirectiveTokenIndex = 0;
42554260
return LexEndOfFile(Result, BufferEnd);
42564261
}
42574262
} while (!Stop);

clang/lib/Lex/PPDirectives.cpp

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,16 @@
3333
#include "clang/Lex/Token.h"
3434
#include "clang/Lex/VariadicMacroSupport.h"
3535
#include "llvm/ADT/ArrayRef.h"
36+
#include "llvm/ADT/STLExtras.h"
3637
#include "llvm/ADT/ScopeExit.h"
3738
#include "llvm/ADT/SmallString.h"
3839
#include "llvm/ADT/SmallVector.h"
39-
#include "llvm/ADT/STLExtras.h"
40-
#include "llvm/ADT/StringSwitch.h"
4140
#include "llvm/ADT/StringRef.h"
41+
#include "llvm/ADT/StringSwitch.h"
4242
#include "llvm/Support/AlignOf.h"
4343
#include "llvm/Support/ErrorHandling.h"
4444
#include "llvm/Support/Path.h"
45+
#include "llvm/Support/SaveAndRestore.h"
4546
#include <algorithm>
4647
#include <cassert>
4748
#include <cstring>
@@ -411,6 +412,19 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
411412
bool FoundNonSkipPortion,
412413
bool FoundElse,
413414
SourceLocation ElseLoc) {
415+
// In SkippingRangeStateTy we are depending on SkipExcludedConditionalBlock()
416+
// not getting called recursively by storing the RecordedSkippedRanges
417+
// DenseMap lookup pointer (field SkipRangePtr). SkippingRangeStateTy expects
418+
// that RecordedSkippedRanges won't get modified and SkipRangePtr won't be
419+
// invalidated. If this changes and there is a need to call
420+
// SkipExcludedConditionalBlock() recursively, SkippingRangeStateTy should
421+
// change to do a second lookup in endLexPass function instead of reusing the
422+
// lookup pointer.
423+
assert(!SkippingExcludedConditionalBlock &&
424+
"calling SkipExcludedConditionalBlock recursively");
425+
llvm::SaveAndRestore<bool> SARSkipping(SkippingExcludedConditionalBlock,
426+
true);
427+
414428
++NumSkipped;
415429
assert(!CurTokenLexer && CurPPLexer && "Lexing a macro, not a file?");
416430

@@ -425,10 +439,53 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
425439
CurPPLexer->LexingRawMode = true;
426440
Token Tok;
427441
SourceLocation endLoc;
442+
443+
/// Keeps track and caches skipped ranges and also retrieves a prior skipped
444+
/// range if the same block is re-visited.
445+
struct SkippingRangeStateTy {
446+
Preprocessor &PP;
447+
448+
const char *BeginPtr = nullptr;
449+
unsigned *SkipRangePtr = nullptr;
450+
451+
SkippingRangeStateTy(Preprocessor &PP) : PP(PP) {}
452+
453+
void beginLexPass() {
454+
if (BeginPtr)
455+
return; // continue skipping a block.
456+
457+
// Initiate a skipping block and adjust the lexer if we already skipped it
458+
// before.
459+
BeginPtr = PP.CurLexer->getBufferLocation();
460+
SkipRangePtr = &PP.RecordedSkippedRanges[BeginPtr];
461+
if (*SkipRangePtr) {
462+
PP.CurLexer->seek(PP.CurLexer->getCurrentBufferOffset() + *SkipRangePtr,
463+
/*IsAtStartOfLine*/ true);
464+
}
465+
}
466+
467+
void endLexPass(const char *Hashptr) {
468+
if (!BeginPtr) {
469+
// Not doing normal lexing.
470+
assert(PP.CurLexer->isDependencyDirectivesLexer());
471+
return;
472+
}
473+
474+
// Finished skipping a block, record the range if it's first time visited.
475+
if (!*SkipRangePtr) {
476+
*SkipRangePtr = Hashptr - BeginPtr;
477+
}
478+
assert(*SkipRangePtr == Hashptr - BeginPtr);
479+
BeginPtr = nullptr;
480+
SkipRangePtr = nullptr;
481+
}
482+
} SkippingRangeState(*this);
483+
428484
while (true) {
429485
if (CurLexer->isDependencyDirectivesLexer()) {
430486
CurLexer->LexDependencyDirectiveTokenWhileSkipping(Tok);
431487
} else {
488+
SkippingRangeState.beginLexPass();
432489
while (true) {
433490
CurLexer->Lex(Tok);
434491

@@ -467,6 +524,9 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
467524
CurPPLexer->ParsingPreprocessorDirective = true;
468525
if (CurLexer) CurLexer->SetKeepWhitespaceMode(false);
469526

527+
assert(Tok.is(tok::hash));
528+
const char *Hashptr = CurLexer->getBufferLocation() - Tok.getLength();
529+
assert(CurLexer->getSourceLocation(Hashptr) == Tok.getLocation());
470530

471531
// Read the next token, the directive flavor.
472532
LexUnexpandedToken(Tok);
@@ -539,6 +599,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
539599

540600
// If we popped the outermost skipping block, we're done skipping!
541601
if (!CondInfo.WasSkipping) {
602+
SkippingRangeState.endLexPass(Hashptr);
542603
// Restore the value of LexingRawMode so that trailing comments
543604
// are handled correctly, if we've reached the outermost block.
544605
CurPPLexer->LexingRawMode = false;
@@ -556,6 +617,9 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
556617
// as a non-skipping conditional.
557618
PPConditionalInfo &CondInfo = CurPPLexer->peekConditionalLevel();
558619

620+
if (!CondInfo.WasSkipping)
621+
SkippingRangeState.endLexPass(Hashptr);
622+
559623
// If this is a #else with a #else before it, report the error.
560624
if (CondInfo.FoundElse)
561625
Diag(Tok, diag::pp_err_else_after_else);
@@ -581,6 +645,9 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
581645
} else if (Sub == "lif") { // "elif".
582646
PPConditionalInfo &CondInfo = CurPPLexer->peekConditionalLevel();
583647

648+
if (!CondInfo.WasSkipping)
649+
SkippingRangeState.endLexPass(Hashptr);
650+
584651
// If this is a #elif with a #else before it, report the error.
585652
if (CondInfo.FoundElse)
586653
Diag(Tok, diag::pp_err_elif_after_else) << PED_Elif;
@@ -623,6 +690,9 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
623690
PPConditionalInfo &CondInfo = CurPPLexer->peekConditionalLevel();
624691
Token DirectiveToken = Tok;
625692

693+
if (!CondInfo.WasSkipping)
694+
SkippingRangeState.endLexPass(Hashptr);
695+
626696
// If this is a #elif with a #else before it, report the error.
627697
if (CondInfo.FoundElse)
628698
Diag(Tok, diag::pp_err_elif_after_else)

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

clang/test/ClangScanDeps/macro-expansions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
//--- cdb.json.template
1616
[{
1717
"directory" : "DIR",
18-
"command" : "clang -c DIR/test.cpp -o DIR/test.o",
18+
"command" : "clang -target x86_64-apple-macosx10.7 -c DIR/test.cpp -o DIR/test.o",
1919
"file" : "DIR/test.o"
2020
}]
2121

0 commit comments

Comments
 (0)