<div dir="ltr">Ping</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, May 21, 2013 at 2:41 PM, Reid Kleckner <span dir="ltr"><<a href="mailto:rnk@google.com" target="_blank">rnk@google.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi pcc,<br>
<br>
MSVC's class data is always comdat, so clang's should always be<br>
linkonce_odr in LLVM IR.<br>
<br>
<a href="http://llvm-reviews.chandlerc.com/D838" target="_blank">http://llvm-reviews.chandlerc.com/D838</a><br>
<br>
Files:<br>
  include/clang/Basic/TargetCXXABI.h<br>
  lib/AST/RecordLayoutBuilder.cpp<br>
  test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp<br>
<br>
Index: include/clang/Basic/TargetCXXABI.h<br>
===================================================================<br>
--- include/clang/Basic/TargetCXXABI.h<br>
+++ include/clang/Basic/TargetCXXABI.h<br>
@@ -152,6 +152,13 @@<br>
     return isItaniumFamily();<br>
   }<br>
<br>
+  /// \brief Does this ABI use key functions?  If so, class data such as the<br>
+  /// vtable is emitted with strong linkage by the TU containing the key<br>
+  /// function.<br>
+  bool hasKeyFunctions() const {<br>
+    return isItaniumFamily();<br>
+  }<br>
+<br>
   /// \brief Can an out-of-line inline function serve as a key function?<br>
   ///<br>
   /// This flag is only useful in ABIs where type data (for example,<br>
Index: lib/AST/RecordLayoutBuilder.cpp<br>
===================================================================<br>
--- lib/AST/RecordLayoutBuilder.cpp<br>
+++ lib/AST/RecordLayoutBuilder.cpp<br>
@@ -2546,6 +2546,9 @@<br>
 }<br>
<br>
 const CXXMethodDecl *ASTContext::getCurrentKeyFunction(const CXXRecordDecl *RD) {<br>
+  if (!getTargetInfo().getCXXABI().hasKeyFunctions())<br>
+    return 0;<br>
+<br>
   assert(RD->getDefinition() && "Cannot get key function for forward decl!");<br>
   RD = cast<CXXRecordDecl>(RD->getDefinition());<br>
<br>
Index: test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp<br>
===================================================================<br>
--- test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp<br>
+++ test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp<br>
@@ -8,41 +8,49 @@<br>
 // RUN: FileCheck --check-prefix=CHECK-F %s < %t<br>
 // RUN: FileCheck --check-prefix=CHECK-G %s < %t<br>
<br>
+// We call the ctors from a static initializer, so all vtables are used.  For<br>
+// some reason when the vtables used by initializers, they come out in reverse<br>
+// order, so we have to pull them out.<br>
+// EMITS-VTABLE-NOT: @"\01??_7G@@6B@"<br>
+// EMITS-VTABLE: @"\01??_7F@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*]<br>
+// EMITS-VTABLE-NOT: @"\01??_7E@@6B@"<br>
+// EMITS-VTABLE: @"\01??_7D@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*]<br>
+// EMITS-VTABLE-NOT: @"\01??_7C@@6B@"<br>
+// EMITS-VTABLE: @"\01??_7B@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*]<br>
+// EMITS-VTABLE: @"\01??_7A@@6B@" = linkonce_odr unnamed_addr constant [3 x i8*]<br>
+<br>
 struct A {<br>
   // CHECK-A: Vtable for 'A' (3 entries)<br>
   // CHECK-A-NEXT: 0 | void A::f()<br>
   // CHECK-A-NEXT: 1 | void A::g()<br>
   // CHECK-A-NEXT: 2 | void A::h()<br>
-  // EMITS-VTABLE: @"\01??_7A@@6B@" = unnamed_addr constant [3 x i8*]<br>
   virtual void f();<br>
   virtual void g();<br>
   virtual void h();<br>
   int ia;<br>
 };<br>
-void A::f() {}<br>
+A a;<br>
<br>
 struct B : A {<br>
   // CHECK-B: Vtable for 'B' (5 entries)<br>
   // CHECK-B-NEXT: 0 | void B::f()<br>
   // CHECK-B-NEXT: 1 | void A::g()<br>
   // CHECK-B-NEXT: 2 | void A::h()<br>
   // CHECK-B-NEXT: 3 | void B::i()<br>
   // CHECK-B-NEXT: 4 | void B::j()<br>
-  // EMITS-VTABLE: @"\01??_7B@@6B@" = unnamed_addr constant [5 x i8*]<br>
   virtual void f();  // overrides A::f()<br>
   virtual void i();<br>
   virtual void j();<br>
 };<br>
-void B::f() {}<br>
+B b;<br>
<br>
 struct C {<br>
   // CHECK-C: Vtable for 'C' (2 entries)<br>
   // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]<br>
   // CHECK-C-NEXT: 1 | void C::f()<br>
   // CHECK-C: VTable indices for 'C' (2 entries).<br>
   // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]<br>
   // CHECK-C-NEXT: 1 | void C::f()<br>
-  // Never used, so doesn't emit a vtable.<br>
   virtual ~C();<br>
<br>
   virtual void f();<br>
@@ -53,12 +61,11 @@<br>
   // CHECK-D: Vtable for 'D' (2 entries)<br>
   // CHECK-D-NEXT: 0 | void D::f()<br>
   // CHECK-D-NEXT: 1 | D::~D() [scalar deleting]<br>
-  // EMITS-VTABLE: @"\01??_7D@@6B@" = unnamed_addr constant [2 x i8*]<br>
   virtual void f();<br>
<br>
   virtual ~D();<br>
 };<br>
-void D::f() {}<br>
+D d;<br>
<br>
 struct E : A {<br>
   // CHECK-E: Vtable for 'E' (5 entries)<br>
@@ -71,7 +78,8 @@<br>
   // CHECK-E-NEXT: 3 | E::~E() [scalar deleting]<br>
   // CHECK-E-NEXT: 4 | void E::i()<br>
<br>
-  // Never used, so doesn't emit a vtable.<br>
+  // ~E would be the key method, but it isn't used, and MS ABI has no key<br>
+  // methods.<br>
   virtual ~E();<br>
   virtual void i();<br>
 };<br>
@@ -87,11 +95,10 @@<br>
   // CHECK-F: VTable indices for 'F' (2 entries).<br>
   // CHECK-F-NEXT: 3 | void F::i()<br>
   // CHECK-F-NEXT: 4 | F::~F() [scalar deleting]<br>
-  // EMITS-VTABLE: @"\01??_7F@@6B@" = unnamed_addr constant [5 x i8*]<br>
   virtual void i();<br>
   virtual ~F();<br>
 };<br>
-void F::i() {}<br>
+F f;<br>
<br>
 struct G : E {<br>
   // CHECK-G: Vtable for 'G' (6 entries)<br>
@@ -105,7 +112,6 @@<br>
   // CHECK-G-NEXT: 0 | void G::f()<br>
   // CHECK-G-NEXT: 3 | G::~G() [scalar deleting]<br>
   // CHECK-G-NEXT: 5 | void G::j()<br>
-  // Never used, so doesn't emit a vtable.<br>
   virtual void f();  // overrides A::f()<br>
   virtual ~G();<br>
   virtual void j();<br>
</blockquote></div><br></div>