[cfe-commits] r58381 - in /cfe/trunk: lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaOverload.h test/SemaCXX/overload-call.cpp
Douglas Gregor
doug.gregor at gmail.com
Wed Oct 29 07:50:44 PDT 2008
Author: dgregor
Date: Wed Oct 29 09:50:44 2008
New Revision: 58381
URL: http://llvm.org/viewvc/llvm-project?rev=58381&view=rev
Log:
Implement overloading rules for reference binding
Modified:
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/lib/Sema/SemaOverload.h
cfe/trunk/test/SemaCXX/overload-call.cpp
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=58381&r1=58380&r2=58381&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Oct 29 09:50:44 2008
@@ -785,8 +785,8 @@
ICS->Standard.Third = ICK_Identity;
ICS->Standard.FromTypePtr = T2.getAsOpaquePtr();
ICS->Standard.ToTypePtr = T1.getAsOpaquePtr();
- ICS->ReferenceBinding = true;
- ICS->DirectBinding = true;
+ ICS->Standard.ReferenceBinding = true;
+ ICS->Standard.DirectBinding = true;
// Nothing more to do: the inaccessibility/ambiguity check for
// derived-to-base conversions is suppressed when we're
@@ -876,8 +876,8 @@
ICS->Standard.Third = ICK_Identity;
ICS->Standard.FromTypePtr = T2.getAsOpaquePtr();
ICS->Standard.ToTypePtr = T1.getAsOpaquePtr();
- ICS->ReferenceBinding = true;
- ICS->DirectBinding = false;
+ ICS->Standard.ReferenceBinding = true;
+ ICS->Standard.DirectBinding = false;
} else {
// FIXME: Binding to a subobject of the rvalue is going to require
// more AST annotation than this.
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=58381&r1=58380&r2=58381&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Oct 29 09:50:44 2008
@@ -471,7 +471,7 @@
ICS.Standard.Third = ICK_Identity;
// C++ [dcl.init]p14 last bullet:
- // Note: an expression of type "cv1 T" can initialize an object
+ // [ Note: an expression of type "cv1 T" can initialize an object
// of type âcv2 Tâ independently of the cv-qualifiers cv1 and
// cv2. -- end note]
//
@@ -877,21 +877,48 @@
// C++ [over.ics.rank]p4b2:
//
// If class B is derived directly or indirectly from class A,
- // conversion of B* to A* is better than conversion of B* to void*,
- // and (FIXME) conversion of A* to void* is better than conversion of B*
- // to void*.
+ // conversion of B* to A* is better than conversion of B* to
+ // void*, and conversion of A* to void* is better than conversion
+ // of B* to void*.
bool SCS1ConvertsToVoid
= SCS1.isPointerConversionToVoidPointer(Context);
bool SCS2ConvertsToVoid
= SCS2.isPointerConversionToVoidPointer(Context);
- if (SCS1ConvertsToVoid != SCS2ConvertsToVoid)
+ if (SCS1ConvertsToVoid != SCS2ConvertsToVoid) {
+ // Exactly one of the conversion sequences is a conversion to
+ // a void pointer; it's the worse conversion.
return SCS2ConvertsToVoid ? ImplicitConversionSequence::Better
: ImplicitConversionSequence::Worse;
-
- if (!SCS1ConvertsToVoid && !SCS2ConvertsToVoid)
+ } else if (!SCS1ConvertsToVoid && !SCS2ConvertsToVoid) {
+ // Neither conversion sequence converts to a void pointer; compare
+ // their derived-to-base conversions.
if (ImplicitConversionSequence::CompareKind DerivedCK
= CompareDerivedToBaseConversions(SCS1, SCS2))
return DerivedCK;
+ } else if (SCS1ConvertsToVoid && SCS2ConvertsToVoid) {
+ // Both conversion sequences are conversions to void
+ // pointers. Compare the source types to determine if there's an
+ // inheritance relationship in their sources.
+ QualType FromType1 = QualType::getFromOpaquePtr(SCS1.FromTypePtr);
+ QualType FromType2 = QualType::getFromOpaquePtr(SCS2.FromTypePtr);
+
+ // Adjust the types we're converting from via the array-to-pointer
+ // conversion, if we need to.
+ if (SCS1.First == ICK_Array_To_Pointer)
+ FromType1 = Context.getArrayDecayedType(FromType1);
+ if (SCS2.First == ICK_Array_To_Pointer)
+ FromType2 = Context.getArrayDecayedType(FromType2);
+
+ QualType FromPointee1
+ = FromType1->getAsPointerType()->getPointeeType().getUnqualifiedType();
+ QualType FromPointee2
+ = FromType2->getAsPointerType()->getPointeeType().getUnqualifiedType();
+
+ if (IsDerivedFrom(FromPointee2, FromPointee1))
+ return ImplicitConversionSequence::Better;
+ else if (IsDerivedFrom(FromPointee1, FromPointee2))
+ return ImplicitConversionSequence::Worse;
+ }
// Compare based on qualification conversions (C++ 13.3.3.2p3,
// bullet 3).
@@ -899,7 +926,24 @@
= CompareQualificationConversions(SCS1, SCS2))
return QualCK;
- // FIXME: Handle comparison of reference bindings.
+ // C++ [over.ics.rank]p3b4:
+ // -- S1 and S2 are reference bindings (8.5.3), and the types to
+ // which the references refer are the same type except for
+ // top-level cv-qualifiers, and the type to which the reference
+ // initialized by S2 refers is more cv-qualified than the type
+ // to which the reference initialized by S1 refers.
+ if (SCS1.ReferenceBinding && SCS2.ReferenceBinding) {
+ QualType T1 = QualType::getFromOpaquePtr(SCS1.ToTypePtr);
+ QualType T2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr);
+ T1 = Context.getCanonicalType(T1);
+ T2 = Context.getCanonicalType(T2);
+ if (T1.getUnqualifiedType() == T2.getUnqualifiedType()) {
+ if (T2.isMoreQualifiedThan(T1))
+ return ImplicitConversionSequence::Better;
+ else if (T1.isMoreQualifiedThan(T2))
+ return ImplicitConversionSequence::Worse;
+ }
+ }
return ImplicitConversionSequence::Indistinguishable;
}
@@ -1018,16 +1062,14 @@
FromType2 = Context.getCanonicalType(FromType2);
ToType2 = Context.getCanonicalType(ToType2);
- // C++ [over.ics.rank]p4b4:
+ // C++ [over.ics.rank]p4b3:
//
// If class B is derived directly or indirectly from class A and
// class C is derived directly or indirectly from B,
- //
- // FIXME: Verify that in this section we're talking about the
- // unqualified forms of C, B, and A.
+
+ // Compare based on pointer conversions.
if (SCS1.Second == ICK_Pointer_Conversion &&
SCS2.Second == ICK_Pointer_Conversion) {
- // -- conversion of C* to B* is better than conversion of C* to A*,
QualType FromPointee1
= FromType1->getAsPointerType()->getPointeeType().getUnqualifiedType();
QualType ToPointee1
@@ -1036,16 +1078,60 @@
= FromType2->getAsPointerType()->getPointeeType().getUnqualifiedType();
QualType ToPointee2
= ToType2->getAsPointerType()->getPointeeType().getUnqualifiedType();
+ // -- conversion of C* to B* is better than conversion of C* to A*,
if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) {
if (IsDerivedFrom(ToPointee1, ToPointee2))
return ImplicitConversionSequence::Better;
else if (IsDerivedFrom(ToPointee2, ToPointee1))
return ImplicitConversionSequence::Worse;
}
+
+ // -- conversion of B* to A* is better than conversion of C* to A*,
+ if (FromPointee1 != FromPointee2 && ToPointee1 == ToPointee2) {
+ if (IsDerivedFrom(FromPointee2, FromPointee1))
+ return ImplicitConversionSequence::Better;
+ else if (IsDerivedFrom(FromPointee1, FromPointee2))
+ return ImplicitConversionSequence::Worse;
+ }
}
- // FIXME: many more sub-bullets of C++ [over.ics.rank]p4b4 to
- // implement.
+ // Compare based on reference bindings.
+ if (SCS1.ReferenceBinding && SCS2.ReferenceBinding &&
+ SCS1.Second == ICK_Derived_To_Base) {
+ // -- binding of an expression of type C to a reference of type
+ // B& is better than binding an expression of type C to a
+ // reference of type A&,
+ if (FromType1.getUnqualifiedType() == FromType2.getUnqualifiedType() &&
+ ToType1.getUnqualifiedType() != ToType2.getUnqualifiedType()) {
+ if (IsDerivedFrom(ToType1, ToType2))
+ return ImplicitConversionSequence::Better;
+ else if (IsDerivedFrom(ToType2, ToType1))
+ return ImplicitConversionSequence::Worse;
+ }
+
+ // -- binding of an expression of type B to a reference of type
+ // A& is better than binding an expression of type C to a
+ // reference of type A&,
+ if (FromType1.getUnqualifiedType() != FromType2.getUnqualifiedType() &&
+ ToType1.getUnqualifiedType() == ToType2.getUnqualifiedType()) {
+ if (IsDerivedFrom(FromType2, FromType1))
+ return ImplicitConversionSequence::Better;
+ else if (IsDerivedFrom(FromType1, FromType2))
+ return ImplicitConversionSequence::Worse;
+ }
+ }
+
+
+ // FIXME: conversion of A::* to B::* is better than conversion of
+ // A::* to C::*,
+
+ // FIXME: conversion of B::* to C::* is better than conversion of
+ // A::* to C::*, and
+
+ // FIXME: conversion of C to B is better than conversion of C to A,
+
+ // FIXME: conversion of B to A is better than conversion of C to A.
+
return ImplicitConversionSequence::Indistinguishable;
}
Modified: cfe/trunk/lib/Sema/SemaOverload.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.h?rev=58381&r1=58380&r2=58381&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.h (original)
+++ cfe/trunk/lib/Sema/SemaOverload.h Wed Oct 29 09:50:44 2008
@@ -97,6 +97,14 @@
/// (C++ 4.2p2).
bool Deprecated : 1;
+ /// ReferenceBinding - True when this is a reference binding
+ /// (C++ [over.ics.ref]).
+ bool ReferenceBinding : 1;
+
+ /// DirectBinding - True when this is a reference binding that is a
+ /// direct binding (C++ [dcl.init.ref]).
+ bool DirectBinding : 1;
+
/// FromType - The type that this conversion is converting
/// from. This is an opaque pointer that can be translated into a
/// QualType.
@@ -155,17 +163,7 @@
};
/// ConversionKind - The kind of implicit conversion sequence.
- /// As usual, we use "unsigned" here because VC++ makes enum bitfields
- /// signed.
- unsigned ConversionKind : 2;
-
- /// ReferenceBinding - True when this is a reference binding
- /// (C++ [over.ics.ref]).
- bool ReferenceBinding : 1;
-
- /// DirectBinding - True when this is a reference binding that is a
- /// direct binding (C++ [dcl.init.ref]).
- bool DirectBinding : 1;
+ Kind ConversionKind;
union {
/// When ConversionKind == StandardConversion, provides the
Modified: cfe/trunk/test/SemaCXX/overload-call.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overload-call.cpp?rev=58381&r1=58380&r2=58381&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/overload-call.cpp (original)
+++ cfe/trunk/test/SemaCXX/overload-call.cpp Wed Oct 29 09:50:44 2008
@@ -253,3 +253,25 @@
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
}
+
+// Test overloading with cv-qualification differences in reference
+// binding.
+int& cvqual_diff(X&);
+float& cvqual_diff(const X&);
+
+void cvqual_diff_test(X x, Z z) {
+ int& i1 = cvqual_diff(x);
+ int& i2 = cvqual_diff(z);
+}
+
+// Test overloading with derived-to-base differences in reference
+// binding.
+struct Z2 : Z { };
+
+int& db_rebind(X&);
+long& db_rebind(Y&);
+float& db_rebind(Z&);
+
+void db_rebind_test(Z2 z2) {
+ float& f1 = db_rebind(z2);
+}
More information about the cfe-commits
mailing list