From 153fe11633e48f661da0e18d6979e6db04d9e0b9 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Wed, 19 Feb 2014 22:06:10 +0000 Subject: [PATCH] MS ABI: Let non-virtual method overloads participate in vftable ordering In the Microsoft ABI, the vftable is laid out as if all methods in every overload set were declared in reverse order of declaration at the point of declaration of the first overload in the set. Previously we only considered virtual methods in an overload set, but MSVC includes non-virtual methods for ordering purposes. Fixes PR18902. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@201722 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/VTableBuilder.cpp | 8 +++--- ...crosoft-abi-vtables-single-inheritance.cpp | 27 +++++++++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/lib/AST/VTableBuilder.cpp b/lib/AST/VTableBuilder.cpp index 30f95d0f25..e0e30a122a 100644 --- a/lib/AST/VTableBuilder.cpp +++ b/lib/AST/VTableBuilder.cpp @@ -2789,7 +2789,7 @@ static void GroupNewVirtualOverloads( // Put the virtual methods into VirtualMethods in the proper order: // 1) Group overloads by declaration name. New groups are added to the // vftable in the order of their first declarations in this class - // (including overrides). + // (including overrides and non-virtual methods). // 2) In each group, new overloads appear in the reverse order of declaration. typedef SmallVector MethodGroup; SmallVector Groups; @@ -2798,16 +2798,14 @@ static void GroupNewVirtualOverloads( for (CXXRecordDecl::method_iterator I = RD->method_begin(), E = RD->method_end(); I != E; ++I) { const CXXMethodDecl *MD = *I; - if (!MD->isVirtual()) - continue; VisitedGroupIndicesTy::iterator J; bool Inserted; llvm::tie(J, Inserted) = VisitedGroupIndices.insert( std::make_pair(MD->getDeclName(), Groups.size())); if (Inserted) - Groups.push_back(MethodGroup(1, MD)); - else + Groups.push_back(MethodGroup()); + if (I->isVirtual()) Groups[J->second].push_back(MD); } diff --git a/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp index 428d9ee7da..088ed17ee6 100644 --- a/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp +++ b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp @@ -15,6 +15,8 @@ // RUN: FileCheck --check-prefix=CHECK-M %s < %t // RUN: FileCheck --check-prefix=CHECK-N %s < %t // RUN: FileCheck --check-prefix=CHECK-O %s < %t +// RUN: FileCheck --check-prefix=CHECK-Q %s < %t +// RUN: FileCheck --check-prefix=CHECK-R %s < %t struct A { // CHECK-A: VFTable for 'A' (3 entries) @@ -260,3 +262,28 @@ P p; // CHECK-O: VFTable for 'O' (1 entries) // CHECK-O-NEXT: 0 | A *O::f() + +struct Q { + // CHECK-Q: VFTable for 'Q' (2 entries) + // CHECK-Q-NEXT: 0 | void Q::foo(int) + // CHECK-Q-NEXT: 1 | void Q::bar(int) + void foo(short); + void bar(short); + virtual void bar(int); + virtual void foo(int); +}; + +Q q; + +// Inherited non-virtual overloads don't participate in the ordering. +struct R : Q { + // CHECK-R: VFTable for 'Q' in 'R' (4 entries) + // CHECK-R-NEXT: 0 | void Q::foo(int) + // CHECK-R-NEXT: 1 | void Q::bar(int) + // CHECK-R-NEXT: 2 | void R::bar(long) + // CHECK-R-NEXT: 3 | void R::foo(long) + virtual void bar(long); + virtual void foo(long); +}; + +R r; -- 2.40.0