当传递 -fsanitize=undefined 时,来自 gcc-trunk 的 -Wconversion 诊断

Oli*_*ock 7 c++ gcc language-lawyer

short int这是关于在“常规算术转换”期间提升 s时的正确诊断。在操作期间,/可以合理地发出诊断信息,但在操作期间/=不应发出任何诊断信息。

gcc-trunk 和 clang-trunk 的行为似乎没问题(都不发出下面第一种或第二种情况的诊断信息)...直到...

我们添加了完全不相关的-fsanitize=undefined...之后,完全奇怪的是:

gcc-trunk 会针对这两种情况发出诊断信息。至少对于第二种情况确实不应该。

这是 gcc 中的错误吗?

神箭链接

Godbolt 与 -O3 链接 - 相同的结果

int main() {
    short sum   = 50;
    short count = 10;

    // sum and count get promoted to int for the "usual arithmetic conversions"
    // then the assignment could result in a reasonable -Wconversion diagnostic for reduction back
    // to short
    // However clang-trunk and gcc-trunk choose NOT TO issue a diagnostic with -Wconversion enabled
    short avg1 = sum / count;

    // we should be able to prevent promotion to int by using /= assignment operator.
    // Both clang-trunk and gcc-trunk, correctly, DON'T issue a diagnostic with -Wconversion enabled
    auto tmp = sum;
    tmp /= count;
    short avg2 = tmp;

    // HOWEVER if we add -fsanitize=undefined for both compilers
    // then, bizarrly, gcc-trunk issues a diagnostic for both cases above and clang-trunk still for
    // neither

    // none of these ever issue a diagnostic (nor should they)
    tmp += count; // all
    tmp -= count; // are
    tmp *= count; // silent

    return (avg1 + avg2) & 0xff; // prevent "unused" diagnostics
}
Run Code Online (Sandbox Code Playgroud)

编辑

这是我向 GCC 提交的错误: https://gcc.gnu.org/bugzilla/show_bug.cgi ?id=104616

use*_*522 4

对于内置复合赋值运算符,$=表达式的A $= B行为与 表达式 相同A = A $ B,只是A仅计算一次。所有升级和其他常见的算术转换以及转换回原始类型仍然会发生。

因此,不应预期 和 之间的警告有所short avg1 = sum / count;不同tmp /= count;

int在每种情况下都会发生从到 的转换short。因此,在任何一种情况下,转换警告都是合适的。

然而,GCC 警告标志的文档明确指出,从升级的小类型算术返回的转换被排除在该-Wconversion标志之外。尽管如此, GCC 还是提供了-Warith-conversion包含此类情况的标志。有了它,示例中的所有算术都会生成警告。

另请注意,此异常-Wconversion仅在 GCC 10 中引入。有关它的更多背景信息,引入它的错误报告位于此处

看来Clang在这些案件上一直比GCC更宽容。例如,请参阅此问题此问题


因为/在 GCC 中似乎打破了应有的-fsanitize=undefined例外。-Wconversion在我看来,这与未定义的行为清理程序专门为除法添加了空值检查有关。也许,在这种转换之后,警告标志逻辑不再将其识别为较小类型的直接算术。

如果我对警告标志的预期行为的理解是正确的,我会说这看起来是无意的,因此是一个错误。