@@ -820,6 +820,88 @@ static void define_va_args_4() // cppcheck trac #9754
820820 ASSERT_EQUALS (" \n printf ( 1 , 2 )" , preprocess (code));
821821}
822822
823+ static void define_va_opt_1 ()
824+ {
825+ const char code[] = " #define p1(fmt, args...) printf(fmt __VA_OPT__(,) args)\n "
826+ " p1(\" hello\" );\n "
827+ " p1(\" %s\" , \" hello\" );\n " ;
828+
829+ ASSERT_EQUALS (" \n printf ( \" hello\" ) ;\n "
830+ " printf ( \" %s\" , \" hello\" ) ;" ,
831+ preprocess (code));
832+ }
833+
834+ static void define_va_opt_2 ()
835+ {
836+ const char code[] = " #define err(...)\\\n "
837+ " __VA_OPT__(\\\n "
838+ " printf(__VA_ARGS__);\\\n "
839+ " )\n "
840+ " #define err2(something, ...) __VA_OPT__(err(__VA_ARGS__))\n "
841+ " err2(test)\n "
842+ " err2(test, \" %d\" , 2)\n " ;
843+
844+ ASSERT_EQUALS (" \n\n\n\n\n\n printf ( \" %d\" , 2 ) ;" , preprocess (code));
845+ }
846+
847+ static void define_va_opt_3 ()
848+ {
849+ // non-escaped newline without closing parenthesis
850+ const char code1[] = " #define err(...) __VA_OPT__(printf( __VA_ARGS__);\n "
851+ " )\n "
852+ " err()" ;
853+
854+ simplecpp::OutputList outputList;
855+ ASSERT_EQUALS (" " , preprocess (code1, &outputList));
856+ ASSERT_EQUALS (" file0,1,syntax_error,failed to expand 'err', Missing parenthesis for __VA_OPT__(content)\n " ,
857+ toString (outputList));
858+
859+ outputList.clear ();
860+
861+ // non-escaped newline without open parenthesis
862+ const char code2[] = " #define err(...) __VA_OPT__\n "
863+ " (something)\n "
864+ " err()" ;
865+
866+ ASSERT_EQUALS (" " , preprocess (code2, &outputList));
867+ ASSERT_EQUALS (" file0,1,syntax_error,failed to expand 'err', Missing parenthesis for __VA_OPT__(content)\n " ,
868+ toString (outputList));
869+ }
870+
871+ static void define_va_opt_4 ()
872+ {
873+ // missing parenthesis
874+ const char code1[] = " #define err(...) __VA_OPT__ something\n "
875+ " err()" ;
876+
877+ simplecpp::OutputList outputList;
878+ ASSERT_EQUALS (" " , preprocess (code1, &outputList));
879+ ASSERT_EQUALS (" file0,1,syntax_error,failed to expand 'err', Missing parenthesis for __VA_OPT__(content)\n " ,
880+ toString (outputList));
881+
882+ outputList.clear ();
883+
884+ // missing open parenthesis
885+ const char code2[] = " #define err(...) __VA_OPT__ something)\n "
886+ " err()" ;
887+
888+ ASSERT_EQUALS (" " , preprocess (code2, &outputList));
889+ ASSERT_EQUALS (" file0,1,syntax_error,failed to expand 'err', Missing parenthesis for __VA_OPT__(content)\n " ,
890+ toString (outputList));
891+ }
892+
893+ static void define_va_opt_5 ()
894+ {
895+ // parenthesis not directly proceeding __VA_OPT__
896+ const char code[] = " #define err(...) __VA_OPT__ something (something)\n "
897+ " err()" ;
898+
899+ simplecpp::OutputList outputList;
900+ ASSERT_EQUALS (" " , preprocess (code, &outputList));
901+ ASSERT_EQUALS (" file0,1,syntax_error,failed to expand 'err', Missing parenthesis for __VA_OPT__(content)\n " ,
902+ toString (outputList));
903+ }
904+
823905static void define_ifdef ()
824906{
825907 const char code[] = " #define A(X) X\n "
@@ -2694,6 +2776,11 @@ int main(int argc, char **argv)
26942776 TEST_CASE (define_va_args_2);
26952777 TEST_CASE (define_va_args_3);
26962778 TEST_CASE (define_va_args_4);
2779+ TEST_CASE (define_va_opt_1);
2780+ TEST_CASE (define_va_opt_2);
2781+ TEST_CASE (define_va_opt_3);
2782+ TEST_CASE (define_va_opt_4);
2783+ TEST_CASE (define_va_opt_5);
26972784
26982785 // UB: #ifdef as macro parameter
26992786 TEST_CASE (define_ifdef);
0 commit comments