如何禁用特定的未知#pragma警告(GCC和/或Clang)

32

我知道如何禁用所有未知的#pragma警告。例如,在 如何禁用 #pragma 警告? 中给出了答案。

是否有一种方法可以禁用特定#pragma的"未知#pragma"警告?例如,如果我禁用了#pragma ugubugu的警告,则以下代码:

#pragma ugubugu
#pragma untiunti

int main() {return 0;}

当编译时使用以下任一选项:

g++ pragma.cpp -Wall
clang++ pragma.cpp -Wall

应该只会产生一个警告:

warning: ignoring #pragma untiunti

也许有一种简单的方法可以注册一个不起作用的自定义pragma吗?

如果Visual Studio中有这样的选项,那就太好了,但这并不是那么重要。


"但为什么他最终要使用自定义pragma呢?"

我的源代码由两个编译器解析。其中一个编译器有一个特殊的#pragma是另一个编译器所不知道的。当然,我可能会在每个#pragma实例周围放置#ifdef COMPILER_IDENTIFICATION_MACRO ... #endif,但那将很麻烦。

3个回答

24

我相当确信没有任何方法可以实现这个。

GCC和Clang都有内部接口,允许语言前端在预处理器中注册#pragma处理程序 - 请参见GCC的libcpp/directives.c和Clang的lib/Lex/Pragma.cpp - 但是,就我所看到的而言,除了基于命令行选项暗示的语言变体之外,没有任何方式可以修改注册了哪些处理程序。

我知道如何禁用所有未知的#pragma警告。例如,答案在这里给出:SO: How to disable #pragma warnings?

请注意,在那里最高投票的答案比接受的答案更好。可以在命令行上简单地添加-Wno-unknown-pragmas以禁用任何未知的#pragma警告(在任何打开警告的选项后面,例如-Wall)。

我的源代码被两个编译器解析。其中一个编译器有一个特殊的#pragma,另一个则不知道。当然,我可能会在每个#pragma实例周围放置#ifdef COMPILER_IDENTIFICATION_MACRO ... #endif,但那会很麻烦。

从更哲学的角度来看,我认为这真的是正确的解决方案,尽管它可能很麻烦!

在我看来,似乎应该将任何不被期望了解其意图的编译器隐藏在#pragma之外,因为整个#pragma的目的就是为编译器提供调用实现定义行为的机制。

(如果您最终这样做,请注意,Clang定义了__clang__,但是两个 GCC和Clang都定义了__GNUC__。)


鉴于没有更好的解决方案,我不得不接受你所说的“无法完成”的答案。此外,如果我决定深入研究,指向编译器内部的指针可能会有所帮助。谢谢! - CygnusX1
有没有办法在代码中抑制警告,没有人知道吗?当我提交后,它会进入一个我无法控制的自动化项目生成过程。最终构建时会出现所有警告。 - Dan
1
#pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunknown-pragmas" ...使用未知预处理指令的代码... #pragma GCC diagnostic push - Dan
1
@Dan的上述注释提到使用#pragma GCC diagnostic push``#pragma GCC diagnostic ignored "-Wunknown-pragmas"是一个可行的解决方案,如果你愿意用这种方式来包围你的未知#pragmas;只是一个注意事项,要用#pragma GCC diagnostic pop而不是#pragma GCC diagnostic push来结束它。我在我的代码中使用#pragma mark语句,以便于我的IDE,并且GCC由于此而发出警告,我想要防止这种情况的发生。 - bluebinary

10

我猜您希望禁用pragma警告,因为它在一个平台上是有效的,但在另一个平台上却无效。如果是这种情况,您可以使用宏来选择性地启用pragma,从而消除了抑制警告的需要。

例如,如果您只想在Visual C++上使用pragma,则可以执行以下操作:

#if defined(_MSC_VER)
#    define SAFE_PRAGMA_UGUBUGU __pragma(ugubugu)
#else
#    define SAFE_PRAGMA_UGUBUGU 
#endif

然后,您可以编写

SAFE_PRAGMA_UGUBUGU
#pragma untiunti   
int main() {return 0;}

-6
  • 编译器不允许自定义编译指示符,因为指示符大多是编译器和/或链接器控制指令。由于这非常接近特定编译器实现和功能,那么对于用户来说,“定义新的指示符”有什么应用呢?实际上,在特定编译器上实现的可用指示符指令完全独立于供应商(没有C++标准化规则)。
  • 也许您想使用指示符来标记代码的特殊部分(例如,为了提供自己的预处理器),因为您要求无操作指令。这可以使用预处理器(#defines)完成。
  • 在C/C++代码中进行自定义“标记”的另一种可能性,例如#MY_PRAGMA,是在C/C++之前使用自己的预处理器。

这种类型的处理的一个例子是用于Qt库的非标准元对象系统,该系统与Qt MOC编译器交互。这用于扩展一些非C++结构(例如Q_OBJECT,Q_PROPERTY等),然后将其提供给C++编译器以获得有效的语法。


6
我认为他不是想要创建一个没有作用的预处理指令,而是认为这是抑制警告的一种可能方法。ugubugu是一个未知的预处理指令,因此注册它,但使其不起作用,这样它就成为一个已知的预处理指令,不会产生警告。 - Dennis Zickefoose
@ Dennis Zickefoose,但他为什么最终要使用自定义pragma呢?我猜测他试图将它们用作代码中的“标记”或类似的东西,这是完全有效的,但是除了使用自己的pragma之外,还有其他选择(这可能会与编译器供应商的pragma发生冲突,因为它们没有标准化)。 - Hernán

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接