Skip to content

Commit 6fe2cd4

Browse files
committed
[clang][Preprocessor] Handle the first pp-token in EnterMainSourceFile
Signed-off-by: yronglin <[email protected]>
1 parent 9bdb305 commit 6fe2cd4

File tree

7 files changed

+45
-46
lines changed

7 files changed

+45
-46
lines changed

clang/include/clang/Lex/Preprocessor.h

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ class Preprocessor {
351351
bool LastTokenWasAt = false;
352352

353353
/// First pp-token in current translation unit.
354-
std::optional<Token> FirstPPToken;
354+
SourceLocation FirstPPTokenLoc;
355355

356356
/// A position within a C++20 import-seq.
357357
class StdCXXImportSeq {
@@ -1769,20 +1769,13 @@ class Preprocessor {
17691769
std::optional<LexEmbedParametersResult> LexEmbedParameters(Token &Current,
17701770
bool ForHasEmbed);
17711771

1772-
/// Whether the preprocessor already seen the first pp-token in main file.
1773-
bool hasSeenMainFileFirstPPToken() const { return FirstPPToken.has_value(); }
1774-
1775-
/// Record first pp-token and check if it has a Token::FirstPPToken flag.
1776-
void HandleMainFileFirstPPToken(const Token &Tok) {
1777-
if (!hasSeenMainFileFirstPPToken() && Tok.isFirstPPToken() &&
1778-
SourceMgr.isWrittenInMainFile(Tok.getLocation()))
1779-
FirstPPToken = Tok;
1772+
/// Get the start location of the first pp-token in main file.
1773+
SourceLocation getMainFileFirstPPTokenLoc() const {
1774+
assert(FirstPPTokenLoc.isValid() &&
1775+
"Did not see the first pp-token in the main file");
1776+
return FirstPPTokenLoc;
17801777
}
17811778

1782-
Token getMainFileFirstPPToken() const {
1783-
assert(FirstPPToken && "First main file pp-token doesn't exists");
1784-
return *FirstPPToken;
1785-
}
17861779
bool LexAfterModuleImport(Token &Result);
17871780
void CollectPpImportSuffix(SmallVectorImpl<Token> &Toks);
17881781

clang/lib/Lex/Lexer.cpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3228,6 +3228,7 @@ std::optional<Token> Lexer::peekNextPPToken() {
32283228
bool atStartOfLine = IsAtStartOfLine;
32293229
bool atPhysicalStartOfLine = IsAtPhysicalStartOfLine;
32303230
bool leadingSpace = HasLeadingSpace;
3231+
bool isFirstPPToken = IsFirstPPToken;
32313232

32323233
Token Tok;
32333234
Lex(Tok);
@@ -3238,7 +3239,7 @@ std::optional<Token> Lexer::peekNextPPToken() {
32383239
HasLeadingSpace = leadingSpace;
32393240
IsAtStartOfLine = atStartOfLine;
32403241
IsAtPhysicalStartOfLine = atPhysicalStartOfLine;
3241-
3242+
IsFirstPPToken = isFirstPPToken;
32423243
// Restore the lexer back to non-skipping mode.
32433244
LexingRawMode = false;
32443245

@@ -3740,10 +3741,6 @@ bool Lexer::Lex(Token &Result) {
37403741
bool returnedToken = LexTokenInternal(Result, atPhysicalStartOfLine);
37413742
// (After the LexTokenInternal call, the lexer might be destroyed.)
37423743
assert((returnedToken || !isRawLex) && "Raw lex must succeed");
3743-
3744-
if (returnedToken && Result.isFirstPPToken() && PP &&
3745-
!PP->hasSeenMainFileFirstPPToken())
3746-
PP->HandleMainFileFirstPPToken(Result);
37473744
return returnedToken;
37483745
}
37493746

@@ -4547,8 +4544,6 @@ const char *Lexer::convertDependencyDirectiveToken(
45474544
Result.setFlag((Token::TokenFlags)DDTok.Flags);
45484545
Result.setLength(DDTok.Length);
45494546
BufferPtr = TokPtr + DDTok.Length;
4550-
if (PP && !PP->hasSeenMainFileFirstPPToken() && Result.isFirstPPToken())
4551-
PP->HandleMainFileFirstPPToken(Result);
45524547
return TokPtr;
45534548
}
45544549

clang/lib/Lex/PPDirectives.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,9 +1242,6 @@ void Preprocessor::HandleDirective(Token &Result) {
12421242
// pp-directive.
12431243
bool ReadAnyTokensBeforeDirective =CurPPLexer->MIOpt.getHasReadAnyTokensVal();
12441244

1245-
if (!hasSeenMainFileFirstPPToken())
1246-
HandleMainFileFirstPPToken(Result);
1247-
12481245
// Save the '#' token in case we need to return it later.
12491246
Token SavedHash = Result;
12501247

clang/lib/Lex/PPMacroExpansion.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -431,9 +431,6 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier,
431431
// to disable the optimization in this case.
432432
if (CurPPLexer) CurPPLexer->MIOpt.ExpandedMacro();
433433

434-
if (!hasSeenMainFileFirstPPToken())
435-
HandleMainFileFirstPPToken(Identifier);
436-
437434
// If this is a builtin macro, like __LINE__ or _Pragma, handle it specially.
438435
if (MI->isBuiltinMacro()) {
439436
if (Callbacks)

clang/lib/Lex/Preprocessor.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,21 @@ void Preprocessor::EnterMainSourceFile() {
566566
// #imported, it won't be re-entered.
567567
if (OptionalFileEntryRef FE = SourceMgr.getFileEntryRefForID(MainFileID))
568568
markIncluded(*FE);
569+
570+
// Record the first PP token in the main file. This is used to generate
571+
// better diagnostics for C++ modules.
572+
//
573+
// // This is a comment.
574+
// #define FOO int // note: add 'module;' to the start of the file
575+
// ^ FirstPPToken // to introduce a global module fragment.
576+
//
577+
// export module M; // error: module declaration must occur
578+
// // at the start of the translation unit.
579+
if (getLangOpts().CPlusPlusModules) {
580+
std::optional<Token> FirstPPTok = CurLexer->peekNextPPToken();
581+
if (FirstPPTok && FirstPPTok->isFirstPPToken())
582+
FirstPPTokenLoc = FirstPPTok->getLocation();
583+
}
569584
}
570585

571586
// Preprocess Predefines to populate the initial preprocessor state.

clang/lib/Sema/SemaModule.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -337,11 +337,9 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
337337
// tokens in a file (excluding the global module fragment.).
338338
if (getLangOpts().CPlusPlusModules && !IntroducerIsFirstPPToken && !SeenGMF) {
339339
Diag(ModuleLoc, diag::err_module_decl_not_at_start);
340-
SourceLocation BeginLoc = PP.getMainFileFirstPPToken().getLocation();
341-
if (BeginLoc.isValid()) {
342-
Diag(BeginLoc, diag::note_global_module_introducer_missing)
343-
<< FixItHint::CreateInsertion(BeginLoc, "module;\n");
344-
}
340+
SourceLocation BeginLoc = PP.getMainFileFirstPPTokenLoc();
341+
Diag(BeginLoc, diag::note_global_module_introducer_missing)
342+
<< FixItHint::CreateInsertion(BeginLoc, "module;\n");
345343
}
346344

347345
// C++23 [module.unit]p1: ... The identifiers module and import shall not

clang/unittests/Lex/LexerTest.cpp

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,7 @@ class LexerTest : public ::testing::Test {
4949
}
5050

5151
std::unique_ptr<Preprocessor> CreatePP(StringRef Source,
52-
TrivialModuleLoader &ModLoader,
53-
StringRef PreDefines = {}) {
52+
TrivialModuleLoader &ModLoader) {
5453
std::unique_ptr<llvm::MemoryBuffer> Buf =
5554
llvm::MemoryBuffer::getMemBuffer(Source);
5655
SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf)));
@@ -63,7 +62,7 @@ class LexerTest : public ::testing::Test {
6362
/*IILookup =*/nullptr,
6463
/*OwnsHeaderSearch =*/false);
6564
if (!PreDefines.empty())
66-
PP->setPredefines(PreDefines.str());
65+
PP->setPredefines(PreDefines);
6766
PP->Initialize(*Target);
6867
PP->EnterMainSourceFile();
6968
return PP;
@@ -111,6 +110,7 @@ class LexerTest : public ::testing::Test {
111110
std::shared_ptr<TargetOptions> TargetOpts;
112111
IntrusiveRefCntPtr<TargetInfo> Target;
113112
std::unique_ptr<Preprocessor> PP;
113+
std::string PreDefines;
114114
};
115115

116116
TEST_F(LexerTest, GetSourceTextExpandsToMaximumInMacroArgument) {
@@ -773,6 +773,7 @@ TEST(LexerPreambleTest, PreambleBounds) {
773773
}
774774

775775
TEST_F(LexerTest, CheckFirstPPToken) {
776+
LangOpts.CPlusPlusModules = true;
776777
{
777778
TrivialModuleLoader ModLoader;
778779
auto PP = CreatePP("// This is a comment\n"
@@ -781,9 +782,8 @@ TEST_F(LexerTest, CheckFirstPPToken) {
781782
Token Tok;
782783
PP->Lex(Tok);
783784
EXPECT_TRUE(Tok.is(tok::kw_int));
784-
EXPECT_TRUE(PP->hasSeenMainFileFirstPPToken());
785-
EXPECT_TRUE(PP->getMainFileFirstPPToken().isFirstPPToken());
786-
EXPECT_TRUE(PP->getMainFileFirstPPToken().is(tok::kw_int));
785+
EXPECT_TRUE(PP->getMainFileFirstPPTokenLoc().isValid());
786+
EXPECT_EQ(PP->getMainFileFirstPPTokenLoc(), Tok.getLocation());
787787
}
788788
{
789789
TrivialModuleLoader ModLoader;
@@ -794,24 +794,28 @@ TEST_F(LexerTest, CheckFirstPPToken) {
794794
Token Tok;
795795
PP->Lex(Tok);
796796
EXPECT_TRUE(Tok.is(tok::kw_int));
797-
EXPECT_TRUE(PP->hasSeenMainFileFirstPPToken());
798-
EXPECT_TRUE(PP->getMainFileFirstPPToken().isFirstPPToken());
799-
EXPECT_TRUE(PP->getMainFileFirstPPToken().is(tok::hash));
797+
EXPECT_FALSE(Lexer::getRawToken(PP->getMainFileFirstPPTokenLoc(), Tok,
798+
PP->getSourceManager(), PP->getLangOpts(),
799+
/*IgnoreWhiteSpace=*/false));
800+
EXPECT_TRUE(Tok.isFirstPPToken());
801+
EXPECT_TRUE(Tok.is(tok::hash));
800802
}
801803

802804
{
805+
PreDefines = "#define FOO int\n";
803806
TrivialModuleLoader ModLoader;
804807
auto PP = CreatePP("// This is a comment\n"
805808
"FOO a;",
806-
ModLoader, "#define FOO int\n");
809+
ModLoader);
807810
Token Tok;
808811
PP->Lex(Tok);
809812
EXPECT_TRUE(Tok.is(tok::kw_int));
810-
EXPECT_TRUE(PP->hasSeenMainFileFirstPPToken());
811-
EXPECT_TRUE(PP->getMainFileFirstPPToken().isFirstPPToken());
812-
EXPECT_TRUE(PP->getMainFileFirstPPToken().is(tok::identifier));
813-
EXPECT_TRUE(
814-
PP->getMainFileFirstPPToken().getIdentifierInfo()->isStr("FOO"));
813+
EXPECT_FALSE(Lexer::getRawToken(PP->getMainFileFirstPPTokenLoc(), Tok,
814+
PP->getSourceManager(), PP->getLangOpts(),
815+
/*IgnoreWhiteSpace=*/false));
816+
EXPECT_TRUE(Tok.isFirstPPToken());
817+
EXPECT_TRUE(Tok.is(tok::raw_identifier));
818+
EXPECT_TRUE(Tok.getRawIdentifier() == "FOO");
815819
}
816820
}
817821
} // anonymous namespace

0 commit comments

Comments
 (0)