+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.
> 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