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