Compile the following test.cpp
# define TopLevelProject X11
#define Concat3(a,b,c) a/**/b/**/c
# define ProjectRulesFile Concat3(<,TopLevelProject,.rules>)
#include ProjectRulesFile
cpp -I. test.cpp
The expected behavior is that an include statement be generated
# 1 "test.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "test.cpp"
# 10 "test.cpp"
# 1 "./X11.rules" 1
# 11 "test.cpp" 2
# 1 "./X11.rules" 1
# 15 "test.cpp" 2
Note that the line "./X11.rules" is indeed output
However, apple's clang cpp gives the output
# 1 "test.cpp"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 361 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "test.cpp" 2
test.cpp:7:10: fatal error: ' X11 .rules' file not found
#include ProjectRulesFile
^~~~~~~~~~~~~~~~
test.cpp:5:35: note: expanded from macro 'ProjectRulesFile'
# define ProjectRulesFile Concat3(<,TopLevelProject,.rules>)
~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
test.cpp:3:24: note: expanded from macro 'Concat3'
#define Concat3(a,b,c) a/**/b/**/c
^~~~~~~~~~~
1 error generated.
Note the malformed filename ' X11 .rules'
Apple's cpp inserted a space before the first parameter, and another between the second and third parameters of the Concat3 macro.
All versions of gcc, clang, and the msdev tools perform the proper text-substitution.
But
All versions of apple's cpp, such as those distributed by xcode, have this bug.
Is there some sort of macro parameter concatenation scheme I could use to write the Concat3 macro so that it works under apple's cpp?
Thanks
Concat3(a,b,c) a/**/b/**/c
is an ancient, pre-standard, long deprecated method of concatenating stuff. It generally doesn't work on anything modern (that is, past 1990 or so). It may work specifically for concatenating header names with some compilers, because that's an implementation-defined area.
6.10.2/4 The method by which a sequence of preprocessing tokens between a
<
and a>
preprocessing token pair or a pair of"
characters is combined into a single header name preprocessing token is implementation-defined.
Concatenating anything that is not a header name with this method is out of the question.
There is NO standard way to concatenate a header name that works for all compilers. The standard trick
#define CAT(a,b) CAT2(a,b)
#define CAT2(a,b) a ## b
does not work if the result is not a valid preprocessing token, which most header names aren't.