diff options
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 24 | ||||
-rw-r--r-- | test/SemaCXX/overload-call.cpp | 15 |
2 files changed, 29 insertions, 10 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index f9cf1e9042..6772672bef 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -2308,20 +2308,23 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, Sema::ReferenceCompareResult RefRelationship = S.CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase); - // C++ [dcl.init.ref]p5: - // A reference to type "cv1 T1" is initialized by an expression - // of type "cv2 T2" as follows: - - // -- If the initializer expression // C++ [over.ics.ref]p3: // Except for an implicit object parameter, for which see 13.3.1, // a standard conversion sequence cannot be formed if it requires // binding an lvalue reference to non-const to an rvalue or // binding an rvalue reference to an lvalue. + // + // FIXME: DPG doesn't trust this code. It seems far too early to + // abort because of a binding of an rvalue reference to an lvalue. if (isRValRef && InitLvalue == Expr::LV_Valid) return ICS; + // C++0x [dcl.init.ref]p16: + // A reference to type "cv1 T1" is initialized by an expression + // of type "cv2 T2" as follows: + + // -- If the initializer expression // -- is an lvalue (but is not a bit-field), and "cv1 T1" is // reference-compatible with "cv2 T2," or // @@ -2444,7 +2447,15 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, // -- Otherwise, the reference shall be 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. - if (!isRValRef && T1.getCVRQualifiers() != Qualifiers::Const) + // + // We actually handle one oddity of C++ [over.ics.ref] at this + // point, which is that, due to p2 (which short-circuits reference + // binding by only attempting a simple conversion for non-direct + // bindings) and p3's strange wording, we allow a const volatile + // reference to bind to an rvalue. Hence the check for the presence + // of "const" rather than checking for "const" being the only + // qualifier. + if (!isRValRef && !T1.isConstQualified()) return ICS; // -- if T2 is a class type and @@ -2508,7 +2519,6 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, return ICS; // C++ [over.ics.ref]p2: - // // When a parameter of reference type is not bound directly to // an argument expression, the conversion sequence is the one // required to convert the argument expression to the diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp index f3a5fba8e6..472e805c29 100644 --- a/test/SemaCXX/overload-call.cpp +++ b/test/SemaCXX/overload-call.cpp @@ -247,14 +247,14 @@ struct Z : X, Y { }; int& cvqual_subsume(X&); // expected-note{{candidate function}} float& cvqual_subsume(const Y&); // expected-note{{candidate function}} -int& cvqual_subsume2(const X&); -float& cvqual_subsume2(const volatile Y&); +int& cvqual_subsume2(const X&); // expected-note{{candidate function}} +float& cvqual_subsume2(const volatile Y&); // expected-note{{candidate function}} Z get_Z(); void cvqual_subsume_test(Z z) { cvqual_subsume(z); // expected-error{{call to 'cvqual_subsume' is ambiguous; candidates are:}} - int& x = cvqual_subsume2(get_Z()); // okay: only binds to the first one + int& x = cvqual_subsume2(get_Z()); // expected-error{{call to 'cvqual_subsume2' is ambiguous; candidates are:}} } // Test overloading with cv-qualification differences in reference @@ -421,3 +421,12 @@ namespace PR6078 { S()(0); // expected-error{{conversion from 'int' to 'PR6078::A' is ambiguous}} } } + +namespace PR6177 { + struct String { String(char const*); }; + + void f(bool const volatile&); + void f(String); + + void g() { f(""); } // expected-error{{volatile lvalue reference to type 'bool const volatile' cannot bind to a value of unrelated type 'char const [1]'}} +} |