<div dir="auto"><div><div class="gmail_extra"><div class="gmail_quote">On 8 Dec 2016 7:17 pm, "Duncan P. N. Exon Smith via cfe-commits" <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br type="attribution"><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">+Eric, Marshall<br>
<br>
I haven't looked, but: from the test name, "copy.fail.cpp", I suspect there is a bug/incompatibility in the test. It likely relies on the compiler trying (and failing) to copy something in a context where r288866 guarantees that there is no copy.</blockquote></div></div></div><div dir="auto"><br></div><div dir="auto">Was this not fixed by "[libcxx] r289033 - Avoid C++17 guaranteed copy elision when testing for non-copyability"?</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="elided-text">
> On 2016-Dec-08, at 18:00, Adrian Prantl <<a href="mailto:aprantl@apple.com">aprantl@apple.com</a>> wrote:<br>
><br>
> Hi Richard,<br>
><br>
> at this point this is more a heads-up than anything actionable, but I wanted to let you know that I bisected this bot failure (<a href="http://lab.llvm.org:8080/green/job/clang-stage2-cmake-RgSan_check/2721/consoleFull#10584592348254eaf0-7326-4999-85b0-388101f2d404" rel="noreferrer" target="_blank">http://lab.llvm.org:8080/<wbr>green/job/clang-stage2-cmake-<wbr>RgSan_check/2721/consoleFull#<wbr>10584592348254eaf0-7326-4999-<wbr>85b0-388101f2d404</a>) of std/input.output/stream.<wbr>buffers/streambuf/streambuf.<wbr>cons/copy.fail.cpp down to this commit.<br>
><br>
> I will follow up once I have a better understanding what is going on there.<br>
><br>
> -- adrian<br>
><br>
>> On Dec 6, 2016, at 3:52 PM, Richard Smith via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br>
>><br>
>> Author: rsmith<br>
>> Date: Tue Dec 6 17:52:28 2016<br>
>> New Revision: 288866<br>
>><br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=288866&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=288866&view=rev</a><br>
>> Log:<br>
>> [c++17] P0135R1: Guaranteed copy elision.<br>
>><br>
>> When an object of class type is initialized from a prvalue of the same type<br>
>> (ignoring cv qualifications), use the prvalue to initialize the object directly<br>
>> instead of inserting a redundant elidable call to a copy constructor.<br>
>><br>
>> Added:<br>
>> cfe/trunk/test/CodeGenCXX/<wbr>cxx1z-copy-omission.cpp<br>
>> cfe/trunk/test/SemaCXX/cxx1z-<wbr>copy-omission.cpp<br>
>> Modified:<br>
>> cfe/trunk/include/clang/AST/<wbr>Expr.h<br>
>> cfe/trunk/lib/AST/Expr.cpp<br>
>> cfe/trunk/lib/AST/<wbr>ExprConstant.cpp<br>
>> cfe/trunk/lib/CodeGen/CGExpr.<wbr>cpp<br>
>> cfe/trunk/lib/CodeGen/<wbr>CGExprAgg.cpp<br>
>> cfe/trunk/lib/CodeGen/<wbr>CGExprConstant.cpp<br>
>> cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp<br>
>> cfe/trunk/lib/Sema/SemaInit.<wbr>cpp<br>
>> cfe/trunk/lib/Sema/<wbr>SemaOverload.cpp<br>
>> cfe/trunk/test/CXX/drs/dr0xx.<wbr>cpp<br>
>> cfe/trunk/test/CXX/drs/dr10xx.<wbr>cpp<br>
>> cfe/trunk/test/CXX/drs/dr1xx.<wbr>cpp<br>
>> cfe/trunk/test/CXX/drs/dr4xx.<wbr>cpp<br>
>> cfe/trunk/test/SemaCXX/<wbr>aggregate-initialization.cpp<br>
>> cfe/trunk/www/cxx_dr_status.<wbr>html<br>
>> cfe/trunk/www/cxx_status.html<br>
>><br>
>> Modified: cfe/trunk/include/clang/AST/<wbr>Expr.h<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=288866&r1=288865&r2=288866&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/AST/Expr.h?rev=288866&<wbr>r1=288865&r2=288866&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/include/clang/AST/<wbr>Expr.h (original)<br>
>> +++ cfe/trunk/include/clang/AST/<wbr>Expr.h Tue Dec 6 17:52:28 2016<br>
>> @@ -3786,7 +3786,7 @@ public:<br>
>><br>
>> /// \brief Build an empty initializer list.<br>
>> explicit InitListExpr(EmptyShell Empty)<br>
>> - : Expr(InitListExprClass, Empty) { }<br>
>> + : Expr(InitListExprClass, Empty), AltForm(nullptr, true) { }<br>
>><br>
>> unsigned getNumInits() const { return InitExprs.size(); }<br>
>><br>
>> @@ -3894,6 +3894,11 @@ public:<br>
>> // literal or an @encode?<br>
>> bool isStringLiteralInit() const;<br>
>><br>
>> + /// Is this a transparent initializer list (that is, an InitListExpr that is<br>
>> + /// purely syntactic, and whose semantics are that of the sole contained<br>
>> + /// initializer)?<br>
>> + bool isTransparent() const;<br>
>> +<br>
>> SourceLocation getLBraceLoc() const { return LBraceLoc; }<br>
>> void setLBraceLoc(SourceLocation Loc) { LBraceLoc = Loc; }<br>
>> SourceLocation getRBraceLoc() const { return RBraceLoc; }<br>
>><br>
>> Modified: cfe/trunk/lib/AST/Expr.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=288866&r1=288865&r2=288866&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/AST/<wbr>Expr.cpp?rev=288866&r1=288865&<wbr>r2=288866&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/lib/AST/Expr.cpp (original)<br>
>> +++ cfe/trunk/lib/AST/Expr.cpp Tue Dec 6 17:52:28 2016<br>
>> @@ -1864,6 +1864,24 @@ bool InitListExpr::<wbr>isStringLiteralInit()<br>
>> return isa<StringLiteral>(Init) || isa<ObjCEncodeExpr>(Init);<br>
>> }<br>
>><br>
>> +bool InitListExpr::isTransparent() const {<br>
>> + assert(isSemanticForm() && "syntactic form never semantically transparent");<br>
>> +<br>
>> + // A glvalue InitListExpr is always just sugar.<br>
>> + if (isGLValue()) {<br>
>> + assert(getNumInits() == 1 && "multiple inits in glvalue init list");<br>
>> + return true;<br>
>> + }<br>
>> +<br>
>> + // Otherwise, we're sugar if and only if we have exactly one initializer that<br>
>> + // is of the same type.<br>
>> + if (getNumInits() != 1 || !getInit(0))<br>
>> + return false;<br>
>> +<br>
>> + return getType().getCanonicalType() ==<br>
>> + getInit(0)->getType().<wbr>getCanonicalType();<br>
>> +}<br>
>> +<br>
>> SourceLocation InitListExpr::getLocStart() const {<br>
>> if (InitListExpr *SyntacticForm = getSyntacticForm())<br>
>> return SyntacticForm->getLocStart();<br>
>> @@ -2246,12 +2264,15 @@ bool Expr::isUnusedResultAWarning(<wbr>const<br>
>> // effects (e.g. a placement new with an uninitialized POD).<br>
>> case CXXDeleteExprClass:<br>
>> return false;<br>
>> + case MaterializeTemporaryExprClass:<br>
>> + return cast<MaterializeTemporaryExpr><wbr>(this)->GetTemporaryExpr()<br>
>> + ->isUnusedResultAWarning(<wbr>WarnE, Loc, R1, R2, Ctx);<br>
>> case CXXBindTemporaryExprClass:<br>
>> - return (cast<CXXBindTemporaryExpr>(<wbr>this)<br>
>> - ->getSubExpr()-><wbr>isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx));<br>
>> + return cast<CXXBindTemporaryExpr>(<wbr>this)->getSubExpr()<br>
>> + ->isUnusedResultAWarning(<wbr>WarnE, Loc, R1, R2, Ctx);<br>
>> case ExprWithCleanupsClass:<br>
>> - return (cast<ExprWithCleanups>(this)<br>
>> - ->getSubExpr()-><wbr>isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx));<br>
>> + return cast<ExprWithCleanups>(this)-><wbr>getSubExpr()<br>
>> + ->isUnusedResultAWarning(<wbr>WarnE, Loc, R1, R2, Ctx);<br>
>> }<br>
>> }<br>
>><br>
>><br>
>> Modified: cfe/trunk/lib/AST/<wbr>ExprConstant.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=288866&r1=288865&r2=288866&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/AST/<wbr>ExprConstant.cpp?rev=288866&<wbr>r1=288865&r2=288866&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/lib/AST/<wbr>ExprConstant.cpp (original)<br>
>> +++ cfe/trunk/lib/AST/<wbr>ExprConstant.cpp Tue Dec 6 17:52:28 2016<br>
>> @@ -5670,6 +5670,9 @@ bool RecordExprEvaluator::<wbr>VisitCastExpr(<br>
>> }<br>
>><br>
>> bool RecordExprEvaluator::<wbr>VisitInitListExpr(const InitListExpr *E) {<br>
>> + if (E->isTransparent())<br>
>> + return Visit(E->getInit(0));<br>
>> +<br>
>> const RecordDecl *RD = E->getType()->castAs<<wbr>RecordType>()->getDecl();<br>
>> if (RD->isInvalidDecl()) return false;<br>
>> const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(<wbr>RD);<br>
>><br>
>> Modified: cfe/trunk/lib/CodeGen/CGExpr.<wbr>cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=288866&r1=288865&r2=288866&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/CodeGen/<wbr>CGExpr.cpp?rev=288866&r1=<wbr>288865&r2=288866&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/lib/CodeGen/CGExpr.<wbr>cpp (original)<br>
>> +++ cfe/trunk/lib/CodeGen/CGExpr.<wbr>cpp Tue Dec 6 17:52:28 2016<br>
>> @@ -3522,7 +3522,7 @@ LValue CodeGenFunction::<wbr>EmitInitListLVal<br>
>> return EmitAggExprToLValue(E);<br>
>><br>
>> // An lvalue initializer list must be initializing a reference.<br>
>> - assert(E->getNumInits() == 1 && "reference init with multiple values");<br>
>> + assert(E->isTransparent() && "non-transparent glvalue init list");<br>
>> return EmitLValue(E->getInit(0));<br>
>> }<br>
>><br>
>><br>
>> Modified: cfe/trunk/lib/CodeGen/<wbr>CGExprAgg.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=288866&r1=288865&r2=288866&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/CodeGen/<wbr>CGExprAgg.cpp?rev=288866&r1=<wbr>288865&r2=288866&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/lib/CodeGen/<wbr>CGExprAgg.cpp (original)<br>
>> +++ cfe/trunk/lib/CodeGen/<wbr>CGExprAgg.cpp Tue Dec 6 17:52:28 2016<br>
>> @@ -1145,15 +1145,15 @@ void AggExprEmitter::<wbr>VisitInitListExpr(I<br>
>> if (E->hadArrayRangeDesignator())<br>
>> CGF.ErrorUnsupported(E, "GNU array range designator extension");<br>
>><br>
>> + if (E->isTransparent())<br>
>> + return Visit(E->getInit(0));<br>
>> +<br>
>> AggValueSlot Dest = EnsureSlot(E->getType());<br>
>><br>
>> LValue DestLV = CGF.MakeAddrLValue(Dest.<wbr>getAddress(), E->getType());<br>
>><br>
>> // Handle initialization of an array.<br>
>> if (E->getType()->isArrayType()) {<br>
>> - if (E->isStringLiteralInit())<br>
>> - return Visit(E->getInit(0));<br>
>> -<br>
>> QualType elementType =<br>
>> CGF.getContext().<wbr>getAsArrayType(E->getType())-><wbr>getElementType();<br>
>><br>
>> @@ -1162,16 +1162,6 @@ void AggExprEmitter::<wbr>VisitInitListExpr(I<br>
>> return;<br>
>> }<br>
>><br>
>> - if (E->getType()->isAtomicType()) {<br>
>> - // An _Atomic(T) object can be list-initialized from an expression<br>
>> - // of the same type.<br>
>> - assert(E->getNumInits() == 1 &&<br>
>> - CGF.getContext().<wbr>hasSameUnqualifiedType(E-><wbr>getInit(0)->getType(),<br>
>> - E->getType()) &&<br>
>> - "unexpected list initialization for atomic object");<br>
>> - return Visit(E->getInit(0));<br>
>> - }<br>
>> -<br>
>> assert(E->getType()-><wbr>isRecordType() && "Only support structs/unions here!");<br>
>><br>
>> // Do struct initialization; this code just sets each individual member<br>
>><br>
>> Modified: cfe/trunk/lib/CodeGen/<wbr>CGExprConstant.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=288866&r1=288865&r2=288866&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/CodeGen/<wbr>CGExprConstant.cpp?rev=288866&<wbr>r1=288865&r2=288866&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/lib/CodeGen/<wbr>CGExprConstant.cpp (original)<br>
>> +++ cfe/trunk/lib/CodeGen/<wbr>CGExprConstant.cpp Tue Dec 6 17:52:28 2016<br>
>> @@ -778,9 +778,6 @@ public:<br>
>> }<br>
>><br>
>> llvm::Constant *EmitArrayInitialization(<wbr>InitListExpr *ILE) {<br>
>> - if (ILE->isStringLiteralInit())<br>
>> - return Visit(ILE->getInit(0));<br>
>> -<br>
>> llvm::ArrayType *AType =<br>
>> cast<llvm::ArrayType>(<wbr>ConvertType(ILE->getType()));<br>
>> llvm::Type *ElemTy = AType->getElementType();<br>
>> @@ -845,6 +842,9 @@ public:<br>
>> }<br>
>><br>
>> llvm::Constant *VisitInitListExpr(<wbr>InitListExpr *ILE) {<br>
>> + if (ILE->isTransparent())<br>
>> + return Visit(ILE->getInit(0));<br>
>> +<br>
>> if (ILE->getType()->isArrayType()<wbr>)<br>
>> return EmitArrayInitialization(ILE);<br>
>><br>
>><br>
>> Modified: cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=288866&r1=288865&r2=288866&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp?rev=288866&r1=<wbr>288865&r2=288866&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp (original)<br>
>> +++ cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp Tue Dec 6 17:52:28 2016<br>
>> @@ -6836,6 +6836,16 @@ ExprResult Sema::IgnoredValueConversions<br>
>> return E;<br>
>> E = Res.get();<br>
>> }<br>
>> +<br>
>> + // C++1z:<br>
>> + // If the expression is a prvalue after this optional conversion, the<br>
>> + // temporary materialization conversion is applied.<br>
>> + //<br>
>> + // We skip this step: IR generation is able to synthesize the storage for<br>
>> + // itself in the aggregate case, and adding the extra node to the AST is<br>
>> + // just clutter.<br>
>> + // FIXME: We don't emit lifetime markers for the temporaries due to this.<br>
>> + // FIXME: Do any other AST consumers care about this?<br>
>> return E;<br>
>> }<br>
>><br>
>><br>
>> Modified: cfe/trunk/lib/Sema/SemaInit.<wbr>cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=288866&r1=288865&r2=288866&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaInit.cpp?rev=288866&r1=<wbr>288865&r2=288866&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/lib/Sema/SemaInit.<wbr>cpp (original)<br>
>> +++ cfe/trunk/lib/Sema/SemaInit.<wbr>cpp Tue Dec 6 17:52:28 2016<br>
>> @@ -3546,8 +3546,14 @@ static void TryConstructorInitialization<br>
>> InitializationSequence &Sequence,<br>
>> bool IsListInit = false,<br>
>> bool IsInitListCopy = false) {<br>
>> - assert((!IsListInit || (Args.size() == 1 && isa<InitListExpr>(Args[0]))) &&<br>
>> - "IsListInit must come with a single initializer list argument.");<br>
>> + assert(((!IsListInit && !IsInitListCopy) ||<br>
>> + (Args.size() == 1 && isa<InitListExpr>(Args[0]))) &&<br>
>> + "IsListInit/IsInitListCopy must come with a single initializer list "<br>
>> + "argument.");<br>
>> + InitListExpr *ILE =<br>
>> + (IsListInit || IsInitListCopy) ? cast<InitListExpr>(Args[0]) : nullptr;<br>
>> + MultiExprArg UnwrappedArgs =<br>
>> + ILE ? MultiExprArg(ILE->getInits(), ILE->getNumInits()) : Args;<br>
>><br>
>> // The type we're constructing needs to be complete.<br>
>> if (!S.isCompleteType(Kind.<wbr>getLocation(), DestType)) {<br>
>> @@ -3555,6 +3561,35 @@ static void TryConstructorInitialization<br>
>> return;<br>
>> }<br>
>><br>
>> + // C++1z [dcl.init]p17:<br>
>> + // - If the initializer expression is a prvalue and the cv-unqualified<br>
>> + // version of the source type is the same class as the class of the<br>
>> + // destination, the initializer expression is used to initialize the<br>
>> + // destination object.<br>
>> + // Per DR (no number yet), this does not apply when initializing a base<br>
>> + // class or delegating to another constructor from a mem-initializer.<br>
>> + if (S.getLangOpts().CPlusPlus1z &&<br>
>> + Entity.getKind() != InitializedEntity::EK_Base &&<br>
>> + Entity.getKind() != InitializedEntity::EK_<wbr>Delegating &&<br>
>> + UnwrappedArgs.size() == 1 && UnwrappedArgs[0]->isRValue() &&<br>
>> + S.Context.<wbr>hasSameUnqualifiedType(<wbr>UnwrappedArgs[0]->getType(), DestType)) {<br>
>> + // Convert qualifications if necessary.<br>
>> + QualType InitType = UnwrappedArgs[0]->getType();<br>
>> + ImplicitConversionSequence ICS;<br>
>> + ICS.setStandard();<br>
>> + ICS.Standard.<wbr>setAsIdentityConversion();<br>
>> + ICS.Standard.setFromType(<wbr>InitType);<br>
>> + ICS.Standard.setAllToTypes(<wbr>InitType);<br>
>> + if (!S.Context.hasSameType(<wbr>InitType, DestType)) {<br>
>> + ICS.Standard.Third = ICK_Qualification;<br>
>> + ICS.Standard.setToType(2, DestType);<br>
>> + }<br>
>> + Sequence.<wbr>AddConversionSequenceStep(ICS, DestType);<br>
>> + if (ILE)<br>
>> + Sequence.<wbr>RewrapReferenceInitList(<wbr>DestType, ILE);<br>
>> + return;<br>
>> + }<br>
>> +<br>
>> const RecordType *DestRecordType = DestType->getAs<RecordType>();<br>
>> assert(DestRecordType && "Constructor initialization requires record type");<br>
>> CXXRecordDecl *DestRecordDecl<br>
>> @@ -3588,20 +3623,16 @@ static void TryConstructorInitialization<br>
>> // constructors of the class T and the argument list consists of the<br>
>> // initializer list as a single argument.<br>
>> if (IsListInit) {<br>
>> - InitListExpr *ILE = cast<InitListExpr>(Args[0]);<br>
>> AsInitializerList = true;<br>
>><br>
>> // If the initializer list has no elements and T has a default constructor,<br>
>> // the first phase is omitted.<br>
>> - if (ILE->getNumInits() != 0 || !DestRecordDecl-><wbr>hasDefaultConstructor())<br>
>> + if (!(UnwrappedArgs.empty() && DestRecordDecl-><wbr>hasDefaultConstructor()))<br>
>> Result = ResolveConstructorOverload(S, Kind.getLocation(), Args,<br>
>> CandidateSet, Ctors, Best,<br>
>> CopyInitialization, AllowExplicit,<br>
>> /*OnlyListConstructor=*/true,<br>
>> IsListInit);<br>
>> -<br>
>> - // Time to unwrap the init list.<br>
>> - Args = MultiExprArg(ILE->getInits(), ILE->getNumInits());<br>
>> }<br>
>><br>
>> // C++11 [over.match.list]p1:<br>
>> @@ -3611,7 +3642,7 @@ static void TryConstructorInitialization<br>
>> // elements of the initializer list.<br>
>> if (Result == OR_No_Viable_Function) {<br>
>> AsInitializerList = false;<br>
>> - Result = ResolveConstructorOverload(S, Kind.getLocation(), Args,<br>
>> + Result = ResolveConstructorOverload(S, Kind.getLocation(), UnwrappedArgs,<br>
>> CandidateSet, Ctors, Best,<br>
>> CopyInitialization, AllowExplicit,<br>
>> /*OnlyListConstructors=*/<wbr>false,<br>
>> @@ -3821,8 +3852,8 @@ static void TryListInitialization(Sema &<br>
>> QualType InitType = InitList->getInit(0)->getType(<wbr>);<br>
>> if (S.Context.<wbr>hasSameUnqualifiedType(<wbr>InitType, DestType) ||<br>
>> S.IsDerivedFrom(InitList-><wbr>getLocStart(), InitType, DestType)) {<br>
>> - Expr *InitAsExpr = InitList->getInit(0);<br>
>> - TryConstructorInitialization(<wbr>S, Entity, Kind, InitAsExpr, DestType,<br>
>> + Expr *InitListAsExpr = InitList;<br>
>> + TryConstructorInitialization(<wbr>S, Entity, Kind, InitListAsExpr, DestType,<br>
>> Sequence, /*InitListSyntax*/ false,<br>
>> /*IsInitListCopy*/ true);<br>
>> return;<br>
>> @@ -4332,16 +4363,21 @@ static void TryReferenceInitializationCo<br>
>> }<br>
>><br>
>> // - If the initializer expression<br>
>> + // C++14-and-before:<br>
>> // - is an xvalue, class prvalue, array prvalue, or function lvalue and<br>
>> // "cv1 T1" is reference-compatible with "cv2 T2"<br>
>> + // C++1z:<br>
>> + // - is an rvalue or function lvalue and "cv1 T1" is reference-compatible<br>
>> + // with "cv2 T2"<br>
>> // Note: functions are handled below.<br>
>> if (!T1Function &&<br>
>> (RefRelationship == Sema::Ref_Compatible ||<br>
>> (Kind.<wbr>isCStyleOrFunctionalCast() &&<br>
>> RefRelationship == Sema::Ref_Related)) &&<br>
>> (InitCategory.isXValue() ||<br>
>> - (InitCategory.isPRValue() && T2->isRecordType()) ||<br>
>> - (InitCategory.isPRValue() && T2->isArrayType()))) {<br>
>> + (InitCategory.isPRValue() &&<br>
>> + (S.getLangOpts().CPlusPlus1z || T2->isRecordType() ||<br>
>> + T2->isArrayType())))) {<br>
>> ExprValueKind ValueKind = InitCategory.isXValue()? VK_XValue : VK_RValue;<br>
>> if (InitCategory.isPRValue() && T2->isRecordType()) {<br>
>> // The corresponding bullet in C++03 [dcl.init.ref]p5 gives the<br>
>> @@ -6604,7 +6640,26 @@ InitializationSequence::<wbr>Perform(Sema &S,<br>
>> CreatedObject = Conversion->getReturnType()-><wbr>isRecordType();<br>
>> }<br>
>><br>
>> + // C++14 and before:<br>
>> + // - if the function is a constructor, the call initializes a temporary<br>
>> + // of the cv-unqualified version of the destination type [...]<br>
>> + // C++1z:<br>
>> + // - if the function is a constructor, the call is a prvalue of the<br>
>> + // cv-unqualified version of the destination type whose return object<br>
>> + // is initialized by the constructor [...]<br>
>> + // Both:<br>
>> + // The [..] call is used to direct-initialize, according to the rules<br>
>> + // above, the object that is the destination of the<br>
>> + // copy-initialization.<br>
>> + // In C++14 and before, that always means the "constructors are<br>
>> + // considered" bullet, because we have arrived at a reference-related<br>
>> + // type. In C++1z, it only means that if the types are different or we<br>
>> + // didn't produce a prvalue, so just check for that case here.<br>
>> bool RequiresCopy = !IsCopy && !isReferenceBinding(Steps.<wbr>back());<br>
>> + if (S.getLangOpts().CPlusPlus1z && CurInit.get()->isRValue() &&<br>
>> + S.Context.<wbr>hasSameUnqualifiedType(<br>
>> + Entity.getType().<wbr>getNonReferenceType(), CurInit.get()->getType()))<br>
>> + RequiresCopy = false;<br>
>> bool MaybeBindToTemp = RequiresCopy || shouldBindAsTemporary(Entity);<br>
>><br>
>> if (!MaybeBindToTemp && CreatedObject && shouldDestroyTemporary(Entity)<wbr>) {<br>
>><br>
>> Modified: cfe/trunk/lib/Sema/<wbr>SemaOverload.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=288866&r1=288865&r2=288866&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaOverload.cpp?rev=288866&<wbr>r1=288865&r2=288866&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/lib/Sema/<wbr>SemaOverload.cpp (original)<br>
>> +++ cfe/trunk/lib/Sema/<wbr>SemaOverload.cpp Tue Dec 6 17:52:28 2016<br>
>> @@ -4979,7 +4979,7 @@ TryObjectArgumentInitializatio<wbr>n(Sema &S,<br>
>> // cv-qualification on the member function declaration.<br>
>> //<br>
>> // However, when finding an implicit conversion sequence for the argument, we<br>
>> - // are not allowed to create temporaries or perform user-defined conversions<br>
>> + // are not allowed to perform user-defined conversions<br>
>> // (C++ [over.match.funcs]p5). We perform a simplified version of<br>
>> // reference binding here, that allows class rvalues to bind to<br>
>> // non-constant references.<br>
>><br>
>> Modified: cfe/trunk/test/CXX/drs/dr0xx.<wbr>cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr0xx.cpp?rev=288866&r1=288865&r2=288866&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/CXX/<wbr>drs/dr0xx.cpp?rev=288866&r1=<wbr>288865&r2=288866&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/test/CXX/drs/dr0xx.<wbr>cpp (original)<br>
>> +++ cfe/trunk/test/CXX/drs/dr0xx.<wbr>cpp Tue Dec 6 17:52:28 2016<br>
>> @@ -248,7 +248,7 @@ namespace dr20 { // dr20: yes<br>
>> private:<br>
>> X(const X&); // expected-note {{here}}<br>
>> };<br>
>> - X f();<br>
>> + X &f();<br>
>> X x = f(); // expected-error {{private}}<br>
>> }<br>
>><br>
>> @@ -316,8 +316,15 @@ namespace dr25 { // dr25: yes<br>
>> namespace dr26 { // dr26: yes<br>
>> struct A { A(A, const A & = A()); }; // expected-error {{must pass its first argument by reference}}<br>
>> struct B {<br>
>> - B(); // expected-note {{candidate}}<br>
>> - B(const B &, B = B()); // expected-error {{no matching constructor}} expected-note {{candidate}} expected-note {{here}}<br>
>> + B(); // expected-note 0-1{{candidate}}<br>
>> + B(const B &, B = B());<br>
>> +#if __cplusplus <= 201402L<br>
>> + // expected-error@-2 {{no matching constructor}} expected-note@-2 {{candidate}} expected-note@-2 {{here}}<br>
>> +#endif<br>
>> + };<br>
>> + struct C {<br>
>> + static C &f();<br>
>> + C(const C &, C = f()); // expected-error {{no matching constructor}} expected-note {{candidate}} expected-note {{here}}<br>
>> };<br>
>> }<br>
>><br>
>> @@ -662,25 +669,33 @@ namespace dr58 { // dr58: yes<br>
>><br>
>> namespace dr59 { // dr59: yes<br>
>> template<typename T> struct convert_to { operator T() const; };<br>
>> - struct A {}; // expected-note 2{{volatile qualifier}} expected-note 2{{requires 0 arguments}}<br>
>> - struct B : A {}; // expected-note 2{{volatile qualifier}} expected-note 2{{requires 0 arguments}}<br>
>> -#if __cplusplus >= 201103L // move constructors<br>
>> - // expected-note@-3 2{{volatile qualifier}}<br>
>> - // expected-note@-3 2{{volatile qualifier}}<br>
>> -#endif<br>
>> + struct A {}; // expected-note 5+{{candidate}}<br>
>> + struct B : A {}; // expected-note 0+{{candidate}}<br>
>><br>
>> A a1 = convert_to<A>();<br>
>> A a2 = convert_to<A&>();<br>
>> A a3 = convert_to<const A>();<br>
>> - A a4 = convert_to<const volatile A>(); // expected-error {{no viable}}<br>
>> + A a4 = convert_to<const volatile A>();<br>
>> +#if __cplusplus <= 201402L<br>
>> + // expected-error@-2 {{no viable}}<br>
>> +#endif<br>
>> A a5 = convert_to<const volatile A&>(); // expected-error {{no viable}}<br>
>><br>
>> B b1 = convert_to<B>();<br>
>> B b2 = convert_to<B&>();<br>
>> B b3 = convert_to<const B>();<br>
>> - B b4 = convert_to<const volatile B>(); // expected-error {{no viable}}<br>
>> + B b4 = convert_to<const volatile B>();<br>
>> +#if __cplusplus <= 201402L<br>
>> + // expected-error@-2 {{no viable}}<br>
>> +#endif<br>
>> B b5 = convert_to<const volatile B&>(); // expected-error {{no viable}}<br>
>><br>
>> + A c1 = convert_to<B>();<br>
>> + A c2 = convert_to<B&>();<br>
>> + A c3 = convert_to<const B>();<br>
>> + A c4 = convert_to<const volatile B>(); // expected-error {{no viable}}<br>
>> + A c5 = convert_to<const volatile B&>(); // expected-error {{no viable}}<br>
>> +<br>
>> int n1 = convert_to<int>();<br>
>> int n2 = convert_to<int&>();<br>
>> int n3 = convert_to<const int>();<br>
>> @@ -920,14 +935,17 @@ namespace dr84 { // dr84: yes<br>
>> struct A { operator B() const; };<br>
>> struct C {};<br>
>> struct B {<br>
>> - B(B&); // expected-note {{candidate}}<br>
>> - B(C); // expected-note {{no known conversion from 'dr84::B' to 'dr84::C'}}<br>
>> + B(B&); // expected-note 0-1{{candidate}}<br>
>> + B(C); // expected-note 0-1{{no known conversion from 'dr84::B' to 'dr84::C'}}<br>
>> operator C() const;<br>
>> };<br>
>> A a;<br>
>> // Cannot use B(C) / operator C() pair to construct the B from the B temporary<br>
>> - // here.<br>
>> - B b = a; // expected-error {{no viable}}<br>
>> + // here. In C++1z, we initialize the B object directly using 'A::operator B()'.<br>
>> + B b = a;<br>
>> +#if __cplusplus <= 201402L<br>
>> + // expected-error@-2 {{no viable}}<br>
>> +#endif<br>
>> }<br>
>><br>
>> namespace dr85 { // dr85: yes<br>
>><br>
>> Modified: cfe/trunk/test/CXX/drs/dr10xx.<wbr>cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr10xx.cpp?rev=288866&r1=288865&r2=288866&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/CXX/<wbr>drs/dr10xx.cpp?rev=288866&r1=<wbr>288865&r2=288866&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/test/CXX/drs/dr10xx.<wbr>cpp (original)<br>
>> +++ cfe/trunk/test/CXX/drs/dr10xx.<wbr>cpp Tue Dec 6 17:52:28 2016<br>
>> @@ -3,8 +3,6 @@<br>
>> // RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors<br>
>> // RUN: %clang_cc1 -std=c++1z %s -verify -fexceptions -fcxx-exceptions -pedantic-errors<br>
>><br>
>> -// expected-no-diagnostics<br>
>> -<br>
>> namespace std {<br>
>> __extension__ typedef __SIZE_TYPE__ size_t;<br>
>><br>
>> @@ -32,6 +30,18 @@ namespace dr1048 { // dr1048: 3.6<br>
>> #endif<br>
>> }<br>
>><br>
>> +namespace dr1054 { // dr1054: no<br>
>> + // FIXME: Test is incomplete.<br>
>> + struct A {} volatile a;<br>
>> + void f() {<br>
>> + // FIXME: This is wrong: an lvalue-to-rvalue conversion is applied here,<br>
>> + // which copy-initializes a temporary from 'a'. Therefore this is<br>
>> + // ill-formed because A does not have a volatile copy constructor.<br>
>> + // (We might want to track this aspect under dr1383 instead?)<br>
>> + a; // expected-warning {{assign into a variable to force a volatile load}}<br>
>> + }<br>
>> +}<br>
>> +<br>
>> namespace dr1070 { // dr1070: 3.5<br>
>> #if __cplusplus >= 201103L<br>
>> struct A {<br>
>><br>
>> Modified: cfe/trunk/test/CXX/drs/dr1xx.<wbr>cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr1xx.cpp?rev=288866&r1=288865&r2=288866&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/CXX/<wbr>drs/dr1xx.cpp?rev=288866&r1=<wbr>288865&r2=288866&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/test/CXX/drs/dr1xx.<wbr>cpp (original)<br>
>> +++ cfe/trunk/test/CXX/drs/dr1xx.<wbr>cpp Tue Dec 6 17:52:28 2016<br>
>> @@ -576,11 +576,18 @@ namespace dr151 { // dr151: yes<br>
>><br>
>> namespace dr152 { // dr152: yes<br>
>> struct A {<br>
>> - A(); // expected-note {{not viable}}<br>
>> + A(); // expected-note 0-2{{not viable}}<br>
>> explicit A(const A&);<br>
>> };<br>
>> - A a1 = A(); // expected-error {{no matching constructor}}<br>
>> + A a1 = A();<br>
>> +#if __cplusplus <= 201402L<br>
>> + // expected-error@-2 {{no matching constructor}}<br>
>> +#endif<br>
>> A a2((A()));<br>
>> +<br>
>> + A &f();<br>
>> + A a3 = f(); // expected-error {{no matching constructor}}<br>
>> + A a4(f());<br>
>> }<br>
>><br>
>> // dr153: na<br>
>> @@ -823,11 +830,20 @@ namespace dr176 { // dr176: yes<br>
>> namespace dr177 { // dr177: yes<br>
>> struct B {};<br>
>> struct A {<br>
>> - A(A &); // expected-note {{not viable: expects an l-value}}<br>
>> - A(const B &); // expected-note {{not viable: no known conversion from 'dr177::A' to}}<br>
>> + A(A &); // expected-note 0-1{{not viable: expects an l-value}}<br>
>> + A(const B &); // expected-note 0-1{{not viable: no known conversion from 'dr177::A' to}}<br>
>> };<br>
>> B b;<br>
>> - A a = b; // expected-error {{no viable constructor copying variable}}<br>
>> + A a = b;<br>
>> +#if __cplusplus <= 201402L<br>
>> + // expected-error@-2 {{no viable constructor copying variable}}<br>
>> +#endif<br>
>> +<br>
>> + struct C { C(C&); }; // expected-note {{not viable: no known conversion from 'dr177::D' to 'dr177::C &'}}<br>
>> + struct D : C {};<br>
>> + struct E { operator D(); };<br>
>> + E e;<br>
>> + C c = e; // expected-error {{no viable constructor copying variable of type 'dr177::D'}}<br>
>> }<br>
>><br>
>> namespace dr178 { // dr178: yes<br>
>><br>
>> Modified: cfe/trunk/test/CXX/drs/dr4xx.<wbr>cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr4xx.cpp?rev=288866&r1=288865&r2=288866&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/CXX/<wbr>drs/dr4xx.cpp?rev=288866&r1=<wbr>288865&r2=288866&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/test/CXX/drs/dr4xx.<wbr>cpp (original)<br>
>> +++ cfe/trunk/test/CXX/drs/dr4xx.<wbr>cpp Tue Dec 6 17:52:28 2016<br>
>> @@ -553,12 +553,21 @@ namespace dr446 { // dr446: yes<br>
>> void(b ? a : a);<br>
>> b ? A() : a; // expected-error {{deleted}}<br>
>> b ? a : A(); // expected-error {{deleted}}<br>
>> - b ? A() : A(); // expected-error {{deleted}}<br>
>> + b ? A() : A();<br>
>> +#if __cplusplus <= 201402L<br>
>> + // expected-error@-2 {{deleted}}<br>
>> +#endif<br>
>><br>
>> void(b ? a : c);<br>
>> b ? a : C(); // expected-error {{deleted}}<br>
>> - b ? c : A(); // expected-error {{deleted}}<br>
>> - b ? A() : C(); // expected-error {{deleted}}<br>
>> + b ? c : A();<br>
>> +#if __cplusplus <= 201402L<br>
>> + // expected-error@-2 {{deleted}}<br>
>> +#endif<br>
>> + b ? A() : C();<br>
>> +#if __cplusplus <= 201402L<br>
>> + // expected-error@-2 {{deleted}}<br>
>> +#endif<br>
>> }<br>
>> }<br>
>><br>
>> @@ -874,10 +883,12 @@ namespace dr479 { // dr479: yes<br>
>> void f() {<br>
>> throw S();<br>
>> // expected-error@-1 {{temporary of type 'dr479::S' has private destructor}}<br>
>> - // expected-error@-2 {{calling a private constructor}}<br>
>> - // expected-error@-3 {{exception object of type 'dr479::S' has private destructor}}<br>
>> + // expected-error@-2 {{exception object of type 'dr479::S' has private destructor}}<br>
>> #if __cplusplus < 201103L<br>
>> - // expected-error@-5 {{C++98 requires an accessible copy constructor}}<br>
>> + // expected-error@-4 {{C++98 requires an accessible copy constructor}}<br>
>> +#endif<br>
>> +#if __cplusplus <= 201402L<br>
>> + // expected-error@-7 {{calling a private constructor}} (copy ctor)<br>
>> #endif<br>
>> }<br>
>> void g() {<br>
>><br>
>> Added: cfe/trunk/test/CodeGenCXX/<wbr>cxx1z-copy-omission.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx1z-copy-omission.cpp?rev=288866&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>CodeGenCXX/cxx1z-copy-<wbr>omission.cpp?rev=288866&view=<wbr>auto</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/test/CodeGenCXX/<wbr>cxx1z-copy-omission.cpp (added)<br>
>> +++ cfe/trunk/test/CodeGenCXX/<wbr>cxx1z-copy-omission.cpp Tue Dec 6 17:52:28 2016<br>
>> @@ -0,0 +1,81 @@<br>
>> +// RUN: %clang_cc1 -std=c++1z -emit-llvm -triple x86_64-linux-gnu -o - %s | FileCheck %s<br>
>> +<br>
>> +struct A {<br>
>> + A(int);<br>
>> + A(A&&);<br>
>> + A(const A&);<br>
>> + ~A();<br>
>> +<br>
>> + int arr[10];<br>
>> +};<br>
>> +<br>
>> +A f();<br>
>> +void h();<br>
>> +<br>
>> +// CHECK-LABEL: define {{.*}} @_Z1gv(<br>
>> +void g() {<br>
>> + // CHECK: %[[A:.*]] = alloca<br>
>> + // CHECK-NOT: alloca<br>
>> + // CHECK-NOT: call<br>
>> + // CHECK: call {{.*}} @_Z1fv({{.*}}* sret %[[A]])<br>
>> + A a = A( A{ f() } );<br>
>> + // CHECK-NOT: call<br>
>> +<br>
>> + // CHECK: call void @_Z1hv(<br>
>> + h();<br>
>> + // CHECK-NOT: call<br>
>> +<br>
>> + // CHECK: call void @_ZN1AD1Ev({{.*}}* %[[A]])<br>
>> + // CHECK-NOT: call<br>
>> + // CHECK-LABEL: }<br>
>> +}<br>
>> +<br>
>> +void f(A);<br>
>> +<br>
>> +// CHECK-LABEL: define {{.*}} @_Z1hv(<br>
>> +void h() {<br>
>> + // CHECK: %[[A:.*]] = alloca<br>
>> + // CHECK-NOT: alloca<br>
>> + // CHECK-NOT: call<br>
>> +<br>
>> + // CHECK: call {{.*}} @_Z1fv({{.*}}* sret %[[A]])<br>
>> + // CHECK-NOT: call<br>
>> + // CHECK: call {{.*}} @_Z1f1A({{.*}}* %[[A]])<br>
>> + f(f());<br>
>> + // CHECK-NOT: call<br>
>> + // CHECK: call void @_ZN1AD1Ev({{.*}}* %[[A]])<br>
>> +<br>
>> + // CHECK: call void @_Z1hv(<br>
>> + h();<br>
>> +<br>
>> + // CHECK-NOT: call<br>
>> + // CHECK-LABEL: }<br>
>> +}<br>
>> +<br>
>> +// We still pass classes with trivial copy/move constructors and destructors in<br>
>> +// registers, even if the copy is formally omitted.<br>
>> +struct B {<br>
>> + B(int);<br>
>> + int n;<br>
>> +};<br>
>> +<br>
>> +B fB();<br>
>> +void fB(B);<br>
>> +<br>
>> +// CHECK-LABEL: define {{.*}} @_Z1iv(<br>
>> +void i() {<br>
>> + // CHECK: %[[B:.*]] = alloca<br>
>> + // CHECK-NOT: alloca<br>
>> + // CHECK-NOT: call<br>
>> +<br>
>> + // CHECK: %[[B_N:.*]] = call i32 @_Z2fBv()<br>
>> + // CHECK-NOT: call<br>
>> + // CHECK: store i32 %[[B_N]],<br>
>> + // CHECK-NOT: call<br>
>> + // CHECK: %[[B_N:.*]] = load i32<br>
>> + // CHECK-NOT: call<br>
>> + // CHECK: call void @_Z2fB1B(i32 %[[B_N]])<br>
>> + fB(fB());<br>
>> +<br>
>> + // CHECK-LABEL: }<br>
>> +}<br>
>><br>
>> Modified: cfe/trunk/test/SemaCXX/<wbr>aggregate-initialization.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/aggregate-initialization.cpp?rev=288866&r1=288865&r2=288866&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>SemaCXX/aggregate-<wbr>initialization.cpp?rev=288866&<wbr>r1=288865&r2=288866&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/test/SemaCXX/<wbr>aggregate-initialization.cpp (original)<br>
>> +++ cfe/trunk/test/SemaCXX/<wbr>aggregate-initialization.cpp Tue Dec 6 17:52:28 2016<br>
>> @@ -57,7 +57,7 @@ struct A {<br>
>> A(int);<br>
>> ~A();<br>
>><br>
>> - A(const A&) = delete; // expected-note 2 {{'A' has been explicitly marked deleted here}}<br>
>> + A(const A&) = delete; // expected-note 0-2{{'A' has been explicitly marked deleted here}}<br>
>> };<br>
>><br>
>> struct B {<br>
>> @@ -70,10 +70,16 @@ struct C {<br>
>><br>
>> void f() {<br>
>> A as1[1] = { };<br>
>> - A as2[1] = { 1 }; // expected-error {{copying array element of type 'A' invokes deleted constructor}}<br>
>> + A as2[1] = { 1 };<br>
>> +#if __cplusplus <= 201402L<br>
>> + // expected-error@-2 {{copying array element of type 'A' invokes deleted constructor}}<br>
>> +#endif<br>
>><br>
>> B b1 = { };<br>
>> - B b2 = { 1 }; // expected-error {{copying member subobject of type 'A' invokes deleted constructor}}<br>
>> + B b2 = { 1 };<br>
>> +#if __cplusplus <= 201402L<br>
>> + // expected-error@-2 {{copying member subobject of type 'A' invokes deleted constructor}}<br>
>> +#endif<br>
>><br>
>> C c1 = { 1 };<br>
>> }<br>
>><br>
>> Added: cfe/trunk/test/SemaCXX/cxx1z-<wbr>copy-omission.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1z-copy-omission.cpp?rev=288866&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>SemaCXX/cxx1z-copy-omission.<wbr>cpp?rev=288866&view=auto</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/test/SemaCXX/cxx1z-<wbr>copy-omission.cpp (added)<br>
>> +++ cfe/trunk/test/SemaCXX/cxx1z-<wbr>copy-omission.cpp Tue Dec 6 17:52:28 2016<br>
>> @@ -0,0 +1,134 @@<br>
>> +// RUN: %clang_cc1 -std=c++1z -verify %s<br>
>> +<br>
>> +struct Noncopyable {<br>
>> + Noncopyable();<br>
>> + Noncopyable(const Noncopyable &) = delete; // expected-note 1+{{deleted}}<br>
>> + virtual ~Noncopyable();<br>
>> +};<br>
>> +struct Derived : Noncopyable {};<br>
>> +struct NoncopyableAggr {<br>
>> + Noncopyable nc;<br>
>> +};<br>
>> +struct Indestructible {<br>
>> + Indestructible();<br>
>> + ~Indestructible() = delete; // expected-note 1+{{deleted}}<br>
>> +};<br>
>> +struct Incomplete; // expected-note 1+{{declar}}<br>
>> +<br>
>> +Noncopyable make(int kind = 0) {<br>
>> + switch (kind) {<br>
>> + case 0: return {};<br>
>> + case 1: return Noncopyable();<br>
>> + case 2: return Noncopyable{};<br>
>> + case 3: return make();<br>
>> + }<br>
>> + __builtin_unreachable();<br>
>> +}<br>
>> +<br>
>> +Indestructible make_indestructible();<br>
>> +Incomplete make_incomplete(); // expected-note 1+{{here}}<br>
>> +<br>
>> +void take(Noncopyable nc) {}<br>
>> +<br>
>> +Noncopyable nrvo() {<br>
>> + Noncopyable nrvo;<br>
>> + return nrvo; // expected-error {{deleted constructor}}<br>
>> +}<br>
>> +<br>
>> +Noncopyable nc1 = make();<br>
>> +Noncopyable nc2 = Noncopyable();<br>
>> +Noncopyable nc3 = Derived(); // expected-error {{deleted constructor}}<br>
>> +<br>
>> +NoncopyableAggr nca1 = NoncopyableAggr{};<br>
>> +NoncopyableAggr nca2 = NoncopyableAggr{{}};<br>
>> +NoncopyableAggr nca3 = NoncopyableAggr{<wbr>NoncopyableAggr{Noncopyable()}<wbr>};<br>
>> +<br>
>> +void test_expressions(bool b) {<br>
>> + auto lambda = [a = make()] {};<br>
>> +<br>
>> + take({});<br>
>> + take(Noncopyable());<br>
>> + take(Noncopyable{});<br>
>> + take(make());<br>
>> +<br>
>> + Noncopyable &&dc1 = dynamic_cast<Noncopyable&&>(<wbr>Noncopyable());<br>
>> + Noncopyable &&dc2 = dynamic_cast<Noncopyable&&>(<wbr>nc1);<br>
>> + Noncopyable &&dc3 = dynamic_cast<Noncopyable&&>(<wbr>Derived());<br>
>> +<br>
>> + Noncopyable sc1 = static_cast<Noncopyable>(<wbr>Noncopyable());<br>
>> + Noncopyable sc2 = static_cast<Noncopyable>(nc1); // expected-error {{deleted}}<br>
>> + Noncopyable sc3 = static_cast<Noncopyable&&>(<wbr>Noncopyable()); // expected-error {{deleted}}<br>
>> + Noncopyable sc4 = static_cast<Noncopyable>(<wbr>static_cast<Noncopyable&&>(<wbr>Noncopyable())); // expected-error {{deleted}}<br>
>> +<br>
>> + Noncopyable cc1 = (Noncopyable)Noncopyable();<br>
>> + Noncopyable cc2 = (Noncopyable)Derived(); // expected-error {{deleted}}<br>
>> +<br>
>> + Noncopyable fc1 = Noncopyable(Noncopyable());<br>
>> + Noncopyable fc2 = Noncopyable(Derived()); // expected-error {{deleted}}<br>
>> +<br>
>> + // We must check for a complete type for every materialized temporary. (Note<br>
>> + // that in the special case of the top level of a decltype, no temporary is<br>
>> + // materialized.)<br>
>> + make_incomplete(); // expected-error {{incomplete}}<br>
>> + make_incomplete().a; // expected-error {{incomplete}}<br>
>> + make_incomplete().*(int Incomplete::*)nullptr; // expected-error {{incomplete}}<br>
>> + dynamic_cast<Incomplete&&>(<wbr>make_incomplete()); // expected-error {{incomplete}}<br>
>> + const_cast<Incomplete&&>(make_<wbr>incomplete()); // expected-error {{incomplete}}<br>
>> +<br>
>> + sizeof(Indestructible{}); // expected-error {{deleted}}<br>
>> + sizeof(make_indestructible()); // expected-error {{deleted}}<br>
>> + sizeof(make_incomplete()); // expected-error {{incomplete}}<br>
>> + typeid(Indestructible{}); // expected-error {{deleted}}<br>
>> + typeid(make_indestructible()); // expected-error {{deleted}}<br>
>> + typeid(make_incomplete()); // expected-error {{incomplete}}<br>
>> +<br>
>> + // FIXME: The first two cases here are now also valid in C++17 onwards.<br>
>> + using I = decltype(Indestructible()); // expected-error {{deleted}}<br>
>> + using I = decltype(Indestructible{}); // expected-error {{deleted}}<br>
>> + using I = decltype(make_indestructible()<wbr>);<br>
>> + using J = decltype(make_incomplete());<br>
>> +<br>
>> + Noncopyable cond1 = b ? Noncopyable() : make();<br>
>> + Noncopyable cond2 = b ? Noncopyable() : Derived(); // expected-error {{incompatible}}<br>
>> + Noncopyable cond3 = b ? Derived() : Noncopyable(); // expected-error {{incompatible}}<br>
>> + Noncopyable cond4 = b ? Noncopyable() : nc1; // expected-error {{deleted}}<br>
>> + Noncopyable cond5 = b ? nc1 : Noncopyable(); // expected-error {{deleted}}<br>
>> + // Could convert both to an xvalue of type Noncopyable here, but we're not<br>
>> + // permitted to consider that.<br>
>> + Noncopyable &&cond6 = b ? Noncopyable() : Derived(); // expected-error {{incompatible}}<br>
>> + Noncopyable &&cond7 = b ? Derived() : Noncopyable(); // expected-error {{incompatible}}<br>
>> + // Could convert both to a const lvalue of type Noncopyable here, but we're<br>
>> + // not permitted to consider that, either.<br>
>> + const Noncopyable cnc;<br>
>> + const Noncopyable &cond8 = b ? cnc : Derived(); // expected-error {{incompatible}}<br>
>> + const Noncopyable &cond9 = b ? Derived() : cnc; // expected-error {{incompatible}}<br>
>> +<br>
>> + extern const volatile Noncopyable make_cv();<br>
>> + Noncopyable cv_difference1 = make_cv();<br>
>> + const volatile Noncopyable cv_difference2 = make();<br>
>> +}<br>
>> +<br>
>> +template<typename T> struct ConversionFunction { operator T(); };<br>
>> +Noncopyable cf1 = ConversionFunction<<wbr>Noncopyable>();<br>
>> +Noncopyable cf2 = ConversionFunction<<wbr>Noncopyable&&>(); // expected-error {{deleted}}<br>
>> +Noncopyable cf3 = ConversionFunction<const volatile Noncopyable>();<br>
>> +const volatile Noncopyable cf4 = ConversionFunction<<wbr>Noncopyable>();<br>
>> +Noncopyable cf5 = ConversionFunction<Derived>(); // expected-error {{deleted}}<br>
>> +<br>
>> +struct AsMember {<br>
>> + Noncopyable member;<br>
>> + AsMember() : member(make()) {}<br>
>> +};<br>
>> +// FIXME: DR (no number yet): we still get a copy for base or delegating construction.<br>
>> +struct AsBase : Noncopyable {<br>
>> + AsBase() : Noncopyable(make()) {} // expected-error {{deleted}}<br>
>> +};<br>
>> +struct AsDelegating final {<br>
>> + AsDelegating(const AsDelegating &) = delete;<br>
>> + static AsDelegating make(int);<br>
>> +<br>
>> + // The base constructor version of this is problematic; the complete object<br>
>> + // version would be OK. Perhaps we could allow copy omission here for final<br>
>> + // classes?<br>
>> + AsDelegating(int n) : AsDelegating(make(n)) {} // expected-error {{deleted}}<br>
>> +};<br>
>><br>
>> Modified: cfe/trunk/www/cxx_dr_status.<wbr>html<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_dr_status.html?rev=288866&r1=288865&r2=288866&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/www/cxx_dr_<wbr>status.html?rev=288866&r1=<wbr>288865&r2=288866&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/www/cxx_dr_status.<wbr>html (original)<br>
>> +++ cfe/trunk/www/cxx_dr_status.<wbr>html Tue Dec 6 17:52:28 2016<br>
>> @@ -6139,7 +6139,7 @@ and <I>POD class</I></td><br>
>> <td><a href="<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1054" rel="noreferrer" target="_blank">http://www.open-std.org/<wbr>jtc1/sc22/wg21/docs/cwg_<wbr>defects.html#1054</a>">1054</a></<wbr>td><br>
>> <td>C++11</td><br>
>> <td>Lvalue-to-rvalue conversions in expression statements</td><br>
>> - <td class="none" align="center">Unknown</td><br>
>> + <td class="none" align="center">No</td><br>
>> </tr><br>
>> <tr id="1055"><br>
>> <td><a href="<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1055" rel="noreferrer" target="_blank">http://www.open-std.org/<wbr>jtc1/sc22/wg21/docs/cwg_<wbr>defects.html#1055</a>">1055</a></<wbr>td><br>
>><br>
>> Modified: cfe/trunk/www/cxx_status.html<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=288866&r1=288865&r2=288866&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/www/cxx_<wbr>status.html?rev=288866&r1=<wbr>288865&r2=288866&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/www/cxx_status.html (original)<br>
>> +++ cfe/trunk/www/cxx_status.html Tue Dec 6 17:52:28 2016<br>
>> @@ -694,7 +694,7 @@ as the draft C++1z standard evolves.<br>
>> <tr><br>
>> <td>Guaranteed copy elision</td><br>
>> <td><a href="<a href="http://wg21.link/p0135r1" rel="noreferrer" target="_blank">http://wg21.link/p0135r1</a><wbr>">P0135R1</a></td><br>
>> - <td class="none" align="center">No</td><br>
>> + <td class="svn" align="center">SVN</td><br>
>> </tr><br>
>> <tr><br>
>> <td rowspan=2>Stricter expression evaluation order</td><br>
>><br>
>><br>
>> ______________________________<wbr>_________________<br>
>> cfe-commits mailing list<br>
>> <a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
>> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
><br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</div></blockquote></div><br></div></div></div>