From aa5952c53f6c6a844a22fa2294186e16018b31e1 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sat, 22 Jan 2011 15:32:35 +0000 Subject: [PATCH] revert r123977 and r123978 to fix PR9026. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124033 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaOverload.cpp | 134 ++++++++++-------- lib/Sema/SemaTemplate.cpp | 1 - .../dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp | 34 +---- test/SemaCXX/conditional-expr.cpp | 5 +- 4 files changed, 78 insertions(+), 96 deletions(-) diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 478684b262..1a50841e3a 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -2798,6 +2798,10 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, CXXRecordDecl *T2RecordDecl = dyn_cast(T2->getAs()->getDecl()); + QualType ToType + = AllowRvalues? DeclType->getAs()->getPointeeType() + : DeclType; + OverloadCandidateSet CandidateSet(DeclLoc); const UnresolvedSetImpl *Conversions = T2RecordDecl->getVisibleConversionFunctions(); @@ -2848,10 +2852,10 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, if (ConvTemplate) S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC, - Init, DeclType, CandidateSet); + Init, ToType, CandidateSet); else S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init, - DeclType, CandidateSet); + ToType, CandidateSet); } OverloadCandidateSet::iterator Best; @@ -2940,7 +2944,9 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, // of type "cv2 T2" as follows: // -- If reference is an lvalue reference and the initializer expression - if (!isRValRef) { + // The next bullet point (T1 is a function) is pretty much equivalent to this + // one, so it's handled here. + if (!isRValRef || T1->isFunctionType()) { // -- is an lvalue (but is not a bit-field), and "cv1 T1" is // reference-compatible with "cv2 T2," or // @@ -2995,7 +3001,8 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, // -- Otherwise, the reference shall be an lvalue reference to a // non-volatile const type (i.e., cv1 shall be const), or the reference - // shall be an rvalue reference. + // shall be an rvalue reference and the initializer expression shall be + // an rvalue or have a function type. // // We actually handle one oddity of C++ [over.ics.ref] at this // point, which is that, due to p2 (which short-circuits reference @@ -3009,63 +3016,74 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, if (!isRValRef && !T1.isConstQualified()) return ICS; - // -- If the initializer expression + // -- If T1 is a function type, then + // -- if T2 is the same type as T1, the reference is bound to the + // initializer expression lvalue; + // -- if T2 is a class type and the initializer expression can be + // implicitly converted to an lvalue of type T1 [...], the + // reference is bound to the function lvalue that is the result + // of the conversion; + // This is the same as for the lvalue case above, so it was handled there. + // -- otherwise, the program is ill-formed. + // This is the one difference to the lvalue case. + if (T1->isFunctionType()) + return ICS; + + // -- Otherwise, if T2 is a class type and + // -- the initializer expression is an rvalue and "cv1 T1" + // is reference-compatible with "cv2 T2," or // - // -- is an xvalue, class prvalue, array prvalue or function - // lvalue and "cv1T1" is reference-compatible with "cv2 T2", or - if (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification && - (InitCategory.isXValue() || - (InitCategory.isPRValue() && (T2->isRecordType() || T2->isArrayType())) || - (InitCategory.isLValue() && T2->isFunctionType()))) { - ICS.setStandard(); - ICS.Standard.First = ICK_Identity; - ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base - : ObjCConversion? ICK_Compatible_Conversion - : ICK_Identity; - ICS.Standard.Third = ICK_Identity; - ICS.Standard.FromTypePtr = T2.getAsOpaquePtr(); - ICS.Standard.setToType(0, T2); - ICS.Standard.setToType(1, T1); - ICS.Standard.setToType(2, T1); - ICS.Standard.ReferenceBinding = true; - // In C++0x, this is always a direct binding. In C++98/03, it's a direct - // binding unless we're binding to a class prvalue. - // Note: Although xvalues wouldn't normally show up in C++98/03 code, we - // allow the use of rvalue references in C++98/03 for the benefit of - // standard library implementors; therefore, we need the xvalue check here. - ICS.Standard.DirectBinding = - S.getLangOptions().CPlusPlus0x || - (InitCategory.isPRValue() && !T2->isRecordType()); - ICS.Standard.RRefBinding = isRValRef; - ICS.Standard.CopyConstructor = 0; - return ICS; - } - - // -- has a class type (i.e., T2 is a class type), where T1 is not - // reference-related to T2, and can be implicitly converted to - // an xvalue, class prvalue, or function lvalue of type - // "cv3 T3", where "cv1 T1" is reference-compatible with - // "cv3 T3", + // -- T1 is not reference-related to T2 and the initializer + // expression can be implicitly converted to an rvalue + // of type "cv3 T3" (this conversion is selected by + // enumerating the applicable conversion functions + // (13.3.1.6) and choosing the best one through overload + // resolution (13.3)), // - // then the reference is bound to the value of the initializer - // expression in the first case and to the result of the conversion - // in the second case (or, in either case, to an appropriate base - // class subobject). - if (T2->isRecordType() && RefRelationship == Sema::Ref_Incompatible && - !S.RequireCompleteType(DeclLoc, T2, 0) && - FindConversionForRefInit(S, ICS, DeclType, DeclLoc, - Init, T2, /*AllowRvalues=*/true, - AllowExplicit)) { - // In the second case, if the reference is an rvalue reference - // and the second standard conversion sequence of the - // user-defined conversion sequence includes an lvalue-to-rvalue - // conversion, the program is ill-formed. - if (ICS.isUserDefined() && isRValRef && - ICS.UserDefined.After.First == ICK_Lvalue_To_Rvalue) - ICS.setBad(BadConversionSequence::no_conversion, Init, DeclType); + // then the reference is bound to the initializer + // expression rvalue in the first case and to the object + // that is the result of the conversion in the second case + // (or, in either case, to the appropriate base class + // subobject of the object). + if (T2->isRecordType()) { + // First case: "cv1 T1" is reference-compatible with "cv2 T2". This is a + // direct binding in C++0x but not in C++03. + if (InitCategory.isRValue() && + RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) { + ICS.setStandard(); + ICS.Standard.First = ICK_Identity; + ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base + : ObjCConversion? ICK_Compatible_Conversion + : ICK_Identity; + ICS.Standard.Third = ICK_Identity; + ICS.Standard.FromTypePtr = T2.getAsOpaquePtr(); + ICS.Standard.setToType(0, T2); + ICS.Standard.setToType(1, T1); + ICS.Standard.setToType(2, T1); + ICS.Standard.ReferenceBinding = true; + ICS.Standard.DirectBinding = S.getLangOptions().CPlusPlus0x; + ICS.Standard.RRefBinding = isRValRef; + ICS.Standard.CopyConstructor = 0; + return ICS; + } + + // Second case: not reference-related. + if (RefRelationship == Sema::Ref_Incompatible && + !S.RequireCompleteType(DeclLoc, T2, 0) && + FindConversionForRefInit(S, ICS, DeclType, DeclLoc, + Init, T2, /*AllowRvalues=*/true, + AllowExplicit)) { + // In the second case, if the reference is an rvalue reference + // and the second standard conversion sequence of the + // user-defined conversion sequence includes an lvalue-to-rvalue + // conversion, the program is ill-formed. + if (ICS.isUserDefined() && isRValRef && + ICS.UserDefined.After.First == ICK_Lvalue_To_Rvalue) + ICS.setBad(BadConversionSequence::no_conversion, Init, DeclType); - return ICS; - } + return ICS; + } + } // -- Otherwise, a temporary of type "cv1 T1" is created and // initialized from the initializer expression using the diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 2d2c3ea672..ad08a11f20 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -2470,7 +2470,6 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, TemplateParameterList::iterator Param = Params->begin(), ParamEnd = Params->end(); unsigned ArgIdx = 0; - LocalInstantiationScope InstScope(*this, true); while (Param != ParamEnd) { if (ArgIdx > NumArgs && PartialTemplateArgs) break; diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp index 7b0fb9c52b..6f81326b1d 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp @@ -17,7 +17,7 @@ int f(int); template struct ConvertsTo { - operator T(); // expected-note 4{{candidate function}} + operator T(); // expected-note 2{{candidate function}} }; void test_rvalue_refs() { @@ -130,35 +130,3 @@ namespace std_example_2 { double&& rrd3 = i; } -namespace argument_passing { - void base_rvalue_ref(Base&&); - void int_rvalue_ref(int&&); // expected-note 2{{passing argument to parameter here}} - void array_rvalue_ref(int (&&)[5]); - void function_rvalue_ref(int (&&)(int)); - - void test() { - base_rvalue_ref(xvalue()); - base_rvalue_ref(xvalue()); - int_rvalue_ref(xvalue()); - - base_rvalue_ref(prvalue()); - base_rvalue_ref(prvalue()); - - array_rvalue_ref(HasArray().array); - - function_rvalue_ref(f); - - base_rvalue_ref(ConvertsTo()); - base_rvalue_ref(ConvertsTo()); - int_rvalue_ref(ConvertsTo()); - - base_rvalue_ref(ConvertsTo()); - base_rvalue_ref(ConvertsTo()); - - function_rvalue_ref(ConvertsTo()); - - int_rvalue_ref(ConvertsTo()); // expected-error{{no viable conversion from 'ConvertsTo' to 'int'}} - int_rvalue_ref(ConvertsTo()); // expected-error{{no viable conversion from 'ConvertsTo' to 'int'}} - } - -} diff --git a/test/SemaCXX/conditional-expr.cpp b/test/SemaCXX/conditional-expr.cpp index efda4ce97a..a7f2a4c915 100644 --- a/test/SemaCXX/conditional-expr.cpp +++ b/test/SemaCXX/conditional-expr.cpp @@ -7,10 +7,7 @@ struct ToBool { explicit operator bool(); }; struct B; -struct A { // expected-note 2{{candidate is the implicit copy constructor}} - A(); - A(const B&); // expected-note 2 {{candidate constructor}} -}; +struct A { A(); A(const B&); }; // expected-note 2 {{candidate constructor}} struct B { operator A() const; }; // expected-note 2 {{candidate function}} struct I { operator int(); }; struct J { operator I(); }; -- 2.40.0