зеркало из https://github.com/microsoft/clang-1.git
Handle cases where we're constructing an array of objects and the constructor has default arguments.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89783 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
80ad16f4b2
Коммит
5d4d946ec2
|
@ -463,20 +463,25 @@ llvm::Value *CodeGenFunction::LoadCXXThis() {
|
|||
/// It is assumed that all relevant checks have been made by the caller.
|
||||
void
|
||||
CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
|
||||
const ConstantArrayType *ArrayTy,
|
||||
llvm::Value *ArrayPtr) {
|
||||
const ConstantArrayType *ArrayTy,
|
||||
llvm::Value *ArrayPtr,
|
||||
CallExpr::const_arg_iterator ArgBeg,
|
||||
CallExpr::const_arg_iterator ArgEnd) {
|
||||
|
||||
const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
|
||||
llvm::Value * NumElements =
|
||||
llvm::ConstantInt::get(SizeTy,
|
||||
getContext().getConstantArrayElementCount(ArrayTy));
|
||||
|
||||
EmitCXXAggrConstructorCall(D, NumElements, ArrayPtr);
|
||||
EmitCXXAggrConstructorCall(D, NumElements, ArrayPtr, ArgBeg, ArgEnd);
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
|
||||
llvm::Value *NumElements,
|
||||
llvm::Value *ArrayPtr) {
|
||||
llvm::Value *NumElements,
|
||||
llvm::Value *ArrayPtr,
|
||||
CallExpr::const_arg_iterator ArgBeg,
|
||||
CallExpr::const_arg_iterator ArgEnd) {
|
||||
const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
|
||||
|
||||
// Create a temporary for the loop index and initialize it with 0.
|
||||
|
@ -506,8 +511,24 @@ CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
|
|||
Counter = Builder.CreateLoad(IndexPtr);
|
||||
llvm::Value *Address = Builder.CreateInBoundsGEP(ArrayPtr, Counter,
|
||||
"arrayidx");
|
||||
EmitCXXConstructorCall(D, Ctor_Complete, Address, 0, 0);
|
||||
|
||||
// C++ [class.temporary]p4:
|
||||
// There are two contexts in which temporaries are destroyed at a different
|
||||
// point than the end of the full- expression. The first context is when a
|
||||
// default constructor is called to initialize an element of an array.
|
||||
// If the constructor has one or more default arguments, the destruction of
|
||||
// every temporary created in a default argument expression is sequenced
|
||||
// before the construction of the next array element, if any.
|
||||
|
||||
// Keep track of the current number of live temporaries.
|
||||
unsigned OldNumLiveTemporaries = LiveTemporaries.size();
|
||||
|
||||
EmitCXXConstructorCall(D, Ctor_Complete, Address, ArgBeg, ArgEnd);
|
||||
|
||||
// Pop temporaries.
|
||||
while (LiveTemporaries.size() > OldNumLiveTemporaries)
|
||||
PopCXXTemporary();
|
||||
|
||||
EmitBlock(ContinueBlock);
|
||||
|
||||
// Emit the increment of the loop counter.
|
||||
|
@ -714,7 +735,8 @@ CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest,
|
|||
BasePtr = llvm::PointerType::getUnqual(BasePtr);
|
||||
llvm::Value *BaseAddrPtr =
|
||||
Builder.CreateBitCast(Dest, BasePtr);
|
||||
EmitCXXAggrConstructorCall(CD, Array, BaseAddrPtr);
|
||||
EmitCXXAggrConstructorCall(CD, Array, BaseAddrPtr,
|
||||
E->arg_begin(), E->arg_end());
|
||||
}
|
||||
else
|
||||
// Call the constructor.
|
||||
|
@ -1559,7 +1581,9 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
|
|||
llvm::Value *BaseAddrPtr =
|
||||
CGF.Builder.CreateBitCast(LHS.getAddress(), BasePtr);
|
||||
CGF.EmitCXXAggrConstructorCall(MemberInit->getConstructor(),
|
||||
Array, BaseAddrPtr);
|
||||
Array, BaseAddrPtr,
|
||||
MemberInit->const_arg_begin(),
|
||||
MemberInit->const_arg_end());
|
||||
}
|
||||
else
|
||||
CGF.EmitCXXConstructorCall(MemberInit->getConstructor(),
|
||||
|
|
|
@ -83,39 +83,41 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
|
|||
static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
|
||||
llvm::Value *NewPtr,
|
||||
llvm::Value *NumElements) {
|
||||
QualType AllocType = E->getAllocatedType();
|
||||
|
||||
if (!E->isArray()) {
|
||||
if (CXXConstructorDecl *Ctor = E->getConstructor()) {
|
||||
CGF.EmitCXXConstructorCall(Ctor, Ctor_Complete, NewPtr,
|
||||
E->constructor_arg_begin(),
|
||||
E->constructor_arg_end());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// We have a POD type.
|
||||
if (E->getNumConstructorArgs() == 0)
|
||||
return;
|
||||
|
||||
assert(E->getNumConstructorArgs() == 1 &&
|
||||
"Can only have one argument to initializer of POD type.");
|
||||
|
||||
const Expr *Init = E->getConstructorArg(0);
|
||||
|
||||
if (!CGF.hasAggregateLLVMType(AllocType))
|
||||
CGF.EmitStoreOfScalar(CGF.EmitScalarExpr(Init), NewPtr,
|
||||
AllocType.isVolatileQualified(), AllocType);
|
||||
else if (AllocType->isAnyComplexType())
|
||||
CGF.EmitComplexExprIntoAddr(Init, NewPtr,
|
||||
AllocType.isVolatileQualified());
|
||||
else
|
||||
CGF.EmitAggExpr(Init, NewPtr, AllocType.isVolatileQualified());
|
||||
if (E->isArray()) {
|
||||
if (CXXConstructorDecl *Ctor = E->getConstructor())
|
||||
CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr,
|
||||
E->constructor_arg_begin(),
|
||||
E->constructor_arg_end());
|
||||
return;
|
||||
}
|
||||
|
||||
if (CXXConstructorDecl *Ctor = E->getConstructor())
|
||||
CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr);
|
||||
QualType AllocType = E->getAllocatedType();
|
||||
|
||||
if (CXXConstructorDecl *Ctor = E->getConstructor()) {
|
||||
CGF.EmitCXXConstructorCall(Ctor, Ctor_Complete, NewPtr,
|
||||
E->constructor_arg_begin(),
|
||||
E->constructor_arg_end());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// We have a POD type.
|
||||
if (E->getNumConstructorArgs() == 0)
|
||||
return;
|
||||
|
||||
assert(E->getNumConstructorArgs() == 1 &&
|
||||
"Can only have one argument to initializer of POD type.");
|
||||
|
||||
const Expr *Init = E->getConstructorArg(0);
|
||||
|
||||
if (!CGF.hasAggregateLLVMType(AllocType))
|
||||
CGF.EmitStoreOfScalar(CGF.EmitScalarExpr(Init), NewPtr,
|
||||
AllocType.isVolatileQualified(), AllocType);
|
||||
else if (AllocType->isAnyComplexType())
|
||||
CGF.EmitComplexExprIntoAddr(Init, NewPtr,
|
||||
AllocType.isVolatileQualified());
|
||||
else
|
||||
CGF.EmitAggExpr(Init, NewPtr, AllocType.isVolatileQualified());
|
||||
}
|
||||
|
||||
llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
|
||||
|
|
|
@ -671,10 +671,15 @@ public:
|
|||
|
||||
void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
|
||||
const ConstantArrayType *ArrayTy,
|
||||
llvm::Value *ArrayPtr);
|
||||
llvm::Value *ArrayPtr,
|
||||
CallExpr::const_arg_iterator ArgBeg,
|
||||
CallExpr::const_arg_iterator ArgEnd);
|
||||
|
||||
void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
|
||||
llvm::Value *NumElements,
|
||||
llvm::Value *ArrayPtr);
|
||||
llvm::Value *ArrayPtr,
|
||||
CallExpr::const_arg_iterator ArgBeg,
|
||||
CallExpr::const_arg_iterator ArgEnd);
|
||||
|
||||
void EmitCXXAggrDestructorCall(const CXXDestructorDecl *D,
|
||||
const ArrayType *Array,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: clang-cc -emit-llvm %s -o - -triple=x86_64-apple-darwin10
|
||||
// RUN: clang-cc %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
|
||||
|
||||
// PR5484
|
||||
namespace PR5484 {
|
||||
|
@ -11,3 +11,59 @@ void g() {
|
|||
f();
|
||||
}
|
||||
}
|
||||
|
||||
struct A1 {
|
||||
A1();
|
||||
~A1();
|
||||
};
|
||||
|
||||
struct A2 {
|
||||
A2();
|
||||
~A2();
|
||||
};
|
||||
|
||||
struct B {
|
||||
B(const A1& = A1(), const A2& = A2());
|
||||
};
|
||||
|
||||
// CHECK: define void @_Z2f1v()
|
||||
void f1() {
|
||||
|
||||
// CHECK: call void @_ZN2A1C1Ev(
|
||||
// CHECK: call void @_ZN2A2C1Ev(
|
||||
// CHECK: call void @_ZN1BC1ERK2A1RK2A2(
|
||||
// CHECK: call void @_ZN2A2D1Ev
|
||||
// CHECK: call void @_ZN2A1D1Ev
|
||||
B bs[2];
|
||||
}
|
||||
|
||||
struct C {
|
||||
B bs[2];
|
||||
C();
|
||||
};
|
||||
|
||||
// CHECK: define void @_ZN1CC1Ev(
|
||||
// CHECK: call void @_ZN2A1C1Ev(
|
||||
// CHECK: call void @_ZN2A2C1Ev(
|
||||
// CHECK: call void @_ZN1BC1ERK2A1RK2A2(
|
||||
// CHECK: call void @_ZN2A2D1Ev
|
||||
// CHECK: call void @_ZN2A1D1Ev
|
||||
|
||||
// CHECK: define void @_ZN1CC2Ev(
|
||||
// CHECK: call void @_ZN2A1C1Ev(
|
||||
// CHECK: call void @_ZN2A2C1Ev(
|
||||
// CHECK: call void @_ZN1BC1ERK2A1RK2A2(
|
||||
// CHECK: call void @_ZN2A2D1Ev
|
||||
// CHECK: call void @_ZN2A1D1Ev
|
||||
C::C() { }
|
||||
|
||||
// CHECK: define void @_Z2f3v()
|
||||
void f3() {
|
||||
// CHECK: call void @_ZN2A1C1Ev(
|
||||
// CHECK: call void @_ZN2A2C1Ev(
|
||||
// CHECK: call void @_ZN1BC1ERK2A1RK2A2(
|
||||
// CHECK: call void @_ZN2A2D1Ev
|
||||
// CHECK: call void @_ZN2A1D1Ev
|
||||
B *bs = new B[2];
|
||||
delete bs;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче