]> granicus.if.org Git - clang/commitdiff
MS ABI: Use the correct this arg when generating implict copy ctor
authorDavid Majnemer <david.majnemer@gmail.com>
Thu, 11 Sep 2014 23:05:02 +0000 (23:05 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Thu, 11 Sep 2014 23:05:02 +0000 (23:05 +0000)
We assumed that the incoming this argument would be the last argument.

However, this is not true under the MS ABI.

This fixes PR20897.

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

lib/CodeGen/CGCXXABI.h
lib/CodeGen/CGClass.cpp
lib/CodeGen/ItaniumCXXABI.cpp
lib/CodeGen/MicrosoftCXXABI.cpp
test/CodeGenCXX/pr20897.cpp [new file with mode: 0644]

index fe331795e91dab49c69e3e9ab9daac47c1b0530b..cf2cccd9910693b8f96bb8258dd15b54ffc6a67c 100644 (file)
@@ -384,6 +384,9 @@ public:
   virtual void EmitReturnFromThunk(CodeGenFunction &CGF,
                                    RValue RV, QualType ResultType);
 
+  virtual size_t getSrcArgforCopyCtor(const CXXConstructorDecl *,
+                                      FunctionArgList &Args) const = 0;
+
   /// Gets the pure virtual member call function.
   virtual StringRef GetPureVirtualCallName() = 0;
 
index 1de325feea388501315df69a3ed92f6bc2a802f6..72869d8ca9b3c4ff27125ff2d674c281634d8f89 100644 (file)
@@ -914,11 +914,12 @@ namespace {
   private:
 
     /// Get source argument for copy constructor. Returns null if not a copy
-    /// constructor. 
-    static const VarDecl* getTrivialCopySource(const CXXConstructorDecl *CD,
+    /// constructor.
+    static const VarDecl *getTrivialCopySource(CodeGenFunction &CGF,
+                                               const CXXConstructorDecl *CD,
                                                FunctionArgList &Args) {
       if (CD->isCopyOrMoveConstructor() && CD->isDefaulted())
-        return Args[Args.size() - 1];
+        return Args[CGF.CGM.getCXXABI().getSrcArgforCopyCtor(CD, Args)];
       return nullptr;
     }
 
@@ -949,7 +950,7 @@ namespace {
   public:
     ConstructorMemcpyizer(CodeGenFunction &CGF, const CXXConstructorDecl *CD,
                           FunctionArgList &Args)
-      : FieldMemcpyizer(CGF, CD->getParent(), getTrivialCopySource(CD, Args)),
+      : FieldMemcpyizer(CGF, CD->getParent(), getTrivialCopySource(CGF, CD, Args)),
         ConstructorDecl(CD),
         MemcpyableCtor(CD->isDefaulted() &&
                        CD->isCopyOrMoveConstructor() &&
index 25e2715daafce659bdbf245dae3a347812e28cf3..bcc0f166203a12daaec0d7a1645d9d1642c7ba4a 100644 (file)
@@ -208,6 +208,12 @@ public:
   llvm::Value *performReturnAdjustment(CodeGenFunction &CGF, llvm::Value *Ret,
                                        const ReturnAdjustment &RA) override;
 
+  size_t getSrcArgforCopyCtor(const CXXConstructorDecl *,
+                              FunctionArgList &Args) const override {
+    assert(!Args.empty() && "expected the arglist to not be empty!");
+    return Args.size() - 1;
+  }
+
   StringRef GetPureVirtualCallName() override { return "__cxa_pure_virtual"; }
   StringRef GetDeletedVirtualCallName() override
     { return "__cxa_deleted_virtual"; }
index 173099a6bba7587f81949d852df7caab9cbebf6e..04b7ea08edc6630d07982b64b21b19a0107dbc85 100644 (file)
@@ -50,6 +50,18 @@ public:
 
   bool isSRetParameterAfterThis() const override { return true; }
 
+  size_t getSrcArgforCopyCtor(const CXXConstructorDecl *CD,
+                              FunctionArgList &Args) const override {
+    assert(Args.size() >= 2 &&
+           "expected the arglist to have at least two args!");
+    // The 'most_derived' parameter goes second if the ctor is variadic and
+    // has v-bases.
+    if (CD->getParent()->getNumVBases() > 0 &&
+        CD->getType()->castAs<FunctionProtoType>()->isVariadic())
+      return 2;
+    return 1;
+  }
+
   StringRef GetPureVirtualCallName() override { return "_purecall"; }
   // No known support for deleted functions in MSVC yet, so this choice is
   // arbitrary.
diff --git a/test/CodeGenCXX/pr20897.cpp b/test/CodeGenCXX/pr20897.cpp
new file mode 100644 (file)
index 0000000..06828c0
--- /dev/null
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -triple i686-windows-msvc   -emit-llvm -std=c++1y -O0 -o - %s | FileCheck %s
+struct Base {};
+
+// __declspec(dllexport) causes us to export the implicit constructor.
+struct __declspec(dllexport) Derived : virtual Base {
+// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc %struct.Derived* @"\01??0Derived@@QAE@ABU0@@Z"
+// CHECK:      %[[this:.*]] = load %struct.Derived** {{.*}}
+// CHECK-NEXT: store %struct.Derived* %[[this]], %struct.Derived** %[[retval:.*]]
+// CHECK:      %[[dest_a_gep:.*]] = getelementptr inbounds %struct.Derived* %[[this]], i32 0, i32 1
+// CHECK-NEXT: %[[src_load:.*]]   = load %struct.Derived** {{.*}}
+// CHECK-NEXT: %[[src_a_gep:.*]]  = getelementptr inbounds %struct.Derived* %[[src_load:.*]], i32 0, i32 1
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %[[dest_a_gep]], i8* %[[src_a_gep]], i64 1, i32 4, i1 false)
+// CHECK-NEXT: %[[dest_this:.*]] = load %struct.Derived** %[[retval]]
+// CHECK-NEXT: ret %struct.Derived* %[[dest_this]]
+  bool a : 1;
+  bool b : 1;
+};