没有宏扩展的延迟字符串化
Delayed stringification without macro expansion
如果 deprecation_message
中的任何标识符标记被定义为类似对象的宏,是否可以修改以下代码片段以防止 #pragma GCC warning
打印的诊断信息发生变化dmacro
已扩展,同时保留将 symbol
替换到消息中的能力?丑陋没有问题,只要 clang 也实现了 GCC 扩展,GCC 扩展就是公平的游戏,但诊断的内容可能不会被修改。
#define deprecation_message(symbol) \
#symbol will be removed from <header.h> in the next release\n\
of $LIBRARY. To use #symbol, include <moved/header.h> instead.
#define make_pw(...) make_pw_(__VA_ARGS__)
#define make_pw_(...) make_pw__(GCC warning #__VA_ARGS__)
#define make_pw__(...) _Pragma(#__VA_ARGS_)
#define dmacro(a,b,c) make_pw(deprecation_message(dmacro)) xmacro(a,b,c)
// Uncommenting any of the following #define lines should *not*
// change the text of the diagnostic in any way.
//#define header
//#define n f
//#define will won't'
dmacro(x,y,z)
(您可能想要实现字符串文字串联,但这行不通;_Pragma
本身和 #pragma GCC warning
都只接受一个字符串文字。_Pragma("this" "that")
是语法错误。)
也许我误解了这个问题,但下面的代码在 clang
和 gcc
上运行和编译,并用 -std=c99
和 -std=c11
测试:
#include <stdio.h>
#include <stdlib.h>
#define deprecation_message(symbol) \
#symbol " will be removed from <header.h> in the next release\n" \
"of $LIBRARY. To use " #symbol ", include <moved/header.h> instead."
#define make_pw__(...) _Pragma(#__VA_ARGS__)
#define make_pw_(...) make_pw__(GCC warning #__VA_ARGS__)
#define make_pw(...) make_pw_(__VA_ARGS__)
#define xmacro(a, b, c) puts("I'm working: " #a #b #c "!")
#define dmacro(a, b, c) make_pw(deprecation_message(dmacro)) xmacro(a, b, c)
int
main(void)
{
dmacro(x, y, z);
return EXIT_SUCCESS;
}
现在,上面的代码将用 clang
:
展开
int
main(void)
{
#pragma GCC warning "2dmacro2 2 will be removed from <header.h> in the next release4n2 2of $LIBRARY. To use 2 2dmacro2 2, include <moved/header.h> instead.2"
puts("I'm working: " "x" "y" "z" "!");
return 0 /* Successful exit status. */;
}
并将在 clang
上产生以下警告:
src/main.c:18:5: warning: "dmacro" " will be removed from <header.h> in the next release\n" "of $LIBRARY. To use " "dmacro" ", include <moved/header.h> instead." [-W#pragma-messages]
dmacro(x, y, z);
^
以及 gcc
上的这个:
src/main.c:18:13: warning: "dmacro" " will be removed from <header.h> in the next release\n" "of $LIBRARY. To use " "dmacro" ", include <moved/header.h> instead."
dmacro(x, y, z);
^~~~~~~~
基本上我所做的就是将弃用消息用引号引起来...
更新1:
现在,有趣的是,如果你从 make_pw_
中删除字符串化,那就是:
#define make_pw_(...) make_pw__(GCC warning __VA_ARGS__)
然后 clang
会给你这个:
src/main.c:18:5: warning: dmacro will be removed from <header.h> in the next releaseof $LIBRARY. To use dmacro, include <moved/header.h> instead. [-W#pragma-messages]
dmacro(x, y, z);
^
这很好,因为它没有不需要的引号,但是 GCC
只会给你这个:
src/main.c:18:13: warning: dmacro
dmacro(x, y, z);
^~~~~~~~
更奇怪的是,如果将 deprecation_message
更改为:
#define deprecation_message(symbol) "" #symbol "..."
然后它会给你一个空警告,就像它只使用宏参数中的第一个非白色-space标记。
老实说,我不知道这是 GCC
的错误,还是定义明确的行为,clang
正在做一些额外的工作以使其有意义除此之外,none 更少,这两个编译器的最新版本都会发生这种情况。 (如果非要我赌的话,我会说,这是个bug :P)
更新2:
这是一个稍微修改过的版本,它适用于您在评论中描述的两种编译器。诀窍是,宏 DEPRECATED
有两个阶段,而不是一个阶段。
#include <stdio.h>
#include <stdlib.h>
#define DEPRECATED_(...) #__VA_ARGS__
#define DEPRECATED(symbol) \
DEPRECATED_(#symbol will be removed from <header.h> in the next release\n \
of $LIBRARY. To use #symbol, include <moved/header.h> instead.)
#define PRAGMA_WARN_(message) _Pragma(#message)
#define PRAGMA_WARN(message) PRAGMA_WARN_(GCC warning message)
#define dmacro(a, b, c) \
PRAGMA_WARN(DEPRECATED(dmacro)) \
puts("I'm working: " #a #b #c "!")
int
main(void)
{
dmacro(x, y, z);
return EXIT_SUCCESS;
}
所以这将在 clang
中产生以下输出:
src/main.c:19:5: warning: "dmacro" will be removed from <header.h> in the next release of $LIBRARY. To use "dmacro", include <moved/header.h> instead. [-W#pragma-messages]
dmacro(x, y, z);
^
以及 GCC
中的以下一项:
src/main.c:19:13: warning: "dmacro" will be removed from <header.h> in the next release
of $LIBRARY. To use "dmacro", include <moved/header.h> instead.
dmacro(x, y, z);
^~~~~~~~
注意:我强烈建议您从邮件中删除 \n
字符!
如果 deprecation_message
中的任何标识符标记被定义为类似对象的宏,是否可以修改以下代码片段以防止 #pragma GCC warning
打印的诊断信息发生变化dmacro
已扩展,同时保留将 symbol
替换到消息中的能力?丑陋没有问题,只要 clang 也实现了 GCC 扩展,GCC 扩展就是公平的游戏,但诊断的内容可能不会被修改。
#define deprecation_message(symbol) \
#symbol will be removed from <header.h> in the next release\n\
of $LIBRARY. To use #symbol, include <moved/header.h> instead.
#define make_pw(...) make_pw_(__VA_ARGS__)
#define make_pw_(...) make_pw__(GCC warning #__VA_ARGS__)
#define make_pw__(...) _Pragma(#__VA_ARGS_)
#define dmacro(a,b,c) make_pw(deprecation_message(dmacro)) xmacro(a,b,c)
// Uncommenting any of the following #define lines should *not*
// change the text of the diagnostic in any way.
//#define header
//#define n f
//#define will won't'
dmacro(x,y,z)
(您可能想要实现字符串文字串联,但这行不通;_Pragma
本身和 #pragma GCC warning
都只接受一个字符串文字。_Pragma("this" "that")
是语法错误。)
也许我误解了这个问题,但下面的代码在 clang
和 gcc
上运行和编译,并用 -std=c99
和 -std=c11
测试:
#include <stdio.h>
#include <stdlib.h>
#define deprecation_message(symbol) \
#symbol " will be removed from <header.h> in the next release\n" \
"of $LIBRARY. To use " #symbol ", include <moved/header.h> instead."
#define make_pw__(...) _Pragma(#__VA_ARGS__)
#define make_pw_(...) make_pw__(GCC warning #__VA_ARGS__)
#define make_pw(...) make_pw_(__VA_ARGS__)
#define xmacro(a, b, c) puts("I'm working: " #a #b #c "!")
#define dmacro(a, b, c) make_pw(deprecation_message(dmacro)) xmacro(a, b, c)
int
main(void)
{
dmacro(x, y, z);
return EXIT_SUCCESS;
}
现在,上面的代码将用 clang
:
int
main(void)
{
#pragma GCC warning "2dmacro2 2 will be removed from <header.h> in the next release4n2 2of $LIBRARY. To use 2 2dmacro2 2, include <moved/header.h> instead.2"
puts("I'm working: " "x" "y" "z" "!");
return 0 /* Successful exit status. */;
}
并将在 clang
上产生以下警告:
src/main.c:18:5: warning: "dmacro" " will be removed from <header.h> in the next release\n" "of $LIBRARY. To use " "dmacro" ", include <moved/header.h> instead." [-W#pragma-messages]
dmacro(x, y, z);
^
以及 gcc
上的这个:
src/main.c:18:13: warning: "dmacro" " will be removed from <header.h> in the next release\n" "of $LIBRARY. To use " "dmacro" ", include <moved/header.h> instead."
dmacro(x, y, z);
^~~~~~~~
基本上我所做的就是将弃用消息用引号引起来...
更新1:
现在,有趣的是,如果你从 make_pw_
中删除字符串化,那就是:
#define make_pw_(...) make_pw__(GCC warning __VA_ARGS__)
然后 clang
会给你这个:
src/main.c:18:5: warning: dmacro will be removed from <header.h> in the next releaseof $LIBRARY. To use dmacro, include <moved/header.h> instead. [-W#pragma-messages]
dmacro(x, y, z);
^
这很好,因为它没有不需要的引号,但是 GCC
只会给你这个:
src/main.c:18:13: warning: dmacro
dmacro(x, y, z);
^~~~~~~~
更奇怪的是,如果将 deprecation_message
更改为:
#define deprecation_message(symbol) "" #symbol "..."
然后它会给你一个空警告,就像它只使用宏参数中的第一个非白色-space标记。
老实说,我不知道这是 GCC
的错误,还是定义明确的行为,clang
正在做一些额外的工作以使其有意义除此之外,none 更少,这两个编译器的最新版本都会发生这种情况。 (如果非要我赌的话,我会说,这是个bug :P)
更新2:
这是一个稍微修改过的版本,它适用于您在评论中描述的两种编译器。诀窍是,宏 DEPRECATED
有两个阶段,而不是一个阶段。
#include <stdio.h>
#include <stdlib.h>
#define DEPRECATED_(...) #__VA_ARGS__
#define DEPRECATED(symbol) \
DEPRECATED_(#symbol will be removed from <header.h> in the next release\n \
of $LIBRARY. To use #symbol, include <moved/header.h> instead.)
#define PRAGMA_WARN_(message) _Pragma(#message)
#define PRAGMA_WARN(message) PRAGMA_WARN_(GCC warning message)
#define dmacro(a, b, c) \
PRAGMA_WARN(DEPRECATED(dmacro)) \
puts("I'm working: " #a #b #c "!")
int
main(void)
{
dmacro(x, y, z);
return EXIT_SUCCESS;
}
所以这将在 clang
中产生以下输出:
src/main.c:19:5: warning: "dmacro" will be removed from <header.h> in the next release of $LIBRARY. To use "dmacro", include <moved/header.h> instead. [-W#pragma-messages]
dmacro(x, y, z);
^
以及 GCC
中的以下一项:
src/main.c:19:13: warning: "dmacro" will be removed from <header.h> in the next release
of $LIBRARY. To use "dmacro", include <moved/header.h> instead.
dmacro(x, y, z);
^~~~~~~~
注意:我强烈建议您从邮件中删除 \n
字符!