An identity conversion is better than any non-identity
conversion. Fixes PR7095.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104476 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index abbf393..6c64905 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -2076,6 +2076,15 @@
   ImplicitConversionSequence::CompareKind Result
     = ImplicitConversionSequence::Indistinguishable;
 
+  // the identity conversion sequence is considered to be a subsequence of 
+  // any non-identity conversion sequence
+  if (SCS1.ReferenceBinding == SCS2.ReferenceBinding) {
+    if (SCS1.isIdentityConversion() && !SCS2.isIdentityConversion())
+      return ImplicitConversionSequence::Better;
+    else if (!SCS1.isIdentityConversion() && SCS2.isIdentityConversion())
+      return ImplicitConversionSequence::Worse;
+  }
+    
   if (SCS1.Second != SCS2.Second) {
     if (SCS1.Second == ICK_Identity)
       Result = ImplicitConversionSequence::Better;
diff --git a/lib/Sema/SemaOverload.h b/lib/Sema/SemaOverload.h
index 8d261dd..eb4fc65 100644
--- a/lib/Sema/SemaOverload.h
+++ b/lib/Sema/SemaOverload.h
@@ -177,6 +177,12 @@
     }
 
     void setAsIdentityConversion();
+    
+    bool isIdentityConversion() const {
+      return First == ICK_Identity && Second == ICK_Identity && 
+             Third == ICK_Identity;
+    }
+    
     ImplicitConversionRank getRank() const;
     bool isPointerConversionToBool() const;
     bool isPointerConversionToVoidPointer(ASTContext& Context) const;
diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp
index 79c74ce..9618ea2 100644
--- a/test/SemaCXX/overload-call.cpp
+++ b/test/SemaCXX/overload-call.cpp
@@ -430,3 +430,17 @@
 
   void g() { f(""); } // expected-error{{volatile lvalue reference to type 'bool const volatile' cannot bind to a value of unrelated type 'char const [1]'}}
 }
+
+namespace PR7095 {
+  struct X { };
+
+  struct Y {
+    operator const X*();
+
+  private:
+    operator X*();
+  };
+
+  void f(const X *);
+  void g(Y y) { f(y); }
+}