]> granicus.if.org Git - clang/commitdiff
[MS ABI] Let arbitrary entities participate in vftable ordering
authorDavid Majnemer <david.majnemer@gmail.com>
Thu, 19 Nov 2015 00:03:54 +0000 (00:03 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Thu, 19 Nov 2015 00:03:54 +0000 (00:03 +0000)
In the Microsoft ABI, the vftable is laid out in the order in the
declaration order of the entities defined within it.

Obviously, only virtual methods end up in the vftable but they will be
placed into the table at the same position as the first entity with the
same name.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@253523 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/VTableBuilder.cpp
test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp

index 6829da5bb142c00dbbcb141356636f60bdc959f5..bae018652f917eab7412c3671b0da5d45ff1bb44 100644 (file)
@@ -2882,22 +2882,26 @@ 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 and non-virtual methods).
+  //    (including overrides, non-virtual methods and any other named decl that
+  //    might be nested within the class).
   // 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 (const auto *MD : RD->methods()) {
-    MD = MD->getCanonicalDecl();
+  for (const auto *D : RD->decls()) {
+    const auto *ND = dyn_cast<NamedDecl>(D);
+    if (!ND)
+      continue;
     VisitedGroupIndicesTy::iterator J;
     bool Inserted;
     std::tie(J, Inserted) = VisitedGroupIndices.insert(
-        std::make_pair(MD->getDeclName(), Groups.size()));
+        std::make_pair(ND->getDeclName(), Groups.size()));
     if (Inserted)
       Groups.push_back(MethodGroup());
-    if (MD->isVirtual())
-      Groups[J->second].push_back(MD);
+    if (const auto *MD = dyn_cast<CXXMethodDecl>(ND))
+      if (MD->isVirtual())
+        Groups[J->second].push_back(MD->getCanonicalDecl());
   }
 
   for (const MethodGroup &Group : Groups)
index baed35145f98dc9cd115e2b1044eae70c28f4141..aa39d6de615a6079eb777513c57daacdcb60f1ea 100644 (file)
@@ -299,3 +299,18 @@ struct S {
 };
 
 S::S() {}
+
+struct T {
+  struct U {};
+};
+struct V : T {
+  // CHECK-LABEL: VFTable for 'V' (2 entries).
+  // CHECK-NEXT:   0 | void V::U()
+  // CHECK-NEXT:   1 | void V::f()
+  using T::U;
+  virtual void f();
+  virtual void U();
+  V();
+};
+
+V::V() {}