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 错误。
我真的希望我遗漏了一些东西,但请考虑以下代码:
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 错误。