]> granicus.if.org Git - clang/commitdiff
Correctly calculate base offsets for 'this' pointer adjustments involving virtual...
authorAnders Carlsson <andersca@mac.com>
Wed, 17 Feb 2010 02:05:23 +0000 (02:05 +0000)
committerAnders Carlsson <andersca@mac.com>
Wed, 17 Feb 2010 02:05:23 +0000 (02:05 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96441 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGVtable.cpp

index b60d470b39586a657c113cf9cf585f4f75f4034f..4fa74496970e13b95f60c9a16212e695e316bf61 100644 (file)
@@ -40,8 +40,9 @@ public:
     const CXXRecordDecl *VirtualBase;
 
     /// NonVirtualOffset - The offset from the derived class to the base class.
-    /// Or the offset from the virtual base class to the base class, if the path
-    /// from the derived class to the base class involves a virtual base class.
+    /// (Or the offset from the virtual base class to the base class, if the 
+    /// path from the derived class to the base class involves a virtual base
+    /// class.
     int64_t NonVirtualOffset;
     
     BaseOffset() : DerivedClass(0), VirtualBase(0), NonVirtualOffset(0) { }
@@ -360,9 +361,45 @@ FinalOverriders::ComputeThisAdjustmentBaseOffset(BaseSubobject Base,
   if (!const_cast<CXXRecordDecl *>(DerivedRD)->
       isDerivedFrom(const_cast<CXXRecordDecl *>(BaseRD), Paths)) {
     assert(false && "Class must be derived from the passed in base class!");
-    return FinalOverriders::BaseOffset();
+    return BaseOffset();
   }
 
+  // We have to go through all the paths, and see which one leads us to the
+  // right base subobject.
+  for (CXXBasePaths::const_paths_iterator I = Paths.begin(), E = Paths.end();
+       I != E; ++I) {
+    BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD, *I);
+    
+    // FIXME: Should not use * 8 here.
+    uint64_t OffsetToBaseSubobject = Offset.NonVirtualOffset * 8;
+    
+    if (Offset.VirtualBase) {
+      // If we have a virtual base class, the non-virtual offset is relative
+      // to the virtual base class offset.
+      const ASTRecordLayout &MostDerivedClassLayout = 
+        Context.getASTRecordLayout(MostDerivedClass);
+      
+      /// Get the virtual base offset, relative to the most derived class 
+      /// layout.
+      OffsetToBaseSubobject += 
+        MostDerivedClassLayout.getVBaseClassOffset(Offset.VirtualBase);
+    } else {
+      // Otherwise, the non-virtual offset is relative to the derived class 
+      // offset.
+      OffsetToBaseSubobject += Derived.getBaseOffset();
+    }
+    
+    // Check if this path gives us the right base subobject.
+    if (OffsetToBaseSubobject == Base.getBaseOffset()) {
+      // Since we're going from the base class _to_ the derived class, we'll
+      // invert the non-virtual offset here.
+      Offset.NonVirtualOffset = -Offset.NonVirtualOffset;
+      return Offset;
+    }      
+  }
+  
+  return BaseOffset();
+    
   assert(!Paths.getDetectedVirtual() && "FIXME: Handle virtual bases!");
 
   BaseOffset Offset;