r288866 - [c++17] P0135R1: Guaranteed copy elision.
Adrian Prantl via cfe-commits
cfe-commits at lists.llvm.org
Fri Dec 9 08:20:29 PST 2016
> On Dec 8, 2016, at 7:31 PM, Duncan P. N. Exon Smith <dexonsmith at apple.com> wrote:
>
>
>> On 2016-Dec-08, at 19:29, Richard Smith <richard at metafoo.co.uk> wrote:
>>
>> On 8 Dec 2016 7:17 pm, "Duncan P. N. Exon Smith via cfe-commits" <cfe-commits at 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 <aprantl at 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 at 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 at -2 {{no matching constructor}} expected-note at -2 {{candidate}} expected-note at -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 at -3 2{{volatile qualifier}}
>>>> - // expected-note at -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 at -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 at -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 at -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 at -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 at -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 at -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 at -2 {{deleted}}
>>>> +#endif
>>>> + b ? A() : C();
>>>> +#if __cplusplus <= 201402L
>>>> + // expected-error at -2 {{deleted}}
>>>> +#endif
>>>> }
>>>> }
>>>>
>>>> @@ -874,10 +883,12 @@ namespace dr479 { // dr479: yes
>>>> void f() {
>>>> throw S();
>>>> // expected-error at -1 {{temporary of type 'dr479::S' has private destructor}}
>>>> - // expected-error at -2 {{calling a private constructor}}
>>>> - // expected-error at -3 {{exception object of type 'dr479::S' has private destructor}}
>>>> + // expected-error at -2 {{exception object of type 'dr479::S' has private destructor}}
>>>> #if __cplusplus < 201103L
>>>> - // expected-error at -5 {{C++98 requires an accessible copy constructor}}
>>>> + // expected-error at -4 {{C++98 requires an accessible copy constructor}}
>>>> +#endif
>>>> +#if __cplusplus <= 201402L
>>>> + // expected-error at -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 at -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 at -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 at lists.llvm.org
>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>
>
More information about the cfe-commits
mailing list