Porting preprocessor macros to be compatible with clang

Hello,

I am sorry to ask for some help on this subject but I am not very comfortable with preprocessor and especially with the differences between compilers.
We have some (ugly) macros used to generate some data structures and methods that works fine on Visual but I would like to use clang to get better errors messages
and to compare the compilation time.
So I have created a repository to reproduce the problem and if someone could give me some help...
There is only one cpp file so a simple clang++ TestClang.cpp is enough to reproduce.
The repository is here: GitHub - vricosti/FixMacroOnClang

Thanks.

I think you’re going to have to give us more information about what the problem is that you’re seeing and what is the behaviour you expected.

So a bit more explanation, the macros are used to generate data structure and methods and the following definition is used to declare a structure:

DEF_STRUCT(namedDate, namedDate, (std::string, name), (std::time_t, date))

On visual when I look at preprocessed file I get this (focus on line starting with struct namedDate) :

namespace LibTech
{
    namespace DataTypes
    {
       #line 1 "E:\\DEV\\FixMacroOnClang\\DeclareDatatypes.h"
       #line 17 "E:\\DEV\\FixMacroOnClang\\DeclareDatatypes.h"
       #line 12 "E:\\DEV\\FixMacroOnClang\\Protocol.h"
       #line 1 "E:\\DEV\\FixMacroOnClang\\DataTypesDef.h"

struct namedDate{ std::string name; std::time_t date; };

       #line 13 "E:\\DEV\\FixMacroOnClang\\Protocol.h"
       #line 1 "E:\\DEV\\FixMacroOnClang\\DeclareDatatypes.h"
    #line 1 "E:\\DEV\\FixMacroOnClang\\macro\\UndefDataTypesDef.h"
    #line 14 "E:\\DEV\\FixMacroOnClang\\DeclareDatatypes.h"
    #line 17 "E:\\DEV\\FixMacroOnClang\\DeclareDatatypes.h"
    #line 14 "E:\\DEV\\FixMacroOnClang\\Protocol.h"
    }

}

but when using clang I have this:

namespace LibTech
{
    namespace DataTypes
    {
       # 1 "E:\\DEV\\FixMacroOnClang/DeclareDatatypes.h" 1
       # 12 "E:\\DEV\\FixMacroOnClang/Protocol.h" 2
       # 1 "E:\\DEV\\FixMacroOnClang/DataTypesDef.h" 1

struct namedDate{ PP_GS 2 (TO_FIELD, (std::string, name), (std::time_t, date)) };

       # 13 "E:\\DEV\\FixMacroOnClang/Protocol.h" 2
       # 1 "E:\\DEV\\FixMacroOnClang/DeclareDatatypes.h" 1
       # 13 "E:\\DEV\\FixMacroOnClang/DeclareDatatypes.h"
       # 1 "E:\\DEV\\FixMacroOnClang/./macro/UndefDataTypesDef.h" 1
       # 14 "E:\\DEV\\FixMacroOnClang/DeclareDatatypes.h" 2
       # 14 "E:\\DEV\\FixMacroOnClang/Protocol.h" 2
  }
}

as you can see the macros used inside preprocessor.h doesn't work with clang I have macro PP_GS and TO_FIELD macros that are not expanded.

I cannot copy/paste all macro definitions because it won't be very easy to read but here is how it starts:

#ifndef DEF_ID_BEGIN

//...

#define TO_FIELD(type, name) type name;
#define DEF_STRUCT(type, dataTypeId, ...) struct type{ PP_FOREACH_GROUP(TO_FIELD,__VA_ARGS__) };

#else

#include "./macro/UndefDataTypesDef.h"
#undef TO_FIELD

#endif

and inside preprocessor.h

#define PP_PREFIX(Method) PP_##Method
#define PP_SUFFIX(N) N
#define PP_ENTRY(Method,N) PP_PREFIX(Method)PP_SUFFIX(N)
#define PP_CALL_PP_SN( Method, Func, N, ...) PP_ENTRY(Method,N) PP_FW(Func, __VA_ARGS__)

#define PP_FOREACH(Func, ...) PP_CALL_PP_SN( S, Func, PP_ARGCOUNT PP_FW(__VA_ARGS__), __VA_ARGS__ )
#define PP_FOREACH_GROUP(Func, ...) PP_CALL_PP_SN( GS, Func, PP_ARGCOUNT PP_FW(__VA_ARGS__), __VA_ARGS__ )

#define PP_RSEQ_N()\
63 ,62 ,61 ,60 ,\
59 ,58 ,57 ,56 ,55 ,54 ,53 ,52 ,51 ,50 ,\
49 ,48 ,47 ,46 ,45 ,44 ,43 ,42 ,41 ,40 ,\
39 ,38 ,37 ,36 ,35 ,34 ,33 ,32 ,31 ,30 ,\
29 ,28 ,27 ,26 ,25 ,24 ,23 ,22 ,21 ,20 ,\
19 ,18 ,17 ,16 ,15 ,14 ,13 ,12 ,11 ,10 ,\
9,8,7,6,5,4,3,2,1,0

#define PP_ARG_N( \
_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 ,_33 ,_34 ,_35 ,_36 ,_37 ,_38 ,_39 ,_40 ,\
_41 ,_42 ,_43 ,_44 ,_45 ,_46 ,_47 ,_48 ,_49 ,_50 ,\
_51 ,_52 ,_53 ,_54 ,_55 ,_56 ,_57 ,_58 ,_59 ,_60 ,\
_61 ,_62 ,_63 , N , ...) N

#define PP_FW(...) (__VA_ARGS__)
#define PP_NARG_(...) PP_ARG_N PP_FW(__VA_ARGS__)
#define PP_ARGCOUNT(...) PP_NARG_(__VA_ARGS__,PP_RSEQ_N())

but have a look here to see all the macros: https://github.com/vrichomme/FixMacroOnClang/blob/master/preprocessor.h

Maybe one of the problem is with PP_FW(...) but not sure about that...

Thanks

It seems like there are two problems: (1) TO_FIELD comes out with a trailing comma and so does not get expanded and (2) PP_GS and 2 tokens are not joined which would also impeded further expansion. I would expect to see a further ## somewhere in your macros. It looks like you’re using 0 when maybe you want something more like 1?