[cfe-commits] r124121 - in /cfe/trunk: lib/Sema/SemaOverload.cpp lib/Sema/SemaTemplate.cpp test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp test/SemaCXX/conditional-expr.cpp test/SemaCXX/decl-init-ref.cpp
Douglas Gregor
dgregor at apple.com
Mon Jan 24 08:14:37 PST 2011
Author: dgregor
Date: Mon Jan 24 10:14:37 2011
New Revision: 124121
URL: http://llvm.org/viewvc/llvm-project?rev=124121&view=rev
Log:
Re-instate r123977/r123978, my updates of the reference-binding
implementation used by overload resolution to support rvalue
references. The original commits caused PR9026 and some
hard-to-reproduce self-host breakage.
The only (crucial!) difference between this commit and the previous
commits is that we now properly check the SuppressUserConversions flag
before attempting to perform a second user-defined conversion in
reference binding, breaking the infinite recursion chain of
user-defined conversions.
Rvalue references should be working a bit better now.
Modified:
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp
cfe/trunk/test/SemaCXX/conditional-expr.cpp
cfe/trunk/test/SemaCXX/decl-init-ref.cpp
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=124121&r1=124120&r2=124121&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Jan 24 10:14:37 2011
@@ -2798,10 +2798,6 @@
CXXRecordDecl *T2RecordDecl
= dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl());
- QualType ToType
- = AllowRvalues? DeclType->getAs<ReferenceType>()->getPointeeType()
- : DeclType;
-
OverloadCandidateSet CandidateSet(DeclLoc);
const UnresolvedSetImpl *Conversions
= T2RecordDecl->getVisibleConversionFunctions();
@@ -2852,10 +2848,10 @@
if (ConvTemplate)
S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC,
- Init, ToType, CandidateSet);
+ Init, DeclType, CandidateSet);
else
S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init,
- ToType, CandidateSet);
+ DeclType, CandidateSet);
}
OverloadCandidateSet::iterator Best;
@@ -2944,9 +2940,7 @@
// of type "cv2 T2" as follows:
// -- If reference is an lvalue reference and the initializer expression
- // The next bullet point (T1 is a function) is pretty much equivalent to this
- // one, so it's handled here.
- if (!isRValRef || T1->isFunctionType()) {
+ if (!isRValRef) {
// -- is an lvalue (but is not a bit-field), and "cv1 T1" is
// reference-compatible with "cv2 T2," or
//
@@ -3001,8 +2995,7 @@
// -- 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 and the initializer expression shall be
- // an rvalue or have a function type.
+ // shall be an rvalue reference.
//
// We actually handle one oddity of C++ [over.ics.ref] at this
// point, which is that, due to p2 (which short-circuits reference
@@ -3016,73 +3009,62 @@
if (!isRValRef && !T1.isConstQualified())
return ICS;
- // -- 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
- //
- // -- 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 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);
+ // -- If the initializer expression
+ //
+ // -- 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",
+ //
+ // 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 (!SuppressUserConversions && RefRelationship == Sema::Ref_Incompatible &&
+ T2->isRecordType() && !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
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=124121&r1=124120&r2=124121&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Jan 24 10:14:37 2011
@@ -2470,6 +2470,7 @@
TemplateParameterList::iterator Param = Params->begin(),
ParamEnd = Params->end();
unsigned ArgIdx = 0;
+ LocalInstantiationScope InstScope(*this, true);
while (Param != ParamEnd) {
if (ArgIdx > NumArgs && PartialTemplateArgs)
break;
Modified: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp?rev=124121&r1=124120&r2=124121&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp (original)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp Mon Jan 24 10:14:37 2011
@@ -17,7 +17,7 @@
template<typename T>
struct ConvertsTo {
- operator T(); // expected-note 2{{candidate function}}
+ operator T(); // expected-note 4{{candidate function}}
};
void test_rvalue_refs() {
@@ -130,3 +130,35 @@
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>());
+ base_rvalue_ref(xvalue<Derived>());
+ int_rvalue_ref(xvalue<int>());
+
+ base_rvalue_ref(prvalue<Base>());
+ base_rvalue_ref(prvalue<Derived>());
+
+ array_rvalue_ref(HasArray().array);
+
+ function_rvalue_ref(f);
+
+ base_rvalue_ref(ConvertsTo<Base&&>());
+ base_rvalue_ref(ConvertsTo<Derived&&>());
+ int_rvalue_ref(ConvertsTo<int&&>());
+
+ base_rvalue_ref(ConvertsTo<Base>());
+ base_rvalue_ref(ConvertsTo<Derived>());
+
+ function_rvalue_ref(ConvertsTo<int(&)(int)>());
+
+ int_rvalue_ref(ConvertsTo<int&>()); // expected-error{{no viable conversion from 'ConvertsTo<int &>' to 'int'}}
+ int_rvalue_ref(ConvertsTo<float&>()); // expected-error{{no viable conversion from 'ConvertsTo<float &>' to 'int'}}
+ }
+
+}
Modified: cfe/trunk/test/SemaCXX/conditional-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conditional-expr.cpp?rev=124121&r1=124120&r2=124121&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/conditional-expr.cpp (original)
+++ cfe/trunk/test/SemaCXX/conditional-expr.cpp Mon Jan 24 10:14:37 2011
@@ -7,7 +7,10 @@
struct ToBool { explicit operator bool(); };
struct B;
-struct A { 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(); };
Modified: cfe/trunk/test/SemaCXX/decl-init-ref.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/decl-init-ref.cpp?rev=124121&r1=124120&r2=124121&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/decl-init-ref.cpp (original)
+++ cfe/trunk/test/SemaCXX/decl-init-ref.cpp Mon Jan 24 10:14:37 2011
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
-struct A {}; // expected-note {{candidate is the implicit copy constructor}}
+struct A {};
struct BASE {
operator A(); // expected-note {{candidate function}}
More information about the cfe-commits
mailing list