Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.

__VA__ARGS__ substitution problem with Intel 13.0 Update 1

Bernhard_B_
Novice
643 Views

Hello,

with Intel(R) Composer XE 2013 Update 1 (package 119) the behaviour of the preprocessor with __VA_ARGS__ has changed unter Windows (Visual Studio 2010 mode).
It seems that the __VA_ARGS__ arguments are inserted now as one argument although they are seperated by commas. Therefore the following preprocessor commands behave differently with the new version as before with Intel Composer XE 2011 Update 13 (package 371). 

[cpp]
#define BOOST_PP_VARIADICS_MSVC 1
#define BOOST_PP_VARIADICS
#include <boost/preprocessor/variadic/size.hpp>


#define ENUMTEXT_ARGUMENT(xxx) { xxx , #xxx }
#define ENUMTEXT_A1(xxx) ENUMTEXT_ARGUMENT(xxx)
#define ENUMTEXT_A2(xxx, ...) ENUMTEXT_ARGUMENT(xxx), BOOST_PP_CAT(ENUMTEXT_A, BOOST_PP_VARIADIC_SIZE(__VA_ARGS__))( __VA_ARGS__ )


#define ENUMTEXT_LIST(...) BOOST_PP_CAT(ENUMTEXT_A, BOOST_PP_VARIADIC_SIZE(__VA_ARGS__))(__VA_ARGS__)
#define ENUMTEXT(xxx) ENUMTEXT_LIST(xxx)


ENUMTEXT_LIST(Test, Test2)
[/cpp]
I used the following command to compile it: icl /Qms0 /P meow.cpp /IF:\Libs\boost_1_50_0 

It generates the output:

[cpp]
#line 1 "meow.cpp"
#line 1 "F:\\Libs\\boost_1_50_0\\boost/preprocessor/variadic/size.hpp"
#line 1 "F:\\Libs\\boost_1_50_0\\boost/preprocessor/cat.hpp"
#line 1 "F:\\Libs\\boost_1_50_0\\boost/preprocessor/config/config.hpp"
#line 18 "F:\\Libs\\boost_1_50_0\\boost/preprocessor/cat.hpp"
#line 17 "F:\\Libs\\boost_1_50_0\\boost/preprocessor/variadic/size.hpp"
#line 1 "F:\\Libs\\boost_1_50_0\\boost/preprocessor/config/config.hpp"
#line 18 "F:\\Libs\\boost_1_50_0\\boost/preprocessor/variadic/size.hpp"
#line 4 "meow.cpp"

{ Test, Test2 , "Test, Test2" }, { , }

[/cpp]

Before it was:

{ Test , "Test" }, { Test2 , "Test2" }

Is the new behaviour the corret one?
Thanks in advance.

0 Kudos
7 Replies
Judith_W_Intel
Employee
643 Views
If it matches the Microsoft compiler then it it correct. I believe that this is the relevant desription of the change: Microsoft compatibility: commas in macro arguments The Microsoft preprocessor gives special treatment to commas appearing in the substituted text of macro arguments: if that text appears as a macro argument when rescanned for further expansion, such commas do not delimit macro arguments. The front end has now been modified to emulate this behavior. For example: #define M1(a) M2(a) #define M2(a) a #define XY x,y M1(XY) // Formerly warned of "too many arguments" and expanded to "x" // Now expands to "x,y" with no warning
0 Kudos
Judith_W_Intel
Employee
643 Views
This change was necesary in order to be able to compile almost any of the C++ standard library headers that are supplied with MSVC++ 2012 so changing the behaviour under /Qms0 to be non Microsoft compatible would probably render that switch useless.
0 Kudos
tpucke
Beginner
643 Views

"If it matches the Microsoft compiler then it it correct."

Thank you for that beautifully disappointing response!  So now Microsoft defines correctness in the compiler universe simply by releasing some library headers?  There are some excellent code examples scattered around the web that now won't build because of this.  Nowhere in your response do you mention what the C++ standard might have to say on the subject.  I would be fine with the consequences if I knew that the change was correct and not just convenient. 

