]> granicus.if.org Git - clang/commitdiff
Used visible conversion function api to do overload
authorFariborz Jahanian <fjahanian@apple.com>
Mon, 14 Sep 2009 20:41:01 +0000 (20:41 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Mon, 14 Sep 2009 20:41:01 +0000 (20:41 +0000)
resolution of type conversion functions in base and
current class.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81784 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaOverload.cpp
test/CodeGenCXX/conversion-function.cpp
test/SemaCXX/conversion-function.cpp

index 5f9a963c9048b5f3de7e28978bf36cee34c15e6a..3e89a6413a2267d5eeab8caa776c145ff76c67e4 100644 (file)
@@ -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;
index 0d21180530db10e47a9b65c084a71c42ea38aaef..e5f303cbaeeff724131e5f42d630e438fbbd7bc5 100644 (file)
@@ -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
index cde2851bf34cd9c7d9a9f9d91f330d8079ee0490..37ffc1bb53023955e746a94040c1b3ed01d2818f 100644 (file)
@@ -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();
+}
+