clang 5.0.0 在涉及虚函数的 coliru/godbolt 上的差异

clang 5.0.0 difference on coliru/godbolt involving virtual function

我真的希望我遗漏了一些东西,但请考虑以下代码:

struct Base {
    virtual void doit() = 0;
};

struct Derived : Base {
    void doit_internal(int n);

    void doit() {
        doit_internal(3);
    }
};

int main() {
    Derived derived;
}

clang (5.0.0-3~16.04.1 (tags/RELEASE_500/final)) 我收到链接器错误 (undefined reference to Derived::doit_internal(int)')。我想知道为什么 doit_internal 如果实际上根本没有被调用,为什么需要它。

此外,在 clang (version 5.0.0 (tags/RELEASE_500/final 334239)) 上编译正常。

哪个叮当声是正确的?是否有技术reason/platform具体thing/something在标准强制doit_internal中被定义?

在这两种情况下,程序都能正确编译。
但是在 coliru 上它在链接过程中失败了,因为没有 Derived::doit_internal(int).

的定义

Compiler Explorer 不要 运行 代码,它只是显示为当前翻译单元定义的 C++ 代码的汇编代码。所以它不必做链接。由于未执行链接阶段,因此未发现问题且未报告错误。

您的程序格式错误,不需要诊断。在定义 doit 时,您 odr-used doit_internal(您编写了一个调用 doit_internal 的表达式)。将您的程序优化为 return 0;

没有任何区别

标准明确表示:

[basic.def.odr]

4 Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program outside of a discarded statement; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see [class.ctor], [class.dtor] and [class.copy]). An inline function or variable shall be defined in every translation unit in which it is odr-used outside of a discarded statement.

Clang 完全有权拒绝它,或者不拒绝它。它甚至可以在版本之间更改其行为,因为您的程序违反了上述要求。

doit_internal 是必需的,因为您的一个函数引用了它。虽然该函数本身未被引用,但它仍然是应用程序的一部分,因此 linker 需要它的依赖项。

如果启用优化,则 clang 会省略 doit 的实施,并且您的应用程序 links 成功:http://coliru.stacked-crooked.com/a/8496f4e097d2f0ee

godbolt 只是一个编译器,它没有 link 或 运行 任何东西,这就是它不显示任何 link 错误的原因。请注意,它在程序集中仍然有 call Derived::doit_internal(int),因此如果您使用此程序集并尝试 link 它,您最终会遇到相同的 linker 错误。