I ran into this issue this week and have spent the last 2 days trying to figure out why my legacy library that worked using your 12.1 compiler was now broken with the upgrade to compiler 2013.5.198.  Microsoft clearly acknowledged this 4 years ago as a bug in their own compiler.  Of course they also said at that time they wouldn't be fixing it; at least they were correct about that part.  See it here:

http://connect.microsoft.com/VisualStudio/feedback/details/521844/variadic-macro-treating-va-args-as-a-single-parameter-for-other-macros#details

Just to be clear, this makes it not possible to use variadic macro parameters as arguments to nested macros.  If there is a general purpose workaround it would be helpful to see it posted here. 

0 Kudos
Bernhard_B_
Novice
643 Views

I worked around it use an indirection, so the above example works with:

<cpp>

#define BOOST_PP_VARIADICS_MSVC 1
#define BOOST_PP_VARIADICS
#include <boost/preprocessor/variadic/size.hpp>

#define ENUMTEXT_INDIREKT(yyy, xxx) yyy xxx
#define ENUMTEXT_INDIREKT2(yyy, xxx) yyy xxx

#define ENUMTEXT_ARGUMENT(xxx) { xxx , #xxx }
#define ENUMTEXT_A1(xxx) ENUMTEXT_ARGUMENT(xxx)
#define ENUMTEXT_A2(xxx, ...) ENUMTEXT_ARGUMENT(xxx), ENUMTEXT_A1( __VA_ARGS__ )
#define ENUMTEXT_A3(xxx, ...) ENUMTEXT_ARGUMENT(xxx), ENUMTEXT_INDIREKT2(ENUMTEXT_A2, ( __VA_ARGS__ ))
#define ENUMTEXT_LIST(...) ENUMTEXT_INDIREKT(BOOST_PP_CAT(ENUMTEXT_A, BOOST_PP_VARIADIC_SIZE(__VA_ARGS__)), (__VA_ARGS__))
#define ENUMTEXT(xxx) ENUMTEXT_LIST(xxx)

ENUMTEXT_LIST(Test, Test2, Test3)

</cpp>

The difference is the additional ENUMTEXT_INDIREKT macro and the additional braces around __VA_ARGS__. I couldn't get the recursion to work with one ENUMTEXT_INDIREKT macro. So i introduced ENUMTEXT_INDIREKT2 to workaround that problem.
 In the end it produces the correct output:
<cpp>

#line 1 "meow.cpp"
#line 1 "E:\\Libs\\boost_1_54_0\\boost/preprocessor/variadic/size.hpp"
#line 1 "E:\\Libs\\boost_1_54_0\\boost/preprocessor/cat.hpp"
#line 1 "E:\\Libs\\boost_1_54_0\\boost/preprocessor/config/config.hpp"
#line 18 "E:\\Libs\\boost_1_54_0\\boost/preprocessor/cat.hpp"
#line 17 "E:\\Libs\\boost_1_54_0\\boost/preprocessor/variadic/size.hpp"
#line 1 "E:\\Libs\\boost_1_54_0\\boost/preprocessor/config/config.hpp"
#line 18 "E:\\Libs\\boost_1_54_0\\boost/preprocessor/variadic/size.hpp"
#line 4 "meow.cpp"


#line 14 "meow.cpp"

{ Test , "Test" }, { Test2 , "Test2" }, { Test3 , "Test3" }
</cpp> 

 

0 Kudos
SergeyKostrov
Valued Contributor II
643 Views
>>...I worked around it use an indirection, so the above example works... For both C++ compilers, or for Intel only? If Yes, please provide information for versions ( including Release dates ) of Intel and Microsoft C++ compilers you've used for verification. Thanks.
0 Kudos
Bernhard_B_
Novice
643 Views

Works with Microsoft Compiler 2008, 2010, 2012 and following Intel Compilers Intel Composer XE 2011 Update 13 and Intel(R) Composer XE 2013 Update 5

0 Kudos
SergeyKostrov
Valued Contributor II
643 Views
>>...Works with Microsoft Compiler 2008, 2010, 2012 and following Intel Compilers Intel Composer XE 2011 Update 13 and >>Intel(R) Composer XE 2013 Update 5... Thank you.
0 Kudos
Reply