良构程序的诊断消息

Diagnostic message for well-formed program

是否允许实现为格式正确的程序发出诊断消息?

例如,一些编译器在编译以下格式正确的程序时发出有关未使用表达式结果的警告:

int main() { 0; }

是否允许此类编译器将该警告视为诊断消息?

只要在任何相应的场景中满足以下规则,就可以发出诊断。 §1.4/2:

Although this International Standard states only requirements on C ++ implementations, those requirements are often easier to understand if they are phrased as requirements on programs, parts of programs, or execution of programs. Such requirements have the following meaning:

  • If a program contains no violations of the rules in this International Standard, a conforming implementation shall, within its resource limits, accept and correctly execute that program.

  • If a program contains a violation of any diagnosable rule or an occurrence of a construct described in this Standard as “conditionally-supported” when the implementation does not support that construct, a conforming implementation shall issue at least one diagnostic message.

  • If a program contains a violation of a rule for which no diagnostic is required, this International Standard places no requirement on implementations with respect to that program.

"Accepting" 仅解决对实现的确认,即这是一个格式正确的程序,而不是没有任何诊断。毕竟,尽管在此过程中发出了任何警告,实现仍然会产生您要求的目标文件。

但是,有一项关于模板的规则确实要求不发布诊断; §14.6/8:

No diagnostic shall be issued for a template for which a valid specialization can be generated.

实施可以发出 (1)任意数量的诊断,只要它确实发出所需的诊断。

它必须能够接受正确的程序,

C++14 §1.4/2:

If a program contains no violations of the rules in this International Standard, a conforming imple- mentation shall, within its resource limits, accept and correctly execute that program"

但它可以发出有关它的诊断。

C++ 标准不区分错误消息警告消息,但这是事实上标准。错误消息意味着(按照惯例)没有生成二进制文件,因为问题太严重了。警告消息意味着(按照惯例)存在潜在问题,但不会直接违反语言规则,因此会生成二进制文件,除非也有错误。


有时界线有点模糊,实现不正确但出于实用原因接受无效代码,只有警告甚至没有诊断。因此,对于新代码,人们可能会要求编译器将每个警告都视为错误,并以完全 clean compiles 为目标。据我了解,现在这种情况绝对并不少见。

使用一些编译器,例如然而,Visual C++ 可能会有问题,因为编译器发出了太多 愚蠢的警告 ,关于完全合法和无问题构造的警告。然后必须以某种方式抑制这些警告。例如。通过 #pragma 指令,如果可能,或通过代码重写。

幸运的是,Visual C++ 存在 a header with such #pragma directives that turn off sillywarnings, compiled about five years ago from a community effort in the comp.lang.c++ Usenet group. And happily, for the community edition of Visual Studio 2015 there is an extension that provides a project template with that header included。这些都是我做的。


对于有问题的代码,

int main() { 0; }

... 而不是抑制通常有用的警告,您应该重写代码以明确表达您的意图:

int main() { (void)0; }

(void) 转换告诉编译器您打算丢弃该表达式的值。

在将此构造用于其他未使用的函数参数的情况下,您可以额外声明一个不完整的同名 class,以防止无意中使用名称:

(void)arg_name; struct arg_name;

但由于它是非常规的,它可能会绊倒其他程序员 – 对于我使用的编译器,以后使用该名称的错误消息并不完全直观。


(1) 除了 ,C++14 §14.6/8 “不应为可以生成有效特化的模板发出诊断。”。