What are the deviations between preprocessors of GCC/CLANG vs MSVC?

匆匆过客 提交于 2019-12-23 18:34:28

问题


The following preprocessor macros (the usual suspects: testing on empty argument list and counting number of arguments) run without warnings on gcc/clang but fail on Microsoft VisualC:

// IS_EMPTY() returns nothing if the parameter list is empty and a single ',' (comma) otherwise.
// The parameter list can have up to 32 parameters
#define IS_EMPTY(...) IS_EMPTY1(__VA_ARGS__)
#define IS_EMPTY1(...) IS_EMPTY2(DROP_PARAMS  __VA_ARGS__ (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,EMPTY))
#define IS_EMPTY2(...) IS_EMPTY3(__VA_ARGS__)
#define IS_EMPTY3(f,...) TEST_EMPTY_##f )
#define DROP(...)
#define DROP_PARAMS(...) DROP_PARAMS1(__VA_ARGS__,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,)
#define DROP_PARAMS1(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,__m,...) CATCH_##__m
#define TEST_EMPTY_DROP_PARAMS , DROP(
#define TEST_EMPTY_CATCH_EMPTY DROP(
#define TEST_EMPTY_CATCH_ , DROP(


//--- testcode below ---
#define TEST_EMPTY(...) __VA_ARGS__ : TAKE_2ND(IS_EMPTY(__VA_ARGS__) not,) empty
#define TAKE_2ND(...) TAKE_2ND_(__VA_ARGS__,,)
#define TAKE_2ND_(f,s,...) s

TEST_EMPTY()
TEST_EMPTY(a.b.)
TEST_EMPTY(A)
TEST_EMPTY(())
TEST_EMPTY(int()(more))
TEST_EMPTY((int))
TEST_EMPTY(foo bar)
TEST_EMPTY(*)

#define FOO(x) x
#define BAR
TEST_EMPTY(FOO(BAR))
TEST_EMPTY(1,2)
TEST_EMPTY(1.)
TEST_EMPTY(.1)
TEST_EMPTY(1,)
TEST_EMPTY((int)(float))
TEST_EMPTY(() this)
TEST_EMPTY(() is, () not ()  empty ())
TEST_EMPTY(,notempty)
TEST_EMPTY((),notempty)
TEST_EMPTY((1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,))

Output on clang & gcc:

: empty
a.b. : not empty
A : not empty
() : not empty
int()(more) : not empty
(int) : not empty
foo bar : not empty
* : not empty



: empty
1,2 : not empty
1. : not empty
.1 : not empty
1, : not empty
(int)(float) : not empty
() this : not empty
() is, () not () empty () : not empty
,notempty : not empty
(),notempty : not empty
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,) : not empty

Output on MSVC:

 :  empty
a.b. :  empty
A :  empty
() :  empty
int()(more) :  empty
(int) :  empty
foo bar :  empty
* :  empty



 :  empty
1,2 :  empty
1. :  empty
.1 :  empty
1, :  empty
(int)(float) :  empty
() this :  empty
() is, () not () empty () :  empty
,notempty :  empty
(),notempty :  empty
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,) :  empty

As MSVC is completely silent, I wonder how far off my solution is. Or is it rather MSVC which is not behaving correctly?


回答1:


Microsoft's Visual C++ preprocessor has known compliance issues.

They have rewritten the preprocessor but the old one is enabled by default. To enable the, hopefully more compliant one select this option:

/experimental:preprocessor

Starting with the Visual Studio 2017 15.8 Preview 3 release.

I ran the macros using the option: /experimental:preprocessor on the latest released version 15.8.9, with the following results:

: empty
a.b. : not empty
A : not empty
() : not empty
int()(more) : not empty
(int) : not empty
foo bar : not empty
* : not empty


: empty
1, 2 : not empty
1. : not empty
.1 : not empty
1, : not empty
(int)(float) : not empty
() this : not empty
() is, () not () empty() : not empty
, notempty : not empty
(), notempty : not empty
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, ) : not empty

The erroneous "empty" is now "not empty" and is consistent with GCC and Clang' preprocessors.



来源:https://stackoverflow.com/questions/53159137/what-are-the-deviations-between-preprocessors-of-gcc-clang-vs-msvc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!