'Guaranteed Copy Elision' (P0135, C++1z) 是否可能需要 ABI 破坏?

Will 'Guaranteed Copy Elision' (P0135, C++1z) potentially require ABI breakage?

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html

上述 'Guaranteed Copy Elision' 的提案在 2016 年 6 月于芬兰奥卢举行的会议上被投票纳入 C++ 工作文件,随后被投票作为委员会草案发布。希望这会导致明年作为 C++17 标准发布。

该提案阐明了涉及临时 object 的各种值类别,以强制在某些用例中不存在复制构造函数调用。

我的问题是"might this new requirement might break ABI compatibility for compilers that might previously not have done copy elision in these circumstances, or have implemented it in a way that won't be compatible with the new requirements?"

我正在考虑诸如在创建 object 时可以内联但不能在跨越编译单元边界时省略副本的初始化。

调用函数时,函数必须 return 一个值。该值需要内存才能存在,但 return 值需要比函数本身长。 ABI 定义了这一切是如何工作的。一般来说,这是通过调用者为函数提供 return 值的 size/alignment 的内存片段而发生的。

因此,如果一个函数计算一个值并 return 对其进行计算,它必须(理论上)将该计算值复制到 return 值内存中。当调用者检索它时,它必须(理论上)将 return 值内存复制到其他一些堆栈对象中以备后用。

非保证复制省略表示这些副本都不是必需的。在 returning 函数方面,允许编译器在生成该值时在内部简单地使用 return 值内存,因此 return 语句不必复制任何内容。而在接收方,如果内存将用于初始化堆栈对象,则不必复制到该内存中。

Guaranteed copy elision 表示如果接收方正在初始化一个相同类型的对象,那么接收方将不会考虑该对象是否具有copy/move构造函数。因此,调用函数 auto t = Func(); 的代码不会将其视为对 t 的潜在复制操作。处理该代码的编译器将使用 t.

的堆栈 space 中的 return 值内存调用 Func

而在被调用方,如果您直接 return 一个纯右值,那么 copy/move 构造函数就没有必要存在了。被调用者将直接在 return 值内存中构造纯右值。

事情是这样的:ABI 不关心这些。 ABI 只关心低级内存。也就是说,只要调用者传递适当大小和对齐的 return 值内存,并且被调用者使用适当类型的对象初始化该内存...... ABI doesn'不关心.

如果调用者想为以后的操作使用那个 return 值内存,这对 ABI 来说没问题。如果被调用者想直接将数据初始化到 return 值内存而不是复制它,ABI 不会注意到。

ABI定义接口;您可以使用该界面做什么。

例如,考虑 Itanium ABI on return values。它允许 class 类型存储在寄存器中,但 只有 如果它们具有普通的 copy/move 构造函数。否则,无论它们的内容如何,​​它们都必须在调用函数提供的内存中构造。如果 class 是普通可复制的,那么你就无法区分省略和非省略。

如果 ABI 任意决定 return 值(可能还有参数)相对于彼此的存储位置,ABI 可能对该功能造成问题的唯一方式。也就是说,ABI 强制调用者将对象放在堆栈上相对于参数的特定位置。

这样的 ABI 可能存在吗?我没有特别的知识可以说它不能。可以?我对此表示怀疑,因为这样的 ABI 通常会使省略变得非常困难。