aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/Sema.h3
-rw-r--r--lib/Sema/SemaExprObjC.cpp10
-rw-r--r--lib/Sema/SemaOverload.cpp21
-rw-r--r--test/SemaObjCXX/conversion-to-objc-pointer.mm51
4 files changed, 85 insertions, 0 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 70e445ffae..9d811a4dbe 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1162,6 +1162,9 @@ public:
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 db9a2e238f..3853e911e7 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -976,6 +976,16 @@ Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE,
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 a45ad15478..04495e5ca4 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -2931,6 +2931,27 @@ bool Sema::PerformContextuallyConvertToBool(Expr *&From) {
<< 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 0000000000..2f146ce206
--- /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;
+}