diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 5a3e1002c62e065a2d91b667699939cf6341dc31..f789787b6166c650b79841cb54cfd0747059c66d 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -361,33 +361,21 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { Builder.CreateStore(Loc, Addr); continue; } else { - E = new (getContext()) DeclRefExpr(const_cast<ValueDecl*>(VD), + if (BDRE->getCopyConstructorExpr()) + E = BDRE->getCopyConstructorExpr(); + else { + E = new (getContext()) DeclRefExpr(const_cast<ValueDecl*>(VD), VD->getType().getNonReferenceType(), SourceLocation()); - if (getContext().getLangOptions().CPlusPlus) { - if (VD->getType()->isReferenceType()) { - E = new (getContext()) - UnaryOperator(const_cast<Expr*>(E), UnaryOperator::AddrOf, - getContext().getPointerType(E->getType()), - SourceLocation()); - } - else { - QualType T = E->getType(); - if (const RecordType *RT = T->getAs<RecordType>()) { - CXXRecordDecl *Record = cast<CXXRecordDecl>(RT->getDecl()); - if (!Record->hasTrivialCopyConstructor()) { - CXXConstructorDecl *D = Record->getCopyConstructor(getContext(), - 0); - Expr *Arg = const_cast<Expr*>(E); - E = CXXConstructExpr::Create(getContext(), T, D->getLocation(), - D, false, &Arg, 1, false, - CXXConstructExpr::CK_Complete); - } - } + if (VD->getType()->isReferenceType()) { + E = new (getContext()) + UnaryOperator(const_cast<Expr*>(E), UnaryOperator::AddrOf, + getContext().getPointerType(E->getType()), + SourceLocation()); + } } } } - } if (BDRE->isByRef()) { E = new (getContext()) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index e1a6a04bfd41494f144bf0a5b7d1c8106b2f3e6f..5655a25b1fdab6ca6e4c4d68ae1f66dcdcc101b4 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1746,8 +1746,28 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, // Variable will be bound by-copy, make it const within the closure. ExprTy.addConst(); - return Owned(new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, false, - constAdded)); + BlockDeclRefExpr *BDRE = new (Context) BlockDeclRefExpr(VD, + ExprTy, Loc, false, + constAdded); + QualType T = VD->getType(); + if (getLangOptions().CPlusPlus && !T->isDependentType() && + !T->isReferenceType()) { + Expr *E = new (Context) + DeclRefExpr(const_cast<ValueDecl*>(BDRE->getDecl()), T, + SourceLocation()); + + OwningExprResult Res = PerformCopyInitialization( + InitializedEntity::InitializeResult(SourceLocation(), + T, false), + SourceLocation(), + Owned(E)); + if (!Res.isInvalid()) { + Expr *Init = Res.takeAs<Expr>(); + if (isa<CXXConstructExpr>(Init)) + BDRE->setCopyConstructorExpr(Init); + } + } + return Owned(BDRE); } // If this reference is not in a block or if the referenced variable is // within the block, create a normal DeclRefExpr. diff --git a/test/CodeGenCXX/copy-in-cplus-object.cpp b/test/CodeGenCXX/copy-in-cplus-object.cpp index 6dcb1285faffbebd9725ebd013d82a077da5da35..819879806d0de4f143494a8fcb3d2c727740d6a4 100644 --- a/test/CodeGenCXX/copy-in-cplus-object.cpp +++ b/test/CodeGenCXX/copy-in-cplus-object.cpp @@ -2,7 +2,7 @@ struct TestObject { - TestObject(const TestObject& inObj); + TestObject(const TestObject& inObj, int def = 100); TestObject(); TestObject& operator=(const TestObject& inObj); int version() const; @@ -14,5 +14,5 @@ void testRoutine() { int (^V)() = ^{ return one.version(); }; } -// CHECK: call void @_ZN10TestObjectC1ERKS_ +// CHECK: call void @_ZN10TestObjectC1ERKS_i