Yes, let's. On 17 Jan 2017 9:11 pm, "Hans Wennborg" <h...@chromium.org> wrote:
What do you think; time to merge it? On Fri, Jan 13, 2017 at 1:21 PM, Richard Smith <rich...@metafoo.co.uk> wrote: > I'd like to wait a bit to see how the dust settles on this one, but this is > a bugfix for a previous bugfix for a standard change, and we've had several > user complaints requesting that we fix the bug in the standard, so it's > probably a good change to get into Clang 4. > > ---------- Forwarded message ---------- > From: Richard Smith via cfe-commits <cfe-commits@lists.llvm.org> > Date: 13 January 2017 at 12:46 > Subject: r291955 - PR31606: Generalize our tentative DR resolution for > inheriting copy/move > To: cfe-commits@lists.llvm.org > > > Author: rsmith > Date: Fri Jan 13 14:46:54 2017 > New Revision: 291955 > > URL: http://llvm.org/viewvc/llvm-project?rev=291955&view=rev > Log: > PR31606: Generalize our tentative DR resolution for inheriting copy/move > constructors to better match the pre-P0136R1 behavior. > > Modified: > cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > cfe/trunk/lib/Sema/SemaOverload.cpp > cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p15.cpp > cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1.cpp > cfe/trunk/test/CXX/drs/dr16xx.cpp > cfe/trunk/test/CXX/drs/dr19xx.cpp > cfe/trunk/test/CXX/special/class.inhctor/p1.cpp > cfe/trunk/test/CXX/special/class.inhctor/p3.cpp > cfe/trunk/test/CXX/special/class.inhctor/p7.cpp > cfe/trunk/test/SemaCXX/cxx11-inheriting-ctors.cpp > cfe/trunk/test/SemaTemplate/cxx1z-using-declaration.cpp > > Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/ DiagnosticSemaKinds.td?rev=291955&r1=291954&r2=291955&view=diff > ============================================================ ================== > --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) > +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Jan 13 14:46:54 > 2017 > @@ -3344,8 +3344,8 @@ def note_ovl_candidate : Note<"candidate > def note_ovl_candidate_inherited_constructor : Note< > "constructor from base class %0 inherited here">; > def note_ovl_candidate_inherited_constructor_slice : Note< > - "constructor inherited from base class cannot be used to initialize > from " > - "an argument of the derived class type">; > + "candidate %select{constructor|template}0 ignored: " > + "inherited constructor cannot be used to %select{copy|move}1 object">; > def note_ovl_candidate_illegal_constructor : Note< > "candidate %select{constructor|template}0 ignored: " > "instantiation %select{takes|would take}0 its own class type by > value">; > > Modified: cfe/trunk/lib/Sema/SemaOverload.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/ SemaOverload.cpp?rev=291955&r1=291954&r2=291955&view=diff > ============================================================ ================== > --- cfe/trunk/lib/Sema/SemaOverload.cpp (original) > +++ cfe/trunk/lib/Sema/SemaOverload.cpp Fri Jan 13 14:46:54 2017 > @@ -5944,6 +5944,28 @@ Sema::AddOverloadCandidate(FunctionDecl > Candidate.FailureKind = ovl_fail_illegal_constructor; > return; > } > + > + // C++ [over.match.funcs]p8: (proposed DR resolution) > + // A constructor inherited from class type C that has a first > parameter > + // of type "reference to P" (including such a constructor > instantiated > + // from a template) is excluded from the set of candidate functions > when > + // constructing an object of type cv D if the argument list has > exactly > + // one argument and D is reference-related to P and P is > reference-related > + // to C. > + auto *Shadow = > dyn_cast<ConstructorUsingShadowDecl>(FoundDecl.getDecl()); > + if (Shadow && Args.size() == 1 && Constructor->getNumParams() >= 1 && > + Constructor->getParamDecl(0)->getType()->isReferenceType()) { > + QualType P = > Constructor->getParamDecl(0)->getType()->getPointeeType(); > + QualType C = Context.getRecordType(Constructor->getParent()); > + QualType D = Context.getRecordType(Shadow->getParent()); > + SourceLocation Loc = Args.front()->getExprLoc(); > + if ((Context.hasSameUnqualifiedType(P, C) || IsDerivedFrom(Loc, P, > C)) && > + (Context.hasSameUnqualifiedType(D, P) || IsDerivedFrom(Loc, D, > P))) { > + Candidate.Viable = false; > + Candidate.FailureKind = ovl_fail_inhctor_slice; > + return; > + } > + } > } > > unsigned NumParams = Proto->getNumParams(); > @@ -6016,31 +6038,6 @@ Sema::AddOverloadCandidate(FunctionDecl > } > } > > - // C++ [over.best.ics]p4+: (proposed DR resolution) > - // If the target is the first parameter of an inherited constructor > when > - // constructing an object of type C with an argument list that has > exactly > - // one expression, an implicit conversion sequence cannot be formed if > C is > - // reference-related to the type that the argument would have after the > - // application of the user-defined conversion (if any) and before the > final > - // standard conversion sequence. > - auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>( FoundDecl.getDecl()); > - if (Shadow && Args.size() == 1 && !isa<InitListExpr>(Args.front())) { > - bool DerivedToBase, ObjCConversion, ObjCLifetimeConversion; > - QualType ConvertedArgumentType = Args.front()->getType(); > - if (Candidate.Conversions[0].isUserDefined()) > - ConvertedArgumentType = > - Candidate.Conversions[0].UserDefined.After.getFromType(); > - if (CompareReferenceRelationship(Args.front()->getLocStart(), > - > Context.getRecordType(Shadow->getParent()), > - ConvertedArgumentType, DerivedToBase, > - ObjCConversion, > - ObjCLifetimeConversion) >= > Ref_Related) { > - Candidate.Viable = false; > - Candidate.FailureKind = ovl_fail_inhctor_slice; > - return; > - } > - } > - > if (EnableIfAttr *FailedAttr = CheckEnableIf(Function, Args)) { > Candidate.Viable = false; > Candidate.FailureKind = ovl_fail_enable_if; > @@ -10222,8 +10219,13 @@ static void NoteFunctionCandidate(Sema & > return DiagnoseOpenCLExtensionDisabled(S, Cand); > > case ovl_fail_inhctor_slice: > + // It's generally not interesting to note copy/move constructors here. > + if (cast<CXXConstructorDecl>(Fn)->isCopyOrMoveConstructor()) > + return; > S.Diag(Fn->getLocation(), > - diag::note_ovl_candidate_inherited_constructor_slice); > + diag::note_ovl_candidate_inherited_constructor_slice) > + << (Fn->getPrimaryTemplate() ? 1 : 0) > + << Fn->getParamDecl(0)->getType()->isRValueReferenceType(); > MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); > return; > > > Modified: cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace. udecl/p15.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/ dcl.dcl/basic.namespace/namespace.udecl/p15.cpp?rev= 291955&r1=291954&r2=291955&view=diff > ============================================================ ================== > --- cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p15.cpp > (original) > +++ cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p15.cpp Fri > Jan 13 14:46:54 2017 > @@ -1,16 +1,16 @@ > // RUN: %clang_cc1 -std=c++11 -verify %s > > -struct B1 { // expected-note 2{{candidate}} > +struct B1 { > B1(int); // expected-note {{candidate}} > }; > > -struct B2 { // expected-note 2{{candidate}} > +struct B2 { > B2(int); // expected-note {{candidate}} > }; > > struct D1 : B1, B2 { // expected-note 2{{candidate}} > - using B1::B1; // expected-note 3{{inherited here}} > - using B2::B2; // expected-note 3{{inherited here}} > + using B1::B1; // expected-note {{inherited here}} > + using B2::B2; // expected-note {{inherited here}} > }; > D1 d1(0); // expected-error {{ambiguous}} > > @@ -35,7 +35,7 @@ namespace default_ctor { > operator D&&(); > }; > > - struct A { // expected-note 4{{candidate}} > + struct A { // expected-note 2{{candidate}} > A(); // expected-note {{candidate}} > > A(C &&); // expected-note {{candidate}} > @@ -47,7 +47,7 @@ namespace default_ctor { > A(convert_to_D2); // expected-note {{candidate}} > }; > > - struct B { // expected-note 4{{candidate}} > + struct B { // expected-note 2{{candidate}} > B(); // expected-note {{candidate}} > > B(C &&); // expected-note {{candidate}} > @@ -66,9 +66,9 @@ namespace default_ctor { > using B::operator=; > }; > struct D : A, B { > - using A::A; // expected-note 5{{inherited here}} > + using A::A; // expected-note 3{{inherited here}} > using A::operator=; > - using B::B; // expected-note 5{{inherited here}} > + using B::B; // expected-note 3{{inherited here}} > using B::operator=; > > D(int); > @@ -93,13 +93,13 @@ namespace default_ctor { > } > > struct Y; > - struct X { // expected-note 2{{candidate}} > + struct X { > X(); > - X(volatile Y &); // expected-note {{constructor inherited from base > class cannot be used to initialize from an argument of the derived class > type}} > + X(volatile Y &); // expected-note 3{{inherited constructor cannot be > used to copy object}} > } x; > - struct Y : X { using X::X; } volatile y; // expected-note 2{{candidate}} > - struct Z : Y { using Y::Y; } volatile z; // expected-note 3{{candidate}} > expected-note 5{{inherited here}} > - Z z1(x); // ok > - Z z2(y); // ok, Z is not reference-related to type of y > + struct Y : X { using X::X; } volatile y; > + struct Z : Y { using Y::Y; } volatile z; // expected-note 4{{no known > conversion}} expected-note 2{{would lose volatile}} expected-note > 3{{requires 0}} expected-note 3{{inherited here}} > + Z z1(x); // expected-error {{no match}} > + Z z2(y); // expected-error {{no match}} > Z z3(z); // expected-error {{no match}} > } > > Modified: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/ dcl.decl/dcl.init/dcl.init.aggr/p1.cpp?rev=291955&r1= 291954&r2=291955&view=diff > ============================================================ ================== > --- cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1.cpp (original) > +++ cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1.cpp Fri Jan 13 > 14:46:54 2017 > @@ -134,13 +134,13 @@ ExplicitDefaultedAggr eda2{}; > > struct DefaultedBase { > int n; > - DefaultedBase() = default; // expected-note 0+ {{candidate}} > - DefaultedBase(DefaultedBase const&) = default; // expected-note 0+ > {{candidate}} > - DefaultedBase(DefaultedBase &&) = default; // expected-note 0+ > {{candidate}} > + DefaultedBase() = default; > + DefaultedBase(DefaultedBase const&) = default; > + DefaultedBase(DefaultedBase &&) = default; > }; > > struct InheritingConstructors : DefaultedBase { // expected-note 3 > {{candidate}} > - using DefaultedBase::DefaultedBase; // expected-note 2 {{inherited here}} > + using DefaultedBase::DefaultedBase; > }; > InheritingConstructors ic = { 42 }; // expected-error {{no matching > constructor}} > > > Modified: cfe/trunk/test/CXX/drs/dr16xx.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/ drs/dr16xx.cpp?rev=291955&r1=291954&r2=291955&view=diff > ============================================================ ================== > --- cfe/trunk/test/CXX/drs/dr16xx.cpp (original) > +++ cfe/trunk/test/CXX/drs/dr16xx.cpp Fri Jan 13 14:46:54 2017 > @@ -71,14 +71,14 @@ namespace dr1638 { // dr1638: yes > > namespace dr1645 { // dr1645: 3.9 > #if __cplusplus >= 201103L > - struct A { // expected-note 2{{candidate}} > + struct A { > constexpr A(int, float = 0); // expected-note 2{{candidate}} > explicit A(int, int = 0); // expected-note 2{{candidate}} > A(int, int, int = 0) = delete; // expected-note {{candidate}} > }; > > struct B : A { // expected-note 2{{candidate}} > - using A::A; // expected-note 7{{inherited here}} > + using A::A; // expected-note 5{{inherited here}} > }; > > constexpr B a(0); // expected-error {{ambiguous}} > > Modified: cfe/trunk/test/CXX/drs/dr19xx.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/ drs/dr19xx.cpp?rev=291955&r1=291954&r2=291955&view=diff > ============================================================ ================== > --- cfe/trunk/test/CXX/drs/dr19xx.cpp (original) > +++ cfe/trunk/test/CXX/drs/dr19xx.cpp Fri Jan 13 14:46:54 2017 > @@ -138,18 +138,21 @@ namespace dr1959 { // dr1959: 3.9 > struct c; > struct a { > a() = default; > - a(const a &) = delete; // expected-note 2{{deleted}} > + a(const a &) = delete; // expected-note {{deleted}} > a(const b &) = delete; // not inherited > - a(c &&) = delete; > - template<typename T> a(T) = delete; > + a(c &&) = delete; // expected-note {{not viable}} > + template<typename T> a(T) = delete; // expected-note {{would take its > own class type by value}} > }; > > - struct b : a { // expected-note {{copy constructor of 'b' is implicitly > deleted because base class 'dr1959::a' has a deleted copy constructor}} > - using a::a; > + struct b : a { // expected-note {{cannot bind}} expected-note {{deleted > because}} > + using a::a; // expected-note 2{{inherited here}} > }; > > a x; > - b y = x; // expected-error {{deleted}} > + // FIXME: As a resolution to an open DR against P0136R0, we disallow > + // use of inherited constructors to construct from a single argument > + // where the base class is reference-related to the argument type. > + b y = x; // expected-error {{no viable conversion}} > b z = z; // expected-error {{deleted}} > > struct c : a { > @@ -158,7 +161,7 @@ namespace dr1959 { // dr1959: 3.9 > }; > // FIXME: As a resolution to an open DR against P0136R0, we disallow > // use of inherited constructors to construct from a single argument > - // where the derived class is reference-related to its type. > + // where the base class is reference-related to the argument type. > c q(static_cast<c&&>(q)); > #endif > } > > Modified: cfe/trunk/test/CXX/special/class.inhctor/p1.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/ special/class.inhctor/p1.cpp?rev=291955&r1=291954&r2=291955&view=diff > ============================================================ ================== > --- cfe/trunk/test/CXX/special/class.inhctor/p1.cpp (original) > +++ cfe/trunk/test/CXX/special/class.inhctor/p1.cpp Fri Jan 13 14:46:54 2017 > @@ -3,7 +3,7 @@ > // Note: [class.inhctor] was removed by P0136R1. This tests the new > behavior > // for the wording that used to be there. > > -struct A { // expected-note 8{{candidate is the implicit}} > +struct A { // expected-note 4{{candidate is the implicit}} > A(...); // expected-note 4{{candidate constructor}} expected-note > 4{{candidate inherited constructor}} > A(int = 0, int = 0, int = 0, int = 0, ...); // expected-note 3{{candidate > constructor}} expected-note 3{{candidate inherited constructor}} > A(int = 0, int = 0, ...); // expected-note 3{{candidate constructor}} > expected-note 3{{candidate inherited constructor}} > @@ -15,7 +15,7 @@ struct A { // expected-note 8{{candidate > }; > > struct B : A { // expected-note 4{{candidate is the implicit}} > - using A::A; // expected-note 19{{inherited here}} > + using A::A; // expected-note 15{{inherited here}} > B(void*); > }; > > > Modified: cfe/trunk/test/CXX/special/class.inhctor/p3.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/ special/class.inhctor/p3.cpp?rev=291955&r1=291954&r2=291955&view=diff > ============================================================ ================== > --- cfe/trunk/test/CXX/special/class.inhctor/p3.cpp (original) > +++ cfe/trunk/test/CXX/special/class.inhctor/p3.cpp Fri Jan 13 14:46:54 2017 > @@ -14,21 +14,21 @@ D1 d1a(1), d1b(1, 1); > > D1 fd1() { return 1; } > > -struct B2 { // expected-note 2{{candidate}} > +struct B2 { > explicit B2(int, int = 0, int = 0); > }; > struct D2 : B2 { // expected-note 2{{candidate constructor}} > - using B2::B2; // expected-note 2{{inherited here}} > + using B2::B2; > }; > D2 d2a(1), d2b(1, 1), d2c(1, 1, 1); > > D2 fd2() { return 1; } // expected-error {{no viable conversion}} > > -struct B3 { // expected-note 2{{candidate}} > +struct B3 { > B3(void*); // expected-note {{candidate}} > }; > struct D3 : B3 { // expected-note 2{{candidate constructor}} > - using B3::B3; // expected-note 3{{inherited here}} > + using B3::B3; // expected-note {{inherited here}} > }; > D3 fd3() { return 1; } // expected-error {{no viable conversion}} > > > Modified: cfe/trunk/test/CXX/special/class.inhctor/p7.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/ special/class.inhctor/p7.cpp?rev=291955&r1=291954&r2=291955&view=diff > ============================================================ ================== > --- cfe/trunk/test/CXX/special/class.inhctor/p7.cpp (original) > +++ cfe/trunk/test/CXX/special/class.inhctor/p7.cpp Fri Jan 13 14:46:54 2017 > @@ -3,15 +3,15 @@ > // Note: [class.inhctor] was removed by P0136R1. This tests the new > behavior > // for the wording that used to be there. > > -struct B1 { // expected-note 2{{candidate}} > +struct B1 { > B1(int); // expected-note {{candidate}} > }; > -struct B2 { // expected-note 2{{candidate}} > +struct B2 { > B2(int); // expected-note {{candidate}} > }; > struct D1 : B1, B2 { // expected-note 2{{candidate}} > - using B1::B1; // expected-note 3{{inherited here}} > - using B2::B2; // expected-note 3{{inherited here}} > + using B1::B1; // expected-note {{inherited here}} > + using B2::B2; // expected-note {{inherited here}} > }; > struct D2 : B1, B2 { > using B1::B1; > > Modified: cfe/trunk/test/SemaCXX/cxx11-inheriting-ctors.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ SemaCXX/cxx11-inheriting-ctors.cpp?rev=291955&r1=291954&r2=291955&view=diff > ============================================================ ================== > --- cfe/trunk/test/SemaCXX/cxx11-inheriting-ctors.cpp (original) > +++ cfe/trunk/test/SemaCXX/cxx11-inheriting-ctors.cpp Fri Jan 13 14:46:54 > 2017 > @@ -56,9 +56,9 @@ namespace InvalidConstruction { > } > > namespace ExplicitConv { > - struct B {}; // expected-note 2{{candidate}} > + struct B {}; > struct D : B { // expected-note 3{{candidate}} > - using B::B; // expected-note 2{{inherited}} > + using B::B; > }; > struct X { explicit operator B(); } x; > struct Y { explicit operator D(); } y; > @@ -68,19 +68,40 @@ namespace ExplicitConv { > } > > namespace NestedListInit { > - struct B { B(); } b; // expected-note 5{{candidate}} > - struct D : B { // expected-note 3{{candidate}} > - using B::B; // expected-note 2{{inherited}} > + struct B { B(); } b; // expected-note 3{{candidate}} > + struct D : B { // expected-note 14{{not viable}} > + using B::B; > }; > // This is a bit weird. We're allowed one pair of braces for overload > // resolution, and one more pair of braces due to [over.ics.list]/2. > B b1 = {b}; > B b2 = {{b}}; > B b3 = {{{b}}}; // expected-error {{no match}} > - // This is the same, but we get one call to D's version of B::B(const B&) > - // before the two permitted calls to D::D(D&&). > - D d1 = {b}; > - D d2 = {{b}}; > - D d3 = {{{b}}}; > + // Per a proposed defect resolution, we don't get to call > + // D's version of B::B(const B&) here. > + D d0 = b; // expected-error {{no viable conversion}} > + D d1 = {b}; // expected-error {{no match}} > + D d2 = {{b}}; // expected-error {{no match}} > + D d3 = {{{b}}}; // expected-error {{no match}} > D d4 = {{{{b}}}}; // expected-error {{no match}} > } > + > +namespace PR31606 { > + // PR31606: as part of a proposed defect resolution, do not consider > + // inherited constructors that would be copy constructors for any class > + // between the declaring class and the constructed class (inclusive). > + struct Base {}; > + > + struct A : Base { > + using Base::Base; > + bool operator==(A const &) const; // expected-note {{no known > conversion from 'PR31606::B' to 'const PR31606::A' for 1st argument}} > + }; > + > + struct B : Base { > + using Base::Base; > + }; > + > + bool a = A{} == A{}; > + // Note, we do *not* allow operator=='s argument to use the inherited > A::A(Base&&) constructor to construct from B{}. > + bool b = A{} == B{}; // expected-error {{invalid operands}} > +} > > Modified: cfe/trunk/test/SemaTemplate/cxx1z-using-declaration.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ SemaTemplate/cxx1z-using-declaration.cpp?rev=291955&r1= 291954&r2=291955&view=diff > ============================================================ ================== > --- cfe/trunk/test/SemaTemplate/cxx1z-using-declaration.cpp (original) > +++ cfe/trunk/test/SemaTemplate/cxx1z-using-declaration.cpp Fri Jan 13 > 14:46:54 2017 > @@ -17,7 +17,7 @@ void test_Unexpanded() { > > // Test using non-type members from pack of base classes. > template<typename ...T> struct A : T... { // expected-note 2{{candidate}} > - using T::T ...; // expected-note 6{{inherited here}} > + using T::T ...; // expected-note 2{{inherited here}} > using T::operator() ...; > using T::operator T* ...; > using T::h ...; > @@ -29,7 +29,7 @@ template<typename ...T> struct A : T... > }; > > namespace test_A { > - struct X { // expected-note 2{{candidate}} > + struct X { > X(); > X(int); // expected-note {{candidate}} > void operator()(int); // expected-note 2{{candidate}} > @@ -43,7 +43,7 @@ namespace test_A { > operator Y *(); > void h(int, int); // expected-note {{not viable}} > }; > - struct Z { // expected-note 2{{candidate}} > + struct Z { > Z(); > Z(int); // expected-note {{candidate}} > void operator()(int); // expected-note 2{{candidate}} > > > _______________________________________________ > 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