summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/VTableBuilder.cpp
diff options
context:
space:
mode:
authorTimur Iskhodzhanov <timurrrr@google.com>2013-10-06 15:31:37 +0000
committerTimur Iskhodzhanov <timurrrr@google.com>2013-10-06 15:31:37 +0000
commit20df98c0d002f7e91b54f1eb74f61615f2bc18c0 (patch)
tree4e5c5723897cd3def9a7d7d5302af58b7e95d49d /clang/lib/AST/VTableBuilder.cpp
parent78527050c28fcdb57c0d24a10b55ab43dc4e5412 (diff)
downloadbcm5719-llvm-20df98c0d002f7e91b54f1eb74f61615f2bc18c0.tar.gz
bcm5719-llvm-20df98c0d002f7e91b54f1eb74f61615f2bc18c0.zip
Fix PR17382 - properly group virtual method overloads in the vftable
llvm-svn: 192067
Diffstat (limited to 'clang/lib/AST/VTableBuilder.cpp')
-rw-r--r--clang/lib/AST/VTableBuilder.cpp44
1 files changed, 38 insertions, 6 deletions
diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp
index c28aeefd99d..9aad711748c 100644
--- a/clang/lib/AST/VTableBuilder.cpp
+++ b/clang/lib/AST/VTableBuilder.cpp
@@ -2730,6 +2730,38 @@ FindDirectlyOverriddenMethodInBases(const CXXMethodDecl *MD,
return 0;
}
+static void GroupNewVirtualOverloads(
+ const CXXRecordDecl *RD,
+ SmallVector<const CXXMethodDecl *, 10> &VirtualMethods) {
+ // 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).
+ // 2) In each group, new overloads appear in the reverse order of declaration.
+ typedef SmallVector<const CXXMethodDecl *, 1> MethodGroup;
+ SmallVector<MethodGroup, 10> Groups;
+ typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy;
+ VisitedGroupIndicesTy VisitedGroupIndices;
+ 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[J->second].push_back(MD);
+ }
+
+ for (unsigned I = 0, E = Groups.size(); I != E; ++I)
+ VirtualMethods.append(Groups[I].rbegin(), Groups[I].rend());
+}
+
void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
const CXXRecordDecl *LastVBase,
BasesSetVectorTy &VisitedBases) {
@@ -2766,6 +2798,10 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
llvm_unreachable("Found a duplicate primary base!");
}
+ SmallVector<const CXXMethodDecl*, 10> VirtualMethods;
+ // Put virtual methods in the proper order.
+ GroupNewVirtualOverloads(RD, VirtualMethods);
+
// Now go through all virtual member functions and add them to the current
// vftable. This is done by
// - replacing overridden methods in their existing slots, as long as they
@@ -2774,12 +2810,8 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
// sub-bases;
// - adding new slots for methods that require Return adjustment.
// We keep track of the methods visited in the sub-bases in MethodInfoMap.
- for (CXXRecordDecl::method_iterator I = RD->method_begin(),
- E = RD->method_end(); I != E; ++I) {
- const CXXMethodDecl *MD = *I;
-
- if (!MD->isVirtual())
- continue;
+ for (unsigned I = 0, E = VirtualMethods.size(); I != E; ++I) {
+ const CXXMethodDecl *MD = VirtualMethods[I];
FinalOverriders::OverriderInfo Overrider =
Overriders.getOverrider(MD, Base.getBaseOffset());
OpenPOWER on IntegriCloud