]> granicus.if.org Git - clang/commitdiff
Fix PR19172 - wrong this adjustment calculated for virtual destructor in a class...
authorTimur Iskhodzhanov <timurrrr@google.com>
Thu, 20 Mar 2014 20:38:34 +0000 (20:38 +0000)
committerTimur Iskhodzhanov <timurrrr@google.com>
Thu, 20 Mar 2014 20:38:34 +0000 (20:38 +0000)
Reviewed at http://llvm-reviews.chandlerc.com/D3128

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

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

index 01372341177ccc804513048789344787d17e0c95..12c5b8f68790b8f3a98b9c3bfcf845f9e2c1be88 100644 (file)
@@ -2414,6 +2414,9 @@ public:
   typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation>
     MethodVFTableLocationsTy;
 
+  typedef llvm::iterator_range<MethodVFTableLocationsTy::const_iterator>
+    method_locations_range;
+
 private:
   /// VTables - Global vtable information.
   MicrosoftVTableContext &VTables;
@@ -2576,12 +2579,9 @@ public:
 
   ThunksMapTy::const_iterator thunks_end() const { return Thunks.end(); }
 
-  MethodVFTableLocationsTy::const_iterator vtable_indices_begin() const {
-    return MethodVFTableLocations.begin();
-  }
-
-  MethodVFTableLocationsTy::const_iterator vtable_indices_end() const {
-    return MethodVFTableLocations.end();
+  method_locations_range vtable_locations() const {
+    return method_locations_range(MethodVFTableLocations.begin(),
+                                  MethodVFTableLocations.end());
   }
 
   uint64_t getNumVTableComponents() const { return Components.size(); }
@@ -3291,9 +3291,15 @@ void MicrosoftVTableContext::computeVTableRelatedInformation(
     VFTableLayouts[id] = new VTableLayout(
         Builder.getNumVTableComponents(), Builder.vtable_component_begin(),
         VTableThunks.size(), VTableThunks.data(), EmptyAddressPointsMap, true);
-    NewMethodLocations.insert(Builder.vtable_indices_begin(),
-                              Builder.vtable_indices_end());
     Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
+
+    for (const auto &I : Builder.vtable_locations()) {
+      GlobalDecl GD = I.first;
+      MethodVFTableLocation NewLoc = I.second;
+      auto M = NewMethodLocations.find(GD);
+      if (M == NewMethodLocations.end() || NewLoc < M->second)
+        NewMethodLocations[GD] = NewLoc;
+    }
   }
 
   MethodVFTableLocations.insert(NewMethodLocations.begin(),
index 22e1fa71ecd34e0ac76f499cabcf804c77dd0692..23cc70994b6a46e206aad5c8eae361c1f78b94ec 100644 (file)
@@ -377,3 +377,45 @@ void D::bar() {
   // CHECK: ret
 }
 }
+
+namespace test4{
+// PR19172: We used to merge method vftable locations wrong.
+
+struct A {
+  virtual ~A() {}
+};
+
+struct B {
+  virtual ~B() {}
+};
+
+struct C : virtual A, B {
+  virtual ~C();
+};
+
+void foo(void*);
+
+C::~C() {
+  // CHECK-LABEL: define x86_thiscallcc void @"\01??1C@test4@@UAE@XZ"(%"struct.test4::C"* %this)
+
+  // In this case "this" points to the most derived class, so no GEPs needed.
+  // CHECK-NOT: getelementptr
+  // CHECK-NOT: bitcast
+  // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::C"* %{{.*}} to [1 x i8*]**
+  // CHECK: store [1 x i8*]* @"\01??_7C@test4@@6BB@1@@", [1 x i8*]** %[[VFPTR_i8]]
+
+  foo(this);
+}
+
+void destroy(C *obj) {
+  // CHECK-LABEL: define void @"\01?destroy@test4@@YAXPAUC@1@@Z"(%"struct.test4::C"* %obj)
+
+  delete obj;
+  // CHECK: %[[VPTR:.*]] = bitcast %"struct.test4::C"* %[[OBJ:.*]] to void (%"struct.test4::C"*, i32)***
+  // CHECK: %[[VFTABLE:.*]] = load void (%"struct.test4::C"*, i32)*** %[[VPTR]]
+  // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds void (%"struct.test4::C"*, i32)** %[[VFTABLE]], i64 0
+  // CHECK: %[[VFUN:.*]] = load void (%"struct.test4::C"*, i32)** %[[VFTENTRY]]
+  // CHECK: call x86_thiscallcc void %[[VFUN]](%"struct.test4::C"* %[[OBJ]], i32 1)
+}
+
+}
index 82eac8a047a1f931be3cb8a149e520ce9455f0e2..5e05d1513650a163c03e3bd69600cf2cea868373 100644 (file)
@@ -21,6 +21,7 @@
 // RUN: FileCheck --check-prefix=VDTORS-U %s < %t
 // RUN: FileCheck --check-prefix=VDTORS-V %s < %t
 // RUN: FileCheck --check-prefix=VDTORS-P %s < %t
+// RUN: FileCheck --check-prefix=VDTORS-R %s < %t
 // RUN: FileCheck --check-prefix=RET-W %s < %t
 // RUN: FileCheck --check-prefix=RET-T %s < %t
 // RUN: FileCheck --check-prefix=RET-V %s < %t
@@ -543,6 +544,30 @@ struct P : T, Y {
 
 P p;
 
+struct Q {
+  virtual ~Q();
+};
+
+// PR19172: Yet another diamond we miscompiled.
+struct R : virtual Q, X {
+  // VDTORS-R: VFTable for 'vdtors::Q' in 'vdtors::R' (1 entry).
+  // VDTORS-R-NEXT: 0 | vdtors::R::~R() [scalar deleting]
+  // VDTORS-R-NEXT:     [this adjustment: -8 non-virtual]
+
+  // VDTORS-R: Thunks for 'vdtors::R::~R()' (1 entry).
+  // VDTORS-R-NEXT: 0 | [this adjustment: -8 non-virtual]
+
+  // VDTORS-R: VFTable for 'vdtors::X' in 'vdtors::R' (2 entries).
+  // VDTORS-R-NEXT: 0 | vdtors::R::~R() [scalar deleting]
+  // VDTORS-R-NEXT: 1 | void vdtors::X::zzz()
+
+  // VDTORS-R: VFTable indices for 'vdtors::R' (1 entry).
+  // VDTORS-R-NEXT: 0 | vdtors::R::~R() [scalar deleting]
+  virtual ~R();
+};
+
+R r;
+
 }
 
 namespace return_adjustment {