]> granicus.if.org Git - clang/commitdiff
Reference binding via user-defined conversion can compute a binding
authorDouglas Gregor <dgregor@apple.com>
Sun, 7 Mar 2010 23:17:44 +0000 (23:17 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sun, 7 Mar 2010 23:17:44 +0000 (23:17 +0000)
that is not reference-related (because it requires another implicit
conversion to which we can find). Fixes PR6483.

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

lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaInit.cpp
test/SemaCXX/overload-call.cpp

index 0708d4176a4f23b86bcdb3b8685a934f5f01fb65..b959202b88562d05cab228afd963d9ce8cb9693d 100644 (file)
@@ -4526,20 +4526,23 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
     OverloadCandidateSet::iterator Best;
     switch (BestViableFunction(CandidateSet, DeclLoc, Best)) {
     case OR_Success:
+      // C++ [over.ics.ref]p1:
+      //
+      //   [...] If the parameter binds directly to the result of
+      //   applying a conversion function to the argument
+      //   expression, the implicit conversion sequence is a
+      //   user-defined conversion sequence (13.3.3.1.2), with the
+      //   second standard conversion sequence either an identity
+      //   conversion or, if the conversion function returns an
+      //   entity of a type that is a derived class of the parameter
+      //   type, a derived-to-base Conversion.
+      if (!Best->FinalConversion.DirectBinding)
+        break;
+
       // This is a direct binding.
       BindsDirectly = true;
 
       if (ICS) {
-        // C++ [over.ics.ref]p1:
-        //
-        //   [...] If the parameter binds directly to the result of
-        //   applying a conversion function to the argument
-        //   expression, the implicit conversion sequence is a
-        //   user-defined conversion sequence (13.3.3.1.2), with the
-        //   second standard conversion sequence either an identity
-        //   conversion or, if the conversion function returns an
-        //   entity of a type that is a derived class of the parameter
-        //   type, a derived-to-base Conversion.
         ICS->setUserDefined();
         ICS->UserDefined.Before = Best->Conversions[0].Standard;
         ICS->UserDefined.After = Best->FinalConversion;
index 98db60854f3ec021b3f1c41ec9f08d0458aaa22b..3540cd02e6da8adb8dc5ad9a80014313da8d8906 100644 (file)
@@ -2273,10 +2273,17 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
   Sema::ReferenceCompareResult NewRefRelationship
     = S.CompareReferenceRelationship(DeclLoc, T1, T2.getNonReferenceType(),
                                      NewDerivedToBase);
-  assert(NewRefRelationship != Sema::Ref_Incompatible &&
-         "Overload resolution picked a bad conversion function");
-  (void)NewRefRelationship;
-  if (NewDerivedToBase)
+  if (NewRefRelationship == Sema::Ref_Incompatible) {
+    // If the type we've converted to is not reference-related to the
+    // type we're looking for, then there is another conversion step
+    // we need to perform to produce a temporary of the right type
+    // that we'll be binding to.
+    ImplicitConversionSequence ICS;
+    ICS.setStandard();
+    ICS.Standard = Best->FinalConversion;
+    T2 = ICS.Standard.getToType(2);
+    Sequence.AddConversionSequenceStep(ICS, T2);
+  } else if (NewDerivedToBase)
     Sequence.AddDerivedToBaseCastStep(
                                 S.Context.getQualifiedType(T1,
                                   T2.getNonReferenceType().getQualifiers()), 
index 77e0908ef46dc48838cf64a52fa4d81cc26a25c8..c286028c29af7b038df99615b8efba307d185ce0 100644 (file)
@@ -386,3 +386,23 @@ namespace DerivedToBase {
     float &fr = f0(C());
   }
 }
+
+namespace PR6483 {
+  struct X0 {
+    operator const unsigned int & () const;
+  };
+
+  struct X1 {
+    operator unsigned int & () const;
+  };
+
+  void f0(const bool &);
+  void f1(bool &); // expected-note 2{{not viable}}
+
+  void g(X0 x0, X1 x1) {
+    f0(x0);
+    f1(x0); // expected-error{{no matching function for call}}
+    f0(x1);
+    f1(x1); // expected-error{{no matching function for call}}
+  }  
+}