use*_*522 5 c++ language-lawyer
[intro.compliance.general]/2指定编译器应如何处理给定的程序。
特别是它有两点处理格式错误的程序。(2.2) 要求编译器针对违反可诊断规则的情况发出至少一个诊断。(2.3) 指出,对于违反不需要诊断的规则的程序,没有对编译器强加任何要求。
不幸的是,我认为该段落没有明确说明这两个要求之间的优先级。如果程序包含违反需要诊断的可诊断规则的情况以及违反不需要诊断的规则的情况,编译器是否需要发出诊断?
作为一个例子(被视为一个完整的单翻译单元程序):
// ill-formed, diagnostic required
int main() { using T = void&; }
// IFNDR according to [temp.res.general]/8.1 and [temp.res.general]/8.4
void f(auto) { using T = void&; }
Run Code Online (Sandbox Code Playgroud)
此外,如果 IFNDR 优先,则同样可能适用于通常被视为运行时 UB 的未定义行为,例如
// always runtime undefined behavior
int main() { return *(int*)0; }
// ill-formed, diagnostic required
using T = void&;
Run Code Online (Sandbox Code Playgroud)
那么从技术上讲也不需要诊断(被视为一个完整的单翻译单元程序)?
从实现质量的角度来看,我认为编译器在这种情况下应该尽可能发出诊断。
但我的印象是,该标准实际上并不要求这样做,这也是我之前读到/听到的。例如,[temp.res.general]/8.1中的“并且模板未实例化”的限定否则没有多大意义。然而,在其他时候,标准不使用似乎应该需要的此类反转限定,例如[dcl.constexpr]/6。
第 2.3 节明确\xe2\x80\x93 “本文档对实现没有提出要求”。不是“除 2.2 之外的本文档”,而是“本文档”。如果存在 IFNDR 情况,则实施可以自由执行任何操作。
\n重写 2.2 是必要的。假设,IFNDR 情况可能会使编译偏离轨道,导致其错过确实需要诊断的格式错误的情况。(被其他错误隐藏的错误并不是一个新概念。)这并不会使实现不合格。尽管进行了善意处理,但 IFNDR 情况的存在为实现提供了可能错过相关代码中的诊断的余地。
\n这确实意味着实现也有可能错过不相关代码中的诊断。那好吧。标准可以尝试区分“相关代码”和“不相关代码”,但这会是浪费精力。在某些时候,最好相信实施是出于善意,而不是过度监管。
\n“不需要诊断”的情况是错过诊断的正当理由。如果某个实现使用它作为主动省略诊断的借口,那么它是合规的,但您应该远离。\n就像您应该远离检测未定义行为并以此为借口格式化您的代码的合规实现一样。硬盘。
\n但从实际角度来看,2.3 不会覆盖 2.2。虽然官方的说法是“不需要诊断”,但更实际的观点是“情况不需要检测”。必须检测需要诊断的情况,以便可以生成诊断。不需要执行任何特定操作的情况不需要被检测。
\n如果实现不尝试检测 IFNDR 情况,则它无法根据现有的 IFNDR 做出决策。也就是说,它必须对其检测到的格式错误提供诊断。这不仅仅是“执行质量”,也不仅仅是“诚信”,而是在面对未知情况时确保合规的必要条件。
\n如果一个实现确实检测到 IFNDR 情况,那么我们就会依靠善意。
\n