invalid-token-paste

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

This also works.