diff options
-rw-r--r-- | lib/Sema/Sema.h | 3 | ||||
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 21 | ||||
-rw-r--r-- | test/SemaObjCXX/conversion-to-objc-pointer.mm | 51 |
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; +} |