apple cpp 破坏宏参数粘贴
apple cpp breaks macro-parameter pasting
编译如下test.cpp
# define TopLevelProject X11
#define Concat3(a,b,c) a/**/b/**/c
# define ProjectRulesFile Concat3(<,TopLevelProject,.rules>)
#include ProjectRulesFile
cpp -I。 test.cpp
预期的行为是生成包含语句
# 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
注意这行
"./X11.rules"
确实是输出
然而,apple 的 clang cpp 给出了输出
# 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.
注意格式错误的文件名 ' X11 .rules'
Apple的cpp在Concat3宏的第一个参数前插入一个space,在第二个和第三个参数之间插入一个
所有版本的 gcc、clang 和 msdev 工具都执行正确的文本替换。
但是
苹果的所有版本的cpp,比如xcode发布的,都有这个bug。
是否可以使用某种宏参数连接方案来编写 Concat3 宏,以便它在苹果的 cpp 下工作?
谢谢
Concat3(a,b,c) a/**/b/**/c
是一种古老的、pre-standard、长期弃用的连接方法。它通常不适用于任何现代(即 1990 年左右)。它 可能 专门用于将 header 名称与 某些 编译器连接起来,因为那是一个 implementation-defined 区域。
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.
无法使用此方法连接任何非 header 名称的内容。
没有标准的方法来连接适用于所有编译器的 header 名称。标准技巧
#define CAT(a,b) CAT2(a,b)
#define CAT2(a,b) a ## b
如果结果不是有效的预处理标记则不起作用,大多数 header 名称都不是。
编译如下test.cpp
# define TopLevelProject X11
#define Concat3(a,b,c) a/**/b/**/c
# define ProjectRulesFile Concat3(<,TopLevelProject,.rules>)
#include ProjectRulesFile
cpp -I。 test.cpp
预期的行为是生成包含语句
# 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
注意这行 "./X11.rules" 确实是输出
然而,apple 的 clang cpp 给出了输出
# 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.
注意格式错误的文件名 ' X11 .rules'
Apple的cpp在Concat3宏的第一个参数前插入一个space,在第二个和第三个参数之间插入一个
所有版本的 gcc、clang 和 msdev 工具都执行正确的文本替换。
但是
苹果的所有版本的cpp,比如xcode发布的,都有这个bug。
是否可以使用某种宏参数连接方案来编写 Concat3 宏,以便它在苹果的 cpp 下工作?
谢谢
Concat3(a,b,c) a/**/b/**/c
是一种古老的、pre-standard、长期弃用的连接方法。它通常不适用于任何现代(即 1990 年左右)。它 可能 专门用于将 header 名称与 某些 编译器连接起来,因为那是一个 implementation-defined 区域。
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.
无法使用此方法连接任何非 header 名称的内容。
没有标准的方法来连接适用于所有编译器的 header 名称。标准技巧
#define CAT(a,b) CAT2(a,b)
#define CAT2(a,b) a ## b
如果结果不是有效的预处理标记则不起作用,大多数 header 名称都不是。