0

考虑以下测试代码:

#include <tgmath.h>

void test()
{
    double x=cos(4.5);
}

编译它

arm-none-eabi-gcc test.c -c

在 Ubuntu 18.04 (gcc 6.3.1, newlib 2.4.0) 上工作正常,但在 Ubuntu 20.04 (gcc 9.2.1, newlib 3.3.0) 上出现以下错误:

In file included from test.c:1:
test.c: In function 'test':
test.c:5:14: error: 'ccosl' undeclared (first use in this function); did you mean 'ccosh'?
    5 |     double x=cos(4.5);
      |              ^~~
test.c:5:14: note: each undeclared identifier is reported only once for each function it appears in
test.c:5:14: error: argument 6 of '__builtin_tgmath' is not a function pointer

显然, 的定义以cos某种方式发生了变化,因此它现在提到ccosl了未在任何地方声明的内容。

如果我从 更改tgmath.hmath.h,则不再出现错误。这当然只是一种解决方法,而不是修复,因为这样我就失去了floatvs的类型通用性double

我的问题是:如何使它正常工作?我是否必须添加一些编译选项,或者它只是工具链中的一个错误?

4

1 回答 1

0

看来工具链版本之间的差异在于tgmath cos不同版本中宏的GCC实现。即,使用-Efor 选项进行编译会产生6.3.1 中gcc的以下(清理后的)扩展:double x=cos(4.5)

double x=__builtin_choose_expr(__builtin_classify_type(4.5) == 9,
                               __builtin_choose_expr(__builtin_types_compatible_p(__typeof__(__real__(4.5)), long double),
                                                     ccosl(4.5),
                                                     __builtin_choose_expr(__builtin_types_compatible_p(__typeof__(__real__(4.5)), double) || __builtin_classify_type(__real__(4.5)) == 1,
                                                                           ccos(4.5),
                                                                           ccosf(4.5))
                                                    ),
                               __builtin_choose_expr(__builtin_types_compatible_p(__typeof__(4.5), long double),
                                                     cosl(4.5),
                                                     __builtin_choose_expr(__builtin_types_compatible_p(__typeof__(4.5), double) || __builtin_classify_type(4.5) == 1,
                                                                           cos(4.5),
                                                                           cosf(4.5))
                                                    )
                              );

而在 GCC 9.3.0 中,扩展是一个简单的函数调用:

double x=__builtin_tgmath (cosf, cos, cosl, ccosf, ccos, ccosl, 4.5);

两者之间的主要区别在于__builtin_choose_expr不评估未选择的表达式(如docs中所述),while__builtin_tgmath是一个函数,它需要所有参数都有效。而且它看起来像 newlib 从来没有ccosl在它的 中complex.h,所以它似乎与新版本的 GCC 不兼容。

于 2020-08-28T12:58:13.940 回答