From: Bogdan Barbu Date: Tue, 4 Aug 2026 21:11:56 +0000 (+0000) Subject: runtime(c): compound literal braces are highlighted as errors X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;ds=sidebyside;p=thirdparty%2Fvim.git runtime(c): compound literal braces are highlighted as errors Problem: Braces in C compound literals and initializers inside parentheses and brackets are highlighted as errors. Solution: Recognize those initializer blocks while preserving syntax recovery for malformed parentheses. fixes: #18709 closes: #20842 Signed-off-by: Bogdan Barbu Signed-off-by: Christian Brabandt --- diff --git a/runtime/syntax/c.vim b/runtime/syntax/c.vim index 6838109520..9b18c2b8a1 100644 --- a/runtime/syntax/c.vim +++ b/runtime/syntax/c.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: C " Maintainer: The Vim Project -" Last Change: 2026 Jun 01 +" Last Change: 2026 Jul 25 " Former Maintainer: Bram Moolenaar " Quit when a (custom) syntax file was already loaded @@ -138,7 +138,7 @@ endif " This should be before cErrInParen to avoid problems with #define ({ xxx }) if exists("c_curly_error") syn match cCurlyError "}" - syn region cBlock start="{" end="}" contains=ALLBUT,cBadBlock,cCurlyError,@cParenGroup,cErrInParen,cCppParen,cErrInBracket,cCppBracket,@cStringGroup,@Spell fold + syn region cBlock start="{" end="}" contains=ALLBUT,cBadBlock,cCurlyError,cInitBlock,@cParenGroup,cErrInParen,cCppParen,cErrInBracket,cCppBracket,@cStringGroup,@Spell fold else syn region cBlock start="{" end="}" transparent fold endif @@ -146,7 +146,7 @@ endif " Catch errors caused by wrong parenthesis and brackets. " Also accept <% for {, %> for }, <: for [ and :> for ] (C99) " But avoid matching <::. -syn cluster cParenGroup contains=cParenError,cIncluded,cSpecial,cCommentSkip,cCommentString,cComment2String,@cCommentGroup,cCommentStartError,cUserLabel,cBitField,cOctalZero,@cCppOutInGroup,cFormat,cNumber,cFloat,cOctal,cOctalError,cNumbersCom +syn cluster cParenGroup contains=cParenError,cIncluded,cSpecial,cCommentSkip,cCommentString,cComment2String,@cCommentGroup,cCommentStartError,cUserLabel,cBitField,cOctalZero,@cCppOutInGroup,cFormat,cNumber,cFloat,cOctal,cOctalError,cNumbersCom,cBadParenBlock if exists("c_no_curly_error") if s:in_cpp_family && !exists("cpp_no_cpp11") syn region cParen transparent start='(' end=')' contains=ALLBUT,@cParenGroup,cCppParen,@cStringGroup,@Spell @@ -198,8 +198,15 @@ endif if s:ft ==# 'c' || exists("cpp_no_cpp11") syn region cBadBlock keepend start="{" end="}" contained containedin=cParen,cBracket,cBadBlock transparent fold + if !exists("c_no_curly_error") && !exists("c_no_bracket_error") + " Do not mistake an unmatched ')' followed by a block for a compound literal. + syn region cBadParenBlock keepend transparent start=')\_s*\ze\%({\|<%\)' matchgroup=cErrInBracket end='}\|%>' contained containedin=cBracket,cBadBlock contains=ALLBUT,cBlock,cBadBlock,cInitBlock,@cParenGroup,cErrInParen,cCppParen,cCppBracket,@cStringGroup,@Spell + endif endif +" Compound literals and initializers may appear inside parentheses or brackets. +syn region cInitBlock transparent matchgroup=cInitBlock start='\%([)=]\_s*\)\@<=\%({\|<%\)' end='}\|%>' contained containedin=cParen,cBracket,cBadBlock contains=ALLBUT,cBlock,cCurlyError,@cParenGroup,cErrInParen,cCppParen,cErrInBracket,cCppBracket,@cStringGroup,@Spell,cInitBlock fold + "integer number, or floating point number without a dot and with "f". syn case ignore syn match cNumbers display transparent "\<\d\|\.\d" contains=cNumber,cFloat,cOctalError,cOctal diff --git a/runtime/syntax/testdir/dumps/c_initializer_00.dump b/runtime/syntax/testdir/dumps/c_initializer_00.dump new file mode 100644 index 0000000000..426a1e9582 --- /dev/null +++ b/runtime/syntax/testdir/dumps/c_initializer_00.dump @@ -0,0 +1,20 @@ +>/+0#0000e05#ffffff0@1| |C|o|m|p|o|u|n|d| |l|i|t|e|r|a|l|s| |a|n|d| |i|n|i|t|i|a|l|i|z|e|r|s| |i|n|s|i|d|e| |e|x|p|r|e|s@1|i|o|n|s| +0#0000000&@18 +|v+0#00e0003&|o|i|d| +0#0000000&|t|e|s|t|(|v+0#00e0003&|o|i|d|)+0#0000000&| @59 +|{| @73 +@4|i+0#00e0003&|n|t| +0#0000000&|a|[|(|s+0#00e0003&|t|r|u|c|t| +0#0000000&|f|o@1|)|{| |4+0#e000002&|2| +0#0000000&|}|.|b|a|r|]|;| @40 +@4|s+0#00e0003&|t|r|u|c|t| +0#0000000&|f|o@1| |b| |=| |(@1|s+0#00e0003&|t|r|u|c|t| +0#0000000&|f|o@1|)|{| |}|)|;| @37 +@4|_+0#af5f00255&|S|t|a|t|i|c|_|a|s@1|e|r|t|(+0#0000000&|s+0#af5f00255&|i|z|e|o|f| +0#0000000&|(|i+0#00e0003&|n|t| +0#0000000&|[|]|)|{| |1+0#e000002&|,+0#0000000&| |2+0#e000002&|,+0#0000000&| |3+0#e000002&| +0#0000000&|}| |=@1| |3+0#e000002&| +0#0000000&|*| |s+0#af5f00255&|i|z|e|o|f| +0#0000000&|(|i+0#00e0003&|n|t|)+0#0000000&|,| |"+0#e000002&@1|)+0#0000000&|;| @3 +@4|f+0#af5f00255&|o|r| +0#0000000&|(|s+0#00e0003&|t|r|u|c|t| +0#0000000&|f|o@1| |i| |=| |{| |}|;@1|)| |b+0#af5f00255&|r|e|a|k|;+0#0000000&| @37 +@4|i+0#00e0003&|n|t| +0#0000000&|c|[|(|s+0#00e0003&|t|r|u|c|t| +0#0000000&|f|o@1|)| |<|%| |4+0#e000002&|2| +0#0000000&|%|>|.|b|a|r|]|;| @37 +@4|s+0#00e0003&|t|r|u|c|t| +0#0000000&|f|o@1| |d| |=| |(@1|s+0#00e0003&|t|r|u|c|t| +0#0000000&|f|o@1|)| |<|%| |%|>|)|;| @34 +@4|f|(@1|i+0#00e0003&|n|t| +0#0000000&|[|2+0#e000002&|]+0#0000000&|[|2+0#e000002&|]+0#0000000&|)|{@1| |1+0#e000002&|,+0#0000000&| |2+0#e000002&| +0#0000000&|}|,| |{| |3+0#e000002&|,+0#0000000&| |4+0#e000002&| +0#0000000&|}@1|)|;| @34 +@4|s|y|s|c|a|l@1|(|S|Y|S|_|c|l|o|c|k|_|s|e|t@1|i|m|e|,| |C|L|O|C|K|_|R|E|A|L|T|I|M|E|,| @28 +@8|t|v| |?| |&|(@1|s+0#00e0003&|t|r|u|c|t| +0#0000000&|t|i|m|e|s|p|e|c|)|{| |.|t|v|_|s|e|c| |=| |t|v|-|>|t|v|_|s|e|c|,| @19 +@12|.|t|v|_|n|s|e|c| |=| |t|v|-|>|t|v|_|u|s|e|c| |*| |1+0#e000002&|0@2| +0#0000000&|}|)| |:| |0+0#e000002&|)+0#0000000&|;| @24 +@4|f|(@1|s+0#00e0003&|t|r|u|c|t| +0#0000000&|t|i|m|e|s|p|e|c|)| @51 +@6|<|%| |.|t|v|_|s|e|c| |=| |0+0#e000002&| +0#0000000&|%|>|)|;| @49 +@4|i+0#00e0003&|n|t| +0#0000000&|e|[|)+0#ffffff16#ff404010|{| +0#0000000#ffffff0|4+0#e000002&|2| +0#0000000&|}+0#ffffff16#ff404010|.+0#0000000#ffffff0|b|a|r|]|;| @51 +@4|f|(|a| |{+0#ffffff16#ff404010| +0#0000000#ffffff0|1+0#e000002&| +0#0000000&|}+0#ffffff16#ff404010|)+0#0000000#ffffff0|;| |f|(|a|,| |{+0#ffffff16#ff404010| +0#0000000#ffffff0|1+0#e000002&| +0#0000000&|}+0#ffffff16#ff404010|)+0#0000000#ffffff0|;| @46 +|}| @73 +|~+0#4040ff13&| @73 +| +0#0000000&@56|1|,|1| @10|A|l@1| diff --git a/runtime/syntax/testdir/input/c_initializer.c b/runtime/syntax/testdir/input/c_initializer.c new file mode 100644 index 0000000000..a64747d46d --- /dev/null +++ b/runtime/syntax/testdir/input/c_initializer.c @@ -0,0 +1,18 @@ +// Compound literals and initializers inside expressions +void test(void) +{ + int a[(struct foo){ 42 }.bar]; + struct foo b = ((struct foo){ }); + _Static_assert(sizeof (int []){ 1, 2, 3 } == 3 * sizeof (int), ""); + for (struct foo i = { };;) break; + int c[(struct foo) <% 42 %>.bar]; + struct foo d = ((struct foo) <% %>); + f((int [2][2]){{ 1, 2 }, { 3, 4 }}); + syscall(SYS_clock_settime, CLOCK_REALTIME, + tv ? &((struct timespec){ .tv_sec = tv->tv_sec, + .tv_nsec = tv->tv_usec * 1000 }) : 0); + f((struct timespec) + <% .tv_sec = 0 %>); + int e[){ 42 }.bar]; + f(a { 1 }); f(a, { 1 }); +}