]> granicus.if.org Git - clang/commitdiff
Refine the vcall for a function that is defined in a virtual base
authorMike Stump <mrs@apple.com>
Fri, 6 Nov 2009 02:38:24 +0000 (02:38 +0000)
committerMike Stump <mrs@apple.com>
Fri, 6 Nov 2009 02:38:24 +0000 (02:38 +0000)
class that is overridden in a base that isn't morally virtual.

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

lib/CodeGen/CGVtable.cpp
test/CodeGenCXX/virt.cpp

index e2e11478de26901dfe205aa744600a5d128e0c72..34012cafe5f37fae67208384f5560b0e4e461c75 100644 (file)
@@ -242,15 +242,13 @@ public:
             idx = VCalls.size()+1;
             VCalls.push_back(0);
             D1(printf("  vcall for %s at %d with delta %d most derived %s\n",
-                      MD->getNameAsCString(),
-                      (int)-VCalls.size()-3, (int)VCallOffset[MD],
+                      MD->getNameAsCString(), (int)-idx-3, (int)VCalls[idx-1],
                       Class->getNameAsCString()));
           } else {
             VCallOffset[MD] = VCallOffset[OMD];
             VCalls[idx-1] = -VCallOffset[OMD] + OverrideOffset/8;
             D1(printf("  vcall patch for %s at %d with delta %d most derived %s\n",
-                      MD->getNameAsCString(),
-                      (int)-VCalls.size()-3, (int)VCallOffset[MD],
+                      MD->getNameAsCString(), (int)-idx-3, (int)VCalls[idx-1],
                       Class->getNameAsCString()));
           }
           VCall[MD] = idx;
@@ -271,6 +269,16 @@ public:
         // FIXME: finish off
         int64_t O = VCallOffset[OMD] - OverrideOffset/8;
         // int64_t O = CurrentVBaseOffset/8 - OverrideOffset/8;
+
+        if (VCall.count(OMD)) {
+          VCallOffset[MD] = VCallOffset[OMD];
+          Index_t idx = VCall[OMD];
+          VCalls[idx-1] = -VCallOffset[OMD] + OverrideOffset/8;
+          D1(printf("  vcall patch for %s at %d with delta %d most derived %s\n",
+                    MD->getNameAsCString(), (int)-idx-3, (int)VCalls[idx-1],
+                    Class->getNameAsCString()));
+          VCall[MD] = idx;
+        }        
         if (O || ReturnOffset.first || ReturnOffset.second) {
           CallOffset ThisOffset = std::make_pair(O, 0);
           
@@ -374,8 +382,7 @@ public:
         idx = VCalls.size()+1;
         VCalls.push_back(0);
         D1(printf("  vcall for %s at %d with delta %d\n",
-                  MD->getNameAsCString(), (int)-VCalls.size()-3,
-                  (int)VCallOffset[MD]));
+                  MD->getNameAsCString(), (int)-VCalls.size()-3, 0));
       }
     }
   }
index 5eeabfac164f96469299f6ddab15c44b2ee2ccd8..0f239eef8ca6e85e5f912eabd93394303ef73fd4 100644 (file)
@@ -895,7 +895,7 @@ class test20_B : virtual test20_V {
 class test20_B1 : virtual test20_V1 {
 };
 class test20_D : public test20_B, public test20_B1 {
-} d;
+};
 
 // CHECK-LP64: __ZTV8test20_D:
 // CHECK-LP64-NEXT: .quad 8
@@ -911,6 +911,34 @@ class test20_D : public test20_B, public test20_B1 {
 // CHECK-LP64-NEXT: .quad __ZN9test20_V14foo2Ev
 
 
+class test21_V {
+  virtual void foo();
+};
+class test21_V1 {
+  virtual void foo();
+};
+class test21_B : virtual test21_V {
+};
+class test21_B1 : virtual test21_V1 {
+};
+class test21_D : public test21_B, public test21_B1 {
+  void foo() { }
+};
+
+// CHECK-LP64: __ZTV8test21_D:
+// CHECK-LP64-NEXT: .quad 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .quad __ZTI8test21_D
+// CHECK-LP64-NEXT: .quad __ZN8test21_D3fooEv
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .quad 18446744073709551608
+// CHECK-LP64-NEXT: .quad 18446744073709551608
+// CHECK-LP64-NEXT: .quad __ZTI8test21_D
+// CHECK-LP64-NEXT .quad __ZTv0_n24_N8test21_D3fooEv
+
+
 
 // CHECK-LP64: __ZTV1B:
 // CHECK-LP64-NEXT: .space 8
@@ -951,6 +979,8 @@ class test20_D : public test20_B, public test20_B1 {
 // CHECK-LP64-NEXT: .quad __ZN2D14bar4Ev
 // CHECK-LP64-NEXT: .quad __ZN2D14bar5Ev
 
+test21_D d21;
+test20_D d20;
 test19_D d19;
 test18_D d18;
 test17_D d17;