[PATCH] [ms-cxxabi] There are no key functions in the Microsoft C++ ABI

Reid Kleckner rnk at google.com
Tue May 21 11:41:38 PDT 2013


Hi pcc,

MSVC's class data is always comdat, so clang's should always be
linkonce_odr in LLVM IR.

http://llvm-reviews.chandlerc.com/D838

Files:
  include/clang/Basic/TargetCXXABI.h
  lib/AST/RecordLayoutBuilder.cpp
  test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp

Index: include/clang/Basic/TargetCXXABI.h
===================================================================
--- include/clang/Basic/TargetCXXABI.h
+++ include/clang/Basic/TargetCXXABI.h
@@ -152,6 +152,13 @@
     return isItaniumFamily();
   }
 
+  /// \brief Does this ABI use key functions?  If so, class data such as the
+  /// vtable is emitted with strong linkage by the TU containing the key
+  /// function.
+  bool hasKeyFunctions() const {
+    return isItaniumFamily();
+  }
+
   /// \brief Can an out-of-line inline function serve as a key function?
   ///
   /// This flag is only useful in ABIs where type data (for example,
Index: lib/AST/RecordLayoutBuilder.cpp
===================================================================
--- lib/AST/RecordLayoutBuilder.cpp
+++ lib/AST/RecordLayoutBuilder.cpp
@@ -2546,6 +2546,9 @@
 }
 
 const CXXMethodDecl *ASTContext::getCurrentKeyFunction(const CXXRecordDecl *RD) {
+  if (!getTargetInfo().getCXXABI().hasKeyFunctions())
+    return 0;
+
   assert(RD->getDefinition() && "Cannot get key function for forward decl!");
   RD = cast<CXXRecordDecl>(RD->getDefinition());
 
Index: test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
===================================================================
--- test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
+++ test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
@@ -8,41 +8,49 @@
 // RUN: FileCheck --check-prefix=CHECK-F %s < %t
 // RUN: FileCheck --check-prefix=CHECK-G %s < %t
 
+// We call the ctors from a static initializer, so all vtables are used.  For
+// some reason when the vtables used by initializers, they come out in reverse
+// order, so we have to pull them out.
+// EMITS-VTABLE-NOT: @"\01??_7G@@6B@"
+// EMITS-VTABLE: @"\01??_7F@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*]
+// EMITS-VTABLE-NOT: @"\01??_7E@@6B@"
+// EMITS-VTABLE: @"\01??_7D@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*]
+// EMITS-VTABLE-NOT: @"\01??_7C@@6B@"
+// EMITS-VTABLE: @"\01??_7B@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*]
+// EMITS-VTABLE: @"\01??_7A@@6B@" = linkonce_odr unnamed_addr constant [3 x i8*]
+
 struct A {
   // CHECK-A: Vtable for 'A' (3 entries)
   // CHECK-A-NEXT: 0 | void A::f()
   // CHECK-A-NEXT: 1 | void A::g()
   // CHECK-A-NEXT: 2 | void A::h()
-  // EMITS-VTABLE: @"\01??_7A@@6B@" = unnamed_addr constant [3 x i8*]
   virtual void f();
   virtual void g();
   virtual void h();
   int ia;
 };
-void A::f() {}
+A a;
 
 struct B : A {
   // CHECK-B: Vtable for 'B' (5 entries)
   // CHECK-B-NEXT: 0 | void B::f()
   // CHECK-B-NEXT: 1 | void A::g()
   // CHECK-B-NEXT: 2 | void A::h()
   // CHECK-B-NEXT: 3 | void B::i()
   // CHECK-B-NEXT: 4 | void B::j()
-  // EMITS-VTABLE: @"\01??_7B@@6B@" = unnamed_addr constant [5 x i8*]
   virtual void f();  // overrides A::f()
   virtual void i();
   virtual void j();
 };
-void B::f() {}
+B b;
 
 struct C {
   // CHECK-C: Vtable for 'C' (2 entries)
   // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]
   // CHECK-C-NEXT: 1 | void C::f()
   // CHECK-C: VTable indices for 'C' (2 entries).
   // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]
   // CHECK-C-NEXT: 1 | void C::f()
-  // Never used, so doesn't emit a vtable.
   virtual ~C();
 
   virtual void f();
@@ -53,12 +61,11 @@
   // CHECK-D: Vtable for 'D' (2 entries)
   // CHECK-D-NEXT: 0 | void D::f()
   // CHECK-D-NEXT: 1 | D::~D() [scalar deleting]
-  // EMITS-VTABLE: @"\01??_7D@@6B@" = unnamed_addr constant [2 x i8*]
   virtual void f();
 
   virtual ~D();
 };
-void D::f() {}
+D d;
 
 struct E : A {
   // CHECK-E: Vtable for 'E' (5 entries)
@@ -71,7 +78,8 @@
   // CHECK-E-NEXT: 3 | E::~E() [scalar deleting]
   // CHECK-E-NEXT: 4 | void E::i()
 
-  // Never used, so doesn't emit a vtable.
+  // ~E would be the key method, but it isn't used, and MS ABI has no key
+  // methods.
   virtual ~E();
   virtual void i();
 };
@@ -87,11 +95,10 @@
   // CHECK-F: VTable indices for 'F' (2 entries).
   // CHECK-F-NEXT: 3 | void F::i()
   // CHECK-F-NEXT: 4 | F::~F() [scalar deleting]
-  // EMITS-VTABLE: @"\01??_7F@@6B@" = unnamed_addr constant [5 x i8*]
   virtual void i();
   virtual ~F();
 };
-void F::i() {}
+F f;
 
 struct G : E {
   // CHECK-G: Vtable for 'G' (6 entries)
@@ -105,7 +112,6 @@
   // CHECK-G-NEXT: 0 | void G::f()
   // CHECK-G-NEXT: 3 | G::~G() [scalar deleting]
   // CHECK-G-NEXT: 5 | void G::j()
-  // Never used, so doesn't emit a vtable.
   virtual void f();  // overrides A::f()
   virtual ~G();
   virtual void j();
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D838.1.patch
Type: text/x-patch
Size: 4525 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130521/77012c3a/attachment.bin>


More information about the cfe-commits mailing list