MS ABI: Use the correct this arg when generating implict copy ctor
We assumed that the incoming this argument would be the last argument. However, this is not true under the MS ABI. This fixes PR20897. llvm-svn: 217642
This commit is contained in:
parent
42fa4af8fe
commit
196ac334f3
|
@ -384,6 +384,9 @@ public:
|
||||||
virtual void EmitReturnFromThunk(CodeGenFunction &CGF,
|
virtual void EmitReturnFromThunk(CodeGenFunction &CGF,
|
||||||
RValue RV, QualType ResultType);
|
RValue RV, QualType ResultType);
|
||||||
|
|
||||||
|
virtual size_t getSrcArgforCopyCtor(const CXXConstructorDecl *,
|
||||||
|
FunctionArgList &Args) const = 0;
|
||||||
|
|
||||||
/// Gets the pure virtual member call function.
|
/// Gets the pure virtual member call function.
|
||||||
virtual StringRef GetPureVirtualCallName() = 0;
|
virtual StringRef GetPureVirtualCallName() = 0;
|
||||||
|
|
||||||
|
|
|
@ -915,10 +915,11 @@ namespace {
|
||||||
|
|
||||||
/// Get source argument for copy constructor. Returns null if not a copy
|
/// Get source argument for copy constructor. Returns null if not a copy
|
||||||
/// constructor.
|
/// constructor.
|
||||||
static const VarDecl* getTrivialCopySource(const CXXConstructorDecl *CD,
|
static const VarDecl *getTrivialCopySource(CodeGenFunction &CGF,
|
||||||
|
const CXXConstructorDecl *CD,
|
||||||
FunctionArgList &Args) {
|
FunctionArgList &Args) {
|
||||||
if (CD->isCopyOrMoveConstructor() && CD->isDefaulted())
|
if (CD->isCopyOrMoveConstructor() && CD->isDefaulted())
|
||||||
return Args[Args.size() - 1];
|
return Args[CGF.CGM.getCXXABI().getSrcArgforCopyCtor(CD, Args)];
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -949,7 +950,7 @@ namespace {
|
||||||
public:
|
public:
|
||||||
ConstructorMemcpyizer(CodeGenFunction &CGF, const CXXConstructorDecl *CD,
|
ConstructorMemcpyizer(CodeGenFunction &CGF, const CXXConstructorDecl *CD,
|
||||||
FunctionArgList &Args)
|
FunctionArgList &Args)
|
||||||
: FieldMemcpyizer(CGF, CD->getParent(), getTrivialCopySource(CD, Args)),
|
: FieldMemcpyizer(CGF, CD->getParent(), getTrivialCopySource(CGF, CD, Args)),
|
||||||
ConstructorDecl(CD),
|
ConstructorDecl(CD),
|
||||||
MemcpyableCtor(CD->isDefaulted() &&
|
MemcpyableCtor(CD->isDefaulted() &&
|
||||||
CD->isCopyOrMoveConstructor() &&
|
CD->isCopyOrMoveConstructor() &&
|
||||||
|
|
|
@ -208,6 +208,12 @@ public:
|
||||||
llvm::Value *performReturnAdjustment(CodeGenFunction &CGF, llvm::Value *Ret,
|
llvm::Value *performReturnAdjustment(CodeGenFunction &CGF, llvm::Value *Ret,
|
||||||
const ReturnAdjustment &RA) override;
|
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 GetPureVirtualCallName() override { return "__cxa_pure_virtual"; }
|
||||||
StringRef GetDeletedVirtualCallName() override
|
StringRef GetDeletedVirtualCallName() override
|
||||||
{ return "__cxa_deleted_virtual"; }
|
{ return "__cxa_deleted_virtual"; }
|
||||||
|
|
|
@ -50,6 +50,18 @@ public:
|
||||||
|
|
||||||
bool isSRetParameterAfterThis() const override { return true; }
|
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"; }
|
StringRef GetPureVirtualCallName() override { return "_purecall"; }
|
||||||
// No known support for deleted functions in MSVC yet, so this choice is
|
// No known support for deleted functions in MSVC yet, so this choice is
|
||||||
// arbitrary.
|
// arbitrary.
|
||||||
|
|
|
@ -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;
|
||||||
|
};
|
Loading…
Reference in New Issue