diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 0e9fcaa5fac6a..837ef80f07e87 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -282,6 +282,7 @@ Crash and bug fixes ^^^^^^^^^^^^^^^^^^^ - Fixed a crash in the static analyzer that when the expression in an ``[[assume(expr)]]`` attribute was enclosed in parentheses. (#GH151529) +- Fixed a crash when parsing ``#embed`` parameters with unmatched closing brackets. (#GH152829) Improvements ^^^^^^^^^^^^ diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 3fa060f7ec1bd..9d01b8d99e227 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -3793,9 +3793,13 @@ Preprocessor::LexEmbedParameters(Token &CurTok, bool ForHasEmbed) { [[fallthrough]]; case tok::r_brace: case tok::r_square: { + if (BracketStack.empty()) { + ExpectOrDiagAndSkipToEOD(tok::r_paren); + return false; + } tok::TokenKind Matching = GetMatchingCloseBracket(BracketStack.back().first); - if (BracketStack.empty() || CurTok.getKind() != Matching) { + if (CurTok.getKind() != Matching) { DiagMismatchedBracesAndSkipToEOD(Matching, BracketStack.back()); return false; } diff --git a/clang/test/Preprocessor/embed_parsing_errors.c b/clang/test/Preprocessor/embed_parsing_errors.c index 490ec6d4ded2c..a8bbdea91eb16 100644 --- a/clang/test/Preprocessor/embed_parsing_errors.c +++ b/clang/test/Preprocessor/embed_parsing_errors.c @@ -94,6 +94,9 @@ char buffer[] = { #embed "embed_parsing_errors.c" prefix() // OK: tokens within parens are optional #embed "embed_parsing_errors.c" prefix) // expected-error@-1 {{expected '('}} +#embed "embed_parsing_errors.c" prefix()) // expected-error {{expected identifier}} +#embed "embed_parsing_errors.c" prefix(]) // expected-error {{expected ')'}} +#embed "embed_parsing_errors.c" prefix(}) // expected-error {{expected ')'}} #embed "embed_parsing_errors.c" suffix // expected-error@-1 {{expected '('}} @@ -115,6 +118,9 @@ char buffer[] = { #embed "embed_parsing_errors.c" suffix() // OK: tokens within parens are optional #embed "embed_parsing_errors.c" suffix) // expected-error@-1 {{expected '('}} +#embed "embed_parsing_errors.c" suffix()) // expected-error {{expected identifier}} +#embed "embed_parsing_errors.c" suffix(]) // expected-error {{expected ')'}} +#embed "embed_parsing_errors.c" suffix(}) // expected-error {{expected ')'}} #embed "embed_parsing_errors.c" if_empty(1/0) // OK: emitted as tokens, not evaluated yet. #embed "embed_parsing_errors.c" if_empty(([{}])) // OK: delimiters balanced @@ -128,3 +134,6 @@ char buffer[] = { #embed "embed_parsing_errors.c" if_empty) // expected-error@-1 {{expected '('}} }; +#embed "embed_parsing_errors.c" if_empty()) // expected-error {{expected identifier}} +#embed "embed_parsing_errors.c" if_empty(]) // expected-error {{expected ')'}} +#embed "embed_parsing_errors.c" if_empty(}) // expected-error {{expected ')'}}