Index: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td @@ -1689,8 +1689,8 @@ "cannot initialize %select{a variable|a parameter|return object|an " "exception object|a member subobject|an array element|a new value|a value|a " "base class|a constructor delegation|a vector element|a block element|a " - "complex element|a lambda capture|a compound literal initializer|a " - "related result|a parameter of CF audited function}0 " + "block element|a complex element|a lambda capture|a compound literal " + "initializer|a related result|a parameter of CF audited function}0 " "%diff{of type $ with an %select{rvalue|lvalue}2 of type $|" "with an %select{rvalue|lvalue}2 of incompatible type}1,3" "%select{|: different classes%diff{ ($ vs $)|}5,6" Index: cfe/trunk/include/clang/Sema/Initialization.h =================================================================== --- cfe/trunk/include/clang/Sema/Initialization.h +++ cfe/trunk/include/clang/Sema/Initialization.h @@ -70,6 +70,9 @@ /// \brief The entity being initialized is a field of block descriptor for /// the copied-in c++ object. EK_BlockElement, + /// The entity being initialized is a field of block descriptor for the + /// copied-in lambda object that's used in the lambda to block conversion. + EK_LambdaToBlockConversionBlockElement, /// \brief The entity being initialized is the real or imaginary part of a /// complex number. EK_ComplexElement, @@ -260,7 +263,13 @@ QualType Type, bool NRVO) { return InitializedEntity(EK_BlockElement, BlockVarLoc, Type, NRVO); } - + + static InitializedEntity InitializeLambdaToBlock(SourceLocation BlockVarLoc, + QualType Type, bool NRVO) { + return InitializedEntity(EK_LambdaToBlockConversionBlockElement, + BlockVarLoc, Type, NRVO); + } + /// \brief Create the initialization entity for an exception object. static InitializedEntity InitializeException(SourceLocation ThrowLoc, QualType Type, bool NRVO) { Index: cfe/trunk/lib/Sema/SemaInit.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaInit.cpp +++ cfe/trunk/lib/Sema/SemaInit.cpp @@ -950,6 +950,7 @@ case InitializedEntity::EK_Base: case InitializedEntity::EK_Delegating: case InitializedEntity::EK_BlockElement: + case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_Binding: llvm_unreachable("unexpected braced scalar init"); } @@ -2934,6 +2935,7 @@ case EK_VectorElement: case EK_ComplexElement: case EK_BlockElement: + case EK_LambdaToBlockConversionBlockElement: case EK_CompoundLiteralInit: case EK_RelatedResult: return DeclarationName(); @@ -2963,6 +2965,7 @@ case EK_VectorElement: case EK_ComplexElement: case EK_BlockElement: + case EK_LambdaToBlockConversionBlockElement: case EK_LambdaCapture: case EK_CompoundLiteralInit: case EK_RelatedResult: @@ -2992,6 +2995,7 @@ case EK_VectorElement: case EK_ComplexElement: case EK_BlockElement: + case EK_LambdaToBlockConversionBlockElement: case EK_LambdaCapture: case EK_RelatedResult: break; @@ -3025,6 +3029,9 @@ case EK_VectorElement: OS << "VectorElement " << Index; break; case EK_ComplexElement: OS << "ComplexElement " << Index; break; case EK_BlockElement: OS << "Block"; break; + case EK_LambdaToBlockConversionBlockElement: + OS << "Block (lambda)"; + break; case EK_LambdaCapture: OS << "LambdaCapture "; OS << DeclarationName(Capture.VarID); @@ -3622,9 +3629,13 @@ // destination object. // Per DR (no number yet), this does not apply when initializing a base // class or delegating to another constructor from a mem-initializer. + // ObjC++: Lambda captured by the block in the lambda to block conversion + // should avoid copy elision. if (S.getLangOpts().CPlusPlus1z && Entity.getKind() != InitializedEntity::EK_Base && Entity.getKind() != InitializedEntity::EK_Delegating && + Entity.getKind() != + InitializedEntity::EK_LambdaToBlockConversionBlockElement && UnwrappedArgs.size() == 1 && UnwrappedArgs[0]->isRValue() && S.Context.hasSameUnqualifiedType(UnwrappedArgs[0]->getType(), DestType)) { // Convert qualifications if necessary. @@ -5488,6 +5499,7 @@ case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_ComplexElement: case InitializedEntity::EK_BlockElement: + case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_LambdaCapture: case InitializedEntity::EK_CompoundLiteralInit: return Sema::AA_Initializing; @@ -5511,6 +5523,7 @@ case InitializedEntity::EK_ComplexElement: case InitializedEntity::EK_Exception: case InitializedEntity::EK_BlockElement: + case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_LambdaCapture: case InitializedEntity::EK_CompoundLiteralInit: return false; @@ -5537,6 +5550,7 @@ case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_ComplexElement: case InitializedEntity::EK_BlockElement: + case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_LambdaCapture: return false; @@ -5584,6 +5598,7 @@ case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_ComplexElement: case InitializedEntity::EK_BlockElement: + case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_CompoundLiteralInit: case InitializedEntity::EK_RelatedResult: return Initializer->getLocStart(); @@ -6021,6 +6036,7 @@ case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_BlockElement: + case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_ComplexElement: // Could not determine what the full initialization is. Assume it might not // outlive the full-expression. @@ -6109,6 +6125,7 @@ return FallbackDecl; case InitializedEntity::EK_BlockElement: + case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_LambdaCapture: case InitializedEntity::EK_Exception: case InitializedEntity::EK_VectorElement: Index: cfe/trunk/lib/Sema/SemaLambda.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaLambda.cpp +++ cfe/trunk/lib/Sema/SemaLambda.cpp @@ -1649,10 +1649,9 @@ CallOperator->markUsed(Context); ExprResult Init = PerformCopyInitialization( - InitializedEntity::InitializeBlock(ConvLocation, - Src->getType(), - /*NRVO=*/false), - CurrentLocation, Src); + InitializedEntity::InitializeLambdaToBlock(ConvLocation, Src->getType(), + /*NRVO=*/false), + CurrentLocation, Src); if (!Init.isInvalid()) Init = ActOnFinishFullExpr(Init.get()); Index: cfe/trunk/test/CodeGenObjCXX/lambda-to-block.mm =================================================================== --- cfe/trunk/test/CodeGenObjCXX/lambda-to-block.mm +++ cfe/trunk/test/CodeGenObjCXX/lambda-to-block.mm @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -x objective-c++ -fblocks -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 -std=c++1z -emit-llvm -o - %s | FileCheck %s + +// rdar://31385153 +// Shouldn't crash! + +void takesBlock(void (^)(void)); + +struct Copyable { + Copyable(const Copyable &x); +}; + +void hasLambda(Copyable x) { + takesBlock([x] () { }); +} +// CHECK-LABEL: define internal void @__copy_helper_block_ +// CHECK: call void @"_ZZ9hasLambda8CopyableEN3$_0C1ERKS0_" +// CHECK-LABEL: define internal void @"_ZZ9hasLambda8CopyableEN3$_0C2ERKS0_" +// CHECK: call void @_ZN8CopyableC1ERKS_