有没有办法在单个翻译单元中使用GCC __attribute __((noreturn))和<stdnoreturn.h>?</stdnoreturn.h>

时间:2015-02-17 00:00:05

标签: c gcc clang c11

在C11中,关键字_Noreturn是函数说明符(如inline所示),表示函数未返回 - 它调用exit()或等效函数。还有一个标题<stdnoreturn.h>,其完整定义为:

  

7.23 _Noreturn <stdnoreturn.h>

     

¶1标题<stdnoreturn.h>定义宏

noreturn
     

扩展为_Noreturn

在GNU C(GCC)中,有一个属性__attribute__((noreturn))基本上完成相同的工作。一个区别是__attribute__((noreturn))可以出现在函数声明符之前或之后:

extern __attribute__((noreturn)) void err_error(const char *format, ...);
extern void err_error(const char *format, ...) __attribute__((noreturn));

问题是,如果在翻译单元(TU)中包含<stdnoreturn.h>__attribute__((noreturn))的任何后续使用都会映射到__attribute__((_Noreturn)),这会导致编译失败,因为属性无法识别_Noreturn(即使关键字被识别为关键字)。也就是说,就我所知,你不能同时使用这两个系统。

  • 除了以下任何一种方法之外,还有什么解决方法:

    1. 使用该属性使用<stdnoreturn.h>
    2. 对所有代码进行大爆炸
    3. 使用不完全优雅的_Noreturn关键字?

您可以通过测试__STDC_VERSION__ >= 201112L来检测C11 - 该值由技术勘误1指定,因为标准意外地保留了未完全指定的值:

  

__STDC_VERSION__整数常量 201ymmL 178)

     

178)此宏未在ISO / IEC 9899:1990中指定,并被指定为199409L in   ISO / IEC 9899:1990 / Amd.1:1995和ISO / IEC 9899:1999中的199901L。意图就是这个   将保留long int类型的整数常量,该常量随着每次修订而增加   国际标准。

这可用于在任何一个头文件中调整处理,但如果你混合使用了修改过的(C11和C99)头文件,我似乎遇到了<stdnoreturn.h>的棘手问题。 / p>

  • 是否值得向GCC提交错误,要求__attribute__((_Noreturn))成为__attribute__((noreturn))的同义词 - 这将解决问题。

2 个答案:

答案 0 :(得分:10)

改为使用__attribute__((__noreturn__))

所有gcc属性都有__版本,这样您就可以在系统标题中合理使用它们,而不会污染用户名空间。

有些平台提供商似乎也没有意识到这个问题。我最近发现,对于OS X,它们在宏__dead2中具有不受保护的版本。

此外,您无法使用__STDC_VERSION__宏可靠地检测C标准版本。所有gcc和clang版本都有&#34;测试&#34; C11的版本声称C11,如果使用-std=c11调用,而没有完全实现它。新版本几乎就在那里,但差不多。

答案 1 :(得分:0)

这正是关键字为_Noreturn而非noreturn的原因。不要包含stdnoreturn.h标题,只需使用:

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
#define noreturn _Noreturn
#elif defined(__GNUC__)
#define noreturn __attribute__((noreturn))
#else
#define noreturn
#endif