GCC与Clang:"-pedantic-errors"的意义

3
我正在使用带有Mingw-w64 5.1.0和GCC 5.1.0的Clang v3.7.0,所有都是64位的,在Windows 10上。我的目标是使用一组Clang和GCC选项,以便在许多不同的编译器中检测可能的C89C++98语言标准可移植性问题。例如,对于C,我一直在使用以下GCC命令行,并取得了相当不错的成功:
gcc -c -x c -std=c89 -pedantic-errors -Wall -Wextra -Wno-comment -Wno-parentheses -Wno-format-zero-length test.c

然而,最近我尝试使用Clang编译器,并得到了不同的结果。以下是我的样例测试代码:

int main(void)
{
    int length = (int)strlen("Hello");
    return 0;
}

使用Clang编译时,我得到了以下错误,而使用GCC编译时,我得到了相同的基本信息,但它将其标记为警告:

test.c:3:22: error: implicitly declaring library function 'strlen'
with type 'unsigned long long (const char *)'
    int length = (int)strlen("Hello");

如果我移除-pedantic-errors选项,或者将其更改为-pedantic,Clang只会将其标记为警告,这正是我想要的。然而,根据GCC文档,-pedantic-errors选项会导致被认为是语言扩展的警告被标记为错误,但在C89中不使用函数原型不是一种扩展。因此,我有三个基本问题:
  1. Has Clang changed the meaning of -pedantic-errors from the meaning used by GCC, or am I misinterpreting something?

  2. What is the best set of options that will enforce adherence to the selected standard and will issue errors for all non-conforming code?

  3. If I continue to use -pedantic-errors with Clang is there a way to get it to issue a warning instead of an error in specific cases? In another posting on this site an answer was given that said to use the following, where foo is the error:

    -Wno-error=foo
    
如果这是正确的方法,那么在像我遇到的没有实际错误编号的错误中,我实际上要用什么来替换foo?我无法相信它实际上需要以下所有内容:
-Wno-error=implicitly declaring library function 'strlen'
with type 'unsigned long long (const char *)'

2
哦,而且你真的不应该使用C89。它已经过时17年了,而且与标准C不完全兼容。C++98也是如此。C++11已经有了很大的改进。 - too honest for this site
3
@Olaf:早期版本的C标准并没有在后来的版本出版时神奇地消失。它们仍然存在,gcc仍然支持它们。请注意,当前的C++标准仍然在规范文本中引用了C99标准,而您声称该标准不存在。我相信POSIX也是如此。 - Keith Thompson
3
@Olaf:请停止无礼行为。 - Keith Thompson
3
@Olaf:IEEE与C或C++标准无关,它们都由ISO发布。ISO已经声明了先前版本的标准已经过时。那么这个声明对其他人有什么约束力呢?选择使用旧版语言标准的人是被允许的。而且,还有一些现行标准,其中一些是由ISO发布的,其规范依赖于旧版C标准。 - Keith Thompson
7
@Olaf,对于一个旨在帮助解决问题的网站来说,似乎将一个相当直接的问题变成一篇关于语义的论文,这让我感到非常奇怪。如果我只是说“C89和C++98语言版本”而不是“C89和C++98语言标准”,所有这些都可以避免吗?我只是不明白为什么有些人喜欢纠缠这些细节,而不是简单地看到显而易见的意图。我也知道旧的“版本”(而不是标准)已经过时了,但是程序员遵循它们可能有很多原因。 - BenevolentDeity
显示剩余7条评论
1个回答

2
您的代码无效且行为未定义,因此编译器可以在编译时执行任何操作。隐式声明的int strlen(char*)size_t strlen(const char *)不兼容。请注意,保留HTML标记。

Clang是否改变了-pedantic-errors的含义,或者我理解错了什么?

据我所知,是的。根据Clang文档:
-pedantic-errors

    Error on language extensions.

在GCC中:

-pedantic

    Issue all the warnings demanded by strict ISO C and ISO C++ [...]

-pedantic-errors

    Give an error whenever the base standard (see -Wpedantic) requires a diagnostic, in some cases where there is undefined behavior at compile-time and in some other cases that do not prevent compilation of programs that are valid according to the standard.

Clang扩展错误。

GCC在标准明确要求及其他“某些情况”下出现错误。

这是不同的,这是一组不同的错误。标准可能不需要诊断,但它仍然是扩展 - GCC将保持沉默,Clang将出错。

哪种选项集最好,可以强制执行所选标准,并对所有不符合规范的代码发出错误?

首先想到的答案是:“没有”。编译器本质上使用“实现定义的行为”和扩展,因为它们旨在首先编译代码,而不是旨在不编译不符合规范的代码。有些情况下,代码符合规范,但是编译器之间的行为仍然不同-您可以在此处探索这样的情况

无论如何,请继续使用-pedantic-errors,因为它似乎能够检测到不符合规范的代码。您的代码无效,行为未定义,因此您的代码不符合规范,因此clang正确地检测到了它。还可以使用linter和sanitizer检测其他未定义行为的情况。

如果我继续使用Clang的-pedantic-errors,有没有办法使其在特定情况下发出警告而不是错误?

使用-fno-builtin


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接