D / DLang:禁止生成模块私有内联函数的代码

时间:2017-02-27 19:31:18

标签: gcc module d information-hiding

我有一个D模块,我希望包含公共和私人部分。我尝试在函数定义之前使用关键字private和static。我有一个功能,我希望外部可调用/公开,理想情况下,我希望它在呼叫站点内联。此函数调用其他旨在为私有的模块内部函数,即不可从外部调用。在模块中成功地对这些调用进行了内联,并且CTFE加上已知的常量传播处理了许多错误。但是,GDC编译器还会生成这些内部例程的副本,即使它们已经在需要的地方内联并且它们不应该是外部可调用的。我正在使用-O3 -frelease进行编译。我应该做什么 - 即使我使用静态和/或私有,我应该期待这个吗?

我还简要介绍了这个thread concerning GCC希望有识之士。

正如我之前提到的,我已尝试在这些内部函数上使用私有和静态,但我似乎无法抑制代码生成。如果一个调试器需要有这些例程的副本来设置断点,我可以理解这一点。我需要强调的是,这可能在链接时以某种方式解决,我所知道的。我还没有尝试过连接程序,我只是使用GDC查看Matt Godbolt D Compiler Explorer中生成的代码。所有内容都可以制作成模板,其中包含零长度的模板参数列表(例如,自动my_fn()(在arg_t x中)),尝试过,它没有帮助,但没有任何伤害。

还有一些其他的尝试:我可以尝试使用私有部分创建一个静态类,作为实现包的方式,Ada风格。 (需要严格单一实例。)我从来没有做过任何C ++,只有大量的asm和C专业。这将是一个学习曲线。

我唯一能想到的是使用嵌套函数定义,Pascal / Ada风格,将内部例程移动到其调用者体内。但这有很多缺点。

粗略的例子

module junk;

auto my_public_fn() {  return my_private_fn();  }

private
static // 'static' and/or 'private', tried both
auto my_private_fn() { xxx ; return whatever; }

1 个答案:

答案 0 :(得分:2)

我刚与Iain就此进行了简短的讨论,实现这一点并不像看起来那么简单。

首先,static在D中有很多含义,但翻译单元本地函数的C含义不是其中之一; - )

因此将这些函数标记为private似乎很直观。毕竟,如果您无法从翻译单元外部访问某个功能,并且您从未向该功能泄漏地址,为什么不将其删除?在这种情况下,它可以完全未使用或内联到所有呼叫者。

现在抓住了:我们无法确定函数是否未被使用:

private void fooPrivate() {}

/*template*/ void fooPublic()()
{
    fooPrivate();
}

编译文件时,GDC对fooPublic模板一无所知(因为模板只能在实例化时进行全面分析),因此fooPrivate似乎未被使用。稍后在其他文件中使用fooPublic时,GDC将依赖于原始来源中已发布的fooPrivate - 毕竟它不是模板,因此它不会被发送到新模块。

可能有解决方法,但整个问题似乎并不重要。我们还可以为此引入自定义gcc.attribute属性。它会导致模板出现同样的问题,但由于它是一个用例的特定注释(与private不同),我们可以依赖用户做正确的事情。