https://github.com/hokein created https://github.com/llvm/llvm-project/pull/191734
During error recovery, a synthetic token (whose length is 0) can be inserted past the end of a FileID, e.g. inserting ")" when a macro-arg containing a comma should be guarded by parentheses. When calculating the location after this token, the calculated `AfterLoc` can point exactly to the start of the next FileID (`NextLocalOffset`), any source manager operations on the `AfterLoc` is invalid. This patch adds a safe guard in `Lexer::isAtEndOfMacroExpansion` to prevent passing this invalid location to `SourceManager`. Fixes #115007 Fixes #21755 >From a3c5022b8de4879073e2fb9c5c6bbcc68be2924e Mon Sep 17 00:00:00 2001 From: Haojian Wu <[email protected]> Date: Sun, 12 Apr 2026 22:47:58 +0200 Subject: [PATCH] [clang] Fix crash in isAtEndOfMacroExpansion at FileID boundary. --- clang/lib/Lex/Lexer.cpp | 16 +++++++++-- clang/test/Parser/macro-braces-recovery.cpp | 31 +++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 clang/test/Parser/macro-braces-recovery.cpp diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index 10246552bb13d..989c4e0cb7cef 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -920,8 +920,20 @@ bool Lexer::isAtEndOfMacroExpansion(SourceLocation loc, SourceLocation afterLoc = loc.getLocWithOffset(tokLen); SourceLocation expansionLoc; - if (!SM.isAtEndOfImmediateMacroExpansion(afterLoc, &expansionLoc)) - return false; + FileID FID = SM.getFileID(loc); + + if (SM.isInFileID(afterLoc, FID)) { + if (!SM.isAtEndOfImmediateMacroExpansion(afterLoc, &expansionLoc)) + return false; + } else { + // During error recovery, a zero-length synthetic token might be inserted + // past the end of the FileID, e.g. inserting ")" when a macro-arg + // containing a comma should be guarded by parentheses. In this case, + // afterLoc reaches the `NextLocalOffset` boundary, any operations on afterLoc will be invalid! + const SrcMgr::SLocEntry &Entry = SM.getSLocEntry(FID); + assert(Entry.isExpansion() && "Should be in an expansion"); + expansionLoc = Entry.getExpansion().getExpansionLocEnd(); + } if (expansionLoc.isFileID()) { // No other macro expansions. diff --git a/clang/test/Parser/macro-braces-recovery.cpp b/clang/test/Parser/macro-braces-recovery.cpp new file mode 100644 index 0000000000000..e8842f44bd623 --- /dev/null +++ b/clang/test/Parser/macro-braces-recovery.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace GH21755 { +#define M(x) f x // expected-note {{macro 'M' defined here}} + +// expected-error@+5 {{too many arguments provided to function-like macro invocation}} +// expected-note@+4 {{parentheses are required around macro argument containing braced initializer list}} +// expected-error@+3 {{a type specifier is required for all declarations}} +// expected-error@+2 {{expected ')'}} +// expected-note@+1 {{to match this '('}} +M(0 {,}) // expected-error {{expected ';' after top level declarator}} +} + +namespace GH115007 { +class Foo { // expected-note {{candidate constructor (the implicit copy constructor) not viable}} \ + // expected-note {{candidate constructor (the implicit move constructor) not viable}} +public: + Foo(int); // expected-note {{candidate constructor not viable: requires 1 argument, but 2 were provided}} + bool operator==(const int l); // expected-note {{candidate function not viable: no known conversion from 'Foo' to 'const int' for 1st argument}} +}; +#define EQ(x,y) (void)(x == y) // expected-note {{macro 'EQ' defined here}} + +void test_EQ() { + Foo F = Foo{1}; + // expected-error@+4 {{too many arguments provided to function-like macro invocation}} + // expected-note@+3 {{parentheses are required around macro argument containing braced initializer list}} + // expected-error@+2 {{no matching constructor for initialization of 'Foo'}} + // expected-error@+1 {{invalid operands to binary expression ('Foo' and 'Foo')}} + EQ(F,Foo{1,2}); +} +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
