Menu

syntaxError for __VA_ARGS__

Zufu Liu
2020-06-01
2020-06-02
  • Zufu Liu

    Zufu Liu - 2020-06-01
    extern int printf(const char *fmt, ...);
    #if defined(__GNUC__) || defined(__clang__)
    #define p1(fmt, ...)    printf((fmt), ##__VA_ARGS__)
    #else
    #define p1(fmt, ...)    printf((fmt), __VA_ARGS__)
    #endif
    
    void test() {
        p1("hello");
    }
    
    cppcheck.exe test.c
    Checking test.c ...
    test.c:9:5: error: syntax error [syntaxError]
        p1("hello");
        ^
    Checking test.c: __GNUC__;__clang__...
    
     
  • Daniel Marjamäki

    ok thanks.. is there some compiler that allows the code printf("hello",); ?

     
  • Zufu Liu

    Zufu Liu - 2020-06-01

    I think it's not supported by any compiler, but the macro expansion for p1("hello") is different than directly call printf("hello",), it's expanded into printf("hello") without trialling comma, though different compiler accepts different syntax on different platform.

    https://godbolt.org/z/x4X_BA

     
  • Daniel Marjamäki

    I am talking about the second macro because Cppcheck writes a syntax error when that is used:

    #define p1(fmt, ...)    printf((fmt), __VA_ARGS__)
    

    For that macro, the preprocessor should add the trailing comma as far as I know. For instance "gcc -E" outputs a comma when that macro is used.

    If it's not supported by any compiler, I am happy about the Cppcheck warning. If you only care about gcc/clang I suggest -f -D__GNUC__.

     
  • Zufu Liu

    Zufu Liu - 2020-06-01

    for following code:

    extern int printf(const char *fmt, ...);
    #define p1(fmt, ...)    printf((fmt), ##__VA_ARGS__)
    #define p2(fmt, ...)    printf((fmt), __VA_ARGS__)
    #define p3(fmt, ...)    printf((fmt) __VA_OPT__(,) __VA_ARGS__)
    
    void test() {
        p1("hello");
        p2("hello");
        p3("hello");
    }
    

    g++ -E test.cpp or gcc -x c -E test.cpp (with g++ 10.1 from msys2):

    # 1 "test.cpp"
    # 1 "<built-in>"
    # 1 "<command-line>"
    # 1 "test.cpp"
    extern int printf(const char *fmt, ...);
    
    void test() {
        printf(("hello"));
        printf(("hello"), );
        printf(("hello") );
    }
    

    clang++ -E test.cpp (Clang 11 Windows default target msvc):

    # 1 "test.cpp"
    # 1 "<built-in>" 1
    # 1 "<built-in>" 3
    # 367 "<built-in>" 3
    # 1 "<command line>" 1
    # 1 "<built-in>" 2
    # 1 "test.cpp" 2
    extern int printf(const char *fmt, ...);
    
    void test() {
        printf(("hello"));
        printf(("hello"));
        printf(("hello") __VA_OPT__(,) );
    }
    

    clang++ -E -std=c++20 test.cpp

    # 1 "test.cpp"
    # 1 "<built-in>" 1
    # 1 "<built-in>" 3
    # 394 "<built-in>" 3
    # 1 "<command line>" 1
    # 1 "<built-in>" 2
    # 1 "test.cpp" 2
    extern int printf(const char *fmt, ...);
    
    void test() {
        printf(("hello"));
        printf(("hello"));
        printf(("hello") );
    }
    

    cppcheck (master) shows syntax error for p2 and p3.

     
  • Daniel Marjamäki

    It seems to me that __VA_OPT__ should be handled in the preprocessor directly so I created https://github.com/danmar/simplecpp/issues/191 for that.

    Well for the other inconsistency it seems to me the standard compliant way is to keep the comma so maybe we should keep simplecpp as it is. maybe it's best that cppcheck removes the comma. I created ticket https://trac.cppcheck.net/ticket/9754 .

     
  • Daniel Marjamäki

    About removing the comma.. hmm that is a problem that we have not bumped into before and it's a deprecated feature. I spontaneosly feels that the payoff would not be that high for it.

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.