Skip to content

Commit 1ce4f15

Browse files
yronglinAnthony Tran
authored andcommitted
[clang][Preprocessor] Add peekNextPPToken, makes look ahead next token without side-effects (llvm#143898)
This PR introduce a new function `peekNextPPToken`. It's an extension of `isNextPPTokenLParen` and can makes look ahead one token in preprocessor without side-effects. It's also the 1st part of llvm#107168 and it was used to look ahead next token then determine whether current lexing pp directive is one of pp-import or pp-module directive. At the start of phase 4 an import or module token is treated as starting a directive and are converted to their respective keywords iff: - After skipping horizontal whitespace are - at the start of a logical line, or - preceded by an export at the start of the logical line. - Are followed by an identifier pp token (before macro expansion), or - <, ", or : (but not ::) pp tokens for import, or - ; for module Otherwise the token is treated as an identifier. --------- Signed-off-by: yronglin <yronglin777@gmail.com>
1 parent 184c23d commit 1ce4f15

File tree

8 files changed

+62
-69
lines changed

8 files changed

+62
-69
lines changed

clang/include/clang/Lex/Lexer.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ class Lexer : public PreprocessorLexer {
124124
//===--------------------------------------------------------------------===//
125125
// Context that changes as the file is lexed.
126126
// NOTE: any state that mutates when in raw mode must have save/restore code
127-
// in Lexer::isNextPPTokenLParen.
127+
// in Lexer::peekNextPPToken.
128128

129129
// BufferPtr - Current pointer into the buffer. This is the next character
130130
// to be lexed.
@@ -645,10 +645,10 @@ class Lexer : public PreprocessorLexer {
645645
BufferPtr = TokEnd;
646646
}
647647

648-
/// isNextPPTokenLParen - Return 1 if the next unexpanded token will return a
649-
/// tok::l_paren token, 0 if it is something else and 2 if there are no more
650-
/// tokens in the buffer controlled by this lexer.
651-
unsigned isNextPPTokenLParen();
648+
/// peekNextPPToken - Return std::nullopt if there are no more tokens in the
649+
/// buffer controlled by this lexer, otherwise return the next unexpanded
650+
/// token.
651+
std::optional<Token> peekNextPPToken();
652652

653653
//===--------------------------------------------------------------------===//
654654
// Lexer character reading interfaces.

clang/include/clang/Lex/Preprocessor.h

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2302,10 +2302,41 @@ class Preprocessor {
23022302
}
23032303
}
23042304

2305-
/// Determine whether the next preprocessor token to be
2306-
/// lexed is a '('. If so, consume the token and return true, if not, this
2305+
/// Check whether the next pp-token is one of the specificed token kind. this
23072306
/// method should have no observable side-effect on the lexed tokens.
2308-
bool isNextPPTokenLParen();
2307+
template <tok::TokenKind K, tok::TokenKind... Ks> bool isNextPPTokenOneOf() {
2308+
// Do some quick tests for rejection cases.
2309+
std::optional<Token> Val;
2310+
if (CurLexer)
2311+
Val = CurLexer->peekNextPPToken();
2312+
else
2313+
Val = CurTokenLexer->peekNextPPToken();
2314+
2315+
if (!Val) {
2316+
// We have run off the end. If it's a source file we don't
2317+
// examine enclosing ones (C99 5.1.1.2p4). Otherwise walk up the
2318+
// macro stack.
2319+
if (CurPPLexer)
2320+
return false;
2321+
for (const IncludeStackInfo &Entry : llvm::reverse(IncludeMacroStack)) {
2322+
if (Entry.TheLexer)
2323+
Val = Entry.TheLexer->peekNextPPToken();
2324+
else
2325+
Val = Entry.TheTokenLexer->peekNextPPToken();
2326+
2327+
if (Val)
2328+
break;
2329+
2330+
// Ran off the end of a source file?
2331+
if (Entry.ThePPLexer)
2332+
return false;
2333+
}
2334+
}
2335+
2336+
// Okay, we found the token and return. Otherwise we found the end of the
2337+
// translation unit.
2338+
return Val->is(K) || (... || Val->is(Ks));
2339+
}
23092340

23102341
private:
23112342
/// Identifiers used for SEH handling in Borland. These are only

clang/include/clang/Lex/TokenLexer.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,9 @@ class TokenLexer {
139139
void Init(const Token *TokArray, unsigned NumToks, bool DisableMacroExpansion,
140140
bool OwnsTokens, bool IsReinject);
141141

142-
/// If the next token lexed will pop this macro off the
143-
/// expansion stack, return 2. If the next unexpanded token is a '(', return
144-
/// 1, otherwise return 0.
145-
unsigned isNextTokenLParen() const;
142+
/// If the next token lexed will pop this macro off the expansion stack,
143+
/// return std::nullopt, otherwise return the next unexpanded token.
144+
std::optional<Token> peekNextPPToken() const;
146145

147146
/// Lex and return a token from this macro stream.
148147
bool Lex(Token &Tok);

clang/lib/Lex/Lexer.cpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3202,18 +3202,19 @@ bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) {
32023202
return PP->HandleEndOfFile(Result, isPragmaLexer());
32033203
}
32043204

3205-
/// isNextPPTokenLParen - Return 1 if the next unexpanded token lexed from
3206-
/// the specified lexer will return a tok::l_paren token, 0 if it is something
3207-
/// else and 2 if there are no more tokens in the buffer controlled by the
3208-
/// lexer.
3209-
unsigned Lexer::isNextPPTokenLParen() {
3205+
/// peekNextPPToken - Return std::nullopt if there are no more tokens in the
3206+
/// buffer controlled by this lexer, otherwise return the next unexpanded
3207+
/// token.
3208+
std::optional<Token> Lexer::peekNextPPToken() {
32103209
assert(!LexingRawMode && "How can we expand a macro from a skipping buffer?");
32113210

32123211
if (isDependencyDirectivesLexer()) {
32133212
if (NextDepDirectiveTokenIndex == DepDirectives.front().Tokens.size())
3214-
return 2;
3215-
return DepDirectives.front().Tokens[NextDepDirectiveTokenIndex].is(
3216-
tok::l_paren);
3213+
return std::nullopt;
3214+
Token Result;
3215+
(void)convertDependencyDirectiveToken(
3216+
DepDirectives.front().Tokens[NextDepDirectiveTokenIndex], Result);
3217+
return Result;
32173218
}
32183219

32193220
// Switch to 'skipping' mode. This will ensure that we can lex a token
@@ -3242,8 +3243,8 @@ unsigned Lexer::isNextPPTokenLParen() {
32423243
LexingRawMode = false;
32433244

32443245
if (Tok.is(tok::eof))
3245-
return 2;
3246-
return Tok.is(tok::l_paren);
3246+
return std::nullopt;
3247+
return Tok;
32473248
}
32483249

32493250
/// Find the end of a version control conflict marker.

clang/lib/Lex/PPDirectives.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,9 @@ static bool isReservedCXXAttributeName(Preprocessor &PP, IdentifierInfo *II) {
183183
AttributeCommonInfo::AttrArgsInfo AttrArgsInfo =
184184
AttributeCommonInfo::getCXX11AttrArgsInfo(II);
185185
if (AttrArgsInfo == AttributeCommonInfo::AttrArgsInfo::Required)
186-
return PP.isNextPPTokenLParen();
186+
return PP.isNextPPTokenOneOf<tok::l_paren>();
187187

188-
return !PP.isNextPPTokenLParen() ||
188+
return !PP.isNextPPTokenOneOf<tok::l_paren>() ||
189189
AttrArgsInfo == AttributeCommonInfo::AttrArgsInfo::Optional;
190190
}
191191
return false;

clang/lib/Lex/PPMacroExpansion.cpp

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -418,44 +418,6 @@ static bool isTrivialSingleTokenExpansion(const MacroInfo *MI,
418418
return !llvm::is_contained(MI->params(), II);
419419
}
420420

421-
/// isNextPPTokenLParen - Determine whether the next preprocessor token to be
422-
/// lexed is a '('. If so, consume the token and return true, if not, this
423-
/// method should have no observable side-effect on the lexed tokens.
424-
bool Preprocessor::isNextPPTokenLParen() {
425-
// Do some quick tests for rejection cases.
426-
unsigned Val;
427-
if (CurLexer)
428-
Val = CurLexer->isNextPPTokenLParen();
429-
else
430-
Val = CurTokenLexer->isNextTokenLParen();
431-
432-
if (Val == 2) {
433-
// We have run off the end. If it's a source file we don't
434-
// examine enclosing ones (C99 5.1.1.2p4). Otherwise walk up the
435-
// macro stack.
436-
if (CurPPLexer)
437-
return false;
438-
for (const IncludeStackInfo &Entry : llvm::reverse(IncludeMacroStack)) {
439-
if (Entry.TheLexer)
440-
Val = Entry.TheLexer->isNextPPTokenLParen();
441-
else
442-
Val = Entry.TheTokenLexer->isNextTokenLParen();
443-
444-
if (Val != 2)
445-
break;
446-
447-
// Ran off the end of a source file?
448-
if (Entry.ThePPLexer)
449-
return false;
450-
}
451-
}
452-
453-
// Okay, if we know that the token is a '(', lex it and return. Otherwise we
454-
// have found something that isn't a '(' or we found the end of the
455-
// translation unit. In either case, return false.
456-
return Val == 1;
457-
}
458-
459421
/// HandleMacroExpandedIdentifier - If an identifier token is read that is to be
460422
/// expanded as a macro, handle it and return the next token as 'Identifier'.
461423
bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier,

clang/lib/Lex/Preprocessor.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -813,14 +813,14 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) {
813813
if (!Identifier.isExpandDisabled() && MI->isEnabled()) {
814814
// C99 6.10.3p10: If the preprocessing token immediately after the
815815
// macro name isn't a '(', this macro should not be expanded.
816-
if (!MI->isFunctionLike() || isNextPPTokenLParen())
816+
if (!MI->isFunctionLike() || isNextPPTokenOneOf<tok::l_paren>())
817817
return HandleMacroExpandedIdentifier(Identifier, MD);
818818
} else {
819819
// C99 6.10.3.4p2 says that a disabled macro may never again be
820820
// expanded, even if it's in a context where it could be expanded in the
821821
// future.
822822
Identifier.setFlag(Token::DisableExpand);
823-
if (MI->isObjectLike() || isNextPPTokenLParen())
823+
if (MI->isObjectLike() || isNextPPTokenOneOf<tok::l_paren>())
824824
Diag(Identifier, diag::pp_disabled_macro_expansion);
825825
}
826826
}

clang/lib/Lex/TokenLexer.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -921,13 +921,13 @@ bool TokenLexer::pasteTokens(Token &LHSTok, ArrayRef<Token> TokenStream,
921921
}
922922

923923
/// isNextTokenLParen - If the next token lexed will pop this macro off the
924-
/// expansion stack, return 2. If the next unexpanded token is a '(', return
925-
/// 1, otherwise return 0.
926-
unsigned TokenLexer::isNextTokenLParen() const {
924+
/// expansion stack, return std::nullopt, otherwise return the next unexpanded
925+
/// token.
926+
std::optional<Token> TokenLexer::peekNextPPToken() const {
927927
// Out of tokens?
928928
if (isAtEnd())
929-
return 2;
930-
return Tokens[CurTokenIdx].is(tok::l_paren);
929+
return std::nullopt;
930+
return Tokens[CurTokenIdx];
931931
}
932932

933933
/// isParsingPreprocessorDirective - Return true if we are in the middle of a

0 commit comments

Comments
 (0)