aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/DeclCXX.cpp38
-rw-r--r--lib/CodeGen/CGClass.cpp360
-rw-r--r--lib/CodeGen/CodeGenFunction.h13
-rw-r--r--lib/Sema/SemaDeclCXX.cpp145
4 files changed, 278 insertions, 278 deletions
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 68f4a821e6..d15cfefed0 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -700,8 +700,8 @@ CXXBaseOrMemberInitializer::
CXXBaseOrMemberInitializer(ASTContext &Context,
TypeSourceInfo *TInfo, bool IsVirtual,
SourceLocation L, Expr *Init, SourceLocation R)
- : BaseOrMember(TInfo), Init(Init), AnonUnionMember(0), IsVirtual(IsVirtual),
- LParenLoc(L), RParenLoc(R)
+ : BaseOrMember(TInfo), Init(Init), AnonUnionMember(0),
+ LParenLoc(L), RParenLoc(R), NumArrayIndices(0), IsVirtual(IsVirtual)
{
}
@@ -710,13 +710,45 @@ CXXBaseOrMemberInitializer(ASTContext &Context,
FieldDecl *Member, SourceLocation MemberLoc,
SourceLocation L, Expr *Init, SourceLocation R)
: BaseOrMember(Member), MemberLocation(MemberLoc), Init(Init),
- AnonUnionMember(0), LParenLoc(L), RParenLoc(R)
+ AnonUnionMember(0), LParenLoc(L), RParenLoc(R) , NumArrayIndices(0),
+ IsVirtual(false)
{
}
+CXXBaseOrMemberInitializer::
+CXXBaseOrMemberInitializer(ASTContext &Context,
+ FieldDecl *Member, SourceLocation MemberLoc,
+ SourceLocation L, Expr *Init, SourceLocation R,
+ VarDecl **Indices,
+ unsigned NumIndices)
+ : BaseOrMember(Member), MemberLocation(MemberLoc), Init(Init),
+ AnonUnionMember(0), LParenLoc(L), RParenLoc(R) ,
+ NumArrayIndices(NumIndices), IsVirtual(false)
+{
+ VarDecl **MyIndices = reinterpret_cast<VarDecl **> (this + 1);
+ memcpy(MyIndices, Indices, NumIndices * sizeof(VarDecl *));
+}
+
+CXXBaseOrMemberInitializer *
+CXXBaseOrMemberInitializer::Create(ASTContext &Context,
+ FieldDecl *Member,
+ SourceLocation MemberLoc,
+ SourceLocation L,
+ Expr *Init,
+ SourceLocation R,
+ VarDecl **Indices,
+ unsigned NumIndices) {
+ void *Mem = Context.Allocate(sizeof(CXXBaseOrMemberInitializer) +
+ sizeof(VarDecl *) * NumIndices,
+ llvm::alignof<CXXBaseOrMemberInitializer>());
+ return new (Mem) CXXBaseOrMemberInitializer(Context, Member, MemberLoc,
+ L, Init, R, Indices, NumIndices);
+}
+
void CXXBaseOrMemberInitializer::Destroy(ASTContext &Context) {
if (Init)
Init->Destroy(Context);
+ // FIXME: Destroy indices
this->~CXXBaseOrMemberInitializer();
}
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index a604eef49a..f3f4d42478 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -262,102 +262,7 @@ CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value,
return Value;
}
-
-/// EmitCopyCtorCall - Emit a call to a copy constructor.
-static void
-EmitCopyCtorCall(CodeGenFunction &CGF, const CXXConstructorDecl *CopyCtor,
- llvm::Value *ThisPtr, llvm::Value *Src) {
- llvm::Value *Callee = CGF.CGM.GetAddrOfCXXConstructor(CopyCtor, Ctor_Complete);
-
- CallArgList CallArgs;
-
- // Push the this ptr.
- CallArgs.push_back(std::make_pair(RValue::get(ThisPtr),
- CopyCtor->getThisType(CGF.getContext())));
-
- // Push the Src ptr.
- CallArgs.push_back(std::make_pair(RValue::get(Src),
- CopyCtor->getParamDecl(0)->getType()));
-
-
- {
- CodeGenFunction::CXXTemporariesCleanupScope Scope(CGF);
-
- // If the copy constructor has default arguments, emit them.
- for (unsigned I = 1, E = CopyCtor->getNumParams(); I < E; ++I) {
- const ParmVarDecl *Param = CopyCtor->getParamDecl(I);
- const Expr *DefaultArgExpr = Param->getDefaultArg();
-
- assert(DefaultArgExpr && "Ctor parameter must have default arg!");
-
- QualType ArgType = Param->getType();
- CallArgs.push_back(std::make_pair(CGF.EmitCallArg(DefaultArgExpr,
- ArgType),
- ArgType));
- }
-
- const FunctionProtoType *FPT =
- CopyCtor->getType()->getAs<FunctionProtoType>();
- CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(CallArgs, FPT),
- Callee, ReturnValueSlot(), CallArgs, CopyCtor);
- }
-}
-/// EmitClassAggrMemberwiseCopy - This routine generates code to copy a class
-/// array of objects from SrcValue to DestValue. Copying can be either a bitwise
-/// copy or via a copy constructor call.
-// FIXME. Consolidate this with EmitCXXAggrConstructorCall.
-void CodeGenFunction::EmitClassAggrMemberwiseCopy(llvm::Value *Dest,
- llvm::Value *Src,
- const ConstantArrayType *Array,
- const CXXRecordDecl *ClassDecl) {
- // Create a temporary for the loop index and initialize it with 0.
- llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext),
- "loop.index");
- llvm::Value* zeroConstant =
- llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext));
- Builder.CreateStore(zeroConstant, IndexPtr);
- // Start the loop with a block that tests the condition.
- llvm::BasicBlock *CondBlock = createBasicBlock("for.cond");
- llvm::BasicBlock *AfterFor = createBasicBlock("for.end");
-
- EmitBlock(CondBlock);
-
- llvm::BasicBlock *ForBody = createBasicBlock("for.body");
- // Generate: if (loop-index < number-of-elements fall to the loop body,
- // otherwise, go to the block after the for-loop.
- uint64_t NumElements = getContext().getConstantArrayElementCount(Array);
- llvm::Value * NumElementsPtr =
- llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), NumElements);
- llvm::Value *Counter = Builder.CreateLoad(IndexPtr);
- llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElementsPtr,
- "isless");
- // If the condition is true, execute the body.
- Builder.CreateCondBr(IsLess, ForBody, AfterFor);
-
- EmitBlock(ForBody);
- llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc");
- // Inside the loop body, emit the constructor call on the array element.
- Counter = Builder.CreateLoad(IndexPtr);
- Src = Builder.CreateInBoundsGEP(Src, Counter, "srcaddress");
- Dest = Builder.CreateInBoundsGEP(Dest, Counter, "destaddress");
- EmitClassMemberwiseCopy(Dest, Src, ClassDecl);
-
- EmitBlock(ContinueBlock);
-
- // Emit the increment of the loop counter.
- llvm::Value *NextVal = llvm::ConstantInt::get(Counter->getType(), 1);
- Counter = Builder.CreateLoad(IndexPtr);
- NextVal = Builder.CreateAdd(Counter, NextVal, "inc");
- Builder.CreateStore(NextVal, IndexPtr);
-
- // Finally, branch back up to the condition for the next iteration.
- EmitBranch(CondBlock);
-
- // Emit the fall-through block.
- EmitBlock(AfterFor, true);
-}
-
/// GetVTTParameter - Return the VTT parameter that should be passed to a
/// base constructor/destructor with virtual bases.
static llvm::Value *GetVTTParameter(CodeGenFunction &CGF, GlobalDecl GD,
@@ -405,111 +310,6 @@ static llvm::Value *GetVTTParameter(CodeGenFunction &CGF, GlobalDecl GD,
return VTT;
}
-
-/// EmitClassMemberwiseCopy - This routine generates code to copy a class
-/// object from SrcValue to DestValue. Copying can be either a bitwise copy
-/// or via a copy constructor call.
-void CodeGenFunction::EmitClassMemberwiseCopy(
- llvm::Value *Dest, llvm::Value *Src,
- const CXXRecordDecl *ClassDecl) {
- if (ClassDecl->hasTrivialCopyConstructor()) {
- EmitAggregateCopy(Dest, Src, getContext().getTagDeclType(ClassDecl));
- return;
- }
-
- CXXConstructorDecl *CopyCtor = ClassDecl->getCopyConstructor(getContext(), 0);
- assert(CopyCtor && "Did not have copy ctor!");
-
- EmitCopyCtorCall(*this, CopyCtor, Dest, Src);
-}
-
-/// SynthesizeCXXCopyConstructor - This routine implicitly defines body of a
-/// copy constructor, in accordance with section 12.8 (p7 and p8) of C++03
-/// The implicitly-defined copy constructor for class X performs a memberwise
-/// copy of its subobjects. The order of copying is the same as the order of
-/// initialization of bases and members in a user-defined constructor
-/// Each subobject is copied in the manner appropriate to its type:
-/// if the subobject is of class type, the copy constructor for the class is
-/// used;
-/// if the subobject is an array, each element is copied, in the manner
-/// appropriate to the element type;
-/// if the subobject is of scalar type, the built-in assignment operator is
-/// used.
-/// Virtual base class subobjects shall be copied only once by the
-/// implicitly-defined copy constructor
-
-void
-CodeGenFunction::SynthesizeCXXCopyConstructor(const FunctionArgList &Args) {
- const CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(CurGD.getDecl());
- CXXCtorType CtorType = CurGD.getCtorType();
- (void) CtorType;
-
- const CXXRecordDecl *ClassDecl = Ctor->getParent();
- assert(!ClassDecl->hasUserDeclaredCopyConstructor() &&
- "SynthesizeCXXCopyConstructor - copy constructor has definition already");
- assert(!Ctor->isTrivial() && "shouldn't need to generate trivial ctor");
-
- llvm::Value *ThisPtr = LoadCXXThis();
-
- // Find the source pointer.
- unsigned SrcArgIndex = Args.size() - 1;
- assert(CtorType == Ctor_Base || SrcArgIndex == 1);
- assert(CtorType != Ctor_Base ||
- (ClassDecl->getNumVBases() != 0 && SrcArgIndex == 2) ||
- SrcArgIndex == 1);
-
- llvm::Value *SrcPtr =
- Builder.CreateLoad(GetAddrOfLocalVar(Args[SrcArgIndex].first));
-
- for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(),
- E = ClassDecl->field_end(); I != E; ++I) {
- const FieldDecl *Field = *I;
-
- QualType FieldType = getContext().getCanonicalType(Field->getType());
- const ConstantArrayType *Array =
- getContext().getAsConstantArrayType(FieldType);
- if (Array)
- FieldType = getContext().getBaseElementType(FieldType);
-
- if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
- CXXRecordDecl *FieldClassDecl
- = cast<CXXRecordDecl>(FieldClassType->getDecl());
- LValue LHS = EmitLValueForField(ThisPtr, Field, 0);
- LValue RHS = EmitLValueForField(SrcPtr, Field, 0);
- if (Array) {
- const llvm::Type *BasePtr = ConvertType(FieldType)->getPointerTo();
- llvm::Value *DestBaseAddrPtr =
- Builder.CreateBitCast(LHS.getAddress(), BasePtr);
- llvm::Value *SrcBaseAddrPtr =
- Builder.CreateBitCast(RHS.getAddress(), BasePtr);
- EmitClassAggrMemberwiseCopy(DestBaseAddrPtr, SrcBaseAddrPtr, Array,
- FieldClassDecl);
- }
- else
- EmitClassMemberwiseCopy(LHS.getAddress(), RHS.getAddress(),
- FieldClassDecl);
- continue;
- }
-
- // Do a built-in assignment of scalar data members.
- LValue LHS = EmitLValueForFieldInitialization(ThisPtr, Field, 0);
- LValue RHS = EmitLValueForFieldInitialization(SrcPtr, Field, 0);
-
- if (!hasAggregateLLVMType(Field->getType())) {
- RValue RVRHS = EmitLoadOfLValue(RHS, Field->getType());
- EmitStoreThroughLValue(RVRHS, LHS, Field->getType());
- } else if (Field->getType()->isAnyComplexType()) {
- ComplexPairTy Pair = LoadComplexFromAddr(RHS.getAddress(),
- RHS.isVolatileQualified());
- StoreComplexToAddr(Pair, LHS.getAddress(), LHS.isVolatileQualified());
- } else {
- EmitAggregateCopy(LHS.getAddress(), RHS.getAddress(), Field->getType());
- }
- }
-
- InitializeVTablePointers(ClassDecl);
-}
-
static void EmitBaseInitializer(CodeGenFunction &CGF,
const CXXRecordDecl *ClassDecl,
CXXBaseOrMemberInitializer *BaseInit,
@@ -547,9 +347,98 @@ static void EmitBaseInitializer(CodeGenFunction &CGF,
}
}
+static void EmitAggMemberInitializer(CodeGenFunction &CGF,
+ LValue LHS,
+ llvm::Value *ArrayIndexVar,
+ CXXBaseOrMemberInitializer *MemberInit,
+ QualType T,
+ unsigned Index) {
+ if (Index == MemberInit->getNumArrayIndices()) {
+ CodeGenFunction::CleanupScope Cleanups(CGF);
+
+ llvm::Value *Dest = LHS.getAddress();
+ if (ArrayIndexVar) {
+ // If we have an array index variable, load it and use it as an offset.
+ // Then, increment the value.
+ llvm::Value *ArrayIndex = CGF.Builder.CreateLoad(ArrayIndexVar);
+ Dest = CGF.Builder.CreateInBoundsGEP(Dest, ArrayIndex, "destaddress");
+ llvm::Value *Next = llvm::ConstantInt::get(ArrayIndex->getType(), 1);
+ Next = CGF.Builder.CreateAdd(ArrayIndex, Next, "inc");
+ CGF.Builder.CreateStore(Next, ArrayIndexVar);
+ }
+
+ CGF.EmitAggExpr(MemberInit->getInit(), Dest,
+ LHS.isVolatileQualified(),
+ /*IgnoreResult*/ false,
+ /*IsInitializer*/ true);
+
+ return;
+ }
+
+ const ConstantArrayType *Array = CGF.getContext().getAsConstantArrayType(T);
+ assert(Array && "Array initialization without the array type?");
+ llvm::Value *IndexVar
+ = CGF.GetAddrOfLocalVar(MemberInit->getArrayIndex(Index));
+ assert(IndexVar && "Array index variable not loaded");
+
+ // Initialize this index variable to zero.
+ llvm::Value* Zero
+ = llvm::Constant::getNullValue(
+ CGF.ConvertType(CGF.getContext().getSizeType()));
+ CGF.Builder.CreateStore(Zero, IndexVar);
+
+ // Start the loop with a block that tests the condition.
+ llvm::BasicBlock *CondBlock = CGF.createBasicBlock("for.cond");
+ llvm::BasicBlock *AfterFor = CGF.createBasicBlock("for.end");
+
+ CGF.EmitBlock(CondBlock);
+
+ llvm::BasicBlock *ForBody = CGF.createBasicBlock("for.body");
+ // Generate: if (loop-index < number-of-elements) fall to the loop body,
+ // otherwise, go to the block after the for-loop.
+ uint64_t NumElements = Array->getSize().getZExtValue();
+ llvm::Value * NumElementsPtr =
+ llvm::ConstantInt::get(llvm::Type::getInt64Ty(CGF.getLLVMContext()),
+ NumElements);
+ llvm::Value *Counter = CGF.Builder.CreateLoad(IndexVar);
+ llvm::Value *IsLess = CGF.Builder.CreateICmpULT(Counter, NumElementsPtr,
+ "isless");
+
+ // If the condition is true, execute the body.
+ CGF.Builder.CreateCondBr(IsLess, ForBody, AfterFor);
+
+ CGF.EmitBlock(ForBody);
+ llvm::BasicBlock *ContinueBlock = CGF.createBasicBlock("for.inc");
+
+ {
+ CodeGenFunction::CleanupScope Cleanups(CGF);
+
+ // Inside the loop body recurse to emit the inner loop or, eventually, the
+ // constructor call.
+ EmitAggMemberInitializer(CGF, LHS, ArrayIndexVar, MemberInit,
+ Array->getElementType(), Index + 1);
+ }
+
+ CGF.EmitBlock(ContinueBlock);
+
+ // Emit the increment of the loop counter.
+ llvm::Value *NextVal = llvm::ConstantInt::get(Counter->getType(), 1);
+ Counter = CGF.Builder.CreateLoad(IndexVar);
+ NextVal = CGF.Builder.CreateAdd(Counter, NextVal, "inc");
+ CGF.Builder.CreateStore(NextVal, IndexVar);
+
+ // Finally, branch back up to the condition for the next iteration.
+ CGF.EmitBranch(CondBlock);
+
+ // Emit the fall-through block.
+ CGF.EmitBlock(AfterFor, true);
+}
+
static void EmitMemberInitializer(CodeGenFunction &CGF,
const CXXRecordDecl *ClassDecl,
- CXXBaseOrMemberInitializer *MemberInit) {
+ CXXBaseOrMemberInitializer *MemberInit,
+ const CXXConstructorDecl *Constructor,
+ FunctionArgList &Args) {
assert(MemberInit->isMemberInitializer() &&
"Must have member initializer!");
@@ -583,14 +472,61 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
CGF.EmitComplexExprIntoAddr(MemberInit->getInit(), LHS.getAddress(),
LHS.isVolatileQualified());
} else {
- CGF.EmitAggExpr(MemberInit->getInit(), LHS.getAddress(),
- LHS.isVolatileQualified(),
- /*IgnoreResult*/ false,
- /*IsInitializer*/ true);
+ llvm::Value *ArrayIndexVar = 0;
+ const ConstantArrayType *Array
+ = CGF.getContext().getAsConstantArrayType(FieldType);
+ if (Array && Constructor->isImplicit() &&
+ Constructor->isCopyConstructor()) {
+ const llvm::Type *SizeTy
+ = CGF.ConvertType(CGF.getContext().getSizeType());
+
+ // The LHS is a pointer to the first object we'll be constructing, as
+ // a flat array.
+ QualType BaseElementTy = CGF.getContext().getBaseElementType(Array);
+ const llvm::Type *BasePtr = CGF.ConvertType(BaseElementTy);
+ BasePtr = llvm::PointerType::getUnqual(BasePtr);
+ llvm::Value *BaseAddrPtr = CGF.Builder.CreateBitCast(LHS.getAddress(),
+ BasePtr);
+ LHS = LValue::MakeAddr(BaseAddrPtr, CGF.MakeQualifiers(BaseElementTy));
+
+ // Create an array index that will be used to walk over all of the
+ // objects we're constructing.
+ ArrayIndexVar = CGF.CreateTempAlloca(SizeTy, "object.index");
+ llvm::Value *Zero = llvm::Constant::getNullValue(SizeTy);
+ CGF.Builder.CreateStore(Zero, ArrayIndexVar);
+
+ // If we are copying an array of scalars or classes with trivial copy
+ // constructors, perform a single aggregate copy.
+ const RecordType *Record = BaseElementTy->getAs<RecordType>();
+ if (!Record ||
+ cast<CXXRecordDecl>(Record->getDecl())->hasTrivialCopyConstructor()) {
+ // Find the source pointer. We knows it's the last argument because
+ // we know we're in a copy constructor.
+ unsigned SrcArgIndex = Args.size() - 1;
+ llvm::Value *SrcPtr
+ = CGF.Builder.CreateLoad(
+ CGF.GetAddrOfLocalVar(Args[SrcArgIndex].first));
+ LValue Src = CGF.EmitLValueForFieldInitialization(SrcPtr, Field, 0);
+
+ // Copy the aggregate.
+ CGF.EmitAggregateCopy(LHS.getAddress(), Src.getAddress(), FieldType,
+ LHS.isVolatileQualified());
+ return;
+ }
+
+ // Emit the block variables for the array indices, if any.
+ for (unsigned I = 0, N = MemberInit->getNumArrayIndices(); I != N; ++I)
+ CGF.EmitLocalBlockVarDecl(*MemberInit->getArrayIndex(I));
+ }
+
+ EmitAggMemberInitializer(CGF, LHS, ArrayIndexVar, MemberInit, FieldType, 0);
if (!CGF.Exceptions)
return;
+ // FIXME: If we have an array of classes w/ non-trivial destructors,
+ // we need to destroy in reverse order of construction along the exception
+ // path.
const RecordType *RT = FieldType->getAs<RecordType>();
if (!RT)
return;
@@ -680,20 +616,13 @@ void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) {
// Emit the constructor prologue, i.e. the base and member
// initializers.
- EmitCtorPrologue(Ctor, CtorType);
+ EmitCtorPrologue(Ctor, CtorType, Args);
// Emit the body of the statement.
if (IsTryBody)
EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock());
else if (Body)
EmitStmt(Body);
- else {
- assert(Ctor->isImplicit() && "bodyless ctor not implicit");
- if (!Ctor->isDefaultConstructor()) {
- assert(Ctor->isCopyConstructor());
- SynthesizeCXXCopyConstructor(Args);
- }
- }
// Emit any cleanup blocks associated with the member or base
// initializers, which includes (along the exceptional path) the
@@ -708,7 +637,8 @@ void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) {
/// EmitCtorPrologue - This routine generates necessary code to initialize
/// base classes and non-static data members belonging to this constructor.
void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
- CXXCtorType CtorType) {
+ CXXCtorType CtorType,
+ FunctionArgList &Args) {
const CXXRecordDecl *ClassDecl = CD->getParent();
llvm::SmallVector<CXXBaseOrMemberInitializer *, 8> MemberInitializers;
@@ -733,7 +663,7 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
assert(LiveTemporaries.empty() &&
"Should not have any live temporaries at initializer start!");
- EmitMemberInitializer(*this, ClassDecl, MemberInitializers[I]);
+ EmitMemberInitializer(*this, ClassDecl, MemberInitializers[I], CD, Args);
}
}
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 90a3ec4a4b..74f0a488b5 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -531,7 +531,8 @@ public:
/// GenerateThunk - Generate a thunk for the given method.
void GenerateThunk(llvm::Function *Fn, GlobalDecl GD, const ThunkInfo &Thunk);
- void EmitCtorPrologue(const CXXConstructorDecl *CD, CXXCtorType Type);
+ void EmitCtorPrologue(const CXXConstructorDecl *CD, CXXCtorType Type,
+ FunctionArgList &Args);
/// InitializeVTablePointer - Initialize the vtable pointer of the given
/// subobject.
@@ -554,8 +555,6 @@ public:
void InitializeVTablePointers(const CXXRecordDecl *ClassDecl);
- void SynthesizeCXXCopyConstructor(const FunctionArgList &Args);
-
/// EmitDtorEpilogue - Emit all code that comes at the end of class's
/// destructor. This is to call destructors on members and base classes in
/// reverse order of their construction.
@@ -802,14 +801,6 @@ public:
const CXXRecordDecl *ClassDecl,
const CXXRecordDecl *BaseClassDecl);
- void EmitClassAggrMemberwiseCopy(llvm::Value *DestValue,
- llvm::Value *SrcValue,
- const ConstantArrayType *Array,
- const CXXRecordDecl *ClassDecl);
-
- void EmitClassMemberwiseCopy(llvm::Value *DestValue, llvm::Value *SrcValue,
- const CXXRecordDecl *ClassDecl);
-
void EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
CXXCtorType CtorType,
const FunctionArgList &Args);
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index b9c7d7948f..818a2bd446 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1551,41 +1551,103 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
FieldDecl *Field,
CXXBaseOrMemberInitializer *&CXXMemberInit) {
if (ImplicitInitKind == IIK_Copy) {
- // FIXME: We should not return early here, but will do so until
- // we know how to handle copy initialization of arrays.
- CXXMemberInit = 0;
- return false;
-
+ SourceLocation Loc = Constructor->getLocation();
ParmVarDecl *Param = Constructor->getParamDecl(0);
QualType ParamType = Param->getType().getNonReferenceType();
Expr *MemberExprBase =
DeclRefExpr::Create(SemaRef.Context, 0, SourceRange(), Param,
- SourceLocation(), ParamType, 0);
+ Loc, ParamType, 0);
+
+ // Build a reference to this field within the parameter.
+ CXXScopeSpec SS;
+ LookupResult MemberLookup(SemaRef, Field->getDeclName(), Loc,
+ Sema::LookupMemberName);
+ MemberLookup.addDecl(Field, AS_public);
+ MemberLookup.resolveKind();
+ Sema::OwningExprResult CopyCtorArg
+ = SemaRef.BuildMemberReferenceExpr(SemaRef.Owned(MemberExprBase),
+ ParamType, Loc,
+ /*IsArrow=*/false,
+ SS,
+ /*FirstQualifierInScope=*/0,
+ MemberLookup,
+ /*TemplateArgs=*/0);
+ if (CopyCtorArg.isInvalid())
+ return true;
+ // When the field we are copying is an array, create index variables for
+ // each dimension of the array. We use these index variables to subscript
+ // the source array, and other clients (e.g., CodeGen) will perform the
+ // necessary iteration with these index variables.
+ llvm::SmallVector<VarDecl *, 4> IndexVariables;
+ QualType BaseType = Field->getType();
+ QualType SizeType = SemaRef.Context.getSizeType();
+ while (const ConstantArrayType *Array
+ = SemaRef.Context.getAsConstantArrayType(BaseType)) {
+ // Create the iteration variable for this array index.
+ IdentifierInfo *IterationVarName = 0;
+ {
+ llvm::SmallString<8> Str;
+ llvm::raw_svector_ostream OS(Str);
+ OS << "__i" << IndexVariables.size();
+ IterationVarName = &SemaRef.Context.Idents.get(OS.str());
+ }
+ VarDecl *IterationVar
+ = VarDecl::Create(SemaRef.Context, SemaRef.CurContext, Loc,
+ IterationVarName, SizeType,
+ SemaRef.Context.getTrivialTypeSourceInfo(SizeType, Loc),
+ VarDecl::None, VarDecl::None);
+ IndexVariables.push_back(IterationVar);
+
+ // Create a reference to the iteration variable.
+ Sema::OwningExprResult IterationVarRef
+ = SemaRef.BuildDeclRefExpr(IterationVar, SizeType, Loc);
+ assert(!IterationVarRef.isInvalid() &&
+ "Reference to invented variable cannot fail!");
+
+ // Subscript the array with this iteration variable.
+ CopyCtorArg = SemaRef.CreateBuiltinArraySubscriptExpr(move(CopyCtorArg),
+ Loc,
+ move(IterationVarRef),
+ Loc);
+ if (CopyCtorArg.isInvalid())
+ return true;
+
+ BaseType = Array->getElementType();
+ }
- Expr *CopyCtorArg =
- MemberExpr::Create(SemaRef.Context, MemberExprBase, /*IsArrow=*/false,
- 0, SourceRange(), Field,
- DeclAccessPair::make(Field, Field->getAccess()),
- SourceLocation(), 0,
- Field->getType().getNonReferenceType());
+ // Construct the entity that we will be initializing. For an array, this
+ // will be first element in the array, which may require several levels
+ // of array-subscript entities.
+ llvm::SmallVector<InitializedEntity, 4> Entities;
+ Entities.reserve(1 + IndexVariables.size());
+ Entities.push_back(InitializedEntity::InitializeMember(Field));
+ for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I)
+ Entities.push_back(InitializedEntity::InitializeElement(SemaRef.Context,
+ 0,
+ Entities.back()));
- InitializedEntity InitEntity = InitializedEntity::InitializeMember(Field);
+ // Direct-initialize to use the copy constructor.
InitializationKind InitKind =
- InitializationKind::CreateDirect(Constructor->getLocation(),
- SourceLocation(), SourceLocation());
+ InitializationKind::CreateDirect(Loc, SourceLocation(), SourceLocation());
- InitializationSequence InitSeq(SemaRef, InitEntity, InitKind,
- &CopyCtorArg, 1);
+ Expr *CopyCtorArgE = CopyCtorArg.takeAs<Expr>();
+ InitializationSequence InitSeq(SemaRef, Entities.back(), InitKind,
+ &CopyCtorArgE, 1);
- Sema::OwningExprResult MemberInit =
- InitSeq.Perform(SemaRef, InitEntity, InitKind,
- Sema::MultiExprArg(SemaRef, (void**)&CopyCtorArg, 1), 0);
+ Sema::OwningExprResult MemberInit
+ = InitSeq.Perform(SemaRef, Entities.back(), InitKind,
+ Sema::MultiExprArg(SemaRef, (void**)&CopyCtorArgE, 1));
+ MemberInit = SemaRef.MaybeCreateCXXExprWithTemporaries(move(MemberInit));
if (MemberInit.isInvalid())
return true;
-
- CXXMemberInit = 0;
+
+ CXXMemberInit
+ = CXXBaseOrMemberInitializer::Create(SemaRef.Context, Field, Loc, Loc,
+ MemberInit.takeAs<Expr>(), Loc,
+ IndexVariables.data(),
+ IndexVariables.size());
return false;
}
@@ -1758,7 +1820,9 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
}
}
}
- continue;
+
+ if (ImplicitInitKind == IIK_Default)
+ continue;
}
if (CXXBaseOrMemberInitializer *Value = AllBaseFields.lookup(*Field)) {
AllToInit.push_back(Value);
@@ -4575,34 +4639,17 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
if (SetBaseOrMemberInitializers(CopyConstructor, 0, 0, /*AnyErrors=*/false)) {
Diag(CurrentLocation, diag::note_member_synthesized_at)
- << CXXCopyConstructor << Context.getTagDeclType(ClassDecl);
+ << CXXCopyConstructor << Context.getTagDeclType(ClassDecl);
CopyConstructor->setInvalidDecl();
- } else {
- CopyConstructor->setUsed();
- }
-
- // FIXME: Once SetBaseOrMemberInitializers can handle copy initialization of
- // fields, this code below should be removed.
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- FieldEnd = ClassDecl->field_end();
- Field != FieldEnd; ++Field) {
- QualType FieldType = Context.getCanonicalType((*Field)->getType());
- if (const ArrayType *Array = Context.getAsArrayType(FieldType))
- FieldType = Array->getElementType();
- if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
- CXXRecordDecl *FieldClassDecl
- = cast<CXXRecordDecl>(FieldClassType->getDecl());
- if (CXXConstructorDecl *FieldCopyCtor =
- FieldClassDecl->getCopyConstructor(Context, TypeQuals)) {
- CheckDirectMemberAccess(Field->getLocation(),
- FieldCopyCtor,
- PDiag(diag::err_access_copy_field)
- << Field->getDeclName() << Field->getType());
-
- MarkDeclarationReferenced(CurrentLocation, FieldCopyCtor);
- }
- }
+ } else {
+ CopyConstructor->setBody(ActOnCompoundStmt(CopyConstructor->getLocation(),
+ CopyConstructor->getLocation(),
+ MultiStmtArg(*this, 0, 0),
+ /*isStmtExpr=*/false)
+ .takeAs<Stmt>());
}
+
+ CopyConstructor->setUsed();
}
Sema::OwningExprResult