llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Oleksandr Tarasiuk (a-tarasyuk)

<details>
<summary>Changes</summary>

Fixes #<!-- -->178635

---

This PR addressed the issue when header-name _lexing_ reentered on nested macro 
expansion.

`__has_include`/`__has_embed` lex a header name by calling `LexHeaderName`, and 
neither expects nested expansion in that context.

If `__has_include` appears inside the header name expression (e.g., 
`__has_include(__has_include)`, or `__has_embed(__has_include)`)

https://github.com/llvm/llvm-project/blob/6a18039298174562a38f28ca06d12dcbf7f14f06/clang/lib/Lex/PPMacroExpansion.cpp#L1252

macro expansion reenters `LexHeaderName` and hits the assertion

https://github.com/llvm/llvm-project/blob/6a18039298174562a38f28ca06d12dcbf7f14f06/clang/lib/Lex/PPMacroExpansion.cpp#L1898

https://github.com/llvm/llvm-project/blob/6a18039298174562a38f28ca06d12dcbf7f14f06/clang/lib/Lex/PPMacroExpansion.cpp#L1156



---
Full diff: https://github.com/llvm/llvm-project/pull/179151.diff


4 Files Affected:

- (modified) clang/docs/ReleaseNotes.rst (+1) 
- (modified) clang/lib/Lex/Preprocessor.cpp (+9-3) 
- (modified) clang/test/Preprocessor/embed___has_embed_parsing_errors.c (+11) 
- (modified) clang/test/Preprocessor/has_include.c (+10) 


``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2e7a9fff3161b..4f75f744089ef 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -221,6 +221,7 @@ Bug Fixes in This Version
 - Fix lifetime extension of temporaries in for-range-initializers in 
templates. (#GH165182)
 - Fixed a preprocessor crash in ``__has_cpp_attribute`` on incomplete scoped 
attributes. (#GH178098)
 - Fixes an assertion failure when evaluating ``__underlying_type`` on enum 
redeclarations. (#GH177943)
+- Fixed an assertion failure caused by nested macro expansion during 
header-name lexing (``__has_embed(__has_include)``). (#GH178635)
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp
index 791a9644b6e85..6abcf37079798 100644
--- a/clang/lib/Lex/Preprocessor.cpp
+++ b/clang/lib/Lex/Preprocessor.cpp
@@ -1041,10 +1041,16 @@ void Preprocessor::LexTokensUntilEOF(std::vector<Token> 
*Tokens) {
 bool Preprocessor::LexHeaderName(Token &FilenameTok, bool AllowMacroExpansion) 
{
   // Lex using header-name tokenization rules if tokens are being lexed from
   // a file. Just grab a token normally if we're in a macro expansion.
-  if (CurPPLexer)
-    CurPPLexer->LexIncludeFilename(FilenameTok);
-  else
+  if (CurPPLexer) {
+    // Avoid nested header-name lexing when macro expansion recurses
+    // __has_include(__has_include))
+    if (CurPPLexer->ParsingFilename)
+      LexUnexpandedToken(FilenameTok);
+    else
+      CurPPLexer->LexIncludeFilename(FilenameTok);
+  } else {
     Lex(FilenameTok);
+  }
 
   // This could be a <foo/bar.h> file coming from a macro expansion.  In this
   // case, glue the tokens together into an angle_string_literal token.
diff --git a/clang/test/Preprocessor/embed___has_embed_parsing_errors.c 
b/clang/test/Preprocessor/embed___has_embed_parsing_errors.c
index 4c6b03069c518..d9f78fa82ecce 100644
--- a/clang/test/Preprocessor/embed___has_embed_parsing_errors.c
+++ b/clang/test/Preprocessor/embed___has_embed_parsing_errors.c
@@ -292,3 +292,14 @@ int a = __has_embed (__FILE__);
    expected-error@+2 {{expected value in expression}}
 #if __has_embed("" limit
 #endif
+
+// expected-error@+2 {{missing '(' after '__has_include'}}
+// expected-error@+1 {{expected "FILENAME" or <FILENAME>}}
+#if __has_embed(__has_include)
+#endif
+
+// expected-error@+3 {{missing '(' after '__has_embed'}}
+// expected-error@+2 {{expected value in expression}}
+// expected-error@+1 {{expected "FILENAME" or <FILENAME>}}
+#if __has_embed(__has_embed)
+#endif
diff --git a/clang/test/Preprocessor/has_include.c 
b/clang/test/Preprocessor/has_include.c
index ff199bf23063f..13f9d99b3c080 100644
--- a/clang/test/Preprocessor/has_include.c
+++ b/clang/test/Preprocessor/has_include.c
@@ -148,6 +148,16 @@ MACRO1  // This should be fine because it is never 
actually reached
 #if __has_include(stdint.h>)
 #endif
 
+// expected-error@+2 {{missing '(' after '__has_include'}}
+// expected-error@+1 {{expected "FILENAME" or <FILENAME>}}
+#if __has_include(__has_include)
+#endif
+
+// expected-error@+2 {{missing '(' after '__has_embed'}}
+// expected-error@+1 {{expected "FILENAME" or <FILENAME>}}
+#if __has_include(__has_embed)
+#endif
+
 // expected-error@+1 {{'__has_include' must be used within a preprocessing 
directive}}
 __has_include
 

``````````

</details>


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

Reply via email to