diff options
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 9 | ||||
-rw-r--r-- | test/CodeGenCXX/conversion-function.cpp | 21 | ||||
-rw-r--r-- | test/SemaCXX/conversion-function.cpp | 18 |
3 files changed, 45 insertions, 3 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 5f9a963c90..3e89a6413a 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -1412,9 +1412,8 @@ bool Sema::IsUserDefinedConversion(Expr *From, QualType ToType, if (CXXRecordDecl *FromRecordDecl = dyn_cast<CXXRecordDecl>(FromRecordType->getDecl())) { // Add all of the conversion functions as candidates. - // FIXME: Look for conversions in base classes! OverloadedFunctionDecl *Conversions - = FromRecordDecl->getConversionFunctions(); + = FromRecordDecl->getVisibleConversionFunctions(); for (OverloadedFunctionDecl::function_iterator Func = Conversions->function_begin(); Func != Conversions->function_end(); ++Func) { @@ -2427,7 +2426,11 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, Candidate.Viable = true; Candidate.Conversions.resize(1); Candidate.Conversions[0] = TryObjectArgumentInitialization(From, Conversion); - + // Conversion functions to a different type in the base class is visible in + // the derived class. So, a derived to base conversion should not participate + // in overload resolution. + if (Candidate.Conversions[0].Standard.Second == ICK_Derived_To_Base) + Candidate.Conversions[0].Standard.Second = ICK_Identity; if (Candidate.Conversions[0].ConversionKind == ImplicitConversionSequence::BadConversion) { Candidate.Viable = false; diff --git a/test/CodeGenCXX/conversion-function.cpp b/test/CodeGenCXX/conversion-function.cpp index 0d21180530..e5f303cbae 100644 --- a/test/CodeGenCXX/conversion-function.cpp +++ b/test/CodeGenCXX/conversion-function.cpp @@ -77,12 +77,31 @@ int main() { g(o1, o2); } +// Test. Conversion in base class is visible in derived class. +class XB { +public: + operator int(); +}; + +class Yb : public XB { +public: + operator char(); +}; + +void f(Yb& a) { + int i = a; // OK. calls XB::operator int(); + char ch = a; // OK. calls Yb::operator char(); +} + + // CHECK-LP64: .globl __ZN1ScviEv // CHECK-LP64-NEXT: __ZN1ScviEv: // CHECK-LP64: call __ZN1Ycv1ZEv // CHECK-LP64: call __ZN1Zcv1XEv // CHECK-LP64: call __ZN1XcviEv // CHECK-LP64: call __ZN1XcvfEv +// CHECK-LP64: call __ZN2XBcviEv +// CHECK-LP64: call __ZN2YbcvcEv // CHECK-LP32: .globl __ZN1ScviEv // CHECK-LP32-NEXT: __ZN1ScviEv: @@ -90,3 +109,5 @@ int main() { // CHECK-LP32: call L__ZN1Zcv1XEv // CHECK-LP32: call L__ZN1XcviEv // CHECK-LP32: call L__ZN1XcvfEv +// CHECK-LP32: call L__ZN2XBcviEv +// CHECK-LP32: call L__ZN2YbcvcEv diff --git a/test/SemaCXX/conversion-function.cpp b/test/SemaCXX/conversion-function.cpp index cde2851bf3..37ffc1bb53 100644 --- a/test/SemaCXX/conversion-function.cpp +++ b/test/SemaCXX/conversion-function.cpp @@ -75,3 +75,21 @@ C::operator const char*() const { return 0; } void f(const C& c) { const char* v = c; } + +// Test. Conversion in base class is visible in derived class. +class XB { +public: + operator int(); +}; + +class Yb : public XB { +public: + operator char(); +}; + +void f(Yb& a) { + if (a) { } // expected-error {{value of type 'class Yb' is not contextually convertible to 'bool'}} + int i = a; // OK. calls XB::operator int(); + char ch = a; // OK. calls Yb::operator char(); +} + |