在#error之后,C预处理无法立即停止

时间:2016-04-06 23:14:02

标签: c gcc compilation c-preprocessor avx

我今天的问题不应该太复杂,但我根本无法找到理由/解决方案。作为一个小型,可重现的示例,请考虑以下玩具C代码

#define _state_ 0

#if _state_ == 1
int foo(void) {return 1;}
#else

/* check GCC flags first
   note that -mfma will automatically turn on -mavx, as shown by [gcc -mfma -dM -E - < /dev/null | egrep "SSE|AVX|FMA"]
   so it is sufficient to check for -mfma only */

#ifndef __FMA__
#error "Please turn on GCC flag: -mfma"
#endif

#include <immintrin.h>  /* All OK, compile C code */
void foo (double *A, double *B) {
  __m256d A1_vec = _mm256_load_pd(A);
  __m256d B_vec = _mm256_broadcast_sd(B);
  __m256d C1_vec = A1_vec * B_vec;
  }
#endif

我打算通过

编译这个test.c文件
gcc -fpic -O2 -c test.c

注意我没有启用GCC标记-mfma,因此会触发#error。我期望的是,在GCC看到#error后,编译将立即停止,但这是我在GCC 5.3中得到的:

test.c:14:2: error: #error "Please turn on GCC flag: -mfma"
 #error "Please turn on GCC flag: -mfma"
  ^
test.c: In function ‘foo’:
test.c:22:11: warning: AVX vector return without AVX enabled changes the ABI [-Wpsabi]
   __m256d A1_vec = _mm256_load_pd(A);
           ^

GCC会停止,但为什么它会在#error之后选择一条线?任何解释?感谢。

对于想要尝试的人,有一些硬件要求。您需要带有AVX FMA指令集的x86-64。

1 个答案:

答案 0 :(得分:5)

我有C ISO规范的草稿副本,并在§4/ 4中说明了

  

实现不应成功翻译包含#error预处理指令的预处理翻译单元,除非它是由条件包含跳过的组的一部分。

后来,在§6.10.5中,正式定义了#error,它说

  

表单的预处理指令   # error pp-tokens opt new-line   导致实现生成包含指定的诊断消息   预处理令牌序列。

换句话说,规范只要求任何具有#error的代码都需要无法编译并报告错误消息,而不是编译立即需要立即终止{{到达了1}}。

鉴于始终检查编译器在之后的报告之前报告的顶级错误被认为是一种好的做法,我想象一个有能力的程序员看到以#error指令开头的一系列错误可能会知道发生了什么事。