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

Reid Kleckner rnk at google.com
Tue May 28 06:20:50 PDT 2013


Ping


On Tue, May 21, 2013 at 2:41 PM, Reid Kleckner <rnk at google.com> wrote:

> 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 --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130528/960765e6/attachment.html>


More information about the cfe-commits mailing list