符号可见性和 gcc 警告

Symbol visibility and gcc warnings

这是 Symbol visibility and namespace

的后续问题

我将稍微修改示例,因为它实际上与命名空间无关:

namespace MyDSO {
  struct __attribute__ ((visibility ("hidden"))) Foo {
    void bar() {}
  };
}

struct Bar {
  MyDSO::Foo foo;
};

int main() {}

通过 gcc example.cpp -o example 编译会发出警告 ‘Bar’ declared with greater visibility than the type of its field ‘Bar::foo’,如链接问题中所示。

问题:为什么如果我

收到警告

a) 显式地为 struct Bar 添加默认可见性,即我有

namespace MyDSO {
  struct __attribute__ ((visibility ("hidden"))) Foo {
    void bar() {}
  };
}

struct __attribute__ ((visibility ("default"))) Bar {
  MyDSO::Foo foo;
};

int main() {}

b) 删除隐藏可见性,为 Bar 添加默认可见性并使用 -fvisibility="hidden"?

编译

在我看来,最终结果是一样的,事实上,所有的二进制文件都是完全一样的(gcc 7.3.1,还有更旧的)。如果我将这两个结构拆分为两个 类 并用它们构建静态库,则符号表 (objdump -t -C) 包含完全相同的符号和完全相同的修饰符(全局、局部等),仅第一列(虚拟地址)中的一些条目不同。

在这两种情况下,明确的可见性属性是在每个 class 基础上消除警告的预期方式。来自 gcc/cp/decl2.c:

/* Don't warn about visibility if the class has explicit visibility.  */
if (CLASSTYPE_VISIBILITY_SPECIFIED (type))
  vis = VISIBILITY_INTERNAL;