// 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<const CXXMethodDecl *, 1> MethodGroup;
SmallVector<MethodGroup, 10> Groups;
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);
}
// 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)
// 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;