Hi dear all,
Look at the following code
#include <stdio.h>
#define STR(a,b) a##b
void test()
{
printf("%s\n" , STR("1","2"));
}
compiled with clang -c test2.cpp will failed with following error:
test2.cpp:9:18: error: pasting formed '"1""2"', an invalid preprocessing token
[-Winvalid-token-paste]
printf("%s\n" , STR("1","2"));
^
test2.cpp:6:19: note: expanded from macro 'STR'
#define STR(a,b) a##b
^
1 error generated.
^
the same code will pass compiled with msvc. Any suggestion ? Many thanks !
Hi dear all,
Look at the following code
#include <stdio.h>
#define STR(a,b) a##b
void test()
{
printf("%s\n" , STR("1","2"));
}
That's invalid code. "1""2" is not a valid token. Fortunately, you
don't need it to be -- adjacent string literals are implicitly
concatenated in a later phase of translation. You could just use
#define STR(a,b) a b
or drop the macro and write
printf("%s\n", "1" "2");
compiled with clang -c test2.cpp will failed with following error:
test2.cpp:9:18: error: pasting formed '"1""2"', an invalid preprocessing token
[-Winvalid-token-paste]
printf("%s\n" , STR("1","2"));
^
test2.cpp:6:19: note: expanded from macro 'STR'
#define STR(a,b) a##b
^
1 error generated.
^
That looks like a good error message to me -- can you suggest any way
to make it clearer, or point out any problems with it?
the same code will pass compiled with msvc. Any suggestion ? Many thanks !
I'd suggest filing a bug against MSVC, but it's not all that important
-- MSVC will likely accept the corrected code, as will all conforming
compilers.
-- James
[James Dennett]
I'd suggest filing a bug against MSVC, but it's not all that important
-- MSVC will likely accept the corrected code, as will all conforming
compilers.
Technically, N3376 16.3.3 [cpp.concat]/3 "If the result is not a valid preprocessing token, the behavior is undefined." allows VC to do whatever it wants with the bogus code, including accepting it silently.
(I would prefer a compiler error.)
Stephan T. Lavavej
Visual C++ Libraries Developer
Hi James, this code is just a simplified example. In fact I
encountered the problem when I'm testing clang against boost. Please
see the attachment.
clang-invalid-token-paste.txt (4.51 KB)
[James Dennett]
I'd suggest filing a bug against MSVC, but it's not all that important
-- MSVC will likely accept the corrected code, as will all conforming
compilers.
Technically, N3376 16.3.3 [cpp.concat]/3 "If the result is not a valid preprocessing token, the behavior is undefined." allows VC to do whatever it wants with the bogus code, including accepting it silently.
Agreed, this isn't actually non-conforming, so my phrasing above could
have been more careful. (It's been UB at least since C++98, which
matches C99 in this respect. I've not checked other versions of C,
but I'm not aware of any changes in this area.)
(I would prefer a compiler error.)
So would I, and I consider it a flaw in the standard that this is left
as UB instead of requiring a diagnostic, and a weakness of any
implementation that doesn't diagnose the problem.
Thanks for the clarification.
-- James
E:\SRC\LIBS\boost_1_49_0\boost/mpl/next_prior.hpp:44:1: error: pasting formed
‘BOOST_PP_TUPLE_ELEM_E_3(’, an invalid preprocessing token
[-Winvalid-token-paste]
BOOST_MPL_AUX_NA_SPEC(1, next)
^
E:\SRC\LIBS\boost_1_49_0\boost/mpl/aux_/na_spec.hpp:161:40: note: expanded from
macro ‘BOOST_MPL_AUX_NA_SPEC’
#define BOOST_MPL_AUX_NA_SPEC(i, name)
^
E:\SRC\LIBS\boost_1_49_0\boost/mpl/aux_/na_spec.hpp:154:47: note: expanded from
macro ’
BOOST_MPL_AUX_NA_SPEC_NO_ETI’
#define BOOST_MPL_AUX_NA_SPEC_NO_ETI(i, name)
^
Well, there’s a bug in this diagnostic: we’re including the <newline> in the name of the macro. Not related to the issue at hand, of course…
The real problem here is a boost bug. boost/preprocessor/config/config.hpp is determining that the compiler is MSVC, and consequently feeding us this non-conforming code:
E:\SRC\LIBS\boost_1_49_0\boost/preprocessor/tuple/elem.hpp:36:114: note:
expanded from macro ‘BOOST_PP_TUPLE_ELEM’
…n), BOOST_PP_CAT(BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM_E_, size), tuple))
^
In the middle of the error message I see
E:\SRC\LIBS\boost_1_49_0\boost/preprocessor/tuple/elem.hpp:36:114: note:
expanded from macro 'BOOST_PP_TUPLE_ELEM'
...n), BOOST_PP_CAT(BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM_E_, size), tuple))
and line 36 of boost/preprocessor/tuple/elem.hpp is inside a
# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MSVC()
block that presumably works around some MSVC problem, but in doing so
relies on non-portable token pasting in this case.
I don't know enough of the magic that is BOOST_PP_CONFIG_FLAGS to know
why it's following that path -- maybe your clang is configured in such
a way that Boost thinks that it's MSVC++ -- but Clang doesn't have
complete emulation of MSVC++ quirks, so if that's the case I'm not
shocked that this isn't working. (If you look ahead to line 47 of the
same file for its more portable definition of BOOST_PP_TUPLE_ELEM
you'll see that it doesn't try to concatenate the 'tuple' macro
argument onto the previous token.)
It looks like you might want to pass
'-DBOOST_PP_CONFIG_FLAGS=(BOOST_PP_CONFIG_STRICT()') or similar on
your command line to tell boost.preprocessor to assume a conforming
preprocessor. (Or just -DBOOST_PP_CONFIG_FLAGS=1, looking at
boost/preprocessor/config/config.hpp.)
As it happens, we do support this quirk, but it’s so quirky that it’s an error by default even in Microsoft mode. One could use -Wno-invalid-token-paste to disable the diagnostic (with MS-style behavior for the result), but I have no idea whether there are other things MSVC mode might enable which we actually don’t support.
It works with -D"BOOST_PP_CONFIG_FLAGS()"=1