1

MSVC uses the traditional preprocessor by default.

When this preprocessor is executed with the /EP command line switch and it invokes the following concatenating macro CONCAT(aa,bb,cc), it generates the correct output:

aabbcc

... but it also generates this undesirable warning:

Warning C4003: not enough arguments for function-like macro invocation 'CONCAT'

See the online simulation here.

The CONCAT() macro is defined below ( it can be invoked with an arbitrary number of arguments ):

#if !defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL

#pragma warning( push )
#pragma warning( disable : 4003 )
#define CONCAT_(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z) A##B##C##D##E##F##G##H##I##J##K##L##M##N##O##P##Q##R##S##T##U##V##W##X##Y##Z
#define CONCAT(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z) CONCAT_(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z)
#pragma warning( pop )

#else

#define CONCAT_EVAL1(...) __VA_ARGS__
#define CONCAT_EVAL2(...) CONCAT_EVAL1(CONCAT_EVAL1(CONCAT_EVAL1(CONCAT_EVAL1(__VA_ARGS__))))
#define CONCAT_EVAL3(...) CONCAT_EVAL2(CONCAT_EVAL2(CONCAT_EVAL2(CONCAT_EVAL2(__VA_ARGS__))))
#define CONCAT_EVAL4(...) CONCAT_EVAL3(CONCAT_EVAL3(CONCAT_EVAL3(CONCAT_EVAL3(__VA_ARGS__))))
#define CONCAT_EVAL5(...) CONCAT_EVAL4(CONCAT_EVAL4(CONCAT_EVAL4(CONCAT_EVAL4(__VA_ARGS__))))

#define CONCAT_EMPTY()

#define CONCAT_TUPLE_AT_1(a,b,...) b
#define CONCAT_CHECK(...) CONCAT_TUPLE_AT_1(__VA_ARGS__)
#define CONCAT_PROBE(...) ,CONCAT_END,

#define CONCAT_IND() CONCAT_
#define CONCAT_(x,a,...) CONCAT_CHECK(CONCAT_PROBE a,CONCAT_NEXT)(x,a,__VA_ARGS__)
#define CONCAT_NEXT(x,a,...) CONCAT_IND CONCAT_EMPTY()()(x##a,__VA_ARGS__)
#define CONCAT_END(x,a,...) x

#define CONCAT(...) CONCAT_EVAL5(CONCAT_(,__VA_ARGS__,()))

#endif

Of course, when the standard conforming preprocessor is invoked with the /Zc:preprocessor command line switch, then the condition #if !defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL fails and the offending code is not expanded and the warning C4003 is not generated.

Notice, that if the /EP switch is not in effect, then the warning C4003 can be disabled for the macro invocation with #pragma warning( disable : 4003 ).
See this online simulation.
...but as soon as you add the /EP switch to the compiler's options, this warning reappears!

QUESTION: How to disable this warning in the traditional preprocessor for just this concatenating macro when the /EP switch is in effect ...or how to alter this macro so it does not generate that warning with the traditional preprocessor and the /EP switch ?

NOTE:
Please do not suggest using the global switch /wd"4003" to disable this warning everywhere, because this warning is needed to check other macros in other code.

1 Answers1

-1

C4003 question was mentioned a long time ago. The experimental preprocessor also treats it as an error.

there is no way to tell VC not to issue a warning when pasing empty arguments to macro parameters, short of suppressing C4003 warning altogether, in all cases.

Minxin Yu - MSFT
  • 2,234
  • 1
  • 3
  • 14
  • But the preprocessor does **not** treat fewer macro arguments as an error - it treats it as a warning. I have a problem that I cannot disable this warning with anything else but a global switch when the `/EP` switch is in effect. The 11 year old discussion, which you had linked to, was discussing the inability to turn this warning into an error - a different issue ...albeit related. – Pavel Stepanek Dec 09 '22 at 09:43
  • According to the [thread](https://stackoverflow.com/questions/54250808/how-to-disable-a-warning-within-a-c-macro), warning 4307 can be disabled, but 4003 not work. You can report the problem to [Developer Community](https://developercommunity.visualstudio.com/cpp)`#define TIMES_A_MILLION(x,b) \ __pragma (warning(suppress: 4003)) \ __pragma (warning(suppress: 4307)) \ x * 1000000` – Minxin Yu - MSFT Dec 16 '22 at 08:17
  • I am afraid of the `Developer Community`. It is full of MSFTs... – Pavel Stepanek Dec 17 '22 at 22:59