Unterminated argument list invoking macro: gcc vs. clang: error vs. no diagnostics

Viewed 33

Consider this code:

/* h2.h */
#define F()
F(

/* t10.c */
#include "h2.h"
)
int x; /* fix for "warning: ISO C requires a translation unit to contain at least one declaration" */

Invocation:

$ gcc t10.c -std=c11 -pedantic -Wall -Wextra -c
In file included from t10.c:1:
h2.h:2:3: error: unterminated argument list invoking macro "F"
    2 | F(
      |   ^
t10.c:2:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘)’ token
    2 | )
      | ^

$ clang t10.c -std=c11 -pedantic -Wall -Wextra -c
<nothing>

Who is correct? Does this code trigger UB?


UPD. Relevant quotes from C11:

5.1.1.2 Translation phases, 1:

A #include preprocessing directive causes the named header or source file to be processed from phase 1 through phase 4, recursively.

6.10.3 Macro replacement, 10:

The replaced sequence of preprocessing tokens is terminated by the matching ) preprocessing token, skipping intervening matched pairs of left and right parenthesis preprocessing tokens.

So, the source file h2.h processed from phase 1 through phase 4, and on phase 4 there is no matching ) preprocessing token. This is violation of semantics of 6.10.3 Macro replacement. However, per 5.1.1.3 Diagnostics violation of semantics does not require producing of any diagnostics. I see it this way. Is that correct?


UPD2. There is a constraint 6.10.3 Macro replacement, 4:

There shall exist a ) preprocessing token that terminates the invocation.

So, it is a constraint violation. Diagnostics is required.

0 Answers
Related