[clang] 17d28a5 - [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 (#187845)

via cfe-commits cfe-commits at lists.llvm.org
Tue Mar 24 06:36:11 PDT 2026


Author: yronglin
Date: 2026-03-24T21:36:06+08:00
New Revision: 17d28a5b53b04c6a89ff3087a3fb57f462e563fa

URL: https://github.com/llvm/llvm-project/commit/17d28a5b53b04c6a89ff3087a3fb57f462e563fa
DIFF: https://github.com/llvm/llvm-project/commit/17d28a5b53b04c6a89ff3087a3fb57f462e563fa.diff

LOG: [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 (#187845)

This PR add the missing check of nullable `std::optional<Token>` object
when the 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>
Co-authored-by: Aaron Ballman <aaron at aaronballman.com>

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Lex/PPDirectives.cpp
    clang/test/CXX/module/dcl.dcl/dcl.module/p1.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 6a2632543d337..7a369fb01bdd9 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -353,6 +353,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.
+- 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
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

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 ';'}}


        


More information about the cfe-commits mailing list