Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
2cce3d1
[Clang] Add peekNextPPToken, makes peek next token without side-effects
yronglin Aug 17, 2024
04ddbf6
[C++20][Modules] Implement P1857R3 Modules Dependency Discovery
yronglin May 26, 2025
8529a7f
P3034R1 Module Declarations Shouldn’t be Macros
yronglin Jun 2, 2025
b75b5ba
Merge branch 'main' of https://github.com/llvm/llvm-project into modu…
yronglin Jun 8, 2025
ece6382
[clang-scan-deps] Only check eod token in C++ modules
yronglin Jun 8, 2025
008844c
A module directive may only appear as the first preprocessing tokens …
yronglin Jun 12, 2025
db17bda
Format code
yronglin Jun 12, 2025
1ce4def
Merge branch 'main' into modules_dependency_discovery
yronglin Jun 21, 2025
1fa3090
Resolve merge conflicts
yronglin Jun 21, 2025
5a85243
Merge remote-tracking branch 'origin' into modules_dependency_discovery
yronglin Jun 24, 2025
687cdee
Use isNextPPTokenOneOf instead of peekNextPPToken
yronglin Jun 24, 2025
a7da327
Merge branch 'main' into modules_dependency_discovery
yronglin Jun 25, 2025
8ce88a0
Follow isNextPPTokenOneOf's change
yronglin Jun 25, 2025
32c142e
Merge remote-tracking branch 'origin' into modules_dependency_discovery
yronglin Jun 26, 2025
4a84a31
Merge branch 'main' into modules_dependency_discovery
yronglin Jul 8, 2025
21cb5ec
Follow getTrailingObjects changes
yronglin Jul 8, 2025
27ab41f
Revert unnecessary changes and refine code
yronglin Jul 8, 2025
63a62ae
Update cxx status
yronglin Jul 9, 2025
0a63a88
Merge branch 'main' into modules_dependency_discovery
yronglin Jul 9, 2025
9fb7cc2
Merge remote-tracking branch 'origin' into modules_dependency_discovery
yronglin Jul 15, 2025
1171f7f
Fix crash
yronglin Jul 15, 2025
3821f67
Revert "Revert unnecessary changes and refine code"
yronglin Jul 16, 2025
eabc2a4
Fix lit test
yronglin Jul 16, 2025
23bad11
Merge remote-tracking branch 'origin' into modules_dependency_discovery
yronglin Jul 22, 2025
dbaa113
Merge remote-tracking branch 'origin' into modules_dependency_discovery
yronglin Jul 30, 2025
b533184
Rebase and fix conflict
yronglin Jul 30, 2025
f479274
Merge branch 'main' into modules_dependency_discovery
yronglin Aug 5, 2025
695869e
Merge branch 'main' into modules_dependency_discovery
yronglin Aug 8, 2025
0164d0d
Stash
yronglin Aug 8, 2025
0c3667c
Merge branch 'main' into modules_dependency_discovery
yronglin Aug 22, 2025
0588245
Handle @import in preprocessor when -frewrite-imports enabled
yronglin Aug 22, 2025
49281ec
Don't use ModuleNameLoc* as ActOnModuleImport
yronglin Aug 27, 2025
1c8b28f
Remove tok::annot_module_name and added error recovery to continue pa…
yronglin Aug 28, 2025
14ba684
Add test for pp-module and pp-import
yronglin Aug 31, 2025
2b930da
Merge branch 'main' into modules_dependency_discovery
yronglin Aug 31, 2025
5dc3c9a
Refine isModuleContextualKeyword and isImportingCXXNamedModules, remo…
yronglin Sep 1, 2025
8a77b45
[ObjC] Handle @import directive as a pp-directive
yronglin Sep 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clang/examples/AnnotateFunctions/AnnotateFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class PragmaAnnotateHandler : public PragmaHandler {
Token Tok;
PP.LexUnexpandedToken(Tok);
if (Tok.isNot(tok::eod))
PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma";
PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "#pragma";

if (HandledDecl) {
DiagnosticsEngine &D = PP.getDiagnostics();
Expand Down
5 changes: 1 addition & 4 deletions clang/include/clang/Basic/DiagnosticLexKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -465,10 +465,7 @@ def err_pp_embed_device_file : Error<
"device files are not yet supported by '#embed' directive">;

def ext_pp_extra_tokens_at_eol : ExtWarn<
"extra tokens at end of #%0 directive">, InGroup<ExtraTokens>;
def ext_pp_extra_tokens_at_module_directive_eol
: ExtWarn<"extra tokens at end of '%0' directive">,
InGroup<ExtraTokens>;
"extra tokens at end of %0 directive">, InGroup<ExtraTokens>;

def ext_pp_comma_expr : Extension<"comma operator in operand of #if">;
def ext_pp_bad_vaargs_use : Extension<
Expand Down
29 changes: 4 additions & 25 deletions clang/include/clang/Lex/Preprocessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,24 +137,6 @@ struct CXXStandardLibraryVersionInfo {
std::uint64_t Version;
};

class ExportContextualKeywordInfo {
Token ExportTok;
bool AtPhysicalStartOfLine = false;

public:
ExportContextualKeywordInfo() = default;
ExportContextualKeywordInfo(const Token &Tok, bool AtPhysicalStartOfLine)
: ExportTok(Tok), AtPhysicalStartOfLine(AtPhysicalStartOfLine) {}

bool isValid() const { return ExportTok.is(tok::kw_export); }
bool isAtPhysicalStartOfLine() const { return AtPhysicalStartOfLine; }
Token getExportTok() const { return ExportTok; }
void reset() {
ExportTok.startToken();
AtPhysicalStartOfLine = false;
}
};

/// Engages in a tight little dance with the lexer to efficiently
/// preprocess tokens.
///
Expand Down Expand Up @@ -378,7 +360,7 @@ class Preprocessor {
bool DeclaringCXXNamedModules = false;

/// Whether the last token we lexed was an 'export' keyword.
ExportContextualKeywordInfo LastTokenWasExportKeyword;
std::optional<Token> ModuleLikeDirectiveIntroducer;

/// First pp-token source location in current translation unit.
SourceLocation FirstPPTokenLoc;
Expand Down Expand Up @@ -1808,15 +1790,15 @@ class Preprocessor {
void EnterModuleSuffixTokenStream(ArrayRef<Token> Toks);
void HandleCXXImportDirective(Token Import);
void HandleCXXModuleDirective(Token Module);
void HandleObjCAtImportDirective(Token &ImportTok);

/// Callback invoked when the lexer sees one of export, import or module token
/// at the start of a line.
///
/// This consumes the import/module directive, modifies the
/// lexer/preprocessor state, and advances the lexer(s) so that the next token
/// read is the correct one.
bool HandleModuleContextualKeyword(Token &Result,
bool TokAtPhysicalStartOfLine);
bool HandleModuleContextualKeyword(Token &Result);

/// Get the start location of the first pp-token in main file.
SourceLocation getMainFileFirstPPTokenLoc() const {
Expand All @@ -1825,7 +1807,6 @@ class Preprocessor {
return FirstPPTokenLoc;
}

bool LexAfterModuleImport(Token &Result);
void CollectPPImportSuffix(SmallVectorImpl<Token> &Toks,
bool StopUntilEOD = false);
bool CollectPPImportSuffixAndEnterStream(SmallVectorImpl<Token> &Toks,
Expand Down Expand Up @@ -2356,6 +2337,7 @@ class Preprocessor {
template <typename... Ts> bool isNextPPTokenOneOf(Ts... Ks) {
static_assert(sizeof...(Ts) > 0,
"requires at least one tok::TokenKind specified");

// Do some quick tests for rejection cases.
std::optional<Token> Val;
if (CurLexer)
Expand Down Expand Up @@ -3175,9 +3157,6 @@ class Preprocessor {
static bool CLK_DependencyDirectivesLexer(Preprocessor &P, Token &Result) {
return P.CurLexer->LexDependencyDirectiveToken(Result);
}
static bool CLK_LexAfterModuleImport(Preprocessor &P, Token &Result) {
return P.LexAfterModuleImport(Result);
}
};

/// Abstract base class that describes a handler that will receive
Expand Down
8 changes: 7 additions & 1 deletion clang/include/clang/Lex/Token.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,10 @@ class Token {
// re-added, e.g. via EnterTokenStream. Annotation
// tokens are *not* reinjected.
HasSeenNoTrivialPPDirective =
0x1000, // Whether we've seen any 'no-trivial' pp-directives before
0x1000, // Whether we've seen any 'no-trivial' pp-directives before//
// current position.
PhysicalStartOfLine =
0x2000, // At the physical start of line or only after whitespace.
};

tok::TokenKind getKind() const { return Kind; }
Expand Down Expand Up @@ -277,6 +279,10 @@ class Token {
///
bool isAtStartOfLine() const { return getFlag(StartOfLine); }

/// isAtPhysicalStartOfLine - Return true if this token is at the physical
/// start of a line.
bool isAtPhysicalStartOfLine() const { return getFlag(PhysicalStartOfLine); }

/// Return true if this token has whitespace before it.
///
bool hasLeadingSpace() const { return getFlag(LeadingSpace); }
Expand Down
19 changes: 8 additions & 11 deletions clang/lib/Lex/DependencyDirectivesScanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -579,15 +579,12 @@ bool Scanner::lexModuleDirectiveBody(DirectiveKind Kind, const char *&First,
return false;
}

const auto &Tok = lexToken(First, End);
pushDirective(Kind);
skipWhitespace(First, End);
if (First == End)
if (Tok.is(tok::eof) || Tok.is(tok::eod))
return false;
if (!isVerticalWhitespace(*First))
return reportError(
DirectiveLoc, diag::err_dep_source_scanner_unexpected_tokens_at_import);
skipNewline(First, End);
return false;
return reportError(DirectiveLoc,
diag::err_dep_source_scanner_unexpected_tokens_at_import);
}

dependency_directives_scan::Token &Scanner::lexToken(const char *&First,
Expand Down Expand Up @@ -931,10 +928,6 @@ bool Scanner::lexPPLine(const char *&First, const char *const End) {
CurDirToks.clear();
});

// FIXME: Shoule we handle @import as a preprocessing directive?
if (*First == '@')
return lexAt(First, End);

if (*First == '_') {
if (isNextIdentifierOrSkipLine("_Pragma", First, End))
return lex_Pragma(First, End);
Expand All @@ -947,6 +940,10 @@ bool Scanner::lexPPLine(const char *&First, const char *const End) {
auto ScEx2 = make_scope_exit(
[&]() { TheLexer.setParsingPreprocessorDirective(false); });

// FIXME: Shoule we handle @import as a preprocessing directive?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this FIXME still relevant after this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, we should remove this comments

if (*First == '@')
return lexAt(First, End);

// Handle module directives for C++20 modules.
if (*First == 'i' || *First == 'e' || *First == 'm')
return lexModule(First, End);
Expand Down
46 changes: 26 additions & 20 deletions clang/lib/Lex/Lexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,13 @@ tok::ObjCKeywordKind Token::getObjCKeywordID() const {
/// or module).
bool Token::isModuleContextualKeyword(const LangOptions &LangOpts,
bool AllowExport) const {
if (!LangOpts.CPlusPlusModules)
if (!LangOpts.CPlusPlusModules || isAnnotation())
return false;
if (AllowExport && is(tok::kw_export))
return true;
if (isOneOf(tok::kw_import, tok::kw_module))
return true;
if (isNot(tok::identifier))
return false;
const auto *II = getIdentifierInfo();
return II->isModulesImport() || II->isModulesDeclaration();
if (const auto *II = getIdentifierInfo())
return II->isModulesImport() || II->isModulesDeclaration();
return false;
}

/// Determine whether the token kind starts a simple-type-specifier.
Expand Down Expand Up @@ -3758,6 +3755,9 @@ bool Lexer::LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine) {
assert(!Result.needsCleaning() && "Result needs cleaning");
assert(!Result.hasPtrData() && "Result has not been reset");

if (TokAtPhysicalStartOfLine)
Result.setFlag(Token::PhysicalStartOfLine);

// CurPtr - Cache BufferPtr in an automatic variable.
const char *CurPtr = BufferPtr;

Expand Down Expand Up @@ -4040,10 +4040,9 @@ bool Lexer::LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine) {
// Notify MIOpt that we read a non-whitespace/non-comment token.
MIOpt.ReadToken();
bool returnedToken = LexIdentifierContinue(Result, CurPtr);
if (returnedToken && Result.isModuleContextualKeyword(LangOpts) &&
!LexingRawMode && !Is_PragmaLexer && !ParsingPreprocessorDirective &&
PP &&
PP->HandleModuleContextualKeyword(Result, TokAtPhysicalStartOfLine))
if (returnedToken && Result.isNot(tok::eof) && !LexingRawMode &&
!Is_PragmaLexer && !ParsingPreprocessorDirective && PP &&
PP->HandleModuleContextualKeyword(Result))
goto HandleDirective;
return returnedToken;
}
Expand Down Expand Up @@ -4454,9 +4453,14 @@ bool Lexer::LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine) {

case '@':
// Objective C support.
if (CurPtr[-1] == '@' && LangOpts.ObjC)
if (CurPtr[-1] == '@' && LangOpts.ObjC) {
if (TokAtPhysicalStartOfLine && !LexingRawMode && !Is_PragmaLexer) {
FormTokenWithChars(Result, CurPtr, tok::at);
(void)PP->HandleModuleContextualKeyword(Result);
return true;
}
Kind = tok::at;
else
} else
Kind = tok::unknown;
break;

Expand Down Expand Up @@ -4538,10 +4542,6 @@ bool Lexer::LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine) {
HandleDirective:
PP->HandleDirective(Result);

if (PP->hadModuleLoaderFatalFailure())
// With a fatal failure in the module loader, we abort parsing.
return true;

// We parsed the directive; lex a token with the new state.
return false;

Expand Down Expand Up @@ -4608,20 +4608,26 @@ bool Lexer::LexDependencyDirectiveToken(Token &Result) {

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

if (Result.is(tok::hash) && Result.isAtStartOfLine()) {
if (Result.is(tok::hash) && Result.isAtStartOfLine() && !isLexingRawMode()) {
PP->HandleDirective(Result);
if (PP->hadModuleLoaderFatalFailure())
// With a fatal failure in the module loader, we abort parsing.
return true;
return false;
}
if (Result.is(tok::at) && Result.isAtStartOfLine() && !isLexingRawMode()) {
(void)PP->HandleModuleContextualKeyword(Result);
return false;
}
if (Result.is(tok::raw_identifier)) {
Result.setRawIdentifierData(TokPtr);
if (!isLexingRawMode()) {
const IdentifierInfo *II = PP->LookUpIdentifierInfo(Result);
if (Result.isModuleContextualKeyword(LangOpts) &&
PP->HandleModuleContextualKeyword(Result, Result.isAtStartOfLine())) {
if (PP->HandleModuleContextualKeyword(Result)) {
PP->HandleDirective(Result);
if (PP->hadModuleLoaderFatalFailure())
// With a fatal failure in the module loader, we abort parsing.
return true;
return false;
}
if (II->isHandleIdentifierCase())
Expand Down
Loading