diff options
| -rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 9 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/conversion-function.cpp | 21 | ||||
| -rw-r--r-- | clang/test/SemaCXX/conversion-function.cpp | 18 | 
3 files changed, 45 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 5f9a963c904..3e89a6413a2 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/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/clang/test/CodeGenCXX/conversion-function.cpp b/clang/test/CodeGenCXX/conversion-function.cpp index 0d21180530d..e5f303cbaee 100644 --- a/clang/test/CodeGenCXX/conversion-function.cpp +++ b/clang/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/clang/test/SemaCXX/conversion-function.cpp b/clang/test/SemaCXX/conversion-function.cpp index cde2851bf34..37ffc1bb530 100644 --- a/clang/test/SemaCXX/conversion-function.cpp +++ b/clang/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(); +} +  | 

