[clang-tools-extra] [clang-tidy] New checker: modernize-use-va-opt to replace the `, ##__VAR_ARG__` GNU extension (PR #188474)

via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 25 06:02:11 PDT 2026


github-actions[bot] wrote:

<!--PREMERGE ADVISOR COMMENT: Windows-->
# :window: Windows x64 Test Results

* 3111 tests passed
* 30 tests skipped
* 1 test failed

## Failed Tests
(click on a test name to see its output)

### Clang Tools
<details>
<summary>Clang Tools.clang-tidy/checkers/modernize/use-va-opt.cpp</summary>

```
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 1
C:/Python312/python.exe C:/_work/llvm-project/llvm-project/clang-tools-extra/test/../test\clang-tidy\check_clang_tidy.py -std=c++20-or-later C:\_work\llvm-project\llvm-project\clang-tools-extra\test\clang-tidy\checkers\modernize\use-va-opt.cpp modernize-use-va-opt C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp
# executed command: C:/Python312/python.exe 'C:/_work/llvm-project/llvm-project/clang-tools-extra/test/../test\clang-tidy\check_clang_tidy.py' -std=c++20-or-later 'C:\_work\llvm-project\llvm-project\clang-tools-extra\test\clang-tidy\checkers\modernize\use-va-opt.cpp' modernize-use-va-opt 'C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp'
# .---command stdout------------
# | Running ['clang-tidy', '--experimental-custom-checks', 'C:\\_work\\llvm-project\\llvm-project\\build\\tools\\clang\\tools\\extra\\test\\clang-tidy\\checkers\\modernize\\Output\\use-va-opt.cpp.tmp.cpp', '-fix', '--checks=-*,modernize-use-va-opt', '--config={}', '--', '-std=c++20', '-nostdinc++', '-isystem', 'C:\\_work\\llvm-project\\llvm-project\\clang-tools-extra\\test\\clang-tidy\\checkers\\Inputs\\Headers\\std']...
# | ------------------------ clang-tidy output -----------------------
# | 6 warnings generated.
# | 
# | C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp.cpp:8:26: warning: Use __VA_OPT__ instead of GNU extension to __VA_ARGS__ [modernize-use-va-opt]
# |     8 | #define M0(...) foo(1, ##__VA_ARGS__)
# |       |                      ~~~~^~~~~~~~~~~
# |       |                       __VA_OPT__(,) __VA_ARGS__
# | C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp.cpp:8:22: note: FIX-IT applied suggested code changes
# |     8 | #define M0(...) foo(1, ##__VA_ARGS__)
# |       |                      ^
# | C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp.cpp:12:27: warning: Use __VA_OPT__ instead of GNU extension to __VA_ARGS__ [modernize-use-va-opt]
# |    12 | #define M1(...) foo(1, ## __VA_ARGS__)
# |       |                      ~~~~~^~~~~~~~~~~
# |       |                       __VA_OPT__(,) __VA_ARGS__
# | C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp.cpp:12:22: note: FIX-IT applied suggested code changes
# |    12 | #define M1(...) foo(1, ## __VA_ARGS__)
# |       |                      ^
# | C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp.cpp:16:27: warning: Use __VA_OPT__ instead of GNU extension to __VA_ARGS__ [modernize-use-va-opt]
# |    16 | #define M2(...) foo(1 ,## __VA_ARGS__)
# |       |                       ~~~~^~~~~~~~~~~
# |       |                        __VA_OPT__(,) __VA_ARGS__
# | C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp.cpp:16:23: note: FIX-IT applied suggested code changes
# |    16 | #define M2(...) foo(1 ,## __VA_ARGS__)
# |       |                       ^
# | C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp.cpp:20:28: warning: Use __VA_OPT__ instead of GNU extension to __VA_ARGS__ [modernize-use-va-opt]
# |    20 | #define M3(...) foo(1 , ## __VA_ARGS__)
# |       |                       ~~~~~^~~~~~~~~~~
# |       |                        __VA_OPT__(,) __VA_ARGS__
# | C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp.cpp:20:23: note: FIX-IT applied suggested code changes
# |    20 | #define M3(...) foo(1 , ## __VA_ARGS__)
# |       |                       ^
# | C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp.cpp:25:28: warning: Use __VA_OPT__ instead of GNU extension to __VA_ARGS__ [modernize-use-va-opt]
# |    25 | #define M4(...) foo(1 , ## __VA_ARGS__, ## __VA_ARGS__)
# |       |                       ~~~~~^~~~~~~~~~~
# |       |                        __VA_OPT__(,) __VA_ARGS__
# | C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp.cpp:25:23: note: FIX-IT applied suggested code changes
# |    25 | #define M4(...) foo(1 , ## __VA_ARGS__, ## __VA_ARGS__)
# |       |                       ^
# | C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp.cpp:25:44: warning: Use __VA_OPT__ instead of GNU extension to __VA_ARGS__ [modernize-use-va-opt]
# |    25 | #define M4(...) foo(1 , ## __VA_ARGS__, ## __VA_ARGS__)
# |       |                                       ~~~~~^~~~~~~~~~~
# |       |                                        __VA_OPT__(,) __VA_ARGS__
# | C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp.cpp:25:39: note: FIX-IT applied suggested code changes
# | clang-tidy applied 6 of 6 suggested fixes.
# | 
# |    25 | #define M4(...) foo(1 , ## __VA_ARGS__, ## __VA_ARGS__)
# |       |                                       ^
# | 
# | ------------------------------------------------------------------
# | diff -u C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp.orig C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp.cpp failed:
# | --- C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp.orig	2026-03-25 13:00:59.503192200 +0000
# | +++ C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp.cpp	2026-03-25 13:00:59.534429400 +0000
# | @@ -5,24 +5,24 @@
# |  
# | 
# |  //
# | 
# |  //
# | 
# | -#define M0(...) foo(1, ##__VA_ARGS__)
# | 
# | +#define M0(...) foo(1 __VA_OPT__() __VA_ARGS__)
# | 
# |  
# | 
# |  //
# | 
# |  //
# | 
# | -#define M1(...) foo(1, ## __VA_ARGS__)
# | 
# | +#define M1(...) foo(1 __VA_OPT__() __VA_ARGS__)
# | 
# |  
# | 
# |  //
# | 
# |  //
# | 
# | -#define M2(...) foo(1 ,## __VA_ARGS__)
# | 
# | +#define M2(...) foo(1  __VA_OPT__() __VA_ARGS__)
# | 
# |  
# | 
# |  //
# | 
# |  //
# | 
# | -#define M3(...) foo(1 , ## __VA_ARGS__)
# | 
# | +#define M3(...) foo(1  __VA_OPT__() __VA_ARGS__)
# | 
# |  
# | 
# |  //
# | 
# |  //
# | 
# |  //
# | 
# | -#define M4(...) foo(1 , ## __VA_ARGS__, ## __VA_ARGS__)
# | 
# | +#define M4(...) foo(1  __VA_OPT__() __VA_ARGS__ __VA_OPT__() __VA_ARGS__)
# | 
# |  
# | 
# |  // No message, this will never add a comma before __VA_ARGS__
# | 
# |  #define P0(...) foo(1 ##__VA_ARGS__)
# | 
# | 
# | ------------------------------ Fixes -----------------------------
# | --- C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp.orig	2026-03-25 13:00:59.503192200 +0000
# | +++ C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp.cpp	2026-03-25 13:00:59.534429400 +0000
# | @@ -5,24 +5,24 @@
# |  
# | 
# |  //
# | 
# |  //
# | 
# | -#define M0(...) foo(1, ##__VA_ARGS__)
# | 
# | +#define M0(...) foo(1 __VA_OPT__() __VA_ARGS__)
# | 
# |  
# | 
# |  //
# | 
# |  //
# | 
# | -#define M1(...) foo(1, ## __VA_ARGS__)
# | 
# | +#define M1(...) foo(1 __VA_OPT__() __VA_ARGS__)
# | 
# |  
# | 
# |  //
# | 
# |  //
# | 
# | -#define M2(...) foo(1 ,## __VA_ARGS__)
# | 
# | +#define M2(...) foo(1  __VA_OPT__() __VA_ARGS__)
# | 
# |  
# | 
# |  //
# | 
# |  //
# | 
# | -#define M3(...) foo(1 , ## __VA_ARGS__)
# | 
# | +#define M3(...) foo(1  __VA_OPT__() __VA_ARGS__)
# | 
# |  
# | 
# |  //
# | 
# |  //
# | 
# |  //
# | 
# | -#define M4(...) foo(1 , ## __VA_ARGS__, ## __VA_ARGS__)
# | 
# | +#define M4(...) foo(1  __VA_OPT__() __VA_ARGS__ __VA_OPT__() __VA_ARGS__)
# | 
# |  
# | 
# |  // No message, this will never add a comma before __VA_ARGS__
# | 
# |  #define P0(...) foo(1 ##__VA_ARGS__)
# | 
# | 
# | ------------------------------------------------------------------
# | FileCheck --input-file=C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp.cpp C:\_work\llvm-project\llvm-project\clang-tools-extra\test\clang-tidy\checkers\modernize\use-va-opt.cpp --check-prefixes=CHECK-FIXES --match-full-lines failed:
# | C:\_work\llvm-project\llvm-project\clang-tools-extra\test\clang-tidy\checkers\modernize\use-va-opt.cpp:7:17: error: CHECK-FIXES: expected string not found in input
# | 
# | // CHECK-FIXES: #define M0(...) foo(1 __VA_OPT__(,) __VA_ARGS__)
# | 
# |                 ^
# | 
# | C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp.cpp:1:1: note: scanning from here
# | 
# | // RUN: %check_clang_tidy -std=c++20-or-later %s modernize-use-va-opt %t
# | 
# | ^
# | 
# | C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp.cpp:8:1: note: possible intended match here
# | 
# | #define M0(...) foo(1 __VA_OPT__() __VA_ARGS__)
# | 
# | ^
# | 
# | 
# | 
# | Input file: C:\_work\llvm-project\llvm-project\build\tools\clang\tools\extra\test\clang-tidy\checkers\modernize\Output\use-va-opt.cpp.tmp.cpp
# | 
# | Check file: C:\_work\llvm-project\llvm-project\clang-tools-extra\test\clang-tidy\checkers\modernize\use-va-opt.cpp
# | 
# | 
# | 
# | -dump-input=help explains the following input dump.
# | 
# | 
# | 
# | Input was:
# | 
# | <<<<<<
# | 
# |            1: // RUN: %check_clang_tidy -std=c++20-or-later %s modernize-use-va-opt %t 
# | 
# | check:7'0     X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: no match found
# | 
# |            2:  
# | 
# | check:7'0     ~
# | 
# |            3: extern void foo(...); 
# | 
# | check:7'0     ~~~~~~~~~~~~~~~~~~~~~~
# | 
# |            4:  
# | 
# | check:7'0     ~
# | 
# |            5:  
# | 
# | check:7'0     ~
# | 
# |            6: // 
# | 
# | check:7'0     ~~~
# | 
# |            7: // 
# | 
# | check:7'0     ~~~
# | 
# |            8: #define M0(...) foo(1 __VA_OPT__() __VA_ARGS__) 
# | 
# | check:7'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# | 
# | check:7'1     ?                                                possible intended match
# | 
# |            9:  
# | 
# | check:7'0     ~
# | 
# |           10: // 
# | 
# | check:7'0     ~~~
# | 
# |           11: // 
# | 
# | check:7'0     ~~~
# | 
# |           12: #define M1(...) foo(1 __VA_OPT__() __VA_ARGS__) 
# | 
# | check:7'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# | 
# |           13:  
# | 
# | check:7'0     ~
# | 
# |            .
# | 
# |            .
# | 
# |            .
# | 
# | >>>>>>
# | 
# | 
# `-----------------------------
# .---command stderr------------
# | Traceback (most recent call last):
# |   File "C:\_work\llvm-project\llvm-project\clang-tools-extra\test\clang-tidy\check_clang_tidy.py", line 554, in <module>
# |     main()
# |   File "C:\_work\llvm-project\llvm-project\clang-tools-extra\test\clang-tidy\check_clang_tidy.py", line 550, in main
# |     CheckRunner(args, extra_args).run()
# |   File "C:\_work\llvm-project\llvm-project\clang-tools-extra\test\clang-tidy\check_clang_tidy.py", line 432, in run
# |     self.check_fixes()
# |   File "C:\_work\llvm-project\llvm-project\clang-tools-extra\test\clang-tidy\check_clang_tidy.py", line 327, in check_fixes
# |     try_run(
# |   File "C:\_work\llvm-project\llvm-project\clang-tools-extra\test\clang-tidy\check_clang_tidy.py", line 64, in try_run
# |     process_output = subprocess.check_output(args, stderr=subprocess.STDOUT).decode(
# |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# |   File "c:\python312\Lib\subprocess.py", line 466, in check_output
# |     return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
# |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# |   File "c:\python312\Lib\subprocess.py", line 571, in run
# |     raise CalledProcessError(retcode, process.args,
# | subprocess.CalledProcessError: Command '['FileCheck', '--input-file=C:\\_work\\llvm-project\\llvm-project\\build\\tools\\clang\\tools\\extra\\test\\clang-tidy\\checkers\\modernize\\Output\\use-va-opt.cpp.tmp.cpp', 'C:\\_work\\llvm-project\\llvm-project\\clang-tools-extra\\test\\clang-tidy\\checkers\\modernize\\use-va-opt.cpp', '--check-prefixes=CHECK-FIXES', '--match-full-lines']' returned non-zero exit status 1.
# `-----------------------------
# error: command failed with exit status: 1

--

```
</details>

If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the `infrastructure` label.

https://github.com/llvm/llvm-project/pull/188474


More information about the cfe-commits mailing list