]> granicus.if.org Git - clang/commitdiff
When doing a derived-to-base class through a virtual class, we don't have to get...
authorAnders Carlsson <andersca@mac.com>
Sat, 29 Jan 2011 03:18:56 +0000 (03:18 +0000)
committerAnders Carlsson <andersca@mac.com>
Sat, 29 Jan 2011 03:18:56 +0000 (03:18 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124523 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGClass.cpp
test/CodeGenCXX/derived-to-virtual-base-class-calls-final.cpp [new file with mode: 0644]

index 2a92258b8469d73b58f1e899c17ec5f604e3d64e..a7b8f659786fc14f966c1f168cbe5b6ae4c046d2 100644 (file)
@@ -180,8 +180,17 @@ CodeGenFunction::GetAddressOfBaseClass(llvm::Value *Value,
 
   llvm::Value *VirtualOffset = 0;
 
-  if (VBase)
-    VirtualOffset = GetVirtualBaseClassOffset(Value, Derived, VBase);
+  if (VBase) {
+    if (Derived->hasAttr<FinalAttr>()) {
+      VirtualOffset = 0;
+
+      const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Derived);
+
+      uint64_t VBaseOffset = Layout.getVBaseClassOffsetInBits(VBase);
+      NonVirtualOffset += VBaseOffset / 8;
+    } else
+      VirtualOffset = GetVirtualBaseClassOffset(Value, Derived, VBase);
+  }
 
   // Apply the offsets.
   Value = ApplyNonVirtualAndVirtualOffset(*this, Value, NonVirtualOffset, 
diff --git a/test/CodeGenCXX/derived-to-virtual-base-class-calls-final.cpp b/test/CodeGenCXX/derived-to-virtual-base-class-calls-final.cpp
new file mode 100644 (file)
index 0000000..e332f40
--- /dev/null
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+
+struct A { int i; };
+struct B { int j; };
+struct C : A, B { int k; };
+
+struct D final : virtual C { 
+  D(); 
+  virtual void f();
+};
+
+// CHECK: define %struct.B* @_Z1fR1D
+B &f(D &d) {
+  // CHECK-NOT: load i8**
+  return d;
+}