[cfe-commits] r111520 - in /cfe/trunk: lib/Sema/SemaOverload.cpp test/SemaCXX/conversion-function.cpp

Douglas Gregor dgregor at apple.com
Thu Aug 19 08:57:50 PDT 2010


Author: dgregor
Date: Thu Aug 19 10:57:50 2010
New Revision: 111520

URL: http://llvm.org/viewvc/llvm-project?rev=111520&view=rev
Log:
Properly implement the part of C++ [over.match.funcs]p4 that treats
conversion functions as if their acting context were the class that
we're converting from (the implicit object argument's
type). Retroactively tweaking the implicit conversion sequence, as we
were trying to do before, breaks the invariants of that implicit
conversion sequence (e.g., the types and conversions don't match
up). Fixes <rdar://problem/8018274>.

Modified:
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/SemaCXX/conversion-function.cpp

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=111520&r1=111519&r2=111520&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Thu Aug 19 10:57:50 2010
@@ -3741,26 +3741,46 @@
   Candidate.FinalConversion.setAsIdentityConversion();
   Candidate.FinalConversion.setFromType(ConvType);
   Candidate.FinalConversion.setAllToTypes(ToType);
-
-  // Determine the implicit conversion sequence for the implicit
-  // object parameter.
   Candidate.Viable = true;
   Candidate.Conversions.resize(1);
-  Candidate.Conversions[0]
-    = TryObjectArgumentInitialization(From->getType(), Conversion,
-                                      ActingContext);
-  
+
   // C++ [over.match.funcs]p4:
   //   For conversion functions, the function is considered to be a member of 
   //   the class of the implicit implied object argument for the purpose of 
   //   defining the type of the implicit object parameter.
-  if (Candidate.Conversions[0].Standard.Second == ICK_Derived_To_Base)
-    Candidate.Conversions[0].Standard.Second = ICK_Identity;
+  //
+  // Determine the implicit conversion sequence for the implicit
+  // object parameter.
+  QualType ImplicitParamType = From->getType();
+  if (const PointerType *FromPtrType = ImplicitParamType->getAs<PointerType>())
+    ImplicitParamType = FromPtrType->getPointeeType();
+  CXXRecordDecl *ConversionContext
+    = cast<CXXRecordDecl>(ImplicitParamType->getAs<RecordType>()->getDecl());
+  
+  Candidate.Conversions[0]
+    = TryObjectArgumentInitialization(From->getType(), Conversion,
+                                      ConversionContext);
+  
   if (Candidate.Conversions[0].isBad()) {
     Candidate.Viable = false;
     Candidate.FailureKind = ovl_fail_bad_conversion;
     return;
   }
+
+  // Make sure that the actual object argument initialization will work, when
+  // it comes down to it. This takes into account the actual acting context.
+  if (ConversionContext->getCanonicalDecl()
+                                        != ActingContext->getCanonicalDecl()) {
+    ImplicitConversionSequence ObjectConvertICS
+      = TryObjectArgumentInitialization(From->getType(), Conversion, 
+                                        ActingContext);
+    if (ObjectConvertICS.isBad()) {
+      Candidate.Viable = false;
+      Candidate.FailureKind = ovl_fail_bad_conversion;
+      Candidate.Conversions[0] = ObjectConvertICS;
+      return;
+    }
+  }
   
   // We won't go through a user-define type conversion function to convert a 
   // derived to base as such conversions are given Conversion Rank. They only

Modified: cfe/trunk/test/SemaCXX/conversion-function.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion-function.cpp?rev=111520&r1=111519&r2=111520&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/conversion-function.cpp (original)
+++ cfe/trunk/test/SemaCXX/conversion-function.cpp Thu Aug 19 10:57:50 2010
@@ -270,3 +270,40 @@
     fake_memcpy(ptr);
   }
 }
+
+namespace rdar8018274 {
+  struct X { };
+  struct Y {
+    operator const struct X *() const;
+  };
+
+  struct Z : Y {
+    operator struct X * ();
+  };
+
+  void test() {
+    Z x;
+    (void) (x != __null);
+  }
+
+
+  struct Base {
+    operator int();
+  };
+
+  struct Derived1 : Base { };
+
+  struct Derived2 : Base { };
+
+  struct SuperDerived : Derived1, Derived2 { 
+    using Derived1::operator int;
+  };
+
+  struct UeberDerived : SuperDerived {
+    operator long();
+  };
+
+  void test2(UeberDerived ud) {
+    int i = ud; // expected-error{{ambiguous conversion from derived class 'rdar8018274::SuperDerived' to base class 'rdar8018274::Base'}}
+  }
+}





More information about the cfe-commits mailing list