Objective-C++ Sema. Support for conversion of a C++
class object used as a receiver to an objective-c
pointer via a converwsion function. wip.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103672 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 70e445f..9d811a4 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1162,6 +1162,9 @@
   ImplicitConversionSequence TryContextuallyConvertToBool(Expr *From);
   bool PerformContextuallyConvertToBool(Expr *&From);
 
+  ImplicitConversionSequence TryContextuallyConvertToObjCId(Expr *From);
+  bool PerformContextuallyConvertToObjCId(Expr *&From);
+
   bool PerformObjectMemberConversion(Expr *&From,
                                      NestedNameSpecifier *Qualifier,
                                      NamedDecl *FoundDecl,
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index db9a2e2..3853e91 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -976,6 +976,16 @@
           ImpCastExprToType(Receiver, Context.getObjCIdType(),
                             CastExpr::CK_IntegralToPointer);
         ReceiverType = Receiver->getType();
+      } 
+      else if (!PerformContextuallyConvertToObjCId(Receiver)) {
+        return BuildInstanceMessage(Owned(Receiver),
+                                    ReceiverType,
+                                    SuperLoc,
+                                    Sel,
+                                    Method,
+                                    LBracLoc, 
+                                    RBracLoc,
+                                    move(ArgsIn));
       } else {
         // Reject other random receiver types (e.g. structs).
         Diag(Loc, diag::err_bad_receiver_type)
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index a45ad15..04495e5 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -2931,6 +2931,27 @@
                   << From->getType() << From->getSourceRange();
   return true;
 }
+  
+/// TryContextuallyConvertToObjCId - Attempt to contextually convert the
+/// expression From to 'id'.
+ImplicitConversionSequence Sema::TryContextuallyConvertToObjCId(Expr *From) {
+  QualType Ty = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy);
+    return TryImplicitConversion(From, Ty,
+                                 // FIXME: Are these flags correct?
+                                 /*SuppressUserConversions=*/false,
+                                 /*AllowExplicit=*/true,
+                                 /*InOverloadResolution=*/false);
+}
+  
+/// PerformContextuallyConvertToObjCId - Perform a contextual conversion
+/// of the expression From to 'id'.
+bool Sema::PerformContextuallyConvertToObjCId(Expr *&From) {
+  QualType Ty = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy);
+  ImplicitConversionSequence ICS = TryContextuallyConvertToObjCId(From);
+  if (!ICS.isBad())
+    return PerformImplicitConversion(From, Ty, ICS, AA_Converting);
+  return true;
+}
 
 /// AddOverloadCandidate - Adds the given function to the set of
 /// candidate functions, using the given function call arguments.  If
diff --git a/test/SemaObjCXX/conversion-to-objc-pointer.mm b/test/SemaObjCXX/conversion-to-objc-pointer.mm
new file mode 100644
index 0000000..2f146ce
--- /dev/null
+++ b/test/SemaObjCXX/conversion-to-objc-pointer.mm
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// rdar: // 7963410
+
+template<class T>
+class TNSAutoRef
+{
+public:
+	TNSAutoRef(T t)
+		:	fRef(t)
+		{ }
+
+	~TNSAutoRef()
+		{  }
+
+	operator T() const
+		{ return fRef; }
+	
+	T Get() const
+		{ return fRef; }
+
+private:
+	T fRef;
+};
+
+@interface NSObject
+- (id) alloc;
+- (id)init;
+@end
+
+@interface TFoo : NSObject
+
+- (void) foo;
+@end
+
+@implementation TFoo
+
+- (void) foo
+	{}
+@end
+
+@interface TBar : NSObject
+@end
+
+@implementation TBar 
+@end
+
+int main () {
+	TNSAutoRef<TBar*> bar([[TBar alloc] init]);
+	[bar foo];
+	return 0;
+}