diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index d3a41d62a774..e1fe0d29a2db 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -802,6 +802,9 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, } RValue CodeGenFunction::EmitCallArg(const Expr *E, QualType ArgType) { + if (const CXXBindReferenceExpr *BE = dyn_cast(E)) + return RValue::get(EmitCXXBindReferenceExpr(BE)); + if (ArgType->isReferenceType()) return EmitReferenceBindingToExpr(E, ArgType); diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 51e194da3427..6ba537e528c2 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -507,6 +507,10 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { Builder.CreateCall4(CGM.getMemCpyFn(), Loc, SrcPtr, SizeVal, AlignVal); } + } else if (const CXXBindReferenceExpr *BE = + dyn_cast(Init)) { + llvm::Value *V = EmitCXXBindReferenceExpr(BE); + EmitStoreOfScalar(V, Loc, /*Volatile=*/false, Ty); } else if (Ty->isReferenceType()) { RValue RV = EmitReferenceBindingToExpr(Init, Ty, /*IsInitializer=*/true); EmitStoreOfScalar(RV.getScalarVal(), Loc, false, Ty); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 605f77975f95..c0dd68bc70b6 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -92,9 +92,31 @@ RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E, IsInitializer); } +llvm::Value * +CodeGenFunction::EmitCXXBindReferenceExpr(const CXXBindReferenceExpr *E) { + QualType T = E->getType(); + assert(T->isAnyComplexType() && "FIXME: Unhandled bind expression!"); + + const Expr *SubExpr = E->getSubExpr(); + + if (!E->requiresTemporaryCopy()) + return EmitLValue(SubExpr).getAddress(); + + llvm::Value *Value = CreateTempAlloca(ConvertTypeForMem(T), "reftmp"); + + if (T->isAnyComplexType()) + EmitComplexExprIntoAddr(SubExpr, Value, /*DestIsVolatile=*/false); + else + assert(false && "Unhandled bind expression"); + + return Value; +} + RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E, QualType DestType, bool IsInitializer) { + assert(!E->getType()->isAnyComplexType() && + "Should not use this function for complex types!"); bool ShouldDestroyTemporaries = false; unsigned OldNumLiveTemporaries = 0; diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 7a8da0c95ba8..69b2fa222c18 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1116,6 +1116,8 @@ public: RValue EmitReferenceBindingToExpr(const Expr* E, QualType DestType, bool IsInitializer = false); + llvm::Value *EmitCXXBindReferenceExpr(const CXXBindReferenceExpr *E); + //===--------------------------------------------------------------------===// // Expression Emission //===--------------------------------------------------------------------===// diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index a9adb70050b7..db888a62a4fa 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3297,15 +3297,31 @@ InitializationSequence::Perform(Sema &S, // Check exception specifications if (S.CheckExceptionSpecCompatibility(CurInitExpr, DestType)) return S.ExprError(); + + // FIXME: We should do this for all types. + if (DestType->isAnyComplexType()) { + CurInit = + S.Owned(CXXBindReferenceExpr::Create(S.Context, + CurInit.takeAs(), + /*ExtendsLifetime=*/false, + /*RequiresTemporaryCopy=*/false)); + } + break; - + case SK_BindReferenceToTemporary: // Check exception specifications if (S.CheckExceptionSpecCompatibility(CurInitExpr, DestType)) return S.ExprError(); - // FIXME: At present, we have no AST to describe when we need to make a - // temporary to bind a reference to. We should. + // FIXME: We should do this for all types. + if (DestType->isAnyComplexType()) { + CurInit = + S.Owned(CXXBindReferenceExpr::Create(S.Context, + CurInit.takeAs(), + /*ExtendsLifetime=*/false, + /*RequiresTemporaryCopy=*/true)); + } break; case SK_UserConversion: {