diff options
Diffstat (limited to 'clang/test')
| -rw-r--r-- | clang/test/Index/annotate-parameterized-classes.m | 12 | ||||
| -rw-r--r-- | clang/test/Index/annotate-tokens.m | 7 | ||||
| -rw-r--r-- | clang/test/Parser/placeholder-recovery.m | 9 | ||||
| -rw-r--r-- | clang/test/SemaObjC/parameterized_classes.m | 12 | ||||
| -rw-r--r-- | clang/test/SemaObjC/protocol-archane.m | 4 | ||||
| -rw-r--r-- | clang/test/SemaObjCXX/parameterized_classes_subst.mm | 407 |
6 files changed, 434 insertions, 17 deletions
diff --git a/clang/test/Index/annotate-parameterized-classes.m b/clang/test/Index/annotate-parameterized-classes.m index 6a53fed4bd7..762ae2aece1 100644 --- a/clang/test/Index/annotate-parameterized-classes.m +++ b/clang/test/Index/annotate-parameterized-classes.m @@ -17,19 +17,15 @@ typedef A<id<NSObject>, NSObject *> ASpecialization1; // RUN: c-index-test -test-annotate-tokens=%s:7:1:9:1 %s -target x86_64-apple-macosx10.7.0 | FileCheck -check-prefix=CHECK-INTERFACE-DECL %s // CHECK-INTERFACE-DECL: Identifier: "T" [7:14 - 7:15] TemplateTypeParameter=T:7:14 -// FIXME: Should be a type reference -// CHECK-INTERFACE-DECL: Identifier: "id" [7:18 - 7:20] TemplateTypeParameter=T:7:14 +// CHECK-INTERFACE-DECL: Identifier: "id" [7:18 - 7:20] TypeRef=id:0:0 // CHECK-INTERFACE-DECL: Identifier: "U" [7:22 - 7:23] TemplateTypeParameter=U:7:22 -// FIXME: Should be a class reference -// CHECK-INTERFACE-DECL: Identifier: "NSObject" [7:26 - 7:34] TemplateTypeParameter=U:7:22 +// CHECK-INTERFACE-DECL: Identifier: "NSObject" [7:26 - 7:34] ObjCClassRef=NSObject:4:12 // RUN: c-index-test -test-annotate-tokens=%s:10:1:12:1 %s -target x86_64-apple-macosx10.7.0 | FileCheck -check-prefix=CHECK-CATEGORY-DECL %s // CHECK-CATEGORY-DECL: Identifier: "T" [10:14 - 10:15] TemplateTypeParameter=T:10:14 -// FIXME: Should be a type reference -// CHECK-CATEGORY-DECL: Identifier: "id" [10:18 - 10:20] TemplateTypeParameter=T:10:14 +// CHECK-CATEGORY-DECL: Identifier: "id" [10:18 - 10:20] TypeRef=id:0:0 // CHECK-CATEGORY-DECL: Identifier: "U" [10:22 - 10:23] TemplateTypeParameter=U:10:22 -// FIXME: Should be a class reference -// CHECK-CATEGORY-DECL: Identifier: "NSObject" [10:26 - 10:34] TemplateTypeParameter=U:10:22 +// CHECK-CATEGORY-DECL: Identifier: "NSObject" [10:26 - 10:34] ObjCClassRef=NSObject:4:12 // RUN: c-index-test -test-annotate-tokens=%s:13:1:14:1 %s -target x86_64-apple-macosx10.7.0 | FileCheck -check-prefix=CHECK-SPECIALIZATION %s // CHECK-SPECIALIZATION: Identifier: "id" [13:11 - 13:13] TypeRef=id:0:0 diff --git a/clang/test/Index/annotate-tokens.m b/clang/test/Index/annotate-tokens.m index 9a7e28a666b..0a76105a94d 100644 --- a/clang/test/Index/annotate-tokens.m +++ b/clang/test/Index/annotate-tokens.m @@ -152,6 +152,7 @@ static Rdar8595462_A * Rdar8595462_staticVar; @property int extensionProperty; @end +typedef id<Proto> *proto_ptr; // RUN: c-index-test -test-annotate-tokens=%s:1:1:118:1 %s -DIBOutlet='__attribute__((iboutlet))' -DIBAction='void)__attribute__((ibaction)' | FileCheck %s // CHECK: Punctuation: "@" [1:1 - 1:2] ObjCInterfaceDecl=Foo:1:12 @@ -596,3 +597,9 @@ static Rdar8595462_A * Rdar8595462_staticVar; // CHECK-PROP: Keyword: "property" [152:4 - 152:12] ObjCPropertyDecl=extensionProperty:152:17 // CHECK-PROP: Keyword: "int" [152:13 - 152:16] ObjCPropertyDecl=extensionProperty:152:17 // CHECK-PROP: Identifier: "extensionProperty" [152:17 - 152:34] ObjCPropertyDecl=extensionProperty:152:17 + +// RUN: c-index-test -test-annotate-tokens=%s:155:1:156:1 %s -DIBOutlet='__attribute__((iboutlet))' -DIBAction='void)__attribute__((ibaction)' -target x86_64-apple-macosx10.7.0 | FileCheck -check-prefix=CHECK-ID-PROTO %s +// CHECK-ID-PROTO: Identifier: "id" [155:9 - 155:11] TypeRef=id:0:0 +// CHECK-ID-PROTO: Punctuation: "<" [155:11 - 155:12] TypedefDecl=proto_ptr:155:20 (Definition) +// CHECK-ID-PROTO: Identifier: "Proto" [155:12 - 155:17] ObjCProtocolRef=Proto +// CHECK-ID-PROTO: Punctuation: ">" [155:17 - 155:18] TypedefDecl=proto_ptr:155:20 (Definition) diff --git a/clang/test/Parser/placeholder-recovery.m b/clang/test/Parser/placeholder-recovery.m index 3fe1d62c304..b43b0e4a57c 100644 --- a/clang/test/Parser/placeholder-recovery.m +++ b/clang/test/Parser/placeholder-recovery.m @@ -3,10 +3,9 @@ // FIXME: We could do much better with this, if we recognized // placeholders somehow. However, we're content with not generating // bogus 'archaic' warnings with bad location info. -@protocol <#protocol name#> <NSObject> // expected-error 2{{expected identifier}} \ -// expected-error{{cannot find protocol declaration for 'NSObject'}} \ +@protocol <#protocol name#> <NSObject> // expected-error {{expected identifier or '('}} \ +// expected-error 2{{expected identifier}} \ // expected-warning{{protocol has no object type specified; defaults to qualified 'id'}} +<#methods#> -<#methods#> // expected-error{{expected identifier}} - -@end // expected-error{{prefix attribute}} +@end diff --git a/clang/test/SemaObjC/parameterized_classes.m b/clang/test/SemaObjC/parameterized_classes.m index 9834f7cd11f..eb3e122e820 100644 --- a/clang/test/SemaObjC/parameterized_classes.m +++ b/clang/test/SemaObjC/parameterized_classes.m @@ -1,5 +1,9 @@ // RUN: %clang_cc1 -fblocks %s -verify +#if !__has_feature(objc_generics) +# error Compiler does not support Objective-C generics? +#endif + @protocol NSObject // expected-note{{'NSObject' declared here}} @end @@ -255,14 +259,14 @@ typedef PC15<int (^)(int, int), // block pointers as 'id' 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'}} + 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 satisy the bound ('NSObject *') of type parameter 'U'}} + 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 satisy the bound ('id<NSCopying>') of type parameter 'V'}} + 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 @@ -306,7 +310,7 @@ void testSpecializedTypePrinting() { @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'}} +@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 diff --git a/clang/test/SemaObjC/protocol-archane.m b/clang/test/SemaObjC/protocol-archane.m index 788edf276d7..f2f6025a5ad 100644 --- a/clang/test/SemaObjC/protocol-archane.m +++ b/clang/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/clang/test/SemaObjCXX/parameterized_classes_subst.mm b/clang/test/SemaObjCXX/parameterized_classes_subst.mm new file mode 100644 index 00000000000..cd0096c3fef --- /dev/null +++ b/clang/test/SemaObjCXX/parameterized_classes_subst.mm @@ -0,0 +1,407 @@ +// RUN: %clang_cc1 -fblocks -fsyntax-only -std=c++11 %s -verify +// +// Test the substitution of type arguments for type parameters when +// using parameterized classes in Objective-C. + +__attribute__((objc_root_class)) +@interface NSObject ++ (instancetype)alloc; +- (instancetype)init; +@end + +@protocol NSCopying +@end + +@interface NSString : NSObject <NSCopying> +@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; +@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> // expected-note 2{{type parameter 'K' declared here}} \ +// expected-note 2{{'NSMutableDictionary' declared here}} +- (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 + + +// -------------------------------------------------------------------------- +// 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, + void (^block)(void)) { + int *ip; + ip = [stringSet firstObject]; // expected-error{{from incompatible type 'NSString *'}} + ip = [mutStringSet firstObject]; // expected-error{{from incompatible type 'NSString *'}} + ip = [widgetSet firstObject]; // expected-error{{from incompatible type 'Widget *'}} + ip = [untypedMutSet firstObject]; // expected-error{{from incompatible type 'id'}} + ip = [mutStringArraySet firstObject]; // expected-error{{from incompatible type 'NSArray<NSString *> *'}} + ip = [set firstObject]; // expected-error{{from incompatible type 'id'}} + ip = [mutSet firstObject]; // expected-error{{from incompatible type 'id'}} + ip = [mutArraySet firstObject]; // expected-error{{from incompatible type 'id'}} + ip = [block firstObject]; // expected-error{{from incompatible type 'id'}} + + ip = [stringSet findObject:@"blah"]; // expected-error{{from incompatible type 'NSString *'}} + + // Class messages. + ip = [NSSet<NSString *> alloc]; // expected-error{{from incompatible type 'NSSet<NSString *> *'}} + ip = [NSSet alloc]; // expected-error{{from incompatible type 'NSSet *'}} + ip = [MutableSetOfArrays<NSString *> alloc]; // expected-error{{from incompatible type 'MutableSetOfArrays<NSString *> *'}} + ip = [MutableSetOfArrays alloc]; // expected-error{{from incompatible type 'MutableSetOfArrays *'}} + ip = [NSArray<NSString *> array]; // expected-error{{from incompatible type 'NSArray<NSString *> *'}} + ip = [NSArray<NSString *><NSCopying> array]; // expected-error{{from incompatible type 'NSArray<NSString *> *'}} + + ip = [[NSMutableArray<NSString *> alloc] init]; // expected-error{{from incompatible type 'NSMutableArray<NSString *> *'}} + + [[NSMutableArray alloc] initWithArray: stringArray]; // okay + [[NSMutableArray<NSString *> alloc] initWithArray: stringArray]; // okay + [[NSMutableArray<NSNumber *> alloc] initWithArray: stringArray]; // expected-error{{parameter of type 'NSArray<NSNumber *> *' with an lvalue of type 'NSArray<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-error{{parameter of type 'NSString *'}} + [widgetSet addObject: window]; // expected-error{{parameter of type 'Widget *'}} + [untypedMutSet addObject: window]; // expected-error{{parameter of type 'id<NSCopying>'}} + [mutStringArraySet addObject: window]; // expected-error{{parameter of type 'NSArray<NSString *> *'}} + [mutSet addObject: window]; // expected-error{{parameter of type 'id<NSCopying>'}} + [mutArraySet addObject: window]; // expected-error{{parameter of type 'id<NSCopying>'}} + [block addObject: window]; // expected-error{{parameter of 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-error{{from incompatible type 'NSArray<NSString *> *'}} + ip = mutStringSet.allObjects; // expected-error{{from incompatible type 'NSArray<NSString *> *'}} + ip = widgetSet.allObjects; // expected-error{{from incompatible type 'NSArray<Widget *> *'}} + ip = untypedMutSet.allObjects; // expected-error{{from incompatible type 'NSArray *'}} + ip = mutStringArraySet.allObjects; // expected-error{{from incompatible type 'NSArray<NSArray<NSString *> *> *'}} + ip = set.allObjects; // expected-error{{from incompatible type 'NSArray *'}} + ip = mutSet.allObjects; // expected-error{{from incompatible type 'NSArray *'}} + ip = mutArraySet.allObjects; // expected-error{{from incompatible type 'NSArray *'}} + + ip = mutDict.someRandomKey; // expected-error{{from incompatible type 'id'}} +} + +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-error{{to 'NSArray<NSString *> *'}} + widgetSet.allObjects = ip; // expected-error{{to 'NSArray<Widget *> *'}} + untypedMutSet.allObjects = ip; // expected-error{{to 'NSArray *'}} + mutStringArraySet.allObjects = ip; // expected-error{{to 'NSArray<NSArray<NSString *> *> *'}} + mutSet.allObjects = ip; // expected-error{{to 'NSArray *'}} + mutArraySet.allObjects = ip; // expected-error{{to 'NSArray *'}} + + mutDict.someRandomKey = ip; // expected-error{{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-error{{from incompatible type 'NSString *'}} + + ip = mutStringArray[0]; // expected-error{{from incompatible type 'NSString *'}} + mutStringArray[0] = ip; // expected-error{{parameter of type 'NSString *'}} + + ip = array[0]; // expected-error{{from incompatible type 'id'}} + + ip = mutArray[0]; // expected-error{{from incompatible type 'id'}} + mutArray[0] = ip; // expected-error{{parameter of type 'id'}} + + ip = stringWidgetDict[string]; // expected-error{{from incompatible type 'Widget *'}} + widget = stringWidgetDict[widget]; // expected-error{{parameter of type 'NSString *'}} + + ip = mutStringWidgetDict[string]; // expected-error{{from incompatible type 'Widget *'}} + widget = mutStringWidgetDict[widget]; // expected-error{{parameter of type 'NSString *'}} + mutStringWidgetDict[string] = ip; // expected-error{{parameter of type 'Widget *'}} + mutStringWidgetDict[widget] = widget; // expected-error{{parameter of type 'NSString *'}} + + ip = dict[string]; // expected-error{{from incompatible type 'id'}} + + ip = mutDict[string]; // expected-error{{incompatible type 'id'}} + mutDict[string] = ip; // expected-error{{parameter of type 'id'}} + + widget = mutDict[window]; + mutDict[window] = widget; // expected-error{{parameter of type 'id<NSCopying>'}} +} + +// -------------------------------------------------------------------------- +// Instance variable access. +// -------------------------------------------------------------------------- +void test_instance_variable(NSArray<NSString *> *stringArray, + NSArray *array) { + int *ip; + + ip = stringArray->data; // expected-error{{from incompatible type 'NSString **'}} + ip = array->data; // expected-error{{from incompatible type 'id *'}} +} + +@implementation WindowArray +- (void)testInstanceVariable { + int *ip; + + ip = data; // expected-error{{from incompatible type '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-error{{assigning to 'NSArray<NSString *> *' from incompatible type 'NSArray<NSNumber *> *'}} + + // Specialized -> specialized (different levels). + stringArray = mutStringArray; + + // Specialized -> specialized failure (different levels). + numberArray = mutStringArray; // expected-error{{assigning to 'NSArray<NSNumber *> *' from incompatible type 'NSMutableArray<NSString *> *'}} + + // Unspecialized -> specialized (different levels). + stringArray = mutArray; + + // Specialized -> unspecialized (different levels). + array = mutStringArray; +} + +// -------------------------------------------------------------------------- +// 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-error{{from incompatible type 'NSArray<NSString *> *'}} + ip = cond ? mutStringArray : stringArray; // expected-error{{from incompatible type 'NSArray<NSString *> *'}} + + ip = cond ? stringArray2 : mutStringArray; // expected-error{{from incompatible type 'NSArray<NSString *> *'}} + ip = cond ? mutStringArray : stringArray2; // expected-error{{from incompatible type 'NSArray<NSString *> *'}} + + ip = cond ? stringArray : mutArray; // expected-error{{from incompatible type 'NSArray *'}} + + ip = cond ? stringArray2 : mutArray; // expected-error{{from incompatible type 'NSArray *'}} + + ip = cond ? mutArray : stringArray; // expected-error{{from incompatible type 'NSArray *'}} + + ip = cond ? mutArray : stringArray2; // expected-error{{from incompatible type '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-error{{from incompatible type 'NSString *'}} + ip = [super objectAtIndexedSubscript:0]; // expected-error{{from incompatible type 'NSString *'}} +} + ++ (void)useSuperMethod { + int *ip; + ip = super.array; // expected-error{{from incompatible type 'NSArray<NSString *> *'}} + ip = [super array]; // expected-error{{from incompatible type 'NSArray<NSString *> *'}} +} +@end + +// -------------------------------------------------------------------------- +// Template instantiation +// -------------------------------------------------------------------------- +template<typename K, typename V> +struct NSMutableDictionaryOf { + typedef NSMutableDictionary<K, V> *type; // expected-error{{type argument 'NSObject *' does not satisfy the bound ('id<NSCopying>') of type parameter 'K'}} +}; + +template<typename ...Args> +struct VariadicNSMutableDictionaryOf { + typedef NSMutableDictionary<Args...> *type; // expected-error{{type argument 'NSObject *' does not satisfy the bound ('id<NSCopying>') of type parameter 'K'}} + // expected-error@-1{{too many type arguments for class 'NSMutableDictionary' (have 3, expected 2)}} + // expected-error@-2{{too few type arguments for class 'NSMutableDictionary' (have 1, expected 2)}} +}; + +void testInstantiation() { + int *ip; + + typedef NSMutableDictionaryOf<NSString *, NSObject *>::type Dict1; + Dict1 d1 = ip; // expected-error{{cannot initialize a variable of type 'Dict1' (aka 'NSMutableDictionary<NSString *,NSObject *> *')}} + + typedef NSMutableDictionaryOf<NSObject *, NSString *>::type Dict2; // expected-note{{in instantiation of template}} +} + +void testVariadicInstantiation() { + int *ip; + + typedef VariadicNSMutableDictionaryOf<NSString *, NSObject *>::type Dict1; + Dict1 d1 = ip; // expected-error{{cannot initialize a variable of type 'Dict1' (aka 'NSMutableDictionary<NSString *,NSObject *> *')}} + + typedef VariadicNSMutableDictionaryOf<NSObject *, NSString *>::type Dict2; // expected-note{{in instantiation of template}} + + typedef VariadicNSMutableDictionaryOf<NSString *, NSObject *, NSObject *>::type Dict3; // expected-note{{in instantiation of template}} + + typedef VariadicNSMutableDictionaryOf<NSString *>::type Dict3; // expected-note{{in instantiation of template}} +} + +// -------------------------------------------------------------------------- +// Parameterized classes are not templates +// -------------------------------------------------------------------------- +template<template<typename T, typename U> class TT> +struct AcceptsTemplateTemplate { }; + +typedef AcceptsTemplateTemplate<NSMutableDictionary> TemplateTemplateFail1; // expected-error{{template argument for template template parameter must be a class template or type alias template}} + +template<typename T> +struct DependentTemplate { + typedef typename T::template apply<NSString *, NSObject *> type; // expected-error{{'apply' following the 'template' keyword does not refer to a template}} +}; + +struct NSMutableDictionaryBuilder { + typedef NSMutableDictionary apply; +}; + +typedef DependentTemplate<NSMutableDictionaryBuilder>::type DependentTemplateFail1; // expected-note{{in instantiation of template class}} + +template<typename K, typename V> +struct NonDependentTemplate { + typedef NSMutableDictionaryBuilder::template apply<NSString *, NSObject *> type; // expected-error{{'apply' following the 'template' keyword does not refer to a template}} + // expected-error@-1{{expected member name or }} +}; + +// However, one can use an alias template to turn a parameterized +// class into a template. +template<typename K, typename V> +using NSMutableDictionaryAlias = NSMutableDictionary<K, V>; + +typedef AcceptsTemplateTemplate<NSMutableDictionaryAlias> TemplateTemplateAlias1; // okay + + |

