]> granicus.if.org Git - clang/commitdiff
[CodeGen] Set construction vtable visibility after creating initializer
authorPetr Hosek <phosek@chromium.org>
Mon, 11 Feb 2019 20:13:42 +0000 (20:13 +0000)
committerPetr Hosek <phosek@chromium.org>
Mon, 11 Feb 2019 20:13:42 +0000 (20:13 +0000)
We must only set the construction vtable visibility after we create the
vtable initializer, otherwise the global value will be treated as
declaration rather than definition and the visibility won't be set.

Differential Revision: https://reviews.llvm.org/D58010

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@353742 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGVTables.cpp
test/CodeGen/construction-vtable-visibility.cpp [new file with mode: 0644]

index a7b81a01f7fc81cb0e17038ad892550a082f893a..3cb3d354483893a5669be1934940f1ece9f1c9f9 100644 (file)
@@ -761,7 +761,6 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
   // Create the variable that will hold the construction vtable.
   llvm::GlobalVariable *VTable =
       CGM.CreateOrReplaceCXXRuntimeVariable(Name, VTType, Linkage, Align);
-  CGM.setGVProperties(VTable, RD);
 
   // V-tables are always unnamed_addr.
   VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
@@ -775,6 +774,11 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
   createVTableInitializer(components, *VTLayout, RTTI);
   components.finishAndSetAsInitializer(VTable);
 
+  // Set properties only after the initializer has been set to ensure that the
+  // GV is treated as definition and not declaration.
+  assert(!VTable->isDeclaration() && "Shouldn't set properties on declaration");
+  CGM.setGVProperties(VTable, RD);
+
   CGM.EmitVTableTypeMetadata(VTable, *VTLayout.get());
 
   return VTable;
diff --git a/test/CodeGen/construction-vtable-visibility.cpp b/test/CodeGen/construction-vtable-visibility.cpp
new file mode 100644 (file)
index 0000000..127e1b1
--- /dev/null
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple x86_64-linux-unknown -fvisibility hidden -emit-llvm %s -o - | FileCheck %s
+
+struct Base {};
+
+class Parent1 : virtual public Base {};
+
+class Parent2 : virtual public Base {};
+
+class Child : public Parent1, public Parent2 {};
+
+void test() {
+  Child x;
+}
+
+// CHECK: @_ZTC5Child0_7Parent1 = linkonce_odr hidden unnamed_addr constant
+// CHECK: @_ZTC5Child8_7Parent2 = linkonce_odr hidden unnamed_addr constant