]> granicus.if.org Git - clang/commitdiff
Handle virtual bases in ComputeBaseOffset.
authorAnders Carlsson <andersca@mac.com>
Sat, 13 Feb 2010 20:41:15 +0000 (20:41 +0000)
committerAnders Carlsson <andersca@mac.com>
Sat, 13 Feb 2010 20:41:15 +0000 (20:41 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96117 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGVtable.cpp

index 7d3f35f077aec8e9cedbf3172b0350713d414d36..f7b8c53d0214e3ad9dd34d2c505ea038b496881d 100644 (file)
@@ -288,7 +288,7 @@ ComputeBaseOffset(ASTContext &Context,
                   const CXXRecordDecl *DerivedRD,
                   const CXXRecordDecl *BaseRD) {
   CXXBasePaths Paths(/*FindAmbiguities=*/false,
-                     /*RecordPaths=*/true, /*DetectVirtual=*/true);
+                     /*RecordPaths=*/true, /*DetectVirtual=*/false);
   
   if (!const_cast<CXXRecordDecl *>(DerivedRD)->
       isDerivedFrom(const_cast<CXXRecordDecl *>(BaseRD), Paths)) {
@@ -296,15 +296,30 @@ ComputeBaseOffset(ASTContext &Context,
     return FinalOverriders::BaseOffset();
   }
 
-  assert(!Paths.getDetectedVirtual() && 
-         "FIXME: Handle virtual bases!");
-
   uint64_t NonVirtualOffset = 0;
 
   const CXXBasePath &Path = Paths.front();
   
-  for (size_t Start = 0, End = Path.size(); Start != End; ++Start) {
-    const CXXBasePathElement &Element = Path[Start];
+  unsigned NonVirtualStart = 0;
+  const CXXRecordDecl *VirtualBase = 0;
+  
+  // First, look for the virtual base class.
+  for (unsigned I = 0, E = Path.size(); I != E; ++I) {
+    const CXXBasePathElement &Element = Path[I];
+    
+    if (Element.Base->isVirtual()) {
+      // FIXME: Can we break when we find the first virtual base?
+      // (If we can't, can't we just iterate over the path in reverse order?)
+      NonVirtualStart = I + 1;
+      QualType VBaseType = Element.Base->getType();
+      VirtualBase = 
+        cast<CXXRecordDecl>(VBaseType->getAs<RecordType>()->getDecl());
+    }
+  }
+  
+  // Now compute the non-virtual offset.
+  for (unsigned I = NonVirtualStart, E = Path.size(); I != E; ++I) {
+    const CXXBasePathElement &Element = Path[I];
     
     // Check the base class offset.
     const ASTRecordLayout &Layout = Context.getASTRecordLayout(Element.Class);
@@ -318,7 +333,7 @@ ComputeBaseOffset(ASTContext &Context,
   // FIXME: This should probably use CharUnits or something. Maybe we should
   // even change the base offsets in ASTRecordLayout to be specified in 
   // CharUnits.
-  return FinalOverriders::BaseOffset(0, NonVirtualOffset / 8);
+  return FinalOverriders::BaseOffset(VirtualBase, NonVirtualOffset / 8);
 }
 
 static FinalOverriders::BaseOffset
@@ -510,10 +525,12 @@ void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base) const {
       ReturnAdjustments.find(std::make_pair(Base, MD));
     if (AI != ReturnAdjustments.end()) {
       const BaseOffset &Offset = AI->second;
-      
-      assert(!Offset.VirtualBase && "FIXME: Handle vbases!");
+
+      Out << " [ret-adj: ";
+      if (Offset.VirtualBase)
+        Out << Offset.VirtualBase->getQualifiedNameAsString() << " vbase, ";
              
-      Out << " [ret-adj: " << Offset.NonVirtualOffset << " nv]";
+      Out << Offset.NonVirtualOffset << " nv]";
     }
     Out << "\n";
   }