summaryrefslogtreecommitdiff
path: root/test/SemaObjC
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-08-07 23:02:44 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-08-07 23:02:44 +0000
commit51ece4aae5857052d224ce52277924c74685714e (patch)
treeca13cf9e2e8c2499f61f1246e455efd2804abd36 /test/SemaObjC
parentc192b3dcffd5e672a2b2e1730e2440febb4fb192 (diff)
Notes
Diffstat (limited to 'test/SemaObjC')
-rw-r--r--test/SemaObjC/block-type-safety.m8
-rw-r--r--test/SemaObjC/conditional-expr-8.m33
-rw-r--r--test/SemaObjC/conditional-expr.m11
-rw-r--r--test/SemaObjC/interface-1.m2
-rw-r--r--test/SemaObjC/kindof.m304
-rw-r--r--test/SemaObjC/objc2-merge-gc-attribue-decl.m16
-rw-r--r--test/SemaObjC/parameterized_classes.m357
-rw-r--r--test/SemaObjC/parameterized_classes_collection_literal.m52
-rw-r--r--test/SemaObjC/parameterized_classes_subst.m428
-rw-r--r--test/SemaObjC/protocol-archane.m4
-rw-r--r--test/SemaObjC/protocol-warn.m2
11 files changed, 1206 insertions, 11 deletions
diff --git a/test/SemaObjC/block-type-safety.m b/test/SemaObjC/block-type-safety.m
index b2c4398dc3c51..96c781b6a561c 100644
--- a/test/SemaObjC/block-type-safety.m
+++ b/test/SemaObjC/block-type-safety.m
@@ -198,3 +198,11 @@ void Test3() {
NSObject<NSObject, P1, NSCopying> *NSO5 = aBlock; // expected-error {{initializing 'NSObject<NSObject,P1,NSCopying> *' with an expression of incompatible type 'void (^)()'}}
NSObject<NSCopying> *NSO6 = aBlock; // Ok
}
+
+// rdar://problem/19420731
+typedef NSObject<P1> NSObject_P1;
+typedef NSObject_P1<P2> NSObject_P1_P2;
+
+void Test4(void (^handler)(NSObject_P1_P2 *p)) {
+ Test4(^(NSObject<P2> *p) { });
+}
diff --git a/test/SemaObjC/conditional-expr-8.m b/test/SemaObjC/conditional-expr-8.m
index beddd205a9071..35f4e75314bd1 100644
--- a/test/SemaObjC/conditional-expr-8.m
+++ b/test/SemaObjC/conditional-expr-8.m
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// expected-no-diagnostics
-// rdar://9296866
+// rdar://9296866
@interface NSResponder
@end
@@ -24,3 +24,34 @@
}
@end
+// rdar://problem/19572837
+@protocol NSObject
+@end
+
+__attribute__((objc_root_class))
+@interface NSObject <NSObject>
+@end
+
+@protocol Goable <NSObject>
+- (void)go;
+@end
+
+@protocol Drivable <Goable>
+- (void)drive;
+@end
+
+@interface Car : NSObject
+- (NSObject <Goable> *)bestGoable:(NSObject <Goable> *)drivable;
+@end
+
+@interface Car(Category) <Drivable>
+@end
+
+@interface Truck : Car
+@end
+
+@implementation Truck
+- (NSObject <Goable> *)bestGoable:(NSObject <Goable> *)drivable value:(int)value{
+ return value > 0 ? self : drivable;
+}
+@end
diff --git a/test/SemaObjC/conditional-expr.m b/test/SemaObjC/conditional-expr.m
index 71e108cce673b..71bdb1b2d341b 100644
--- a/test/SemaObjC/conditional-expr.m
+++ b/test/SemaObjC/conditional-expr.m
@@ -51,6 +51,10 @@
@end
@protocol P2
@end
+@protocol P3 <P1>
+@end
+@protocol P4 <P1>
+@end
@interface A <P0>
@end
@@ -64,6 +68,9 @@
@interface D
@end
+@interface E : A
+@end
+
void f0(id<P0> x) {
x.intProp = 1;
}
@@ -118,3 +125,7 @@ void f11(int a, id<P0> x, id<P1> y) {
void f12(int a, A<P0> *x, A<P1> *y) {
A<P1>* l0 = (a ? x : y ); // expected-warning {{incompatible pointer types initializing 'A<P1> *' with an expression of type 'A<P0> *'}}
}
+
+void f13(int a, B<P3, P0> *x, E<P0, P4> *y) {
+ int *ip = a ? x : y; // expected-warning{{expression of type 'A<P1> *'}}
+}
diff --git a/test/SemaObjC/interface-1.m b/test/SemaObjC/interface-1.m
index 79fbad8ba4bfb..0e47fa08bd77a 100644
--- a/test/SemaObjC/interface-1.m
+++ b/test/SemaObjC/interface-1.m
@@ -3,7 +3,7 @@
@interface NSWhatever :
NSObject // expected-error {{cannot find interface declaration for 'NSObject'}}
-<NSCopying> // expected-error {{cannot find protocol declaration for 'NSCopying'}}
+<NSCopying> // expected-error {{no type or protocol named 'NSCopying'}}
@end
diff --git a/test/SemaObjC/kindof.m b/test/SemaObjC/kindof.m
new file mode 100644
index 0000000000000..b19e423720788
--- /dev/null
+++ b/test/SemaObjC/kindof.m
@@ -0,0 +1,304 @@
+// RUN: %clang_cc1 -fblocks -fsyntax-only %s -verify
+
+// Tests Objective-C 'kindof' types.
+
+#if !__has_feature(objc_kindof)
+#error does not support __kindof
+#endif
+
+@protocol NSObject
+@end
+
+@protocol NSCopying
+- (id)copy;
++ (Class)classCopy;
+@end
+
+@protocol NSRandomProto
+- (void)randomMethod;
++ (void)randomClassMethod;
+@end
+
+__attribute__((objc_root_class))
+@interface NSObject <NSObject>
+- (NSObject *)retain;
+@end
+
+@interface NSString : NSObject <NSCopying>
+- (NSString *)stringByAppendingString:(NSString *)string;
++ (instancetype)string;
+@end
+
+@interface NSMutableString : NSString
+- (void)appendString:(NSString *)string;
+@end
+
+@interface NSNumber : NSObject <NSCopying>
+- (NSNumber *)numberByAddingNumber:(NSNumber *)number;
+@end
+
+// ---------------------------------------------------------------------------
+// Parsing and semantic analysis for __kindof
+// ---------------------------------------------------------------------------
+
+// Test proper application of __kindof.
+typedef __kindof NSObject *typedef1;
+typedef NSObject __kindof *typedef2;
+typedef __kindof NSObject<NSCopying> typedef3;
+typedef NSObject<NSCopying> __kindof *typedef4;
+typedef __kindof id<NSCopying> typedef5;
+typedef __kindof Class<NSCopying> typedef6;
+
+// Test redundancy of __kindof.
+typedef __kindof id __kindof redundant_typedef1;
+typedef __kindof NSObject __kindof *redundant_typedef2;
+
+// Test application of __kindof to typedefs.
+typedef NSObject *NSObject_ptr_typedef;
+typedef NSObject NSObject_typedef;
+typedef __kindof NSObject_ptr_typedef typedef_typedef1;
+typedef __kindof NSObject_typedef typedef_typedef2;
+
+// Test application of __kindof to non-object types.
+typedef __kindof int nonobject_typedef1; // expected-error{{'__kindof' specifier cannot be applied to non-object type 'int'}}
+typedef NSObject **NSObject_ptr_ptr;
+typedef __kindof NSObject_ptr_ptr nonobject_typedef2; // expected-error{{'__kindof' specifier cannot be applied to non-object type 'NSObject_ptr_ptr' (aka 'NSObject **')}}
+
+// Test application of __kindof outside of the decl-specifiers.
+typedef NSObject * __kindof bad_specifier_location1; // expected-error{{'__kindof' type specifier must precede the declarator}}
+typedef NSObject bad_specifier_location2 __kindof; // expected-error{{expected ';' after top level declarator}}
+// expected-warning@-1{{declaration does not declare anything}}
+
+// ---------------------------------------------------------------------------
+// Pretty printing of __kindof
+// ---------------------------------------------------------------------------
+void test_pretty_print(int *ip) {
+ __kindof NSObject *kindof_NSObject;
+ ip = kindof_NSObject; // expected-warning{{from '__kindof NSObject *'}}
+
+ __kindof NSObject_ptr_typedef kindof_NSObject_ptr;
+ ip = kindof_NSObject_ptr; // expected-warning{{from '__kindof NSObject_ptr_typedef'}}
+
+ __kindof id <NSCopying> *kindof_NSCopying;
+ ip = kindof_NSCopying; // expected-warning{{from '__kindof id<NSCopying> *'}}
+
+ __kindof NSObject_ptr_typedef *kindof_NSObject_ptr_typedef;
+ ip = kindof_NSObject_ptr_typedef; // expected-warning{{from '__kindof NSObject_ptr_typedef *'}}
+}
+
+// ---------------------------------------------------------------------------
+// Basic implicit conversions (dropping __kindof, upcasts, etc.)
+// ---------------------------------------------------------------------------
+void test_add_remove_kindof_conversions(void) {
+ __kindof NSObject *kindof_NSObject_obj;
+ NSObject *NSObject_obj;
+
+ // Conversion back and forth
+ kindof_NSObject_obj = NSObject_obj;
+ NSObject_obj = kindof_NSObject_obj;
+
+ // Qualified-id conversion back and forth.
+ __kindof id <NSCopying> kindof_id_NSCopying_obj;
+ id <NSCopying> id_NSCopying_obj;
+ kindof_id_NSCopying_obj = id_NSCopying_obj;
+ id_NSCopying_obj = kindof_id_NSCopying_obj;
+}
+
+void test_upcast_conversions(void) {
+ __kindof NSObject *kindof_NSObject_obj;
+ NSObject *NSObject_obj;
+
+ // Upcasts
+ __kindof NSString *kindof_NSString_obj;
+ NSString *NSString_obj;
+ kindof_NSObject_obj = kindof_NSString_obj;
+ kindof_NSObject_obj = NSString_obj;
+ NSObject_obj = kindof_NSString_obj;
+ NSObject_obj = NSString_obj;
+
+ // "Upcasts" with qualified-id.
+ __kindof id <NSCopying> kindof_id_NSCopying_obj;
+ id <NSCopying> id_NSCopying_obj;
+ kindof_id_NSCopying_obj = kindof_NSString_obj;
+ kindof_id_NSCopying_obj = NSString_obj;
+ id_NSCopying_obj = kindof_NSString_obj;
+ id_NSCopying_obj = NSString_obj;
+}
+
+
+void test_ptr_object_conversions(void) {
+ __kindof NSObject **ptr_kindof_NSObject_obj;
+ NSObject **ptr_NSObject_obj;
+
+ // Conversions back and forth.
+ ptr_kindof_NSObject_obj = ptr_NSObject_obj;
+ ptr_NSObject_obj = ptr_kindof_NSObject_obj;
+
+ // Conversions back and forth with qualified-id.
+ __kindof id <NSCopying> *ptr_kindof_id_NSCopying_obj;
+ id <NSCopying> *ptr_id_NSCopying_obj;
+ ptr_kindof_id_NSCopying_obj = ptr_id_NSCopying_obj;
+ ptr_id_NSCopying_obj = ptr_kindof_id_NSCopying_obj;
+
+ // Upcasts.
+ __kindof NSString **ptr_kindof_NSString_obj;
+ NSString **ptr_NSString_obj;
+ ptr_kindof_NSObject_obj = ptr_kindof_NSString_obj;
+ ptr_kindof_NSObject_obj = ptr_NSString_obj;
+ ptr_NSObject_obj = ptr_kindof_NSString_obj;
+ ptr_NSObject_obj = ptr_NSString_obj;
+}
+
+// ---------------------------------------------------------------------------
+// Implicit downcasting
+// ---------------------------------------------------------------------------
+void test_downcast_conversions(void) {
+ __kindof NSObject *kindof_NSObject_obj;
+ NSObject *NSObject_obj;
+ __kindof NSString *kindof_NSString_obj;
+ NSString *NSString_obj;
+
+ // Implicit downcasting.
+ kindof_NSString_obj = kindof_NSObject_obj;
+ kindof_NSString_obj = NSObject_obj; // expected-warning{{assigning to '__kindof NSString *' from 'NSObject *'}}
+ NSString_obj = kindof_NSObject_obj;
+ NSString_obj = NSObject_obj; // expected-warning{{assigning to 'NSString *' from 'NSObject *'}}
+
+ // Implicit downcasting with qualified id.
+ __kindof id <NSCopying> kindof_NSCopying_obj;
+ id <NSCopying> NSCopying_obj;
+ kindof_NSString_obj = kindof_NSCopying_obj;
+ kindof_NSString_obj = NSCopying_obj; // expected-warning{{from incompatible type 'id<NSCopying>'}}
+ NSString_obj = kindof_NSCopying_obj;
+ NSString_obj = NSCopying_obj; // expected-warning{{from incompatible type 'id<NSCopying>'}}
+ kindof_NSObject_obj = kindof_NSCopying_obj;
+ kindof_NSObject_obj = NSCopying_obj; // expected-warning{{from incompatible type 'id<NSCopying>'}}
+ NSObject_obj = kindof_NSCopying_obj;
+ NSObject_obj = NSCopying_obj; // expected-warning{{from incompatible type 'id<NSCopying>'}}
+}
+
+void test_crosscast_conversions(void) {
+ __kindof NSString *kindof_NSString_obj;
+ NSString *NSString_obj;
+ __kindof NSNumber *kindof_NSNumber_obj;
+ NSNumber *NSNumber_obj;
+
+ NSString_obj = kindof_NSNumber_obj; // expected-warning{{from '__kindof NSNumber *'}}
+}
+
+// ---------------------------------------------------------------------------
+// Blocks
+// ---------------------------------------------------------------------------
+void test_block_conversions(void) {
+ // Adding/removing __kindof from return type.
+ __kindof NSString *(^kindof_NSString_void_block)(void);
+ NSString *(^NSString_void_block)(void);
+ kindof_NSString_void_block = NSString_void_block;
+ NSString_void_block = kindof_NSString_void_block;
+
+ // Covariant return type.
+ __kindof NSMutableString *(^kindof_NSMutableString_void_block)(void);
+ NSMutableString *(^NSMutableString_void_block)(void);
+ kindof_NSString_void_block = NSMutableString_void_block;
+ NSString_void_block = kindof_NSMutableString_void_block;
+ kindof_NSString_void_block = NSMutableString_void_block;
+ NSString_void_block = kindof_NSMutableString_void_block;
+
+ // "Covariant" return type via downcasting rule.
+ kindof_NSMutableString_void_block = NSString_void_block; // expected-error{{from 'NSString *(^)(void)'}}
+ NSMutableString_void_block = kindof_NSString_void_block;
+ kindof_NSMutableString_void_block = NSString_void_block; // expected-error{{from 'NSString *(^)(void)'}}
+ NSMutableString_void_block = kindof_NSString_void_block;
+
+ // Cross-casted return type.
+ __kindof NSNumber *(^kindof_NSNumber_void_block)(void);
+ NSNumber *(^NSNumber_void_block)(void);
+ kindof_NSString_void_block = NSNumber_void_block; // expected-error{{from 'NSNumber *(^)(void)'}}
+ NSString_void_block = kindof_NSNumber_void_block; // expected-error{{'__kindof NSNumber *(^)(void)'}}
+ kindof_NSString_void_block = NSNumber_void_block; // expected-error{{from 'NSNumber *(^)(void)'}}
+ NSString_void_block = kindof_NSNumber_void_block; // expected-error{{'__kindof NSNumber *(^)(void)'}}
+
+ // Adding/removing __kindof from argument type.
+ void (^void_kindof_NSString_block)(__kindof NSString *);
+ void (^void_NSString_block)(NSString *);
+ void_kindof_NSString_block = void_NSString_block;
+ void_NSString_block = void_kindof_NSString_block;
+
+ // Contravariant argument type.
+ void (^void_kindof_NSMutableString_block)(__kindof NSMutableString *);
+ void (^void_NSMutableString_block)(NSMutableString *);
+ void_kindof_NSMutableString_block = void_kindof_NSString_block;
+ void_kindof_NSMutableString_block = void_NSString_block;
+ void_NSMutableString_block = void_kindof_NSString_block;
+ void_NSMutableString_block = void_NSString_block;
+
+ // "Contravariant" argument type via downcasting rule.
+ void_kindof_NSString_block = void_kindof_NSMutableString_block;
+ void_kindof_NSString_block = void_NSMutableString_block;
+ void_NSString_block = void_kindof_NSMutableString_block; // expected-error{{from 'void (^)(__kindof NSMutableString *)'}}
+ void_NSString_block = void_NSMutableString_block; // expected-error{{from 'void (^)(NSMutableString *)'}}
+}
+
+// ---------------------------------------------------------------------------
+// Messaging __kindof types.
+// ---------------------------------------------------------------------------
+void message_kindof_object(__kindof NSString *kindof_NSString) {
+ [kindof_NSString retain]; // in superclass
+ [kindof_NSString stringByAppendingString:0]; // in class
+ [kindof_NSString appendString:0]; // in subclass
+ [kindof_NSString numberByAddingNumber: 0]; // FIXME: in unrelated class
+ [kindof_NSString randomMethod]; // in protocol
+}
+
+void message_kindof_qualified_id(__kindof id <NSCopying> kindof_NSCopying) {
+ [kindof_NSCopying copy]; // in protocol
+ [kindof_NSCopying stringByAppendingString:0]; // in some class
+ [kindof_NSCopying randomMethod]; // in unrelated protocol
+}
+
+void message_kindof_qualified_class(
+ __kindof Class <NSCopying> kindof_NSCopying) {
+ [kindof_NSCopying classCopy]; // in protocol
+ [kindof_NSCopying string]; // in some class
+ [kindof_NSCopying randomClassMethod]; // in unrelated protocol
+}
+
+// ---------------------------------------------------------------------------
+// __kindof within specialized types
+// ---------------------------------------------------------------------------
+@interface NSArray<T> : NSObject
+@end
+
+void implicit_convert_array(NSArray<__kindof NSString *> *kindofStringsArray,
+ NSArray<NSString *> *stringsArray,
+ NSArray<__kindof NSMutableString *>
+ *kindofMutStringsArray,
+ NSArray<NSMutableString *> *mutStringsArray) {
+ // Adding/removing __kindof is okay.
+ kindofStringsArray = stringsArray;
+ stringsArray = kindofStringsArray;
+
+ // Other covariant and contravariant conversions still not permitted.
+ kindofStringsArray = mutStringsArray; // expected-warning{{incompatible pointer types}}
+ stringsArray = kindofMutStringsArray; // expected-warning{{incompatible pointer types}}
+ mutStringsArray = kindofStringsArray; // expected-warning{{incompatible pointer types}}
+
+ // Adding/removing nested __kindof is okay.
+ NSArray<NSArray<__kindof NSString *> *> *kindofStringsArrayArray;
+ NSArray<NSArray<NSString *> *> *stringsArrayArray;
+ kindofStringsArrayArray = stringsArrayArray;
+ stringsArrayArray = kindofStringsArrayArray;
+}
+
+// ---------------------------------------------------------------------------
+// __kindof + nullability
+// ---------------------------------------------------------------------------
+
+void testNullability() {
+ // The base type being a pointer type tickles the bug.
+ extern __kindof id <NSCopying> _Nonnull getSomeCopyable();
+ NSString *string = getSomeCopyable(); // no-warning
+
+ void processCopyable(__typeof(getSomeCopyable()) string);
+ processCopyable(0); // expected-warning{{null passed to a callee that requires a non-null argument}}
+}
diff --git a/test/SemaObjC/objc2-merge-gc-attribue-decl.m b/test/SemaObjC/objc2-merge-gc-attribue-decl.m
index 673a7417e384c..232f8dd794d6d 100644
--- a/test/SemaObjC/objc2-merge-gc-attribue-decl.m
+++ b/test/SemaObjC/objc2-merge-gc-attribue-decl.m
@@ -13,17 +13,17 @@ extern __strong id CFRunLoopGetMain();
extern __weak id WLoopGetMain(); // expected-note {{previous declaration is here}}
extern id WLoopGetMain(); // expected-error {{conflicting types for 'WLoopGetMain'}}
-extern id p3; // expected-note {{previous definition is here}}
-extern __weak id p3; // expected-error {{redefinition of 'p3' with a different type}}
+extern id p3; // expected-note {{previous declaration is here}}
+extern __weak id p3; // expected-error {{redeclaration of 'p3' with a different type}}
-extern void *p4; // expected-note {{previous definition is here}}
-extern void * __strong p4; // expected-error {{redefinition of 'p4' with a different type}}
+extern void *p4; // expected-note {{previous declaration is here}}
+extern void * __strong p4; // expected-error {{redeclaration of 'p4' with a different type}}
extern id p5;
extern __strong id p5;
-extern char* __strong p6; // expected-note {{previous definition is here}}
-extern char* p6; // expected-error {{redefinition of 'p6' with a different type}}
+extern char* __strong p6; // expected-note {{previous declaration is here}}
+extern char* p6; // expected-error {{redeclaration of 'p6' with a different type}}
-extern __strong char* p7; // expected-note {{previous definition is here}}
-extern char* p7; // expected-error {{redefinition of 'p7' with a different type}}
+extern __strong char* p7; // expected-note {{previous declaration is here}}
+extern char* p7; // expected-error {{redeclaration of 'p7' with a different type}}
diff --git a/test/SemaObjC/parameterized_classes.m b/test/SemaObjC/parameterized_classes.m
new file mode 100644
index 0000000000000..644fe3a329af3
--- /dev/null
+++ b/test/SemaObjC/parameterized_classes.m
@@ -0,0 +1,357 @@
+// RUN: %clang_cc1 -fblocks %s -verify
+
+#if !__has_feature(objc_generics)
+# error Compiler does not support Objective-C generics?
+#endif
+
+#if !__has_feature(objc_generics_variance)
+# error Compiler does not support co- and contr-variance?
+#endif
+
+@protocol NSObject // expected-note{{'NSObject' declared here}}
+@end
+
+@protocol NSCopying // expected-note{{'NSCopying' declared here}}
+@end
+
+__attribute__((objc_root_class))
+@interface NSObject <NSObject> // expected-note{{'NSObject' defined here}}
+@end
+
+@interface NSString : NSObject <NSCopying>
+@end
+
+// --------------------------------------------------------------------------
+// Parsing parameterized classes.
+// --------------------------------------------------------------------------
+
+// Parse type parameters with a bound
+@interface PC1<T, U : NSObject*> : NSObject // expected-note{{'PC1' declared here}}
+// expected-note@-1{{type parameter 'T' declared here}}
+// expected-note@-2{{type parameter 'U' declared here}}
+// expected-note@-3{{type parameter 'U' declared here}}
+@end
+
+// Parse a type parameter with a bound that terminates in '>>'.
+@interface PC2<T : id<NSObject>> : NSObject
+@end
+
+// Parse multiple type parameters.
+@interface PC3<T, U : id> : NSObject
+@end
+
+// Parse multiple type parameters--grammatically ambiguous with protocol refs.
+@interface PC4<T, U, V> : NSObject // expected-note 2{{'PC4' declared here}}
+@end
+
+// Parse a type parameter list without a superclass.
+@interface PC5<T : id>
+@end
+
+// Parse a type parameter with name conflicts.
+@interface PC6<T, U,
+ T> : NSObject // expected-error{{redeclaration of type parameter 'T'}}
+@end
+
+// Parse Objective-C protocol references.
+@interface PC7<T> // expected-error{{cannot find protocol declaration for 'T'}}
+@end
+
+// Parse both type parameters and protocol references.
+@interface PC8<T> : NSObject <NSObject>
+@end
+
+// Type parameters with improper bounds.
+@interface PC9<T : int, // expected-error{{type bound 'int' for type parameter 'T' is not an Objective-C pointer type}}
+ U : NSString> : NSObject // expected-error{{missing '*' in type bound 'NSString' for type parameter 'U'}}
+@end
+
+// --------------------------------------------------------------------------
+// Parsing parameterized forward declarations classes.
+// --------------------------------------------------------------------------
+
+// Okay: forward declaration without type parameters.
+@class PC10;
+
+// Okay: forward declarations with type parameters.
+@class PC10<T, U : NSObject *>, PC11<T : NSObject *, U : id>; // expected-note{{type parameter 'T' declared here}}
+
+// Okay: forward declaration without type parameters following ones
+// with type parameters.
+@class PC10, PC11;
+
+// Okay: definition of class with type parameters that was formerly
+// declared with the same type parameters.
+@interface PC10<T, U : NSObject *> : NSObject
+@end
+
+// Mismatched parameters in declaration of @interface following @class.
+@interface PC11<T, U> : NSObject // expected-error{{missing type bound 'NSObject *' for type parameter 'T' in @interface}}
+@end
+
+@interface PC12<T : NSObject *> : NSObject // expected-note{{type parameter 'T' declared here}}
+@end
+
+@class PC12;
+
+// Mismatched parameters in subsequent forward declarations.
+@class PC13<T : NSObject *>; // expected-note{{type parameter 'T' declared here}}
+@class PC13;
+@class PC13<U>; // expected-error{{missing type bound 'NSObject *' for type parameter 'U' in @class}}
+
+// Mismatch parameters in declaration of @class following @interface.
+@class PC12<T>; // expected-error{{missing type bound 'NSObject *' for type parameter 'T' in @class}}
+
+// Parameterized forward declaration a class that is not parameterized.
+@class NSObject<T>; // expected-error{{forward declaration of non-parameterized class 'NSObject' cannot have type parameters}}
+// expected-note@-1{{'NSObject' declared here}}
+
+// Parameterized forward declaration preceding the definition (that is
+// not parameterized).
+@class NSNumber<T : NSObject *>; // expected-note{{'NSNumber' declared here}}
+@interface NSNumber : NSObject // expected-error{{class 'NSNumber' previously declared with type parameters}}
+@end
+
+@class PC14;
+
+// Okay: definition of class with type parameters that was formerly
+// declared without type parameters.
+@interface PC14<T, U : NSObject *> : NSObject
+@end
+
+// --------------------------------------------------------------------------
+// Parsing parameterized categories and extensions.
+// --------------------------------------------------------------------------
+
+// Inferring type bounds
+@interface PC1<T, U> (Cat1) <NSObject>
+@end
+
+// Matching type bounds
+@interface PC1<T : id, U : NSObject *> (Cat2) <NSObject>
+@end
+
+// Inferring type bounds
+@interface PC1<T, U> () <NSObject>
+@end
+
+// Matching type bounds
+@interface PC1<T : id, U : NSObject *> () <NSObject>
+@end
+
+// Missing type parameters.
+@interface PC1<T> () // expected-error{{extension has too few type parameters (expected 2, have 1)}}
+@end
+
+// Extra type parameters.
+@interface PC1<T, U, V> (Cat3) // expected-error{{category has too many type parameters (expected 2, have 3)}}
+@end
+
+// Mismatched bounds.
+@interface PC1<T : NSObject *, // expected-error{{type bound 'NSObject *' for type parameter 'T' conflicts with implicit bound 'id'}}
+ X : id> () // expected-error{{type bound 'id' for type parameter 'X' conflicts with previous bound 'NSObject *'for type parameter 'U'}}
+@end
+
+// Parameterized category/extension of non-parameterized class.
+@interface NSObject<T> (Cat1) // expected-error{{category of non-parameterized class 'NSObject' cannot have type parameters}}
+@end
+
+@interface NSObject<T> () // expected-error{{extension of non-parameterized class 'NSObject' cannot have type parameters}}
+@end
+
+// --------------------------------------------------------------------------
+// @implementations cannot have type parameters
+// --------------------------------------------------------------------------
+@implementation PC1<T : id> // expected-error{{@implementation cannot have type parameters}}
+@end
+
+@implementation PC2<T> // expected-error{{@implementation declaration cannot be protocol qualified}}
+@end
+
+@implementation PC1<T> (Cat1) // expected-error{{@implementation cannot have type parameters}}
+@end
+
+@implementation PC1<T : id> (Cat2) // expected-error{{@implementation cannot have type parameters}}
+@end
+
+// --------------------------------------------------------------------------
+// Interfaces involving type parameters
+// --------------------------------------------------------------------------
+@interface PC20<T : id, U : NSObject *, V : NSString *> : NSObject {
+ T object;
+}
+
+- (U)method:(V)param;
+@end
+
+@interface PC20<T, U, V> (Cat1)
+- (U)catMethod:(V)param;
+@end
+
+@interface PC20<X, Y, Z>()
+- (X)extMethod:(Y)param;
+@end
+
+// --------------------------------------------------------------------------
+// Parsing type arguments.
+// --------------------------------------------------------------------------
+
+typedef NSString * ObjCStringRef; // expected-note{{'ObjCStringRef' declared here}}
+
+// Type arguments with a mix of identifiers and type-names.
+typedef PC4<id, NSObject *, NSString *> typeArgs1;
+
+// Type arguments with only identifiers.
+typedef PC4<id, id, id> typeArgs2;
+
+// Type arguments with only identifiers; one is ambiguous (resolved as
+// types).
+typedef PC4<NSObject, id, id> typeArgs3; // expected-error{{type argument 'NSObject' must be a pointer (requires a '*')}}
+
+// Type arguments with only identifiers; one is ambiguous (resolved as
+// protocol qualifiers).
+typedef PC4<NSObject, NSCopying> protocolQuals1;
+
+// Type arguments and protocol qualifiers.
+typedef PC4<id, NSObject *, id><NSObject, NSCopying> typeArgsAndProtocolQuals1;
+
+// Type arguments and protocol qualifiers in the wrong order.
+typedef PC4<NSObject, NSCopying><id, NSObject *, id> typeArgsAndProtocolQuals2; // expected-error{{protocol qualifiers must precede type arguments}}
+
+// Type arguments and protocol qualifiers (identifiers).
+typedef PC4<id, NSObject, id><NSObject, NSCopying> typeArgsAndProtocolQuals3; // expected-error{{type argument 'NSObject' must be a pointer (requires a '*')}}
+
+// Typo correction: protocol bias.
+typedef PC4<NSCopying, NSObjec> protocolQuals2; // expected-error{{cannot find protocol declaration for 'NSObjec'; did you mean 'NSObject'?}}
+
+// Typo correction: type bias.
+typedef PC4<id, id, NSObjec> typeArgs4; // expected-error{{unknown class name 'NSObjec'; did you mean 'NSObject'?}}
+// expected-error@-1{{type argument 'NSObject' must be a pointer (requires a '*')}}
+
+// Typo correction: bias set by correction itself to a protocol.
+typedef PC4<NSObject, NSObject, NSCopyin> protocolQuals3; // expected-error{{cannot find protocol declaration for 'NSCopyin'; did you mean 'NSCopying'?}}
+
+// Typo correction: bias set by correction itself to a type.
+typedef PC4<NSObject, NSObject, ObjCStringref> typeArgs5; // expected-error{{unknown type name 'ObjCStringref'; did you mean 'ObjCStringRef'?}}
+// expected-error@-1{{type argument 'NSObject' must be a pointer (requires a '*')}}
+// expected-error@-2{{type argument 'NSObject' must be a pointer (requires a '*')}}
+
+// Type/protocol conflict.
+typedef PC4<NSCopying, ObjCStringRef> typeArgsProtocolQualsConflict1; // expected-error{{angle brackets contain both a type ('ObjCStringRef') and a protocol ('NSCopying')}}
+
+// Handling the '>>' in type argument lists.
+typedef PC4<id<NSCopying>, NSObject *, id<NSObject>> typeArgs6;
+
+// --------------------------------------------------------------------------
+// Checking type arguments.
+// --------------------------------------------------------------------------
+
+@interface PC15<T : id, U : NSObject *, V : id<NSCopying>> : NSObject
+// expected-note@-1{{type parameter 'V' declared here}}
+// expected-note@-2{{type parameter 'V' declared here}}
+// expected-note@-3{{type parameter 'U' declared here}}
+@end
+
+typedef PC4<NSString *> tooFewTypeArgs1; // expected-error{{too few type arguments for class 'PC4' (have 1, expected 3)}}
+
+typedef PC4<NSString *, NSString *, NSString *, NSString *> tooManyTypeArgs1; // expected-error{{too many type arguments for class 'PC4' (have 4, expected 3)}}
+
+typedef PC15<int (^)(int, int), // block pointers as 'id'
+ NSString *, // subclass
+ NSString *> typeArgs7; // class that conforms to the protocol
+
+typedef PC15<NSObject *, NSObject *, id<NSCopying>> typeArgs8;
+
+typedef PC15<NSObject *, NSObject *,
+ NSObject *> typeArgs8b; // expected-error{{type argument 'NSObject *' does not satisfy the bound ('id<NSCopying>') of type parameter 'V'}}
+
+typedef PC15<id,
+ id, // expected-error{{type argument 'id' does not satisfy the bound ('NSObject *') of type parameter 'U'}}
+ id> typeArgs9;
+
+typedef PC15<id, NSObject *,
+ id> typeArgs10; // expected-error{{type argument 'id' does not satisfy the bound ('id<NSCopying>') of type parameter 'V'}}
+
+typedef PC15<id,
+ int (^)(int, int), // okay
+ id<NSCopying, NSObject>> typeArgs11;
+
+typedef PC15<id, NSString *, int (^)(int, int)> typeArgs12; // okay
+
+typedef NSObject<id, id> typeArgs13; // expected-error{{type arguments cannot be applied to non-parameterized class 'NSObject'}}
+
+typedef id<id, id> typeArgs14; // expected-error{{type arguments cannot be applied to non-class type 'id'}}
+
+typedef PC1<NSObject *, NSString *> typeArgs15;
+
+typedef PC1<NSObject *, NSString *><NSCopying> typeArgsAndProtocolQuals4;
+
+typedef typeArgs15<NSCopying> typeArgsAndProtocolQuals5;
+
+typedef typeArgs15<NSObject *, NSString *> typeArgs16; // expected-error{{type arguments cannot be applied to already-specialized class type 'typeArgs15' (aka 'PC1<NSObject *,NSString *>')}}
+
+typedef typeArgs15<NSObject> typeArgsAndProtocolQuals6;
+
+void testSpecializedTypePrinting() {
+ int *ip;
+
+ ip = (typeArgs15*)0; // expected-warning{{'typeArgs15 *' (aka 'PC1<NSObject *,NSString *> *')}}
+ ip = (typeArgsAndProtocolQuals4*)0; // expected-warning{{'typeArgsAndProtocolQuals4 *' (aka 'PC1<NSObject *,NSString *><NSCopying> *')}}
+ ip = (typeArgsAndProtocolQuals5*)0; // expected-warning{{'typeArgsAndProtocolQuals5 *' (aka 'typeArgs15<NSCopying> *')}}
+ ip = (typeArgsAndProtocolQuals6)0; // expected-error{{used type 'typeArgsAndProtocolQuals6' (aka 'typeArgs15<NSObject>')}}
+ ip = (typeArgsAndProtocolQuals6*)0;// expected-warning{{'typeArgsAndProtocolQuals6 *' (aka 'typeArgs15<NSObject> *')}}
+}
+
+// --------------------------------------------------------------------------
+// Specialized superclasses
+// --------------------------------------------------------------------------
+@interface PC21<T : NSObject *> : PC1<T, T>
+@end
+
+@interface PC22<T : NSObject *> : PC1<T> // expected-error{{too few type arguments for class 'PC1' (have 1, expected 2)}}
+@end
+
+@interface PC23<T : NSObject *> : PC1<T, U> // expected-error{{unknown type name 'U'}}
+@end
+
+@interface PC24<T> : PC1<T, T> // expected-error{{type argument 'T' (aka 'id') does not satisfy the bound ('NSObject *') of type parameter 'U'}}
+@end
+
+@interface NSFoo : PC1<NSObject *, NSObject *> // okay
+@end
+
+// --------------------------------------------------------------------------
+// Co- and contra-variance.
+// --------------------------------------------------------------------------
+@class Variance1<T, U>;
+
+@class Variance1<__covariant T, __contravariant U>;
+
+@interface Variance1<__covariant T, __contravariant U> : NSObject // expected-note 2{{declared here}}
+@end
+
+@interface Variance1<T, U> () // okay, inferred
+@end
+
+@interface Variance1<T, U> (Cat1) // okay, inferred
+@end
+
+@class Variance1<T, U>; // okay, inferred
+
+@interface Variance1<__covariant T, __contravariant U> () // okay, matches
+@end
+
+@interface Variance1<__covariant T, __contravariant U> (Cat2) // okay, matches
+@end
+
+@class Variance1<__covariant T, __contravariant U>; // okay, matches
+
+@interface Variance1<__contravariant X, // expected-error{{contravariant type parameter 'X' conflicts with previous covariant type parameter 'T'}}
+ __covariant Y> () // expected-error{{covariant type parameter 'Y' conflicts with previous contravariant type parameter 'U'}}
+@end
+
+@class Variance2<__covariant T, __contravariant U>; // expected-note 2{{declared here}}
+
+@interface Variance2<__contravariant T, // expected-error{{contravariant type parameter 'T' conflicts with previous covariant type parameter 'T'}}
+ U> : NSObject // expected-error{{invariant type parameter 'U' conflicts with previous contravariant type parameter 'U'}}
+@end
diff --git a/test/SemaObjC/parameterized_classes_collection_literal.m b/test/SemaObjC/parameterized_classes_collection_literal.m
new file mode 100644
index 0000000000000..472746e09db9e
--- /dev/null
+++ b/test/SemaObjC/parameterized_classes_collection_literal.m
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -x objective-c++ -fsyntax-only -verify %s
+
+#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
+typedef unsigned long NSUInteger;
+#else
+typedef unsigned int NSUInteger;
+#endif
+
+@protocol NSObject
+@end
+
+@protocol NSCopying
+@end
+
+__attribute__((objc_root_class))
+@interface NSObject <NSObject>
+@end
+
+@interface NSString : NSObject <NSCopying>
+@end
+
+@interface NSNumber : NSObject <NSCopying>
++ (NSNumber *)numberWithInt:(int)value;
+@end
+
+@interface NSArray<T> : NSObject <NSCopying>
++ (instancetype)arrayWithObjects:(const T [])objects count:(NSUInteger)cnt;
+@end
+
+@interface NSDictionary<K, V> : NSObject <NSCopying>
++ (instancetype)dictionaryWithObjects:(const V [])objects forKeys:(const K [])keys count:(NSUInteger)cnt;
+@end
+
+void testArrayLiteral(void) {
+ NSArray<NSString *> *array1 = @[@"hello",
+ @1, // expected-warning{{of type 'NSNumber *' is not compatible with array element type 'NSString *'}}
+ @"world",
+ @[@1, @2]]; // expected-warning{{of type 'NSArray *' is not compatible with array element type 'NSString *'}}
+
+ NSArray<NSArray<NSString *> *> *array2 = @[@[@"hello", @"world"],
+ @"blah", // expected-warning{{object of type 'NSString *' is not compatible with array element type 'NSArray<NSString *> *'}}
+ @[@1]]; // expected-warning{{object of type 'NSNumber *' is not compatible with array element type 'NSString *'}}
+}
+
+void testDictionaryLiteral(void) {
+ NSDictionary<NSString *, NSNumber *> *dict1 = @{
+ @"hello" : @17,
+ @18 : @18, // expected-warning{{object of type 'NSNumber *' is not compatible with dictionary key type 'NSString *'}}
+ @"world" : @"blah" // expected-warning{{object of type 'NSString *' is not compatible with dictionary value type 'NSNumber *'}}
+ };
+}
diff --git a/test/SemaObjC/parameterized_classes_subst.m b/test/SemaObjC/parameterized_classes_subst.m
new file mode 100644
index 0000000000000..f90ee9093592c
--- /dev/null
+++ b/test/SemaObjC/parameterized_classes_subst.m
@@ -0,0 +1,428 @@
+// RUN: %clang_cc1 -fblocks -fsyntax-only -Wnullable-to-nonnull-conversion %s -verify
+//
+// Test the substitution of type arguments for type parameters when
+// using parameterized classes in Objective-C.
+
+@protocol NSObject
+@end
+
+__attribute__((objc_root_class))
+@interface NSObject <NSObject>
++ (instancetype)alloc;
+- (instancetype)init;
+@end
+
+@protocol NSCopying
+@end
+
+@interface NSString : NSObject <NSCopying>
+@end
+
+@interface NSMutableString : NSString
+@end
+
+@interface NSNumber : NSObject <NSCopying>
+@end
+
+@interface NSArray<T> : NSObject <NSCopying> {
+@public
+ T *data; // don't try this at home
+}
+- (T)objectAtIndexedSubscript:(int)index;
++ (NSArray<T> *)array;
++ (void)setArray:(NSArray <T> *)array;
+@property (copy,nonatomic) T lastObject;
+@end
+
+@interface NSMutableArray<T> : NSArray<T>
+-(instancetype)initWithArray:(NSArray<T> *)array; // expected-note{{passing argument}}
+- (void)setObject:(T)object atIndexedSubscript:(int)index; // expected-note 2{{passing argument to parameter 'object' here}}
+@end
+
+@interface NSStringArray : NSArray<NSString *>
+@end
+
+@interface NSSet<T> : NSObject <NSCopying>
+- (T)firstObject;
+@property (nonatomic, copy) NSArray<T> *allObjects;
+@end
+
+// Parameterized inheritance (simple case)
+@interface NSMutableSet<U : id<NSCopying>> : NSSet<U>
+- (void)addObject:(U)object; // expected-note 7{{passing argument to parameter 'object' here}}
+@end
+
+@interface Widget : NSObject <NSCopying>
+@end
+
+// Non-parameterized class inheriting from a specialization of a
+// parameterized class.
+@interface WidgetSet : NSMutableSet<Widget *>
+@end
+
+// Parameterized inheritance with a more interesting transformation in
+// the specialization.
+@interface MutableSetOfArrays<T> : NSMutableSet<NSArray<T>*>
+@end
+
+// Inheriting from an unspecialized form of a parameterized type.
+@interface UntypedMutableSet : NSMutableSet
+@end
+
+@interface Window : NSObject
+@end
+
+@interface NSDictionary<K, V> : NSObject <NSCopying>
+- (V)objectForKeyedSubscript:(K)key; // expected-note 2{{parameter 'key'}}
+@end
+
+@interface NSMutableDictionary<K : id<NSCopying>, V> : NSDictionary<K, V>
+- (void)setObject:(V)object forKeyedSubscript:(K)key;
+// expected-note@-1 {{parameter 'object' here}}
+// expected-note@-2 {{parameter 'object' here}}
+// expected-note@-3 {{parameter 'key' here}}
+// expected-note@-4 {{parameter 'key' here}}
+
+@property (strong) K someRandomKey;
+@end
+
+@interface WindowArray : NSArray<Window *>
+@end
+
+@interface NSSet<T> (Searching)
+- (T)findObject:(T)object;
+@end
+
+@interface NSView : NSObject
+@end
+
+@interface NSControl : NSView
+- (void)toggle;
+@end
+
+@interface NSViewController<ViewType : NSView *> : NSObject
+@property (nonatomic,retain) ViewType view;
+@end
+
+// --------------------------------------------------------------------------
+// Nullability
+// --------------------------------------------------------------------------
+typedef NSControl * _Nonnull Nonnull_NSControl;
+
+@interface NSNullableTest<ViewType : NSView *> : NSObject
+- (ViewType)view;
+- (nullable ViewType)maybeView;
+@end
+
+@interface NSNullableTest2<ViewType : NSView * _Nullable> : NSObject // expected-error{{type parameter 'ViewType' bound 'NSView * _Nullable' cannot explicitly specify nullability}}
+@end
+
+void test_nullability(void) {
+ NSControl * _Nonnull nonnull_NSControl;
+
+ // Nullability introduced by substitution.
+ NSNullableTest<NSControl *> *unspecifiedControl;
+ nonnull_NSControl = [unspecifiedControl view];
+ nonnull_NSControl = [unspecifiedControl maybeView]; // expected-warning{{from nullable pointer 'NSControl * _Nullable' to non-nullable pointer type 'NSControl * _Nonnull'}}
+
+ // Nullability overridden by substitution.
+ NSNullableTest<Nonnull_NSControl> *nonnullControl;
+ nonnull_NSControl = [nonnullControl view];
+ nonnull_NSControl = [nonnullControl maybeView]; // expected-warning{{from nullable pointer 'Nonnull_NSControl _Nullable' (aka 'NSControl *') to non-nullable pointer type 'NSControl * _Nonnull'}}
+
+ // Nullability cannot be specified directly on a type argument.
+ NSNullableTest<NSControl * _Nonnull> *nonnullControl2; // expected-error{{type argument 'NSControl *' cannot explicitly specify nullability}}
+}
+
+// --------------------------------------------------------------------------
+// Message sends.
+// --------------------------------------------------------------------------
+void test_message_send_result(
+ NSSet<NSString *> *stringSet,
+ NSMutableSet<NSString *> *mutStringSet,
+ WidgetSet *widgetSet,
+ UntypedMutableSet *untypedMutSet,
+ MutableSetOfArrays<NSString *> *mutStringArraySet,
+ NSSet *set,
+ NSMutableSet *mutSet,
+ MutableSetOfArrays *mutArraySet,
+ NSArray<NSString *> *stringArray,
+ NSArray<__kindof NSString *> *kindofStringArray,
+ void (^block)(void)) {
+ int *ip;
+ ip = [stringSet firstObject]; // expected-warning{{from 'NSString *'}}
+ ip = [mutStringSet firstObject]; // expected-warning{{from 'NSString *'}}
+ ip = [widgetSet firstObject]; // expected-warning{{from 'Widget *'}}
+ ip = [untypedMutSet firstObject]; // expected-warning{{from 'id'}}
+ ip = [mutStringArraySet firstObject]; // expected-warning{{from 'NSArray<NSString *> *'}}
+ ip = [set firstObject]; // expected-warning{{from 'id'}}
+ ip = [mutSet firstObject]; // expected-warning{{from 'id'}}
+ ip = [mutArraySet firstObject]; // expected-warning{{from 'id'}}
+ ip = [block firstObject]; // expected-warning{{from 'id'}}
+
+ ip = [stringSet findObject:@"blah"]; // expected-warning{{from 'NSString *'}}
+
+ // Class messages.
+ ip = [NSSet<NSString *> alloc]; // expected-warning{{from 'NSSet<NSString *> *'}}
+ ip = [NSSet alloc]; // expected-warning{{from 'NSSet *'}}
+ ip = [MutableSetOfArrays<NSString *> alloc]; // expected-warning{{from 'MutableSetOfArrays<NSString *> *'}}
+ ip = [MutableSetOfArrays alloc]; // expected-warning{{from 'MutableSetOfArrays *'}}
+ ip = [NSArray<NSString *> array]; // expected-warning{{from 'NSArray<NSString *> *'}}
+ ip = [NSArray<NSString *><NSCopying> array]; // expected-warning{{from 'NSArray<NSString *> *'}}
+
+ ip = [[NSMutableArray<NSString *> alloc] init]; // expected-warning{{from 'NSMutableArray<NSString *> *'}}
+
+ [[NSMutableArray alloc] initWithArray: stringArray]; // okay
+ [[NSMutableArray<NSString *> alloc] initWithArray: stringArray]; // okay
+ [[NSMutableArray<NSNumber *> alloc] initWithArray: stringArray]; // expected-warning{{sending 'NSArray<NSString *> *' to parameter of type 'NSArray<NSNumber *> *'}}
+
+ ip = [[[NSViewController alloc] init] view]; // expected-warning{{from '__kindof NSView *'}}
+ [[[[NSViewController alloc] init] view] toggle];
+
+ NSMutableString *mutStr = kindofStringArray[0];
+ NSNumber *number = kindofStringArray[0]; // expected-warning{{of type '__kindof NSString *'}}
+}
+
+void test_message_send_param(
+ NSMutableSet<NSString *> *mutStringSet,
+ WidgetSet *widgetSet,
+ UntypedMutableSet *untypedMutSet,
+ MutableSetOfArrays<NSString *> *mutStringArraySet,
+ NSMutableSet *mutSet,
+ MutableSetOfArrays *mutArraySet,
+ void (^block)(void)) {
+ Window *window;
+
+ [mutStringSet addObject: window]; // expected-warning{{parameter of type 'NSString *'}}
+ [widgetSet addObject: window]; // expected-warning{{parameter of type 'Widget *'}}
+ [untypedMutSet addObject: window]; // expected-warning{{parameter of incompatible type 'id<NSCopying>'}}
+ [mutStringArraySet addObject: window]; // expected-warning{{parameter of type 'NSArray<NSString *> *'}}
+ [mutSet addObject: window]; // expected-warning{{parameter of incompatible type 'id<NSCopying>'}}
+ [mutArraySet addObject: window]; // expected-warning{{parameter of incompatible type 'id<NSCopying>'}}
+ [block addObject: window]; // expected-warning{{parameter of incompatible type 'id<NSCopying>'}}
+}
+
+// --------------------------------------------------------------------------
+// Property accesses.
+// --------------------------------------------------------------------------
+void test_property_read(
+ NSSet<NSString *> *stringSet,
+ NSMutableSet<NSString *> *mutStringSet,
+ WidgetSet *widgetSet,
+ UntypedMutableSet *untypedMutSet,
+ MutableSetOfArrays<NSString *> *mutStringArraySet,
+ NSSet *set,
+ NSMutableSet *mutSet,
+ MutableSetOfArrays *mutArraySet,
+ NSMutableDictionary *mutDict) {
+ int *ip;
+ ip = stringSet.allObjects; // expected-warning{{from 'NSArray<NSString *> *'}}
+ ip = mutStringSet.allObjects; // expected-warning{{from 'NSArray<NSString *> *'}}
+ ip = widgetSet.allObjects; // expected-warning{{from 'NSArray<Widget *> *'}}
+ ip = untypedMutSet.allObjects; // expected-warning{{from 'NSArray *'}}
+ ip = mutStringArraySet.allObjects; // expected-warning{{from 'NSArray<NSArray<NSString *> *> *'}}
+ ip = set.allObjects; // expected-warning{{from 'NSArray *'}}
+ ip = mutSet.allObjects; // expected-warning{{from 'NSArray *'}}
+ ip = mutArraySet.allObjects; // expected-warning{{from 'NSArray *'}}
+
+ ip = mutDict.someRandomKey; // expected-warning{{from '__kindof id<NSCopying>'}}
+
+ ip = [[NSViewController alloc] init].view; // expected-warning{{from '__kindof NSView *'}}
+}
+
+void test_property_write(
+ NSMutableSet<NSString *> *mutStringSet,
+ WidgetSet *widgetSet,
+ UntypedMutableSet *untypedMutSet,
+ MutableSetOfArrays<NSString *> *mutStringArraySet,
+ NSMutableSet *mutSet,
+ MutableSetOfArrays *mutArraySet,
+ NSMutableDictionary *mutDict) {
+ int *ip;
+
+ mutStringSet.allObjects = ip; // expected-warning{{to 'NSArray<NSString *> *'}}
+ widgetSet.allObjects = ip; // expected-warning{{to 'NSArray<Widget *> *'}}
+ untypedMutSet.allObjects = ip; // expected-warning{{to 'NSArray *'}}
+ mutStringArraySet.allObjects = ip; // expected-warning{{to 'NSArray<NSArray<NSString *> *> *'}}
+ mutSet.allObjects = ip; // expected-warning{{to 'NSArray *'}}
+ mutArraySet.allObjects = ip; // expected-warning{{to 'NSArray *'}}
+
+ mutDict.someRandomKey = ip; // expected-warning{{to 'id<NSCopying>'}}
+}
+
+// --------------------------------------------------------------------------
+// Subscripting
+// --------------------------------------------------------------------------
+void test_subscripting(
+ NSArray<NSString *> *stringArray,
+ NSMutableArray<NSString *> *mutStringArray,
+ NSArray *array,
+ NSMutableArray *mutArray,
+ NSDictionary<NSString *, Widget *> *stringWidgetDict,
+ NSMutableDictionary<NSString *, Widget *> *mutStringWidgetDict,
+ NSDictionary *dict,
+ NSMutableDictionary *mutDict) {
+ int *ip;
+ NSString *string;
+ Widget *widget;
+ Window *window;
+
+ ip = stringArray[0]; // expected-warning{{from 'NSString *'}}
+
+ ip = mutStringArray[0]; // expected-warning{{from 'NSString *'}}
+ mutStringArray[0] = ip; // expected-warning{{parameter of type 'NSString *'}}
+
+ ip = array[0]; // expected-warning{{from 'id'}}
+
+ ip = mutArray[0]; // expected-warning{{from 'id'}}
+ mutArray[0] = ip; // expected-warning{{parameter of type 'id'}}
+
+ ip = stringWidgetDict[string]; // expected-warning{{from 'Widget *'}}
+ widget = stringWidgetDict[widget]; // expected-warning{{to parameter of type 'NSString *'}}
+
+ ip = mutStringWidgetDict[string]; // expected-warning{{from 'Widget *'}}
+ widget = mutStringWidgetDict[widget]; // expected-warning{{to parameter of type 'NSString *'}}
+ mutStringWidgetDict[string] = ip; // expected-warning{{to parameter of type 'Widget *'}}
+ mutStringWidgetDict[widget] = widget; // expected-warning{{to parameter of type 'NSString *'}}
+
+ ip = dict[string]; // expected-warning{{from 'id'}}
+
+ ip = mutDict[string]; // expected-warning{{from 'id'}}
+ mutDict[string] = ip; // expected-warning{{to parameter of type 'id'}}
+
+ widget = mutDict[window];
+ mutDict[window] = widget; // expected-warning{{parameter of incompatible type 'id<NSCopying>'}}
+}
+
+// --------------------------------------------------------------------------
+// Instance variable access.
+// --------------------------------------------------------------------------
+void test_instance_variable(NSArray<NSString *> *stringArray,
+ NSArray *array) {
+ int *ip;
+
+ ip = stringArray->data; // expected-warning{{from 'NSString **'}}
+ ip = array->data; // expected-warning{{from 'id *'}}
+}
+
+@implementation WindowArray
+- (void)testInstanceVariable {
+ int *ip;
+
+ ip = data; // expected-warning{{from 'Window **'}}
+}
+@end
+
+// --------------------------------------------------------------------------
+// Implicit conversions.
+// --------------------------------------------------------------------------
+void test_implicit_conversions(NSArray<NSString *> *stringArray,
+ NSArray<NSNumber *> *numberArray,
+ NSMutableArray<NSString *> *mutStringArray,
+ NSArray *array,
+ NSMutableArray *mutArray) {
+ // Specialized -> unspecialized (same level)
+ array = stringArray;
+
+ // Unspecialized -> specialized (same level)
+ stringArray = array;
+
+ // Specialized -> specialized failure (same level).
+ stringArray = numberArray; // expected-warning{{incompatible pointer types assigning to 'NSArray<NSString *> *' from 'NSArray<NSNumber *> *'}}
+
+ // Specialized -> specialized (different levels).
+ stringArray = mutStringArray;
+
+ // Specialized -> specialized failure (different levels).
+ numberArray = mutStringArray; // expected-warning{{incompatible pointer types assigning to 'NSArray<NSNumber *> *' from 'NSMutableArray<NSString *> *'}}
+
+ // Unspecialized -> specialized (different levels).
+ stringArray = mutArray;
+
+ // Specialized -> unspecialized (different levels).
+ array = mutStringArray;
+}
+
+@interface NSCovariant1<__covariant T>
+@end
+
+@interface NSContravariant1<__contravariant T>
+@end
+
+void test_variance(NSCovariant1<NSString *> *covariant1,
+ NSCovariant1<NSMutableString *> *covariant2,
+ NSCovariant1<NSString *(^)(void)> *covariant3,
+ NSCovariant1<NSMutableString *(^)(void)> *covariant4,
+ NSCovariant1<id> *covariant5,
+ NSCovariant1<id<NSCopying>> *covariant6,
+ NSContravariant1<NSString *> *contravariant1,
+ NSContravariant1<NSMutableString *> *contravariant2) {
+ covariant1 = covariant2; // okay
+ covariant2 = covariant1; // expected-warning{{incompatible pointer types assigning to 'NSCovariant1<NSMutableString *> *' from 'NSCovariant1<NSString *> *'}}
+
+ covariant3 = covariant4; // okay
+ covariant4 = covariant3; // expected-warning{{incompatible pointer types assigning to 'NSCovariant1<NSMutableString *(^)(void)> *' from 'NSCovariant1<NSString *(^)(void)> *'}}
+
+ covariant5 = covariant1; // okay
+ covariant1 = covariant5; // okay: id is promiscuous
+
+ covariant5 = covariant3; // okay
+ covariant3 = covariant5; // okay
+
+ contravariant1 = contravariant2; // expected-warning{{incompatible pointer types assigning to 'NSContravariant1<NSString *> *' from 'NSContravariant1<NSMutableString *> *'}}
+ contravariant2 = contravariant1; // okay
+}
+
+// --------------------------------------------------------------------------
+// Ternary operator
+// --------------------------------------------------------------------------
+void test_ternary_operator(NSArray<NSString *> *stringArray,
+ NSArray<NSNumber *> *numberArray,
+ NSMutableArray<NSString *> *mutStringArray,
+ NSStringArray *stringArray2,
+ NSArray *array,
+ NSMutableArray *mutArray,
+ int cond) {
+ int *ip;
+ id object;
+
+ ip = cond ? stringArray : mutStringArray; // expected-warning{{from 'NSArray<NSString *> *'}}
+ ip = cond ? mutStringArray : stringArray; // expected-warning{{from 'NSArray<NSString *> *'}}
+
+ ip = cond ? stringArray2 : mutStringArray; // expected-warning{{from 'NSArray<NSString *> *'}}
+ ip = cond ? mutStringArray : stringArray2; // expected-warning{{from 'NSArray<NSString *> *'}}
+
+ ip = cond ? stringArray : mutArray; // expected-warning{{from 'NSArray *'}}
+
+ ip = cond ? stringArray2 : mutArray; // expected-warning{{from 'NSArray *'}}
+
+ ip = cond ? mutArray : stringArray; // expected-warning{{from 'NSArray *'}}
+
+ ip = cond ? mutArray : stringArray2; // expected-warning{{from 'NSArray *'}}
+
+ object = cond ? stringArray : numberArray; // expected-warning{{incompatible operand types ('NSArray<NSString *> *' and 'NSArray<NSNumber *> *')}}
+}
+
+// --------------------------------------------------------------------------
+// super
+// --------------------------------------------------------------------------
+@implementation NSStringArray
+- (void)useSuperMethod {
+ int *ip;
+ ip = super.lastObject; // expected-warning{{from 'NSString *'}}
+ super.lastObject = ip; // expected-warning{{to 'NSString *'}}
+ ip = [super objectAtIndexedSubscript:0]; // expected-warning{{from 'NSString *'}}
+}
+
++ (void)useSuperMethod {
+ int *ip;
+ ip = super.array; // expected-warning{{from 'NSArray<NSString *> *'}}
+ super.array = ip; // expected-warning{{to 'NSArray<NSString *> *'}}
+ ip = [super array]; // expected-warning{{from 'NSArray<NSString *> *'}}
+}
+@end
+
+// --------------------------------------------------------------------------
+// warning about likely protocol/class name typos.
+// --------------------------------------------------------------------------
+typedef NSArray<NSObject> ArrayOfNSObjectWarning; // expected-warning{{parameterized class 'NSArray' already conforms to the protocols listed; did you forget a '*'?}}
diff --git a/test/SemaObjC/protocol-archane.m b/test/SemaObjC/protocol-archane.m
index 788edf276d7bf..f2f6025a5ad6f 100644
--- a/test/SemaObjC/protocol-archane.m
+++ b/test/SemaObjC/protocol-archane.m
@@ -40,3 +40,7 @@ Class <SomeProtocol> UnfortunateGCCExtension;
- (void)crashWith:(<Broken>)a { // expected-warning {{protocol has no object type specified; defaults to qualified 'id'}}
}
@end
+
+typedef <SomeProtocol> id TwoTypeSpecs; // expected-warning{{no object type specified}}
+// expected-error@-1{{typedef redefinition with different types ('id<SomeProtocol>' vs 'id')}}
+// expected-error@-2{{expected ';' after top level declarator}}
diff --git a/test/SemaObjC/protocol-warn.m b/test/SemaObjC/protocol-warn.m
index 2d042380582e1..04df5031ab474 100644
--- a/test/SemaObjC/protocol-warn.m
+++ b/test/SemaObjC/protocol-warn.m
@@ -51,5 +51,5 @@ UIWebPDFView *getView()
{
UIWebBrowserView *browserView;
UIWebPDFView *pdfView;
- return pdfView ? pdfView : browserView; // expected-warning {{incompatible pointer types returning 'UIView<NSObject> *' from a function with result type 'UIWebPDFView *'}}
+ return pdfView ? pdfView : browserView; // expected-warning {{incompatible pointer types returning 'UIView *' from a function with result type 'UIWebPDFView *'}}
}