[clang] [clang] Don't crash when module directive `export module foo` not following a semicolon and there are no rest pp-tokens in current module file (PR #187845)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 24 05:59:11 PDT 2026
https://github.com/yronglin updated https://github.com/llvm/llvm-project/pull/187845
>From f0394ded3e23fb3fbcc7ac948ae0f2851b9378b1 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Sat, 21 Mar 2026 15:16:18 +0800
Subject: [PATCH 1/2] [clang] Don't crash when module directive export module
foo not following a semicolon and there are no rest pp-tokens in current
module file
Signed-off-by: yronglin <yronglin777 at gmail.com>
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/Lex/PPDirectives.cpp | 19 ++++++++++---------
.../test/CXX/module/dcl.dcl/dcl.module/p1.cpp | 5 +++++
3 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b13171f7ecafc..dd2f3e25b9223 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -339,6 +339,7 @@ Bug Fixes in This Version
- Fixed a crash when normalizing constraints involving concept template parameters whose index coincided with non-concept template parameters in the same parameter mapping.
- Fixed a crash caused by accessing dependent diagnostics of a non-dependent context.
- Fixed a crash when substituting into a non-type template parameter that has a type containing an undeduced placeholder type.
+- Fixed a crash when module directive ``export module foo`` not following a semicolon and there are no rest pp-tokens in current module file. (#GH187771)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index 09f0c3fe8c61e..c89402fa137c0 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -4407,18 +4407,19 @@ void Preprocessor::HandleCXXModuleDirective(Token ModuleTok) {
// Consume the pp-import-suffix and expand any macros in it now, if we're not
// at the semicolon already.
- std::optional<Token> NextPPTok = DirToks.back();
- if (DirToks.back().is(tok::eod)) {
- NextPPTok = peekNextPPToken();
- if (NextPPTok && NextPPTok->is(tok::raw_identifier))
- LookUpIdentifierInfo(*NextPPTok);
- }
+ std::optional<Token> NextPPTok =
+ DirToks.back().is(tok::eod) ? peekNextPPToken() : DirToks.back();
// Only ';' and '[' are allowed after module name.
// We also check 'private' because the previous is not a module name.
- if (!NextPPTok->isOneOf(tok::semi, tok::eod, tok::l_square, tok::kw_private))
- Diag(*NextPPTok, diag::err_pp_unexpected_tok_after_module_name)
- << getSpelling(*NextPPTok);
+ if (NextPPTok) {
+ if (NextPPTok->is(tok::raw_identifier))
+ LookUpIdentifierInfo(*NextPPTok);
+ if (!NextPPTok->isOneOf(tok::semi, tok::eod, tok::l_square,
+ tok::kw_private))
+ Diag(*NextPPTok, diag::err_pp_unexpected_tok_after_module_name)
+ << getSpelling(*NextPPTok);
+ }
if (!DirToks.back().isOneOf(tok::semi, tok::eod)) {
// Consume the pp-import-suffix and expand any macros in it now. We'll add
diff --git a/clang/test/CXX/module/dcl.dcl/dcl.module/p1.cpp b/clang/test/CXX/module/dcl.dcl/dcl.module/p1.cpp
index 95d087e0f6c78..190d4f5ef4871 100644
--- a/clang/test/CXX/module/dcl.dcl/dcl.module/p1.cpp
+++ b/clang/test/CXX/module/dcl.dcl/dcl.module/p1.cpp
@@ -7,6 +7,7 @@
// RUN: %clang_cc1 -std=c++20 %t/D.cppm -fmodule-file=foo=%t/C.pcm
// RUN: %clang_cc1 -std=c++20 %t/E.cppm -fmodule-file=foo=%t/C.pcm
// RUN: %clang_cc1 -std=c++20 -verify %t/F.cppm -fmodule-file=foo=%t/C.pcm
+// RUN: %clang_cc1 -std=c++20 -verify %t/NoSemi.cppm
//--- A.cppm
export module foo; // expected-note {{previous module declaration is here}}
@@ -28,3 +29,7 @@ export module bar;
//--- F.cppm
module foo; // expected-note {{previous module declaration is here}}
export module bar; // expected-error {{translation unit contains multiple module declarations}}
+
+//--- NoSemi.cppm
+// This test checked issue: https://github.com/llvm/llvm-project/issues/187771
+export module foo //expected-error {{module directive must end with a ';'}}
>From 9422ea51de5db274f41e168de4014191fb2e6749 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Tue, 24 Mar 2026 20:58:56 +0800
Subject: [PATCH 2/2] Update clang/docs/ReleaseNotes.rst
Co-authored-by: Aaron Ballman <aaron at aaronballman.com>
---
clang/docs/ReleaseNotes.rst | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index dd2f3e25b9223..92a5324a61a68 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -339,7 +339,8 @@ Bug Fixes in This Version
- Fixed a crash when normalizing constraints involving concept template parameters whose index coincided with non-concept template parameters in the same parameter mapping.
- Fixed a crash caused by accessing dependent diagnostics of a non-dependent context.
- Fixed a crash when substituting into a non-type template parameter that has a type containing an undeduced placeholder type.
-- Fixed a crash when module directive ``export module foo`` not following a semicolon and there are no rest pp-tokens in current module file. (#GH187771)
+- Correctly diagnosing and no longer crashing when ``export module foo``
+ (without a semicolon) are the final tokens in a module file. (#GH187771)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
More information about the cfe-commits
mailing list