From: Douglas Gregor Date: Tue, 2 Mar 2010 17:18:33 +0000 (+0000) Subject: Use CXXTemporaryObjectExpr for explicitly-constructed temporaries. We X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=91be6f5ccbde073e592bed9a3e3bc363957714fb;p=clang Use CXXTemporaryObjectExpr for explicitly-constructed temporaries. We used to do this, but it got lost when we switched functional-style cast syntax over to using the new initialization code. Fixes PR6457. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97568 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 762f6db0a4..0f8107ac5e 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -3439,10 +3439,25 @@ InitializationSequence::Perform(Sema &S, return S.ExprError(); // Build the an expression that constructs a temporary. - CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), - Constructor, - move_arg(ConstructorArgs), - ConstructorInitRequiresZeroInit, + if (Entity.getKind() == InitializedEntity::EK_Temporary && + (Kind.getKind() == InitializationKind::IK_Direct || + Kind.getKind() == InitializationKind::IK_Value)) { + // An explicitly-constructed temporary, e.g., X(1, 2). + unsigned NumExprs = ConstructorArgs.size(); + Expr **Exprs = (Expr **)ConstructorArgs.take(); + S.MarkDeclarationReferenced(Kind.getLocation(), Constructor); + CurInit = S.Owned(new (S.Context) CXXTemporaryObjectExpr(S.Context, + Constructor, + Entity.getType(), + Kind.getLocation(), + Exprs, + NumExprs, + Kind.getParenRange().getEnd())); + } else + CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), + Constructor, + move_arg(ConstructorArgs), + ConstructorInitRequiresZeroInit, Entity.getKind() == InitializedEntity::EK_Base); if (CurInit.isInvalid()) return S.ExprError(); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index dccea49878..2f3c482321 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -5051,6 +5051,11 @@ TreeTransform::TransformCXXTemporaryObjectExpr( for (CXXTemporaryObjectExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end(); Arg != ArgEnd; ++Arg) { + if (getDerived().DropCallArgument(*Arg)) { + ArgumentChanged = true; + break; + } + OwningExprResult TransArg = getDerived().TransformExpr(*Arg); if (TransArg.isInvalid()) return SemaRef.ExprError(); @@ -5062,8 +5067,11 @@ TreeTransform::TransformCXXTemporaryObjectExpr( if (!getDerived().AlwaysRebuild() && T == E->getType() && Constructor == E->getConstructor() && - !ArgumentChanged) + !ArgumentChanged) { + // FIXME: Instantiation-specific + SemaRef.MarkDeclarationReferenced(E->getTypeBeginLoc(), Constructor); return SemaRef.Owned(E->Retain()); + } // FIXME: Bogus location information SourceLocation CommaLoc; diff --git a/test/SemaTemplate/instantiate-init.cpp b/test/SemaTemplate/instantiate-init.cpp index 8a10a87e61..16ecc4758a 100644 --- a/test/SemaTemplate/instantiate-init.cpp +++ b/test/SemaTemplate/instantiate-init.cpp @@ -26,3 +26,14 @@ void test_f1(X0 *x0, int *ip, float *fp, double *dp) { f1(x0, ip, dp); // expected-note{{instantiation}} } +namespace PR6457 { + template struct X { explicit X(T* p = 0) { }; }; + template struct Y { Y(int, const T& x); }; + struct A { }; + template + struct B { + B() : y(0, X()) { } + Y > y; + }; + B b; +}