https://github.com/thorsten-klein updated 
https://github.com/llvm/llvm-project/pull/180700

>From e22206b6053d311fbb84f931b9156a5e37372af1 Mon Sep 17 00:00:00 2001
From: Thorsten Klein <[email protected]>
Date: Mon, 9 Feb 2026 14:35:47 +0100
Subject: [PATCH] [clang][Lexer] Save and restore MIOpt in peekNextPPToken()

Fixes issue #180155 which is caused by peekNextPPToken() not saving and
restoring the MIOpt state when peeking ahead at tokens.

When processing C++20 code, peekNextPPToken() is called on the main file
to check the first token. Inside peekNextPPToken(), the Lex() call
modifies the MIOpt state machine by calling ReadToken(), which sets
ReadAnyTokens=true.
Without proper save/restore, this corrupts the MIOpt state for the file
being lexed.

The corruption can prevent include guard detection. If ReadAnyTokens is
already true from the peek, EnterTopLevelIfndef is not called, and the
controlling macro is not recorded.
---
 clang/lib/Lex/Lexer.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index 1498657047bd6..2215a2c623bab 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -3233,6 +3233,7 @@ std::optional<Token> Lexer::peekNextPPToken() {
   bool atStartOfLine = IsAtStartOfLine;
   bool atPhysicalStartOfLine = IsAtPhysicalStartOfLine;
   bool leadingSpace = HasLeadingSpace;
+  MultipleIncludeOpt SavedMIOpt = MIOpt;
 
   Token Tok;
   Lex(Tok);
@@ -3243,6 +3244,7 @@ std::optional<Token> Lexer::peekNextPPToken() {
   HasLeadingSpace = leadingSpace;
   IsAtStartOfLine = atStartOfLine;
   IsAtPhysicalStartOfLine = atPhysicalStartOfLine;
+  MIOpt = SavedMIOpt;
   // Restore the lexer back to non-skipping mode.
   LexingRawMode = false;
 

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

Reply via email to