summaryrefslogtreecommitdiffstats
path: root/clang/test/SemaObjC/parameterized_classes.m
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2015-07-07 03:57:35 +0000
committerDouglas Gregor <dgregor@apple.com>2015-07-07 03:57:35 +0000
commite9d95f1ecc98ced831cace8b4b78cb7cc380f4aa (patch)
tree73962adb18c3f8c191701021f69a14b4121676e6 /clang/test/SemaObjC/parameterized_classes.m
parent85f3f9513dbc88b9898d022a1a55a03d55612721 (diff)
downloadbcm5719-llvm-e9d95f1ecc98ced831cace8b4b78cb7cc380f4aa.tar.gz
bcm5719-llvm-e9d95f1ecc98ced831cace8b4b78cb7cc380f4aa.zip
Handle Objective-C type arguments.
Objective-C type arguments can be provided in angle brackets following an Objective-C interface type. Syntactically, this is the same position as one would provide protocol qualifiers (e.g., id<NSCopying>), so parse both together and let Sema sort out the ambiguous cases. This applies both when parsing types and when parsing the superclass of an Objective-C class, which can now be a specialized type (e.g., NSMutableArray<T> inherits from NSArray<T>). Check Objective-C type arguments against the type parameters of the corresponding class. Verify the length of the type argument list and that each type argument satisfies the corresponding bound. Specializations of parameterized Objective-C classes are represented in the type system as distinct types. Both specialized types (e.g., NSArray<NSString *> *) and unspecialized types (NSArray *) are represented, separately. llvm-svn: 241542
Diffstat (limited to 'clang/test/SemaObjC/parameterized_classes.m')
-rw-r--r--clang/test/SemaObjC/parameterized_classes.m147
1 files changed, 140 insertions, 7 deletions
diff --git a/clang/test/SemaObjC/parameterized_classes.m b/clang/test/SemaObjC/parameterized_classes.m
index e6eae442142..bf81ad9a078 100644
--- a/clang/test/SemaObjC/parameterized_classes.m
+++ b/clang/test/SemaObjC/parameterized_classes.m
@@ -1,13 +1,16 @@
-// RUN: %clang_cc1 %s -verify
+// RUN: %clang_cc1 -fblocks %s -verify
-@protocol NSObject
+@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
+@interface NSString : NSObject <NSCopying>
@end
// --------------------------------------------------------------------------
@@ -15,13 +18,14 @@ __attribute__((objc_root_class))
// --------------------------------------------------------------------------
// Parse type parameters with a bound
-@interface PC1<T, U : NSObject*> : NSObject
+@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 // expected-error{{a space is required between consecutive right angle brackets (use '> >')}}
+@interface PC2<T : id<NSObject>> : NSObject
@end
// Parse multiple type parameters.
@@ -29,11 +33,11 @@ __attribute__((objc_root_class))
@end
// Parse multiple type parameters--grammatically ambiguous with protocol refs.
-@interface PC4<T, U, V> : NSObject
+@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> // expected-error{{parameterized Objective-C class 'PC5' must have a superclass}}
+@interface PC5<T : id>
@end
// Parse a type parameter with name conflicts.
@@ -92,6 +96,7 @@ __attribute__((objc_root_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).
@@ -190,3 +195,131 @@ void test_PC20_unspecialized(PC20 *pc20) {
ip = [pc20 extMethod: 0]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'X' (aka 'id')}}
[pc20 extMethod: ip]; // expected-warning{{incompatible pointer types sending 'int *' to parameter of type 'Y' (aka 'NSObject *')}}
}
+
+// --------------------------------------------------------------------------
+// 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 satisy the bound ('id<NSCopying>') of type parameter 'V'}}
+
+typedef PC15<id,
+ id, // expected-error{{type argument 'id' does not satisy the bound ('NSObject *') of type parameter 'U'}}
+ id> typeArgs9;
+
+typedef PC15<id, NSObject *,
+ id> typeArgs10; // expected-error{{type argument 'id' does not satisy 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 satisy the bound ('NSObject *') of type parameter 'U'}}
+@end
+
+@interface NSFoo : PC1<NSObject *, NSObject *> // okay
+@end
OpenPOWER on IntegriCloud