]> granicus.if.org Git - clang/commitdiff
Keep track of the address points for all primary bases, and add the ability to dump...
authorAnders Carlsson <andersca@mac.com>
Fri, 12 Feb 2010 07:43:48 +0000 (07:43 +0000)
committerAnders Carlsson <andersca@mac.com>
Fri, 12 Feb 2010 07:43:48 +0000 (07:43 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95970 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGVtable.cpp
test/CodeGenCXX/vtable-layout.cpp

index e2ea4736d3054e9c31034e66fac2d725499a3058..226be1972e2a1e61192431489f886fefbb4ed214 100644 (file)
@@ -16,6 +16,7 @@
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/RecordLayout.h"
 #include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Format.h"
 #include <cstdio>
 
@@ -608,14 +609,26 @@ void VtableBuilder::layoutSimpleVtable(BaseSubobject Base) {
   // Next, add the RTTI.
   Components.push_back(VtableComponent::MakeRTTI(RD));
   
-  // Record the address point.
-  // FIXME: Record the address point for all primary bases.
-  AddressPoints.insert(std::make_pair(Base, Components.size()));
+  uint64_t AddressPoint = Components.size();
 
   // Now go through all virtual member functions and add them.
   PrimaryBasesSetTy PrimaryBases;
   layoutVirtualMemberFunctions(Base, PrimaryBases);
 
+  // Record the address point.
+  AddressPoints.insert(std::make_pair(Base, AddressPoint));
+  
+  // Record the address points for all primary bases.
+  for (PrimaryBasesSetTy::const_iterator I = PrimaryBases.begin(),
+       E = PrimaryBases.end(); I != E; ++I) {
+    const CXXRecordDecl *BaseDecl = *I;
+    
+    // We know that all the primary bases have the same offset as the base
+    // subobject.
+    BaseSubobject PrimaryBase(BaseDecl, Base.getBaseOffset());
+    AddressPoints.insert(std::make_pair(PrimaryBase, AddressPoint));
+  }
+
   const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
   const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
 
@@ -655,16 +668,40 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
   }
   
   for (unsigned I = 0, E = Components.size(); I != E; ++I) {
+    uint64_t Index = I;
+    
     if (AddressPointsByIndex.count(I)) {
-      assert(AddressPointsByIndex.count(I) == 1 &&
-             "FIXME: Handle dumping multiple base subobjects for a single "
-             "address point!");
-      
-      const BaseSubobject &Base = AddressPointsByIndex.find(I)->second;
-      Out << "       -- (" << Base.getBase()->getQualifiedNameAsString();
+      std::string Str;
+
       
-      // FIXME: Instead of dividing by 8, we should be using CharUnits.
-      Out << ", " << Base.getBaseOffset() / 8 << ") vtable address --\n";
+      if (AddressPointsByIndex.count(Index) == 1) {
+        const BaseSubobject &Base = AddressPointsByIndex.find(Index)->second;
+        
+        // FIXME: Instead of dividing by 8, we should be using CharUnits.
+        Out << "       -- (" << Base.getBase()->getQualifiedNameAsString();
+        Out << ", " << Base.getBaseOffset() / 8 << ") vtable address --\n";
+      } else {
+        uint64_t BaseOffset = 
+          AddressPointsByIndex.lower_bound(Index)->second.getBaseOffset();
+        
+        // We store the class names in a set to get a stable order.
+        std::set<std::string> ClassNames;
+        for (std::multimap<uint64_t, BaseSubobject>::const_iterator I =
+             AddressPointsByIndex.lower_bound(Index), E =
+             AddressPointsByIndex.upper_bound(Index); I != E; ++I) {
+          assert(I->second.getBaseOffset() == BaseOffset &&
+                 "Invalid base offset!");
+          const CXXRecordDecl *RD = I->second.getBase();
+          ClassNames.insert(RD->getQualifiedNameAsString());
+        }
+        
+        for (std::set<std::string>::const_iterator I = ClassNames.begin(),
+             E = ClassNames.end(); I != E; ++I) {
+          // FIXME: Instead of dividing by 8, we should be using CharUnits.
+          Out << "       -- (" << *I;
+          Out << ", " << BaseOffset / 8 << ") vtable address --\n";
+        }
+      }
     }
 
     Out << llvm::format("%4d | ", I);
index 6cc1b0b691eea4359cf91f3ad95c10e470fb200c..b9054410a90d1e996372e7a37eb9c8ae7c6bfdba 100644 (file)
@@ -76,6 +76,7 @@ void A::f() { }
 // CHECK:     Vtable for 'Test3::B' (4 entries).
 // CHECK-NEXT:  0 | offset_to_top (0)
 // CHECK-NEXT:  1 | Test3::B RTTI
+// CHECK-NEXT:      -- (Test3::A, 0) vtable address --
 // CHECK-NEXT:      -- (Test3::B, 0) vtable address --
 // CHECK-NEXT:  2 | void Test3::A::f()
 // CHECK-NEXT:  3 | void Test3::B::g()
@@ -88,6 +89,7 @@ void B::f() { }
 // CHECK:     Vtable for 'Test3::C' (5 entries).
 // CHECK-NEXT:  0 | offset_to_top (0)
 // CHECK-NEXT:  1 | Test3::C RTTI
+// CHECK-NEXT:     -- (Test3::A, 0) vtable address --
 // CHECK-NEXT:     -- (Test3::C, 0) vtable address --
 // CHECK-NEXT:  2 | void Test3::A::f()
 // CHECK-NEXT:  3 | void Test3::C::g()
@@ -101,6 +103,8 @@ void C::g() { }
 // CHECK:     Vtable for 'Test3::D' (5 entries).
 // CHECK-NEXT:  0 | offset_to_top (0)
 // CHECK-NEXT:  1 | Test3::D RTTI
+// CHECK-NEXT:     -- (Test3::A, 0) vtable address --
+// CHECK-NEXT:     -- (Test3::B, 0) vtable address --
 // CHECK-NEXT:     -- (Test3::D, 0) vtable address --
 // CHECK-NEXT:  2 | void Test3::A::f()
 // CHECK-NEXT:  3 | void Test3::B::g()