【问题标题】:Is GCC warning on const qualifier correct?GCC 对 const 限定符的警告是否正确?
【发布时间】:2019-02-03 21:38:54
【问题描述】:

考虑下面的代码,它来自this question:

const int (*foo(const char *a))[1]
    { return (const int (*)[1]) a; }

compiled with GCC 8.2 (and older versions) using -Wcast-qual 时,GCC 会发出警告:

来源>:2:15:警告:cast从指针目标类型[-Wcast-qual]中丢弃'const'限定符 { return (const int (*)[1]) a; } ^

这个警告正确吗?显然,目标类型中有一个 const 限定符。

它在元素类型上,而不是在指针直接指向的东西上,即数组类型。然而,即使我们使用typedef int T[1]; 并用(const T *) 替换演员表,警告仍然存在。此外,根据 C 2018 6.7.3 10,数组类型的限定符适用于元素类型,而不是数组类型,因此类型是相同的。

Clang 不显示此警告。

如果我们将演员更改为(const void *):

const int (*foo(const char *a))[1]
    { return (const void *) a; }

然后警告消失。如果我们将-pedantic 添加到编译开关,我们会收到关于const 的不同警告:

来源>:2:15:警告:从指针目标类型 [-Wdiscarded-qualifiers] 返回丢弃“const”限定符 { return (const void *) a; } ^~~~~~~~~~~~~~~~

这看起来像相同的警告,除了它是关于从返回表达式到函数返回类型的隐式转换,而前面的警告是关于强制转换中的显式转换。但是这个只出现在-pedantic。为什么?

【问题讨论】:

  • 对我来说看起来像一个 gcc 错误?这是一个返回类型的 typedef 版本仍然显示问题:godbolt.org/z/mC8qS6
  • 纯猜测:可能是您在问题中确定了“数组类型上的限定符适用于元素类型”的问题。 GCC 可能会看到“指向(const char)的指针”到“指向((const int)的数组)的指针”,看到指向的东西不是const,发出警告(实际上它如果它愿意更深一层,它仍然是 const)。
  • 注意:从指向 char 的指针更改为 int 会引发对齐问题。
  • 如果你想检验我的假设,这个警告会在 gcc/c/c-typeck.c 的 handle_warn_cast_qual 中生成,在 discarded |= (TYPE_QUALS_NO_ADDR_SPACE (in_otype) & ~TYPE_QUALS_NO_ADDR_SPACE (in_type)); 的两行中。您必须深入了解in_otype 以查看它是否为数组类型,以及元素类型是否设置了base.readonly_flag 位。
  • 用(int (*)[1])(const int(*)[1])42; 甚至typedef int T[1]; (T*)(const T*)42; 铸造const 对gcc 和clang 都没有警告。

标签: c gcc language-lawyer


【解决方案1】:

这是GCC bug 81631。由于应用于数组的限定符实际应用于数组元素的复杂性,GCC 无法识别指向数组指针的强制转换保留了 const 限定符。

【讨论】:

    猜你喜欢
    • 2016-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多