https://github.com/freaknbigpanda updated 
https://github.com/llvm/llvm-project/pull/183425

>From dc6fefed70ebda39b3718ab35161c10011c84571 Mon Sep 17 00:00:00 2001
From: Benjamin Luke <[email protected]>
Date: Fri, 20 Feb 2026 15:31:32 -0800
Subject: [PATCH 1/3] [clang][Lex] Preserve MultipleIncludeOpt state in
 Lexer::peekNextPPToken

peekNextPPToken lexed a token and mutated MIOpt, which could clear the
controlling-macro state for main files in C++20 modules mode.

Save/restore MIOpt in Lexer::peekNextPPToken.

Add regression coverage in LexerTest.MainFileHeaderGuardedWithCPlusPlusModules 
that
checks to make sure the controlling macro is properly set in C++20 mode.

`Add source level lit test in miopt-peek-restore-header-guard.cpp that checks 
to make
sure that the warnings that depend on the MIOpt state machine are emitted in 
C++20 mode.
---
 clang/lib/Lex/Lexer.cpp                       |  2 ++
 .../miopt-peek-restore-header-guard.cpp       | 12 +++++++
 clang/unittests/Lex/LexerTest.cpp             | 34 +++++++++++++++++++
 3 files changed, 48 insertions(+)
 create mode 100644 clang/test/Preprocessor/miopt-peek-restore-header-guard.cpp

diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index 92c3046a6fd19..0e72a27b852d7 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -3231,6 +3231,7 @@ std::optional<Token> Lexer::peekNextPPToken() {
   bool atStartOfLine = IsAtStartOfLine;
   bool atPhysicalStartOfLine = IsAtPhysicalStartOfLine;
   bool leadingSpace = HasLeadingSpace;
+  MultipleIncludeOpt MIOptState = MIOpt;
 
   Token Tok;
   Lex(Tok);
@@ -3241,6 +3242,7 @@ std::optional<Token> Lexer::peekNextPPToken() {
   HasLeadingSpace = leadingSpace;
   IsAtStartOfLine = atStartOfLine;
   IsAtPhysicalStartOfLine = atPhysicalStartOfLine;
+  MIOpt = MIOptState;
   // Restore the lexer back to non-skipping mode.
   LexingRawMode = false;
 
diff --git a/clang/test/Preprocessor/miopt-peek-restore-header-guard.cpp 
b/clang/test/Preprocessor/miopt-peek-restore-header-guard.cpp
new file mode 100644
index 0000000000000..8f3e9f49cf1b6
--- /dev/null
+++ b/clang/test/Preprocessor/miopt-peek-restore-header-guard.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -Wheader-guard -verify %s
+
+// Regression test for Lexer::peekNextPPToken() saving/restoring MIOpt state.
+// In C++20 module mode, the preprocessor peeks the first pp-token in the main
+// file before lexing begins. That must not perturb MIOpt state used for
+// header-guard analysis.
+
+#ifndef GOOD_GUARD
+#define BAD_GUARD
+#endif
+// expected-warning@-3 {{'GOOD_GUARD' is used as a header guard here, followed 
by #define of a different macro}}
+// expected-note@-3 {{'BAD_GUARD' is defined here; did you mean 'GOOD_GUARD'?}}
diff --git a/clang/unittests/Lex/LexerTest.cpp 
b/clang/unittests/Lex/LexerTest.cpp
index c51cd0d2bfdaa..da335d6e81820 100644
--- a/clang/unittests/Lex/LexerTest.cpp
+++ b/clang/unittests/Lex/LexerTest.cpp
@@ -89,6 +89,30 @@ class LexerTest : public ::testing::Test {
     return toks;
   }
 
+  bool MainFileIsMultipleIncludeGuarded(StringRef Filename, StringRef Source) {
+    FileEntryRef FE = FileMgr.getVirtualFileRef(Filename, Source.size(), 0);
+    SourceMgr.setMainFileID(
+        SourceMgr.createFileID(FE, SourceLocation(), SrcMgr::C_User));
+    SourceMgr.overrideFileContents(
+        FE, llvm::MemoryBuffer::getMemBufferCopy(Source, Filename));
+
+    TrivialModuleLoader ModLoader;
+    HeaderSearchOptions HSOpts;
+    HeaderSearch HeaderInfo(HSOpts, SourceMgr, Diags, LangOpts, Target.get());
+    PreprocessorOptions PPOpts;
+    std::unique_ptr<Preprocessor> LocalPP = std::make_unique<Preprocessor>(
+        PPOpts, Diags, LangOpts, SourceMgr, HeaderInfo, ModLoader,
+        /*IILookup=*/nullptr,
+        /*OwnsHeaderSearch=*/false);
+    if (!PreDefines.empty())
+      LocalPP->setPredefines(PreDefines);
+    LocalPP->Initialize(*Target);
+    LocalPP->EnterMainSourceFile();
+    std::vector<Token> Toks;
+    LocalPP->LexTokensUntilEOF(&Toks);
+    return LocalPP->getHeaderSearchInfo().isFileMultipleIncludeGuarded(FE);
+  }
+
   std::string getSourceText(Token Begin, Token End) {
     bool Invalid;
     StringRef Str =
@@ -360,6 +384,16 @@ TEST_F(LexerTest, LexAPI) {
   EXPECT_EQ("N", Lexer::getImmediateMacroName(idLoc4, SourceMgr, LangOpts));
 }
 
+TEST_F(LexerTest, MainFileHeaderGuardedWithCPlusPlusModules) {
+  LangOpts.CPlusPlus = true;
+  LangOpts.CPlusPlusModules = true;
+
+  EXPECT_TRUE(MainFileIsMultipleIncludeGuarded("guarded.h", "#ifndef GUARD\n"
+                                                            "#define GUARD\n"
+                                                            "int x;\n"
+                                                            "#endif\n"));
+}
+
 TEST_F(LexerTest, HandlesSplitTokens) {
   std::vector<tok::TokenKind> ExpectedTokens;
   // Line 1 (after the #defines)

>From f95bb5ca1504f44bc7ac188cca2937e71f4afd39 Mon Sep 17 00:00:00 2001
From: Benjamin Luke <[email protected]>
Date: Thu, 26 Feb 2026 16:51:26 -0800
Subject: [PATCH 2/3] Added release note

---
 clang/docs/ReleaseNotes.rst | 1 +
 1 file changed, 1 insertion(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index af124fce2bc64..2a297d9a71889 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -299,6 +299,7 @@ Bug Fixes in This Version
 - Fixed an assertion failure when evaluating ``_Countof`` on invalid 
``void``-typed operands. (#GH180893)
 - Fixed an assertion failure in the serialized diagnostic printer when it is 
destroyed without calling ``finish()``. (#GH140433)
 - Fixed an assertion failure caused by error recovery while extending a nested 
name specifier with results from ordinary lookup. (#GH181470)
+- Fixed a bug with multiple-include optimization (MIOpt) state not being 
preserved in some cases during lexing, which could suppress header-guard 
mismatch diagnostics and interfere with include-guard optimization.
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

>From e0a2baf242992367d17c4019833d9bbfbcaa7c15 Mon Sep 17 00:00:00 2001
From: Benjamin Luke <[email protected]>
Date: Thu, 26 Feb 2026 16:53:06 -0800
Subject: [PATCH 3/3] Added github issue tag

---
 clang/docs/ReleaseNotes.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2a297d9a71889..0ba70934682b8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -299,7 +299,7 @@ Bug Fixes in This Version
 - Fixed an assertion failure when evaluating ``_Countof`` on invalid 
``void``-typed operands. (#GH180893)
 - Fixed an assertion failure in the serialized diagnostic printer when it is 
destroyed without calling ``finish()``. (#GH140433)
 - Fixed an assertion failure caused by error recovery while extending a nested 
name specifier with results from ordinary lookup. (#GH181470)
-- Fixed a bug with multiple-include optimization (MIOpt) state not being 
preserved in some cases during lexing, which could suppress header-guard 
mismatch diagnostics and interfere with include-guard optimization.
+- Fixed a bug with multiple-include optimization (MIOpt) state not being 
preserved in some cases during lexing, which could suppress header-guard 
mismatch diagnostics and interfere with include-guard optimization. (#GH180155)
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to