Browse Source

Support ObjC Generic Collections

- Extend GPB*ObjectDictionary to support generic syntax.
- Update the generator to output generics so the enclosed type is exposed for compiler checks.
- Use generics in a the public interfaces.
- Update the generated sources that are checked in.
Thomas Van Lenten 10 năm trước cách đây
mục cha
commit
2480acb6d9
35 tập tin đã thay đổi với 588 bổ sung490 xóa
  1. 16 16
      objectivec/GPBCodedOutputStream.h
  2. 4 4
      objectivec/GPBDescriptor.h
  3. 43 37
      objectivec/GPBDictionary.h
  4. 2 2
      objectivec/GPBUnknownField.h
  5. 2 2
      objectivec/GPBUnknownField.m
  6. 2 2
      objectivec/GPBUnknownFieldSet.h
  7. 33 33
      objectivec/Tests/GPBDictionaryTests+Bool.m
  8. 32 32
      objectivec/Tests/GPBDictionaryTests+Int32.m
  9. 32 32
      objectivec/Tests/GPBDictionaryTests+Int64.m
  10. 32 32
      objectivec/Tests/GPBDictionaryTests+UInt32.m
  11. 32 32
      objectivec/Tests/GPBDictionaryTests+UInt64.m
  12. 59 52
      objectivec/Tests/GPBDictionaryTests.pddm
  13. 7 8
      objectivec/google/protobuf/Api.pbobjc.h
  14. 41 54
      objectivec/google/protobuf/Descriptor.pbobjc.h
  15. 1 2
      objectivec/google/protobuf/FieldMask.pbobjc.h
  16. 3 4
      objectivec/google/protobuf/Struct.pbobjc.h
  17. 10 14
      objectivec/google/protobuf/Type.pbobjc.h
  18. 1 1
      src/google/protobuf/compiler/main.cc
  19. 13 4
      src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
  20. 8 4
      src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
  21. 34 26
      src/google/protobuf/compiler/objectivec/objectivec_field.cc
  22. 19 9
      src/google/protobuf/compiler/objectivec/objectivec_field.h
  23. 6 4
      src/google/protobuf/compiler/objectivec/objectivec_file.cc
  24. 3 1
      src/google/protobuf/compiler/objectivec/objectivec_file.h
  25. 15 5
      src/google/protobuf/compiler/objectivec/objectivec_generator.cc
  26. 29 19
      src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
  27. 9 1
      src/google/protobuf/compiler/objectivec/objectivec_helpers.h
  28. 35 16
      src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
  29. 6 2
      src/google/protobuf/compiler/objectivec/objectivec_map_field.h
  30. 6 8
      src/google/protobuf/compiler/objectivec/objectivec_message.cc
  31. 3 1
      src/google/protobuf/compiler/objectivec/objectivec_message.h
  32. 16 4
      src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
  33. 11 4
      src/google/protobuf/compiler/objectivec/objectivec_message_field.h
  34. 11 16
      src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
  35. 12 7
      src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h

+ 16 - 16
objectivec/GPBCodedOutputStream.h

@@ -168,26 +168,26 @@ NS_ASSUME_NONNULL_BEGIN
 - (void)writeEnumNoTag:(int32_t)value;
 - (void)writeEnumNoTag:(int32_t)value;
 
 
 - (void)writeString:(int32_t)fieldNumber value:(NSString *)value;
 - (void)writeString:(int32_t)fieldNumber value:(NSString *)value;
-- (void)writeStringArray:(int32_t)fieldNumber values:(NSArray *)values;
+- (void)writeStringArray:(int32_t)fieldNumber values:(NSArray<NSString*> *)values;
 - (void)writeStringNoTag:(NSString *)value;
 - (void)writeStringNoTag:(NSString *)value;
 
 
 - (void)writeMessage:(int32_t)fieldNumber value:(GPBMessage *)value;
 - (void)writeMessage:(int32_t)fieldNumber value:(GPBMessage *)value;
-- (void)writeMessageArray:(int32_t)fieldNumber values:(NSArray *)values;
+- (void)writeMessageArray:(int32_t)fieldNumber values:(NSArray<GPBMessage*> *)values;
 - (void)writeMessageNoTag:(GPBMessage *)value;
 - (void)writeMessageNoTag:(GPBMessage *)value;
 
 
 - (void)writeBytes:(int32_t)fieldNumber value:(NSData *)value;
 - (void)writeBytes:(int32_t)fieldNumber value:(NSData *)value;
-- (void)writeBytesArray:(int32_t)fieldNumber values:(NSArray *)values;
+- (void)writeBytesArray:(int32_t)fieldNumber values:(NSArray<NSData*> *)values;
 - (void)writeBytesNoTag:(NSData *)value;
 - (void)writeBytesNoTag:(NSData *)value;
 
 
 - (void)writeGroup:(int32_t)fieldNumber
 - (void)writeGroup:(int32_t)fieldNumber
              value:(GPBMessage *)value;
              value:(GPBMessage *)value;
-- (void)writeGroupArray:(int32_t)fieldNumber values:(NSArray *)values;
+- (void)writeGroupArray:(int32_t)fieldNumber values:(NSArray<GPBMessage*> *)values;
 - (void)writeGroupNoTag:(int32_t)fieldNumber
 - (void)writeGroupNoTag:(int32_t)fieldNumber
                   value:(GPBMessage *)value;
                   value:(GPBMessage *)value;
 
 
 - (void)writeUnknownGroup:(int32_t)fieldNumber
 - (void)writeUnknownGroup:(int32_t)fieldNumber
                     value:(GPBUnknownFieldSet *)value;
                     value:(GPBUnknownFieldSet *)value;
-- (void)writeUnknownGroupArray:(int32_t)fieldNumber values:(NSArray *)values;
+- (void)writeUnknownGroupArray:(int32_t)fieldNumber values:(NSArray<GPBUnknownFieldSet*> *)values;
 - (void)writeUnknownGroupNoTag:(int32_t)fieldNumber
 - (void)writeUnknownGroupNoTag:(int32_t)fieldNumber
                          value:(GPBUnknownFieldSet *)value;
                          value:(GPBUnknownFieldSet *)value;
 
 
@@ -306,17 +306,17 @@ NS_ASSUME_NONNULL_END
 //%
 //%
 // Write methods for types that aren't in packed arrays.
 // Write methods for types that aren't in packed arrays.
 //%PDDM-DEFINE _WRITE_UNPACKABLE_DECLS(NAME, TYPE)
 //%PDDM-DEFINE _WRITE_UNPACKABLE_DECLS(NAME, TYPE)
-//%- (void)write##NAME:(int32_t)fieldNumber value:(TYPE)value;
-//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray *)values;
-//%- (void)write##NAME##NoTag:(TYPE)value;
+//%- (void)write##NAME:(int32_t)fieldNumber value:(TYPE *)value;
+//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray<##TYPE##*> *)values;
+//%- (void)write##NAME##NoTag:(TYPE *)value;
 //%
 //%
 // Special write methods for Groups.
 // Special write methods for Groups.
 //%PDDM-DEFINE _WRITE_GROUP_DECLS(NAME, TYPE)
 //%PDDM-DEFINE _WRITE_GROUP_DECLS(NAME, TYPE)
 //%- (void)write##NAME:(int32_t)fieldNumber
 //%- (void)write##NAME:(int32_t)fieldNumber
-//%       NAME$S value:(TYPE)value;
-//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray *)values;
+//%       NAME$S value:(TYPE *)value;
+//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray<##TYPE##*> *)values;
 //%- (void)write##NAME##NoTag:(int32_t)fieldNumber
 //%- (void)write##NAME##NoTag:(int32_t)fieldNumber
-//%            NAME$S value:(TYPE)value;
+//%            NAME$S value:(TYPE *)value;
 //%
 //%
 
 
 // One macro to hide it all up above.
 // One macro to hide it all up above.
@@ -335,8 +335,8 @@ NS_ASSUME_NONNULL_END
 //%_WRITE_PACKABLE_DECLS(SFixed32, Int32, int32_t)
 //%_WRITE_PACKABLE_DECLS(SFixed32, Int32, int32_t)
 //%_WRITE_PACKABLE_DECLS(Bool, Bool, BOOL)
 //%_WRITE_PACKABLE_DECLS(Bool, Bool, BOOL)
 //%_WRITE_PACKABLE_DECLS(Enum, Enum, int32_t)
 //%_WRITE_PACKABLE_DECLS(Enum, Enum, int32_t)
-//%_WRITE_UNPACKABLE_DECLS(String, NSString *)
-//%_WRITE_UNPACKABLE_DECLS(Message, GPBMessage *)
-//%_WRITE_UNPACKABLE_DECLS(Bytes, NSData *)
-//%_WRITE_GROUP_DECLS(Group, GPBMessage *)
-//%_WRITE_GROUP_DECLS(UnknownGroup, GPBUnknownFieldSet *)
+//%_WRITE_UNPACKABLE_DECLS(String, NSString)
+//%_WRITE_UNPACKABLE_DECLS(Message, GPBMessage)
+//%_WRITE_UNPACKABLE_DECLS(Bytes, NSData)
+//%_WRITE_GROUP_DECLS(Group, GPBMessage)
+//%_WRITE_GROUP_DECLS(UnknownGroup, GPBUnknownFieldSet)

+ 4 - 4
objectivec/GPBDescriptor.h

@@ -55,9 +55,9 @@ typedef NS_ENUM(NSInteger, GPBFieldType) {
 @interface GPBDescriptor : NSObject<NSCopying>
 @interface GPBDescriptor : NSObject<NSCopying>
 
 
 @property(nonatomic, readonly, copy) NSString *name;
 @property(nonatomic, readonly, copy) NSString *name;
-@property(nonatomic, readonly, strong, nullable) NSArray *fields;
-@property(nonatomic, readonly, strong, nullable) NSArray *oneofs;
-@property(nonatomic, readonly, strong, nullable) NSArray *enums;
+@property(nonatomic, readonly, strong, nullable) NSArray<GPBFieldDescriptor*> *fields;
+@property(nonatomic, readonly, strong, nullable) NSArray<GPBOneofDescriptor*> *oneofs;
+@property(nonatomic, readonly, strong, nullable) NSArray<GPBEnumDescriptor*> *enums;
 @property(nonatomic, readonly, nullable) const GPBExtensionRange *extensionRanges;
 @property(nonatomic, readonly, nullable) const GPBExtensionRange *extensionRanges;
 @property(nonatomic, readonly) NSUInteger extensionRangesCount;
 @property(nonatomic, readonly) NSUInteger extensionRangesCount;
 @property(nonatomic, readonly, assign) GPBFileDescriptor *file;
 @property(nonatomic, readonly, assign) GPBFileDescriptor *file;
@@ -81,7 +81,7 @@ typedef NS_ENUM(NSInteger, GPBFieldType) {
 
 
 @interface GPBOneofDescriptor : NSObject
 @interface GPBOneofDescriptor : NSObject
 @property(nonatomic, readonly) NSString *name;
 @property(nonatomic, readonly) NSString *name;
-@property(nonatomic, readonly) NSArray *fields;
+@property(nonatomic, readonly) NSArray<GPBFieldDescriptor*> *fields;
 
 
 - (nullable GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber;
 - (nullable GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber;
 - (nullable GPBFieldDescriptor *)fieldWithName:(NSString *)name;
 - (nullable GPBFieldDescriptor *)fieldWithName:(NSString *)name;

+ 43 - 37
objectivec/GPBDictionary.h

@@ -355,33 +355,33 @@ NS_ASSUME_NONNULL_BEGIN
 
 
 #pragma mark - UInt32 -> Object
 #pragma mark - UInt32 -> Object
 
 
-@interface GPBUInt32ObjectDictionary : NSObject <NSCopying>
+@interface GPBUInt32ObjectDictionary<__covariant ObjectType> : NSObject <NSCopying>
 
 
 @property(nonatomic, readonly) NSUInteger count;
 @property(nonatomic, readonly) NSUInteger count;
 
 
 + (instancetype)dictionary;
 + (instancetype)dictionary;
-+ (instancetype)dictionaryWithObject:(id)object
++ (instancetype)dictionaryWithObject:(ObjectType)object
                               forKey:(uint32_t)key;
                               forKey:(uint32_t)key;
-+ (instancetype)dictionaryWithObjects:(const id GPB_UNSAFE_UNRETAINED [])objects
++ (instancetype)dictionaryWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
                               forKeys:(const uint32_t [])keys
                               forKeys:(const uint32_t [])keys
                                 count:(NSUInteger)count;
                                 count:(NSUInteger)count;
 + (instancetype)dictionaryWithDictionary:(GPBUInt32ObjectDictionary *)dictionary;
 + (instancetype)dictionaryWithDictionary:(GPBUInt32ObjectDictionary *)dictionary;
 + (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
 + (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
 
 
-- (instancetype)initWithObjects:(const id GPB_UNSAFE_UNRETAINED [])objects
+- (instancetype)initWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
                         forKeys:(const uint32_t [])keys
                         forKeys:(const uint32_t [])keys
                           count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
                           count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
 - (instancetype)initWithDictionary:(GPBUInt32ObjectDictionary *)dictionary;
 - (instancetype)initWithDictionary:(GPBUInt32ObjectDictionary *)dictionary;
 - (instancetype)initWithCapacity:(NSUInteger)numItems;
 - (instancetype)initWithCapacity:(NSUInteger)numItems;
 
 
-- (id)objectForKey:(uint32_t)key;
+- (ObjectType)objectForKey:(uint32_t)key;
 
 
 - (void)enumerateKeysAndObjectsUsingBlock:
 - (void)enumerateKeysAndObjectsUsingBlock:
-    (void (^)(uint32_t key, id object, BOOL *stop))block;
+    (void (^)(uint32_t key, ObjectType object, BOOL *stop))block;
 
 
 - (void)addEntriesFromDictionary:(GPBUInt32ObjectDictionary *)otherDictionary;
 - (void)addEntriesFromDictionary:(GPBUInt32ObjectDictionary *)otherDictionary;
 
 
-- (void)setObject:(id)object forKey:(uint32_t)key;
+- (void)setObject:(ObjectType)object forKey:(uint32_t)key;
 
 
 - (void)removeObjectForKey:(uint32_t)aKey;
 - (void)removeObjectForKey:(uint32_t)aKey;
 - (void)removeAll;
 - (void)removeAll;
@@ -701,33 +701,33 @@ NS_ASSUME_NONNULL_BEGIN
 
 
 #pragma mark - Int32 -> Object
 #pragma mark - Int32 -> Object
 
 
-@interface GPBInt32ObjectDictionary : NSObject <NSCopying>
+@interface GPBInt32ObjectDictionary<__covariant ObjectType> : NSObject <NSCopying>
 
 
 @property(nonatomic, readonly) NSUInteger count;
 @property(nonatomic, readonly) NSUInteger count;
 
 
 + (instancetype)dictionary;
 + (instancetype)dictionary;
-+ (instancetype)dictionaryWithObject:(id)object
++ (instancetype)dictionaryWithObject:(ObjectType)object
                               forKey:(int32_t)key;
                               forKey:(int32_t)key;
-+ (instancetype)dictionaryWithObjects:(const id GPB_UNSAFE_UNRETAINED [])objects
++ (instancetype)dictionaryWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
                               forKeys:(const int32_t [])keys
                               forKeys:(const int32_t [])keys
                                 count:(NSUInteger)count;
                                 count:(NSUInteger)count;
 + (instancetype)dictionaryWithDictionary:(GPBInt32ObjectDictionary *)dictionary;
 + (instancetype)dictionaryWithDictionary:(GPBInt32ObjectDictionary *)dictionary;
 + (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
 + (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
 
 
-- (instancetype)initWithObjects:(const id GPB_UNSAFE_UNRETAINED [])objects
+- (instancetype)initWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
                         forKeys:(const int32_t [])keys
                         forKeys:(const int32_t [])keys
                           count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
                           count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
 - (instancetype)initWithDictionary:(GPBInt32ObjectDictionary *)dictionary;
 - (instancetype)initWithDictionary:(GPBInt32ObjectDictionary *)dictionary;
 - (instancetype)initWithCapacity:(NSUInteger)numItems;
 - (instancetype)initWithCapacity:(NSUInteger)numItems;
 
 
-- (id)objectForKey:(int32_t)key;
+- (ObjectType)objectForKey:(int32_t)key;
 
 
 - (void)enumerateKeysAndObjectsUsingBlock:
 - (void)enumerateKeysAndObjectsUsingBlock:
-    (void (^)(int32_t key, id object, BOOL *stop))block;
+    (void (^)(int32_t key, ObjectType object, BOOL *stop))block;
 
 
 - (void)addEntriesFromDictionary:(GPBInt32ObjectDictionary *)otherDictionary;
 - (void)addEntriesFromDictionary:(GPBInt32ObjectDictionary *)otherDictionary;
 
 
-- (void)setObject:(id)object forKey:(int32_t)key;
+- (void)setObject:(ObjectType)object forKey:(int32_t)key;
 
 
 - (void)removeObjectForKey:(int32_t)aKey;
 - (void)removeObjectForKey:(int32_t)aKey;
 - (void)removeAll;
 - (void)removeAll;
@@ -1047,33 +1047,33 @@ NS_ASSUME_NONNULL_BEGIN
 
 
 #pragma mark - UInt64 -> Object
 #pragma mark - UInt64 -> Object
 
 
-@interface GPBUInt64ObjectDictionary : NSObject <NSCopying>
+@interface GPBUInt64ObjectDictionary<__covariant ObjectType> : NSObject <NSCopying>
 
 
 @property(nonatomic, readonly) NSUInteger count;
 @property(nonatomic, readonly) NSUInteger count;
 
 
 + (instancetype)dictionary;
 + (instancetype)dictionary;
-+ (instancetype)dictionaryWithObject:(id)object
++ (instancetype)dictionaryWithObject:(ObjectType)object
                               forKey:(uint64_t)key;
                               forKey:(uint64_t)key;
-+ (instancetype)dictionaryWithObjects:(const id GPB_UNSAFE_UNRETAINED [])objects
++ (instancetype)dictionaryWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
                               forKeys:(const uint64_t [])keys
                               forKeys:(const uint64_t [])keys
                                 count:(NSUInteger)count;
                                 count:(NSUInteger)count;
 + (instancetype)dictionaryWithDictionary:(GPBUInt64ObjectDictionary *)dictionary;
 + (instancetype)dictionaryWithDictionary:(GPBUInt64ObjectDictionary *)dictionary;
 + (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
 + (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
 
 
-- (instancetype)initWithObjects:(const id GPB_UNSAFE_UNRETAINED [])objects
+- (instancetype)initWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
                         forKeys:(const uint64_t [])keys
                         forKeys:(const uint64_t [])keys
                           count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
                           count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
 - (instancetype)initWithDictionary:(GPBUInt64ObjectDictionary *)dictionary;
 - (instancetype)initWithDictionary:(GPBUInt64ObjectDictionary *)dictionary;
 - (instancetype)initWithCapacity:(NSUInteger)numItems;
 - (instancetype)initWithCapacity:(NSUInteger)numItems;
 
 
-- (id)objectForKey:(uint64_t)key;
+- (ObjectType)objectForKey:(uint64_t)key;
 
 
 - (void)enumerateKeysAndObjectsUsingBlock:
 - (void)enumerateKeysAndObjectsUsingBlock:
-    (void (^)(uint64_t key, id object, BOOL *stop))block;
+    (void (^)(uint64_t key, ObjectType object, BOOL *stop))block;
 
 
 - (void)addEntriesFromDictionary:(GPBUInt64ObjectDictionary *)otherDictionary;
 - (void)addEntriesFromDictionary:(GPBUInt64ObjectDictionary *)otherDictionary;
 
 
-- (void)setObject:(id)object forKey:(uint64_t)key;
+- (void)setObject:(ObjectType)object forKey:(uint64_t)key;
 
 
 - (void)removeObjectForKey:(uint64_t)aKey;
 - (void)removeObjectForKey:(uint64_t)aKey;
 - (void)removeAll;
 - (void)removeAll;
@@ -1393,33 +1393,33 @@ NS_ASSUME_NONNULL_BEGIN
 
 
 #pragma mark - Int64 -> Object
 #pragma mark - Int64 -> Object
 
 
-@interface GPBInt64ObjectDictionary : NSObject <NSCopying>
+@interface GPBInt64ObjectDictionary<__covariant ObjectType> : NSObject <NSCopying>
 
 
 @property(nonatomic, readonly) NSUInteger count;
 @property(nonatomic, readonly) NSUInteger count;
 
 
 + (instancetype)dictionary;
 + (instancetype)dictionary;
-+ (instancetype)dictionaryWithObject:(id)object
++ (instancetype)dictionaryWithObject:(ObjectType)object
                               forKey:(int64_t)key;
                               forKey:(int64_t)key;
-+ (instancetype)dictionaryWithObjects:(const id GPB_UNSAFE_UNRETAINED [])objects
++ (instancetype)dictionaryWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
                               forKeys:(const int64_t [])keys
                               forKeys:(const int64_t [])keys
                                 count:(NSUInteger)count;
                                 count:(NSUInteger)count;
 + (instancetype)dictionaryWithDictionary:(GPBInt64ObjectDictionary *)dictionary;
 + (instancetype)dictionaryWithDictionary:(GPBInt64ObjectDictionary *)dictionary;
 + (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
 + (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
 
 
-- (instancetype)initWithObjects:(const id GPB_UNSAFE_UNRETAINED [])objects
+- (instancetype)initWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
                         forKeys:(const int64_t [])keys
                         forKeys:(const int64_t [])keys
                           count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
                           count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
 - (instancetype)initWithDictionary:(GPBInt64ObjectDictionary *)dictionary;
 - (instancetype)initWithDictionary:(GPBInt64ObjectDictionary *)dictionary;
 - (instancetype)initWithCapacity:(NSUInteger)numItems;
 - (instancetype)initWithCapacity:(NSUInteger)numItems;
 
 
-- (id)objectForKey:(int64_t)key;
+- (ObjectType)objectForKey:(int64_t)key;
 
 
 - (void)enumerateKeysAndObjectsUsingBlock:
 - (void)enumerateKeysAndObjectsUsingBlock:
-    (void (^)(int64_t key, id object, BOOL *stop))block;
+    (void (^)(int64_t key, ObjectType object, BOOL *stop))block;
 
 
 - (void)addEntriesFromDictionary:(GPBInt64ObjectDictionary *)otherDictionary;
 - (void)addEntriesFromDictionary:(GPBInt64ObjectDictionary *)otherDictionary;
 
 
-- (void)setObject:(id)object forKey:(int64_t)key;
+- (void)setObject:(ObjectType)object forKey:(int64_t)key;
 
 
 - (void)removeObjectForKey:(int64_t)aKey;
 - (void)removeObjectForKey:(int64_t)aKey;
 - (void)removeAll;
 - (void)removeAll;
@@ -1739,33 +1739,33 @@ NS_ASSUME_NONNULL_BEGIN
 
 
 #pragma mark - Bool -> Object
 #pragma mark - Bool -> Object
 
 
-@interface GPBBoolObjectDictionary : NSObject <NSCopying>
+@interface GPBBoolObjectDictionary<__covariant ObjectType> : NSObject <NSCopying>
 
 
 @property(nonatomic, readonly) NSUInteger count;
 @property(nonatomic, readonly) NSUInteger count;
 
 
 + (instancetype)dictionary;
 + (instancetype)dictionary;
-+ (instancetype)dictionaryWithObject:(id)object
++ (instancetype)dictionaryWithObject:(ObjectType)object
                               forKey:(BOOL)key;
                               forKey:(BOOL)key;
-+ (instancetype)dictionaryWithObjects:(const id GPB_UNSAFE_UNRETAINED [])objects
++ (instancetype)dictionaryWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
                               forKeys:(const BOOL [])keys
                               forKeys:(const BOOL [])keys
                                 count:(NSUInteger)count;
                                 count:(NSUInteger)count;
 + (instancetype)dictionaryWithDictionary:(GPBBoolObjectDictionary *)dictionary;
 + (instancetype)dictionaryWithDictionary:(GPBBoolObjectDictionary *)dictionary;
 + (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
 + (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
 
 
-- (instancetype)initWithObjects:(const id GPB_UNSAFE_UNRETAINED [])objects
+- (instancetype)initWithObjects:(const ObjectType GPB_UNSAFE_UNRETAINED [])objects
                         forKeys:(const BOOL [])keys
                         forKeys:(const BOOL [])keys
                           count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
                           count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
 - (instancetype)initWithDictionary:(GPBBoolObjectDictionary *)dictionary;
 - (instancetype)initWithDictionary:(GPBBoolObjectDictionary *)dictionary;
 - (instancetype)initWithCapacity:(NSUInteger)numItems;
 - (instancetype)initWithCapacity:(NSUInteger)numItems;
 
 
-- (id)objectForKey:(BOOL)key;
+- (ObjectType)objectForKey:(BOOL)key;
 
 
 - (void)enumerateKeysAndObjectsUsingBlock:
 - (void)enumerateKeysAndObjectsUsingBlock:
-    (void (^)(BOOL key, id object, BOOL *stop))block;
+    (void (^)(BOOL key, ObjectType object, BOOL *stop))block;
 
 
 - (void)addEntriesFromDictionary:(GPBBoolObjectDictionary *)otherDictionary;
 - (void)addEntriesFromDictionary:(GPBBoolObjectDictionary *)otherDictionary;
 
 
-- (void)setObject:(id)object forKey:(BOOL)key;
+- (void)setObject:(ObjectType)object forKey:(BOOL)key;
 
 
 - (void)removeObjectForKey:(BOOL)aKey;
 - (void)removeObjectForKey:(BOOL)aKey;
 - (void)removeAll;
 - (void)removeAll;
@@ -2096,7 +2096,7 @@ NS_ASSUME_NONNULL_END
 //%DICTIONARY_POD_INTERFACES_FOR_KEY(String, NSString, *, OBJECT)
 //%DICTIONARY_POD_INTERFACES_FOR_KEY(String, NSString, *, OBJECT)
 //%PDDM-DEFINE DICTIONARY_INTERFACES_FOR_POD_KEY(KEY_NAME, KEY_TYPE)
 //%PDDM-DEFINE DICTIONARY_INTERFACES_FOR_POD_KEY(KEY_NAME, KEY_TYPE)
 //%DICTIONARY_POD_INTERFACES_FOR_KEY(KEY_NAME, KEY_TYPE, , POD)
 //%DICTIONARY_POD_INTERFACES_FOR_KEY(KEY_NAME, KEY_TYPE, , POD)
-//%DICTIONARY_POD_KEY_TO_OBJECT_INTERFACE(KEY_NAME, KEY_TYPE, Object, id)
+//%DICTIONARY_POD_KEY_TO_OBJECT_INTERFACE(KEY_NAME, KEY_TYPE, Object, ObjectType)
 //%PDDM-DEFINE DICTIONARY_POD_INTERFACES_FOR_KEY(KEY_NAME, KEY_TYPE, KisP, KHELPER)
 //%PDDM-DEFINE DICTIONARY_POD_INTERFACES_FOR_KEY(KEY_NAME, KEY_TYPE, KisP, KHELPER)
 //%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, UInt32, uint32_t)
 //%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, UInt32, uint32_t)
 //%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Int32, int32_t)
 //%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Int32, int32_t)
@@ -2122,10 +2122,16 @@ NS_ASSUME_NONNULL_END
 // Nothing
 // Nothing
 //%PDDM-DEFINE ARRAY_ARG_MODIFIEROBJECT()
 //%PDDM-DEFINE ARRAY_ARG_MODIFIEROBJECT()
 //%GPB_UNSAFE_UNRETAINED ##
 //%GPB_UNSAFE_UNRETAINED ##
+//%PDDM-DEFINE DICTIONARY_CLASS_DECLPOD(KEY_NAME, VALUE_NAME, VALUE_TYPE)
+//%GPB##KEY_NAME##VALUE_NAME##Dictionary
+//%PDDM-DEFINE DICTIONARY_CLASS_DECLEnum(KEY_NAME, VALUE_NAME, VALUE_TYPE)
+//%GPB##KEY_NAME##VALUE_NAME##Dictionary
+//%PDDM-DEFINE DICTIONARY_CLASS_DECLOBJECT(KEY_NAME, VALUE_NAME, VALUE_TYPE)
+//%GPB##KEY_NAME##VALUE_NAME##Dictionary<__covariant VALUE_TYPE>
 //%PDDM-DEFINE DICTIONARY_COMMON_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE, VHELPER, VNAME)
 //%PDDM-DEFINE DICTIONARY_COMMON_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE, VHELPER, VNAME)
 //%#pragma mark - KEY_NAME -> VALUE_NAME
 //%#pragma mark - KEY_NAME -> VALUE_NAME
 //%
 //%
-//%@interface GPB##KEY_NAME##VALUE_NAME##Dictionary : NSObject <NSCopying>
+//%@interface DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) : NSObject <NSCopying>
 //%
 //%
 //%@property(nonatomic, readonly) NSUInteger count;
 //%@property(nonatomic, readonly) NSUInteger count;
 //%
 //%

+ 2 - 2
objectivec/GPBUnknownField.h

@@ -45,8 +45,8 @@ NS_ASSUME_NONNULL_BEGIN
 @property(nonatomic, readonly, strong) GPBUInt64Array *varintList;
 @property(nonatomic, readonly, strong) GPBUInt64Array *varintList;
 @property(nonatomic, readonly, strong) GPBUInt32Array *fixed32List;
 @property(nonatomic, readonly, strong) GPBUInt32Array *fixed32List;
 @property(nonatomic, readonly, strong) GPBUInt64Array *fixed64List;
 @property(nonatomic, readonly, strong) GPBUInt64Array *fixed64List;
-@property(nonatomic, readonly, strong) NSArray *lengthDelimitedList;  // NSData
-@property(nonatomic, readonly, strong) NSArray *groupList;  // GPBUnknownFieldSet
+@property(nonatomic, readonly, strong) NSArray<NSData*> *lengthDelimitedList;
+@property(nonatomic, readonly, strong) NSArray<GPBUnknownFieldSet*> *groupList;
 
 
 // Only one of these should be used per Field.
 // Only one of these should be used per Field.
 - (void)addVarint:(uint64_t)value;
 - (void)addVarint:(uint64_t)value;

+ 2 - 2
objectivec/GPBUnknownField.m

@@ -39,8 +39,8 @@
   GPBUInt64Array *mutableVarintList_;
   GPBUInt64Array *mutableVarintList_;
   GPBUInt32Array *mutableFixed32List_;
   GPBUInt32Array *mutableFixed32List_;
   GPBUInt64Array *mutableFixed64List_;
   GPBUInt64Array *mutableFixed64List_;
-  NSMutableArray *mutableLengthDelimitedList_;
-  NSMutableArray *mutableGroupList_;
+  NSMutableArray<NSData*> *mutableLengthDelimitedList_;
+  NSMutableArray<GPBUnknownFieldSet*> *mutableGroupList_;
 }
 }
 
 
 @synthesize number = number_;
 @synthesize number = number_;

+ 2 - 2
objectivec/GPBUnknownFieldSet.h

@@ -42,8 +42,8 @@ NS_ASSUME_NONNULL_BEGIN
 
 
 - (void)addField:(GPBUnknownField *)field;
 - (void)addField:(GPBUnknownField *)field;
 
 
-// Returns an NSArray of the GPBFields sorted by the field numbers.
-- (NSArray *)sortedFields;
+// Returns an NSArray of the GPBUnknownFields sorted by the field numbers.
+- (NSArray<GPBUnknownField*> *)sortedFields;
 
 
 @end
 @end
 
 

+ 33 - 33
objectivec/Tests/GPBDictionaryTests+Bool.m

@@ -2147,7 +2147,7 @@
 
 
 @end
 @end
 
 
-//%PDDM-EXPAND TESTS_FOR_BOOL_KEY_OBJECT_VALUE(Object, id, @"abc", @"def")
+//%PDDM-EXPAND TESTS_FOR_BOOL_KEY_OBJECT_VALUE(Object, NSString*, @"abc", @"def")
 // This block of code is generated, do not edit it directly.
 // This block of code is generated, do not edit it directly.
 
 
 #pragma mark - Bool -> Object
 #pragma mark - Bool -> Object
@@ -2158,11 +2158,11 @@
 @implementation GPBBoolObjectDictionaryTests
 @implementation GPBBoolObjectDictionaryTests
 
 
 - (void)testEmpty {
 - (void)testEmpty {
-  GPBBoolObjectDictionary *dict = [[GPBBoolObjectDictionary alloc] init];
+  GPBBoolObjectDictionary<NSString*> *dict = [[GPBBoolObjectDictionary alloc] init];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertNil([dict objectForKey:YES]);
   XCTAssertNil([dict objectForKey:YES]);
-  [dict enumerateKeysAndObjectsUsingBlock:^(BOOL aKey, id aObject, BOOL *stop) {
+  [dict enumerateKeysAndObjectsUsingBlock:^(BOOL aKey, NSString* aObject, BOOL *stop) {
     #pragma unused(aKey, aObject, stop)
     #pragma unused(aKey, aObject, stop)
     XCTFail(@"Shouldn't get here!");
     XCTFail(@"Shouldn't get here!");
   }];
   }];
@@ -2170,12 +2170,12 @@
 }
 }
 
 
 - (void)testOne {
 - (void)testOne {
-  GPBBoolObjectDictionary *dict = [GPBBoolObjectDictionary dictionaryWithObject:@"abc" forKey:YES];
+  GPBBoolObjectDictionary<NSString*> *dict = [GPBBoolObjectDictionary dictionaryWithObject:@"abc" forKey:YES];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 1U);
   XCTAssertEqual(dict.count, 1U);
   XCTAssertEqualObjects([dict objectForKey:YES], @"abc");
   XCTAssertEqualObjects([dict objectForKey:YES], @"abc");
   XCTAssertNil([dict objectForKey:NO]);
   XCTAssertNil([dict objectForKey:NO]);
-  [dict enumerateKeysAndObjectsUsingBlock:^(BOOL aKey, id aObject, BOOL *stop) {
+  [dict enumerateKeysAndObjectsUsingBlock:^(BOOL aKey, NSString* aObject, BOOL *stop) {
     XCTAssertEqual(aKey, YES);
     XCTAssertEqual(aKey, YES);
     XCTAssertEqualObjects(aObject, @"abc");
     XCTAssertEqualObjects(aObject, @"abc");
     XCTAssertNotEqual(stop, NULL);
     XCTAssertNotEqual(stop, NULL);
@@ -2184,8 +2184,8 @@
 
 
 - (void)testBasics {
 - (void)testBasics {
   const BOOL kKeys[] = { YES, NO };
   const BOOL kKeys[] = { YES, NO };
-  const id kObjects[] = { @"abc", @"def" };
-  GPBBoolObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def" };
+  GPBBoolObjectDictionary<NSString*> *dict =
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects
                                                forKeys:kKeys
                                                forKeys:kKeys
                                                  count:GPBARRAYSIZE(kObjects)];
                                                  count:GPBARRAYSIZE(kObjects)];
@@ -2196,8 +2196,8 @@
 
 
   __block NSUInteger idx = 0;
   __block NSUInteger idx = 0;
   BOOL *seenKeys = malloc(2 * sizeof(BOOL));
   BOOL *seenKeys = malloc(2 * sizeof(BOOL));
-  id *seenObjects = malloc(2 * sizeof(id));
-  [dict enumerateKeysAndObjectsUsingBlock:^(BOOL aKey, id aObject, BOOL *stop) {
+  NSString* *seenObjects = malloc(2 * sizeof(NSString*));
+  [dict enumerateKeysAndObjectsUsingBlock:^(BOOL aKey, NSString* aObject, BOOL *stop) {
     XCTAssertLessThan(idx, 2U);
     XCTAssertLessThan(idx, 2U);
     seenKeys[idx] = aKey;
     seenKeys[idx] = aKey;
     seenObjects[idx] = aObject;
     seenObjects[idx] = aObject;
@@ -2219,7 +2219,7 @@
 
 
   // Stopping the enumeration.
   // Stopping the enumeration.
   idx = 0;
   idx = 0;
-  [dict enumerateKeysAndObjectsUsingBlock:^(BOOL aKey, id aObject, BOOL *stop) {
+  [dict enumerateKeysAndObjectsUsingBlock:^(BOOL aKey, NSString* aObject, BOOL *stop) {
     #pragma unused(aKey, aObject)
     #pragma unused(aKey, aObject)
     if (idx == 0) *stop = YES;
     if (idx == 0) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     XCTAssertNotEqual(idx, 2U);
@@ -2231,30 +2231,30 @@
 - (void)testEquality {
 - (void)testEquality {
   const BOOL kKeys1[] = { YES, NO };
   const BOOL kKeys1[] = { YES, NO };
   const BOOL kKeys2[] = { NO, YES };
   const BOOL kKeys2[] = { NO, YES };
-  const id kObjects1[] = { @"abc", @"def" };
-  const id kObjects2[] = { @"def", @"abc" };
-  const id kObjects3[] = { @"def" };
-  GPBBoolObjectDictionary *dict1 =
+  const NSString* kObjects1[] = { @"abc", @"def" };
+  const NSString* kObjects2[] = { @"def", @"abc" };
+  const NSString* kObjects3[] = { @"def" };
+  GPBBoolObjectDictionary<NSString*> *dict1 =
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects1
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects1
                                                forKeys:kKeys1
                                                forKeys:kKeys1
                                                  count:GPBARRAYSIZE(kObjects1)];
                                                  count:GPBARRAYSIZE(kObjects1)];
   XCTAssertNotNil(dict1);
   XCTAssertNotNil(dict1);
-  GPBBoolObjectDictionary *dict1prime =
+  GPBBoolObjectDictionary<NSString*> *dict1prime =
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects1
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects1
                                                forKeys:kKeys1
                                                forKeys:kKeys1
                                                  count:GPBARRAYSIZE(kObjects1)];
                                                  count:GPBARRAYSIZE(kObjects1)];
   XCTAssertNotNil(dict1prime);
   XCTAssertNotNil(dict1prime);
-  GPBBoolObjectDictionary *dict2 =
+  GPBBoolObjectDictionary<NSString*> *dict2 =
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects2
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects2
                                                forKeys:kKeys1
                                                forKeys:kKeys1
                                                  count:GPBARRAYSIZE(kObjects2)];
                                                  count:GPBARRAYSIZE(kObjects2)];
   XCTAssertNotNil(dict2);
   XCTAssertNotNil(dict2);
-  GPBBoolObjectDictionary *dict3 =
+  GPBBoolObjectDictionary<NSString*> *dict3 =
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects1
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects1
                                                forKeys:kKeys2
                                                forKeys:kKeys2
                                                  count:GPBARRAYSIZE(kObjects1)];
                                                  count:GPBARRAYSIZE(kObjects1)];
   XCTAssertNotNil(dict3);
   XCTAssertNotNil(dict3);
-  GPBBoolObjectDictionary *dict4 =
+  GPBBoolObjectDictionary<NSString*> *dict4 =
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects3
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects3
                                                forKeys:kKeys1
                                                forKeys:kKeys1
                                                  count:GPBARRAYSIZE(kObjects3)];
                                                  count:GPBARRAYSIZE(kObjects3)];
@@ -2284,14 +2284,14 @@
 
 
 - (void)testCopy {
 - (void)testCopy {
   const BOOL kKeys[] = { YES, NO };
   const BOOL kKeys[] = { YES, NO };
-  const id kObjects[] = { @"abc", @"def" };
-  GPBBoolObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def" };
+  GPBBoolObjectDictionary<NSString*> *dict =
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects
                                                forKeys:kKeys
                                                forKeys:kKeys
                                                  count:GPBARRAYSIZE(kObjects)];
                                                  count:GPBARRAYSIZE(kObjects)];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
 
 
-  GPBBoolObjectDictionary *dict2 = [dict copy];
+  GPBBoolObjectDictionary<NSString*> *dict2 = [dict copy];
   XCTAssertNotNil(dict2);
   XCTAssertNotNil(dict2);
 
 
   // Should be new object but equal.
   // Should be new object but equal.
@@ -2305,14 +2305,14 @@
 
 
 - (void)testDictionaryFromDictionary {
 - (void)testDictionaryFromDictionary {
   const BOOL kKeys[] = { YES, NO };
   const BOOL kKeys[] = { YES, NO };
-  const id kObjects[] = { @"abc", @"def" };
-  GPBBoolObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def" };
+  GPBBoolObjectDictionary<NSString*> *dict =
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects
                                                forKeys:kKeys
                                                forKeys:kKeys
                                                  count:GPBARRAYSIZE(kObjects)];
                                                  count:GPBARRAYSIZE(kObjects)];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
 
 
-  GPBBoolObjectDictionary *dict2 =
+  GPBBoolObjectDictionary<NSString*> *dict2 =
       [GPBBoolObjectDictionary dictionaryWithDictionary:dict];
       [GPBBoolObjectDictionary dictionaryWithDictionary:dict];
   XCTAssertNotNil(dict2);
   XCTAssertNotNil(dict2);
 
 
@@ -2323,7 +2323,7 @@
 }
 }
 
 
 - (void)testAdds {
 - (void)testAdds {
-  GPBBoolObjectDictionary *dict = [GPBBoolObjectDictionary dictionary];
+  GPBBoolObjectDictionary<NSString*> *dict = [GPBBoolObjectDictionary dictionary];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
 
 
   XCTAssertEqual(dict.count, 0U);
   XCTAssertEqual(dict.count, 0U);
@@ -2331,8 +2331,8 @@
   XCTAssertEqual(dict.count, 1U);
   XCTAssertEqual(dict.count, 1U);
 
 
   const BOOL kKeys[] = { NO };
   const BOOL kKeys[] = { NO };
-  const id kObjects[] = { @"def" };
-  GPBBoolObjectDictionary *dict2 =
+  const NSString* kObjects[] = { @"def" };
+  GPBBoolObjectDictionary<NSString*> *dict2 =
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects
                                                forKeys:kKeys
                                                forKeys:kKeys
                                                  count:GPBARRAYSIZE(kObjects)];
                                                  count:GPBARRAYSIZE(kObjects)];
@@ -2347,8 +2347,8 @@
 
 
 - (void)testRemove {
 - (void)testRemove {
   const BOOL kKeys[] = { YES, NO};
   const BOOL kKeys[] = { YES, NO};
-  const id kObjects[] = { @"abc", @"def" };
-  GPBBoolObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def" };
+  GPBBoolObjectDictionary<NSString*> *dict =
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects
                                         forKeys:kKeys
                                         forKeys:kKeys
                                           count:GPBARRAYSIZE(kObjects)];
                                           count:GPBARRAYSIZE(kObjects)];
@@ -2375,8 +2375,8 @@
 
 
 - (void)testInplaceMutation {
 - (void)testInplaceMutation {
   const BOOL kKeys[] = { YES, NO };
   const BOOL kKeys[] = { YES, NO };
-  const id kObjects[] = { @"abc", @"def" };
-  GPBBoolObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def" };
+  GPBBoolObjectDictionary<NSString*> *dict =
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects
                                         forKeys:kKeys
                                         forKeys:kKeys
                                           count:GPBARRAYSIZE(kObjects)];
                                           count:GPBARRAYSIZE(kObjects)];
@@ -2396,8 +2396,8 @@
   XCTAssertEqualObjects([dict objectForKey:NO], @"abc");
   XCTAssertEqualObjects([dict objectForKey:NO], @"abc");
 
 
   const BOOL kKeys2[] = { NO, YES };
   const BOOL kKeys2[] = { NO, YES };
-  const id kObjects2[] = { @"def", @"abc" };
-  GPBBoolObjectDictionary *dict2 =
+  const NSString* kObjects2[] = { @"def", @"abc" };
+  GPBBoolObjectDictionary<NSString*> *dict2 =
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects2
       [[GPBBoolObjectDictionary alloc] initWithObjects:kObjects2
                                                forKeys:kKeys2
                                                forKeys:kKeys2
                                                  count:GPBARRAYSIZE(kObjects2)];
                                                  count:GPBARRAYSIZE(kObjects2)];

+ 32 - 32
objectivec/Tests/GPBDictionaryTests+Int32.m

@@ -3363,11 +3363,11 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 @implementation GPBInt32ObjectDictionaryTests
 @implementation GPBInt32ObjectDictionaryTests
 
 
 - (void)testEmpty {
 - (void)testEmpty {
-  GPBInt32ObjectDictionary *dict = [[GPBInt32ObjectDictionary alloc] init];
+  GPBInt32ObjectDictionary<NSString*> *dict = [[GPBInt32ObjectDictionary alloc] init];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertNil([dict objectForKey:11]);
   XCTAssertNil([dict objectForKey:11]);
-  [dict enumerateKeysAndObjectsUsingBlock:^(int32_t aKey, id aObject, BOOL *stop) {
+  [dict enumerateKeysAndObjectsUsingBlock:^(int32_t aKey, NSString* aObject, BOOL *stop) {
     #pragma unused(aKey, aObject, stop)
     #pragma unused(aKey, aObject, stop)
     XCTFail(@"Shouldn't get here!");
     XCTFail(@"Shouldn't get here!");
   }];
   }];
@@ -3375,12 +3375,12 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 }
 }
 
 
 - (void)testOne {
 - (void)testOne {
-  GPBInt32ObjectDictionary *dict = [GPBInt32ObjectDictionary dictionaryWithObject:@"abc" forKey:11];
+  GPBInt32ObjectDictionary<NSString*> *dict = [GPBInt32ObjectDictionary dictionaryWithObject:@"abc" forKey:11];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 1U);
   XCTAssertEqual(dict.count, 1U);
   XCTAssertEqualObjects([dict objectForKey:11], @"abc");
   XCTAssertEqualObjects([dict objectForKey:11], @"abc");
   XCTAssertNil([dict objectForKey:12]);
   XCTAssertNil([dict objectForKey:12]);
-  [dict enumerateKeysAndObjectsUsingBlock:^(int32_t aKey, id aObject, BOOL *stop) {
+  [dict enumerateKeysAndObjectsUsingBlock:^(int32_t aKey, NSString* aObject, BOOL *stop) {
     XCTAssertEqual(aKey, 11);
     XCTAssertEqual(aKey, 11);
     XCTAssertEqualObjects(aObject, @"abc");
     XCTAssertEqualObjects(aObject, @"abc");
     XCTAssertNotEqual(stop, NULL);
     XCTAssertNotEqual(stop, NULL);
@@ -3389,8 +3389,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
 - (void)testBasics {
 - (void)testBasics {
   const int32_t kKeys[] = { 11, 12, 13 };
   const int32_t kKeys[] = { 11, 12, 13 };
-  const id kObjects[] = { @"abc", @"def", @"ghi" };
-  GPBInt32ObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi" };
+  GPBInt32ObjectDictionary<NSString*> *dict =
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects
                                                 forKeys:kKeys
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kObjects)];
                                                   count:GPBARRAYSIZE(kObjects)];
@@ -3403,8 +3403,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
   __block NSUInteger idx = 0;
   __block NSUInteger idx = 0;
   int32_t *seenKeys = malloc(3 * sizeof(int32_t));
   int32_t *seenKeys = malloc(3 * sizeof(int32_t));
-  id *seenObjects = malloc(3 * sizeof(id));
-  [dict enumerateKeysAndObjectsUsingBlock:^(int32_t aKey, id aObject, BOOL *stop) {
+  NSString* *seenObjects = malloc(3 * sizeof(NSString*));
+  [dict enumerateKeysAndObjectsUsingBlock:^(int32_t aKey, NSString* aObject, BOOL *stop) {
     XCTAssertLessThan(idx, 3U);
     XCTAssertLessThan(idx, 3U);
     seenKeys[idx] = aKey;
     seenKeys[idx] = aKey;
     seenObjects[idx] = aObject;
     seenObjects[idx] = aObject;
@@ -3426,7 +3426,7 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
   // Stopping the enumeration.
   // Stopping the enumeration.
   idx = 0;
   idx = 0;
-  [dict enumerateKeysAndObjectsUsingBlock:^(int32_t aKey, id aObject, BOOL *stop) {
+  [dict enumerateKeysAndObjectsUsingBlock:^(int32_t aKey, NSString* aObject, BOOL *stop) {
     #pragma unused(aKey, aObject)
     #pragma unused(aKey, aObject)
     if (idx == 1) *stop = YES;
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     XCTAssertNotEqual(idx, 2U);
@@ -3438,30 +3438,30 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 - (void)testEquality {
 - (void)testEquality {
   const int32_t kKeys1[] = { 11, 12, 13, 14 };
   const int32_t kKeys1[] = { 11, 12, 13, 14 };
   const int32_t kKeys2[] = { 12, 11, 14 };
   const int32_t kKeys2[] = { 12, 11, 14 };
-  const id kObjects1[] = { @"abc", @"def", @"ghi" };
-  const id kObjects2[] = { @"abc", @"jkl", @"ghi" };
-  const id kObjects3[] = { @"abc", @"def", @"ghi", @"jkl" };
-  GPBInt32ObjectDictionary *dict1 =
+  const NSString* kObjects1[] = { @"abc", @"def", @"ghi" };
+  const NSString* kObjects2[] = { @"abc", @"jkl", @"ghi" };
+  const NSString* kObjects3[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBInt32ObjectDictionary<NSString*> *dict1 =
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects1
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects1
                                                 forKeys:kKeys1
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kObjects1)];
                                                   count:GPBARRAYSIZE(kObjects1)];
   XCTAssertNotNil(dict1);
   XCTAssertNotNil(dict1);
-  GPBInt32ObjectDictionary *dict1prime =
+  GPBInt32ObjectDictionary<NSString*> *dict1prime =
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects1
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects1
                                                 forKeys:kKeys1
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kObjects1)];
                                                   count:GPBARRAYSIZE(kObjects1)];
   XCTAssertNotNil(dict1prime);
   XCTAssertNotNil(dict1prime);
-  GPBInt32ObjectDictionary *dict2 =
+  GPBInt32ObjectDictionary<NSString*> *dict2 =
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects2
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects2
                                                 forKeys:kKeys1
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kObjects2)];
                                                   count:GPBARRAYSIZE(kObjects2)];
   XCTAssertNotNil(dict2);
   XCTAssertNotNil(dict2);
-  GPBInt32ObjectDictionary *dict3 =
+  GPBInt32ObjectDictionary<NSString*> *dict3 =
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects1
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects1
                                                 forKeys:kKeys2
                                                 forKeys:kKeys2
                                                   count:GPBARRAYSIZE(kObjects1)];
                                                   count:GPBARRAYSIZE(kObjects1)];
   XCTAssertNotNil(dict3);
   XCTAssertNotNil(dict3);
-  GPBInt32ObjectDictionary *dict4 =
+  GPBInt32ObjectDictionary<NSString*> *dict4 =
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects3
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects3
                                                 forKeys:kKeys1
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kObjects3)];
                                                   count:GPBARRAYSIZE(kObjects3)];
@@ -3491,14 +3491,14 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
 - (void)testCopy {
 - (void)testCopy {
   const int32_t kKeys[] = { 11, 12, 13, 14 };
   const int32_t kKeys[] = { 11, 12, 13, 14 };
-  const id kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
-  GPBInt32ObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBInt32ObjectDictionary<NSString*> *dict =
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects
                                                 forKeys:kKeys
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kObjects)];
                                                   count:GPBARRAYSIZE(kObjects)];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
 
 
-  GPBInt32ObjectDictionary *dict2 = [dict copy];
+  GPBInt32ObjectDictionary<NSString*> *dict2 = [dict copy];
   XCTAssertNotNil(dict2);
   XCTAssertNotNil(dict2);
 
 
   // Should be new object but equal.
   // Should be new object but equal.
@@ -3512,14 +3512,14 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
 - (void)testDictionaryFromDictionary {
 - (void)testDictionaryFromDictionary {
   const int32_t kKeys[] = { 11, 12, 13, 14 };
   const int32_t kKeys[] = { 11, 12, 13, 14 };
-  const id kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
-  GPBInt32ObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBInt32ObjectDictionary<NSString*> *dict =
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects
                                                 forKeys:kKeys
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kObjects)];
                                                   count:GPBARRAYSIZE(kObjects)];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
 
 
-  GPBInt32ObjectDictionary *dict2 =
+  GPBInt32ObjectDictionary<NSString*> *dict2 =
       [GPBInt32ObjectDictionary dictionaryWithDictionary:dict];
       [GPBInt32ObjectDictionary dictionaryWithDictionary:dict];
   XCTAssertNotNil(dict2);
   XCTAssertNotNil(dict2);
 
 
@@ -3530,7 +3530,7 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 }
 }
 
 
 - (void)testAdds {
 - (void)testAdds {
-  GPBInt32ObjectDictionary *dict = [GPBInt32ObjectDictionary dictionary];
+  GPBInt32ObjectDictionary<NSString*> *dict = [GPBInt32ObjectDictionary dictionary];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
 
 
   XCTAssertEqual(dict.count, 0U);
   XCTAssertEqual(dict.count, 0U);
@@ -3538,8 +3538,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
   XCTAssertEqual(dict.count, 1U);
   XCTAssertEqual(dict.count, 1U);
 
 
   const int32_t kKeys[] = { 12, 13, 14 };
   const int32_t kKeys[] = { 12, 13, 14 };
-  const id kObjects[] = { @"def", @"ghi", @"jkl" };
-  GPBInt32ObjectDictionary *dict2 =
+  const NSString* kObjects[] = { @"def", @"ghi", @"jkl" };
+  GPBInt32ObjectDictionary<NSString*> *dict2 =
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects
                                                 forKeys:kKeys
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kObjects)];
                                                   count:GPBARRAYSIZE(kObjects)];
@@ -3556,8 +3556,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
 - (void)testRemove {
 - (void)testRemove {
   const int32_t kKeys[] = { 11, 12, 13, 14 };
   const int32_t kKeys[] = { 11, 12, 13, 14 };
-  const id kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
-  GPBInt32ObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBInt32ObjectDictionary<NSString*> *dict =
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects
                                          forKeys:kKeys
                                          forKeys:kKeys
                                            count:GPBARRAYSIZE(kObjects)];
                                            count:GPBARRAYSIZE(kObjects)];
@@ -3597,8 +3597,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
 - (void)testInplaceMutation {
 - (void)testInplaceMutation {
   const int32_t kKeys[] = { 11, 12, 13, 14 };
   const int32_t kKeys[] = { 11, 12, 13, 14 };
-  const id kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
-  GPBInt32ObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBInt32ObjectDictionary<NSString*> *dict =
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects
                                          forKeys:kKeys
                                          forKeys:kKeys
                                            count:GPBARRAYSIZE(kObjects)];
                                            count:GPBARRAYSIZE(kObjects)];
@@ -3624,8 +3624,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
   XCTAssertEqualObjects([dict objectForKey:14], @"def");
   XCTAssertEqualObjects([dict objectForKey:14], @"def");
 
 
   const int32_t kKeys2[] = { 12, 13 };
   const int32_t kKeys2[] = { 12, 13 };
-  const id kObjects2[] = { @"ghi", @"abc" };
-  GPBInt32ObjectDictionary *dict2 =
+  const NSString* kObjects2[] = { @"ghi", @"abc" };
+  GPBInt32ObjectDictionary<NSString*> *dict2 =
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects2
       [[GPBInt32ObjectDictionary alloc] initWithObjects:kObjects2
                                                 forKeys:kKeys2
                                                 forKeys:kKeys2
                                                   count:GPBARRAYSIZE(kObjects2)];
                                                   count:GPBARRAYSIZE(kObjects2)];

+ 32 - 32
objectivec/Tests/GPBDictionaryTests+Int64.m

@@ -3363,11 +3363,11 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 @implementation GPBInt64ObjectDictionaryTests
 @implementation GPBInt64ObjectDictionaryTests
 
 
 - (void)testEmpty {
 - (void)testEmpty {
-  GPBInt64ObjectDictionary *dict = [[GPBInt64ObjectDictionary alloc] init];
+  GPBInt64ObjectDictionary<NSString*> *dict = [[GPBInt64ObjectDictionary alloc] init];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertNil([dict objectForKey:21LL]);
   XCTAssertNil([dict objectForKey:21LL]);
-  [dict enumerateKeysAndObjectsUsingBlock:^(int64_t aKey, id aObject, BOOL *stop) {
+  [dict enumerateKeysAndObjectsUsingBlock:^(int64_t aKey, NSString* aObject, BOOL *stop) {
     #pragma unused(aKey, aObject, stop)
     #pragma unused(aKey, aObject, stop)
     XCTFail(@"Shouldn't get here!");
     XCTFail(@"Shouldn't get here!");
   }];
   }];
@@ -3375,12 +3375,12 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 }
 }
 
 
 - (void)testOne {
 - (void)testOne {
-  GPBInt64ObjectDictionary *dict = [GPBInt64ObjectDictionary dictionaryWithObject:@"abc" forKey:21LL];
+  GPBInt64ObjectDictionary<NSString*> *dict = [GPBInt64ObjectDictionary dictionaryWithObject:@"abc" forKey:21LL];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 1U);
   XCTAssertEqual(dict.count, 1U);
   XCTAssertEqualObjects([dict objectForKey:21LL], @"abc");
   XCTAssertEqualObjects([dict objectForKey:21LL], @"abc");
   XCTAssertNil([dict objectForKey:22LL]);
   XCTAssertNil([dict objectForKey:22LL]);
-  [dict enumerateKeysAndObjectsUsingBlock:^(int64_t aKey, id aObject, BOOL *stop) {
+  [dict enumerateKeysAndObjectsUsingBlock:^(int64_t aKey, NSString* aObject, BOOL *stop) {
     XCTAssertEqual(aKey, 21LL);
     XCTAssertEqual(aKey, 21LL);
     XCTAssertEqualObjects(aObject, @"abc");
     XCTAssertEqualObjects(aObject, @"abc");
     XCTAssertNotEqual(stop, NULL);
     XCTAssertNotEqual(stop, NULL);
@@ -3389,8 +3389,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
 - (void)testBasics {
 - (void)testBasics {
   const int64_t kKeys[] = { 21LL, 22LL, 23LL };
   const int64_t kKeys[] = { 21LL, 22LL, 23LL };
-  const id kObjects[] = { @"abc", @"def", @"ghi" };
-  GPBInt64ObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi" };
+  GPBInt64ObjectDictionary<NSString*> *dict =
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects
                                                 forKeys:kKeys
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kObjects)];
                                                   count:GPBARRAYSIZE(kObjects)];
@@ -3403,8 +3403,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
   __block NSUInteger idx = 0;
   __block NSUInteger idx = 0;
   int64_t *seenKeys = malloc(3 * sizeof(int64_t));
   int64_t *seenKeys = malloc(3 * sizeof(int64_t));
-  id *seenObjects = malloc(3 * sizeof(id));
-  [dict enumerateKeysAndObjectsUsingBlock:^(int64_t aKey, id aObject, BOOL *stop) {
+  NSString* *seenObjects = malloc(3 * sizeof(NSString*));
+  [dict enumerateKeysAndObjectsUsingBlock:^(int64_t aKey, NSString* aObject, BOOL *stop) {
     XCTAssertLessThan(idx, 3U);
     XCTAssertLessThan(idx, 3U);
     seenKeys[idx] = aKey;
     seenKeys[idx] = aKey;
     seenObjects[idx] = aObject;
     seenObjects[idx] = aObject;
@@ -3426,7 +3426,7 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
   // Stopping the enumeration.
   // Stopping the enumeration.
   idx = 0;
   idx = 0;
-  [dict enumerateKeysAndObjectsUsingBlock:^(int64_t aKey, id aObject, BOOL *stop) {
+  [dict enumerateKeysAndObjectsUsingBlock:^(int64_t aKey, NSString* aObject, BOOL *stop) {
     #pragma unused(aKey, aObject)
     #pragma unused(aKey, aObject)
     if (idx == 1) *stop = YES;
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     XCTAssertNotEqual(idx, 2U);
@@ -3438,30 +3438,30 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 - (void)testEquality {
 - (void)testEquality {
   const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
   const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
   const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
   const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
-  const id kObjects1[] = { @"abc", @"def", @"ghi" };
-  const id kObjects2[] = { @"abc", @"jkl", @"ghi" };
-  const id kObjects3[] = { @"abc", @"def", @"ghi", @"jkl" };
-  GPBInt64ObjectDictionary *dict1 =
+  const NSString* kObjects1[] = { @"abc", @"def", @"ghi" };
+  const NSString* kObjects2[] = { @"abc", @"jkl", @"ghi" };
+  const NSString* kObjects3[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBInt64ObjectDictionary<NSString*> *dict1 =
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects1
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects1
                                                 forKeys:kKeys1
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kObjects1)];
                                                   count:GPBARRAYSIZE(kObjects1)];
   XCTAssertNotNil(dict1);
   XCTAssertNotNil(dict1);
-  GPBInt64ObjectDictionary *dict1prime =
+  GPBInt64ObjectDictionary<NSString*> *dict1prime =
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects1
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects1
                                                 forKeys:kKeys1
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kObjects1)];
                                                   count:GPBARRAYSIZE(kObjects1)];
   XCTAssertNotNil(dict1prime);
   XCTAssertNotNil(dict1prime);
-  GPBInt64ObjectDictionary *dict2 =
+  GPBInt64ObjectDictionary<NSString*> *dict2 =
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects2
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects2
                                                 forKeys:kKeys1
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kObjects2)];
                                                   count:GPBARRAYSIZE(kObjects2)];
   XCTAssertNotNil(dict2);
   XCTAssertNotNil(dict2);
-  GPBInt64ObjectDictionary *dict3 =
+  GPBInt64ObjectDictionary<NSString*> *dict3 =
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects1
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects1
                                                 forKeys:kKeys2
                                                 forKeys:kKeys2
                                                   count:GPBARRAYSIZE(kObjects1)];
                                                   count:GPBARRAYSIZE(kObjects1)];
   XCTAssertNotNil(dict3);
   XCTAssertNotNil(dict3);
-  GPBInt64ObjectDictionary *dict4 =
+  GPBInt64ObjectDictionary<NSString*> *dict4 =
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects3
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects3
                                                 forKeys:kKeys1
                                                 forKeys:kKeys1
                                                   count:GPBARRAYSIZE(kObjects3)];
                                                   count:GPBARRAYSIZE(kObjects3)];
@@ -3491,14 +3491,14 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
 - (void)testCopy {
 - (void)testCopy {
   const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
   const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
-  const id kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
-  GPBInt64ObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBInt64ObjectDictionary<NSString*> *dict =
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects
                                                 forKeys:kKeys
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kObjects)];
                                                   count:GPBARRAYSIZE(kObjects)];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
 
 
-  GPBInt64ObjectDictionary *dict2 = [dict copy];
+  GPBInt64ObjectDictionary<NSString*> *dict2 = [dict copy];
   XCTAssertNotNil(dict2);
   XCTAssertNotNil(dict2);
 
 
   // Should be new object but equal.
   // Should be new object but equal.
@@ -3512,14 +3512,14 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
 - (void)testDictionaryFromDictionary {
 - (void)testDictionaryFromDictionary {
   const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
   const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
-  const id kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
-  GPBInt64ObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBInt64ObjectDictionary<NSString*> *dict =
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects
                                                 forKeys:kKeys
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kObjects)];
                                                   count:GPBARRAYSIZE(kObjects)];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
 
 
-  GPBInt64ObjectDictionary *dict2 =
+  GPBInt64ObjectDictionary<NSString*> *dict2 =
       [GPBInt64ObjectDictionary dictionaryWithDictionary:dict];
       [GPBInt64ObjectDictionary dictionaryWithDictionary:dict];
   XCTAssertNotNil(dict2);
   XCTAssertNotNil(dict2);
 
 
@@ -3530,7 +3530,7 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 }
 }
 
 
 - (void)testAdds {
 - (void)testAdds {
-  GPBInt64ObjectDictionary *dict = [GPBInt64ObjectDictionary dictionary];
+  GPBInt64ObjectDictionary<NSString*> *dict = [GPBInt64ObjectDictionary dictionary];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
 
 
   XCTAssertEqual(dict.count, 0U);
   XCTAssertEqual(dict.count, 0U);
@@ -3538,8 +3538,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
   XCTAssertEqual(dict.count, 1U);
   XCTAssertEqual(dict.count, 1U);
 
 
   const int64_t kKeys[] = { 22LL, 23LL, 24LL };
   const int64_t kKeys[] = { 22LL, 23LL, 24LL };
-  const id kObjects[] = { @"def", @"ghi", @"jkl" };
-  GPBInt64ObjectDictionary *dict2 =
+  const NSString* kObjects[] = { @"def", @"ghi", @"jkl" };
+  GPBInt64ObjectDictionary<NSString*> *dict2 =
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects
                                                 forKeys:kKeys
                                                 forKeys:kKeys
                                                   count:GPBARRAYSIZE(kObjects)];
                                                   count:GPBARRAYSIZE(kObjects)];
@@ -3556,8 +3556,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
 - (void)testRemove {
 - (void)testRemove {
   const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
   const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
-  const id kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
-  GPBInt64ObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBInt64ObjectDictionary<NSString*> *dict =
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects
                                          forKeys:kKeys
                                          forKeys:kKeys
                                            count:GPBARRAYSIZE(kObjects)];
                                            count:GPBARRAYSIZE(kObjects)];
@@ -3597,8 +3597,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
 - (void)testInplaceMutation {
 - (void)testInplaceMutation {
   const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
   const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
-  const id kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
-  GPBInt64ObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBInt64ObjectDictionary<NSString*> *dict =
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects
                                          forKeys:kKeys
                                          forKeys:kKeys
                                            count:GPBARRAYSIZE(kObjects)];
                                            count:GPBARRAYSIZE(kObjects)];
@@ -3624,8 +3624,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
   XCTAssertEqualObjects([dict objectForKey:24LL], @"def");
   XCTAssertEqualObjects([dict objectForKey:24LL], @"def");
 
 
   const int64_t kKeys2[] = { 22LL, 23LL };
   const int64_t kKeys2[] = { 22LL, 23LL };
-  const id kObjects2[] = { @"ghi", @"abc" };
-  GPBInt64ObjectDictionary *dict2 =
+  const NSString* kObjects2[] = { @"ghi", @"abc" };
+  GPBInt64ObjectDictionary<NSString*> *dict2 =
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects2
       [[GPBInt64ObjectDictionary alloc] initWithObjects:kObjects2
                                                 forKeys:kKeys2
                                                 forKeys:kKeys2
                                                   count:GPBARRAYSIZE(kObjects2)];
                                                   count:GPBARRAYSIZE(kObjects2)];

+ 32 - 32
objectivec/Tests/GPBDictionaryTests+UInt32.m

@@ -3363,11 +3363,11 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 @implementation GPBUInt32ObjectDictionaryTests
 @implementation GPBUInt32ObjectDictionaryTests
 
 
 - (void)testEmpty {
 - (void)testEmpty {
-  GPBUInt32ObjectDictionary *dict = [[GPBUInt32ObjectDictionary alloc] init];
+  GPBUInt32ObjectDictionary<NSString*> *dict = [[GPBUInt32ObjectDictionary alloc] init];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertNil([dict objectForKey:1U]);
   XCTAssertNil([dict objectForKey:1U]);
-  [dict enumerateKeysAndObjectsUsingBlock:^(uint32_t aKey, id aObject, BOOL *stop) {
+  [dict enumerateKeysAndObjectsUsingBlock:^(uint32_t aKey, NSString* aObject, BOOL *stop) {
     #pragma unused(aKey, aObject, stop)
     #pragma unused(aKey, aObject, stop)
     XCTFail(@"Shouldn't get here!");
     XCTFail(@"Shouldn't get here!");
   }];
   }];
@@ -3375,12 +3375,12 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 }
 }
 
 
 - (void)testOne {
 - (void)testOne {
-  GPBUInt32ObjectDictionary *dict = [GPBUInt32ObjectDictionary dictionaryWithObject:@"abc" forKey:1U];
+  GPBUInt32ObjectDictionary<NSString*> *dict = [GPBUInt32ObjectDictionary dictionaryWithObject:@"abc" forKey:1U];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 1U);
   XCTAssertEqual(dict.count, 1U);
   XCTAssertEqualObjects([dict objectForKey:1U], @"abc");
   XCTAssertEqualObjects([dict objectForKey:1U], @"abc");
   XCTAssertNil([dict objectForKey:2U]);
   XCTAssertNil([dict objectForKey:2U]);
-  [dict enumerateKeysAndObjectsUsingBlock:^(uint32_t aKey, id aObject, BOOL *stop) {
+  [dict enumerateKeysAndObjectsUsingBlock:^(uint32_t aKey, NSString* aObject, BOOL *stop) {
     XCTAssertEqual(aKey, 1U);
     XCTAssertEqual(aKey, 1U);
     XCTAssertEqualObjects(aObject, @"abc");
     XCTAssertEqualObjects(aObject, @"abc");
     XCTAssertNotEqual(stop, NULL);
     XCTAssertNotEqual(stop, NULL);
@@ -3389,8 +3389,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
 - (void)testBasics {
 - (void)testBasics {
   const uint32_t kKeys[] = { 1U, 2U, 3U };
   const uint32_t kKeys[] = { 1U, 2U, 3U };
-  const id kObjects[] = { @"abc", @"def", @"ghi" };
-  GPBUInt32ObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi" };
+  GPBUInt32ObjectDictionary<NSString*> *dict =
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
                                                  forKeys:kKeys
                                                  forKeys:kKeys
                                                    count:GPBARRAYSIZE(kObjects)];
                                                    count:GPBARRAYSIZE(kObjects)];
@@ -3403,8 +3403,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
   __block NSUInteger idx = 0;
   __block NSUInteger idx = 0;
   uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
   uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
-  id *seenObjects = malloc(3 * sizeof(id));
-  [dict enumerateKeysAndObjectsUsingBlock:^(uint32_t aKey, id aObject, BOOL *stop) {
+  NSString* *seenObjects = malloc(3 * sizeof(NSString*));
+  [dict enumerateKeysAndObjectsUsingBlock:^(uint32_t aKey, NSString* aObject, BOOL *stop) {
     XCTAssertLessThan(idx, 3U);
     XCTAssertLessThan(idx, 3U);
     seenKeys[idx] = aKey;
     seenKeys[idx] = aKey;
     seenObjects[idx] = aObject;
     seenObjects[idx] = aObject;
@@ -3426,7 +3426,7 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
   // Stopping the enumeration.
   // Stopping the enumeration.
   idx = 0;
   idx = 0;
-  [dict enumerateKeysAndObjectsUsingBlock:^(uint32_t aKey, id aObject, BOOL *stop) {
+  [dict enumerateKeysAndObjectsUsingBlock:^(uint32_t aKey, NSString* aObject, BOOL *stop) {
     #pragma unused(aKey, aObject)
     #pragma unused(aKey, aObject)
     if (idx == 1) *stop = YES;
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     XCTAssertNotEqual(idx, 2U);
@@ -3438,30 +3438,30 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 - (void)testEquality {
 - (void)testEquality {
   const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
   const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
   const uint32_t kKeys2[] = { 2U, 1U, 4U };
   const uint32_t kKeys2[] = { 2U, 1U, 4U };
-  const id kObjects1[] = { @"abc", @"def", @"ghi" };
-  const id kObjects2[] = { @"abc", @"jkl", @"ghi" };
-  const id kObjects3[] = { @"abc", @"def", @"ghi", @"jkl" };
-  GPBUInt32ObjectDictionary *dict1 =
+  const NSString* kObjects1[] = { @"abc", @"def", @"ghi" };
+  const NSString* kObjects2[] = { @"abc", @"jkl", @"ghi" };
+  const NSString* kObjects3[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBUInt32ObjectDictionary<NSString*> *dict1 =
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects1
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects1
                                                  forKeys:kKeys1
                                                  forKeys:kKeys1
                                                    count:GPBARRAYSIZE(kObjects1)];
                                                    count:GPBARRAYSIZE(kObjects1)];
   XCTAssertNotNil(dict1);
   XCTAssertNotNil(dict1);
-  GPBUInt32ObjectDictionary *dict1prime =
+  GPBUInt32ObjectDictionary<NSString*> *dict1prime =
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects1
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects1
                                                  forKeys:kKeys1
                                                  forKeys:kKeys1
                                                    count:GPBARRAYSIZE(kObjects1)];
                                                    count:GPBARRAYSIZE(kObjects1)];
   XCTAssertNotNil(dict1prime);
   XCTAssertNotNil(dict1prime);
-  GPBUInt32ObjectDictionary *dict2 =
+  GPBUInt32ObjectDictionary<NSString*> *dict2 =
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects2
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects2
                                                  forKeys:kKeys1
                                                  forKeys:kKeys1
                                                    count:GPBARRAYSIZE(kObjects2)];
                                                    count:GPBARRAYSIZE(kObjects2)];
   XCTAssertNotNil(dict2);
   XCTAssertNotNil(dict2);
-  GPBUInt32ObjectDictionary *dict3 =
+  GPBUInt32ObjectDictionary<NSString*> *dict3 =
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects1
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects1
                                                  forKeys:kKeys2
                                                  forKeys:kKeys2
                                                    count:GPBARRAYSIZE(kObjects1)];
                                                    count:GPBARRAYSIZE(kObjects1)];
   XCTAssertNotNil(dict3);
   XCTAssertNotNil(dict3);
-  GPBUInt32ObjectDictionary *dict4 =
+  GPBUInt32ObjectDictionary<NSString*> *dict4 =
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects3
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects3
                                                  forKeys:kKeys1
                                                  forKeys:kKeys1
                                                    count:GPBARRAYSIZE(kObjects3)];
                                                    count:GPBARRAYSIZE(kObjects3)];
@@ -3491,14 +3491,14 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
 - (void)testCopy {
 - (void)testCopy {
   const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
   const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
-  const id kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
-  GPBUInt32ObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBUInt32ObjectDictionary<NSString*> *dict =
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
                                                  forKeys:kKeys
                                                  forKeys:kKeys
                                                    count:GPBARRAYSIZE(kObjects)];
                                                    count:GPBARRAYSIZE(kObjects)];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
 
 
-  GPBUInt32ObjectDictionary *dict2 = [dict copy];
+  GPBUInt32ObjectDictionary<NSString*> *dict2 = [dict copy];
   XCTAssertNotNil(dict2);
   XCTAssertNotNil(dict2);
 
 
   // Should be new object but equal.
   // Should be new object but equal.
@@ -3512,14 +3512,14 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
 - (void)testDictionaryFromDictionary {
 - (void)testDictionaryFromDictionary {
   const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
   const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
-  const id kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
-  GPBUInt32ObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBUInt32ObjectDictionary<NSString*> *dict =
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
                                                  forKeys:kKeys
                                                  forKeys:kKeys
                                                    count:GPBARRAYSIZE(kObjects)];
                                                    count:GPBARRAYSIZE(kObjects)];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
 
 
-  GPBUInt32ObjectDictionary *dict2 =
+  GPBUInt32ObjectDictionary<NSString*> *dict2 =
       [GPBUInt32ObjectDictionary dictionaryWithDictionary:dict];
       [GPBUInt32ObjectDictionary dictionaryWithDictionary:dict];
   XCTAssertNotNil(dict2);
   XCTAssertNotNil(dict2);
 
 
@@ -3530,7 +3530,7 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 }
 }
 
 
 - (void)testAdds {
 - (void)testAdds {
-  GPBUInt32ObjectDictionary *dict = [GPBUInt32ObjectDictionary dictionary];
+  GPBUInt32ObjectDictionary<NSString*> *dict = [GPBUInt32ObjectDictionary dictionary];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
 
 
   XCTAssertEqual(dict.count, 0U);
   XCTAssertEqual(dict.count, 0U);
@@ -3538,8 +3538,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
   XCTAssertEqual(dict.count, 1U);
   XCTAssertEqual(dict.count, 1U);
 
 
   const uint32_t kKeys[] = { 2U, 3U, 4U };
   const uint32_t kKeys[] = { 2U, 3U, 4U };
-  const id kObjects[] = { @"def", @"ghi", @"jkl" };
-  GPBUInt32ObjectDictionary *dict2 =
+  const NSString* kObjects[] = { @"def", @"ghi", @"jkl" };
+  GPBUInt32ObjectDictionary<NSString*> *dict2 =
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
                                                  forKeys:kKeys
                                                  forKeys:kKeys
                                                    count:GPBARRAYSIZE(kObjects)];
                                                    count:GPBARRAYSIZE(kObjects)];
@@ -3556,8 +3556,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
 - (void)testRemove {
 - (void)testRemove {
   const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
   const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
-  const id kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
-  GPBUInt32ObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBUInt32ObjectDictionary<NSString*> *dict =
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
                                           forKeys:kKeys
                                           forKeys:kKeys
                                             count:GPBARRAYSIZE(kObjects)];
                                             count:GPBARRAYSIZE(kObjects)];
@@ -3597,8 +3597,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
 - (void)testInplaceMutation {
 - (void)testInplaceMutation {
   const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
   const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
-  const id kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
-  GPBUInt32ObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBUInt32ObjectDictionary<NSString*> *dict =
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects
                                           forKeys:kKeys
                                           forKeys:kKeys
                                             count:GPBARRAYSIZE(kObjects)];
                                             count:GPBARRAYSIZE(kObjects)];
@@ -3624,8 +3624,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
   XCTAssertEqualObjects([dict objectForKey:4U], @"def");
   XCTAssertEqualObjects([dict objectForKey:4U], @"def");
 
 
   const uint32_t kKeys2[] = { 2U, 3U };
   const uint32_t kKeys2[] = { 2U, 3U };
-  const id kObjects2[] = { @"ghi", @"abc" };
-  GPBUInt32ObjectDictionary *dict2 =
+  const NSString* kObjects2[] = { @"ghi", @"abc" };
+  GPBUInt32ObjectDictionary<NSString*> *dict2 =
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects2
       [[GPBUInt32ObjectDictionary alloc] initWithObjects:kObjects2
                                                  forKeys:kKeys2
                                                  forKeys:kKeys2
                                                    count:GPBARRAYSIZE(kObjects2)];
                                                    count:GPBARRAYSIZE(kObjects2)];

+ 32 - 32
objectivec/Tests/GPBDictionaryTests+UInt64.m

@@ -3363,11 +3363,11 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 @implementation GPBUInt64ObjectDictionaryTests
 @implementation GPBUInt64ObjectDictionaryTests
 
 
 - (void)testEmpty {
 - (void)testEmpty {
-  GPBUInt64ObjectDictionary *dict = [[GPBUInt64ObjectDictionary alloc] init];
+  GPBUInt64ObjectDictionary<NSString*> *dict = [[GPBUInt64ObjectDictionary alloc] init];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertNil([dict objectForKey:31ULL]);
   XCTAssertNil([dict objectForKey:31ULL]);
-  [dict enumerateKeysAndObjectsUsingBlock:^(uint64_t aKey, id aObject, BOOL *stop) {
+  [dict enumerateKeysAndObjectsUsingBlock:^(uint64_t aKey, NSString* aObject, BOOL *stop) {
     #pragma unused(aKey, aObject, stop)
     #pragma unused(aKey, aObject, stop)
     XCTFail(@"Shouldn't get here!");
     XCTFail(@"Shouldn't get here!");
   }];
   }];
@@ -3375,12 +3375,12 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 }
 }
 
 
 - (void)testOne {
 - (void)testOne {
-  GPBUInt64ObjectDictionary *dict = [GPBUInt64ObjectDictionary dictionaryWithObject:@"abc" forKey:31ULL];
+  GPBUInt64ObjectDictionary<NSString*> *dict = [GPBUInt64ObjectDictionary dictionaryWithObject:@"abc" forKey:31ULL];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 1U);
   XCTAssertEqual(dict.count, 1U);
   XCTAssertEqualObjects([dict objectForKey:31ULL], @"abc");
   XCTAssertEqualObjects([dict objectForKey:31ULL], @"abc");
   XCTAssertNil([dict objectForKey:32ULL]);
   XCTAssertNil([dict objectForKey:32ULL]);
-  [dict enumerateKeysAndObjectsUsingBlock:^(uint64_t aKey, id aObject, BOOL *stop) {
+  [dict enumerateKeysAndObjectsUsingBlock:^(uint64_t aKey, NSString* aObject, BOOL *stop) {
     XCTAssertEqual(aKey, 31ULL);
     XCTAssertEqual(aKey, 31ULL);
     XCTAssertEqualObjects(aObject, @"abc");
     XCTAssertEqualObjects(aObject, @"abc");
     XCTAssertNotEqual(stop, NULL);
     XCTAssertNotEqual(stop, NULL);
@@ -3389,8 +3389,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
 - (void)testBasics {
 - (void)testBasics {
   const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
   const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
-  const id kObjects[] = { @"abc", @"def", @"ghi" };
-  GPBUInt64ObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi" };
+  GPBUInt64ObjectDictionary<NSString*> *dict =
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects
                                                  forKeys:kKeys
                                                  forKeys:kKeys
                                                    count:GPBARRAYSIZE(kObjects)];
                                                    count:GPBARRAYSIZE(kObjects)];
@@ -3403,8 +3403,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
   __block NSUInteger idx = 0;
   __block NSUInteger idx = 0;
   uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
   uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
-  id *seenObjects = malloc(3 * sizeof(id));
-  [dict enumerateKeysAndObjectsUsingBlock:^(uint64_t aKey, id aObject, BOOL *stop) {
+  NSString* *seenObjects = malloc(3 * sizeof(NSString*));
+  [dict enumerateKeysAndObjectsUsingBlock:^(uint64_t aKey, NSString* aObject, BOOL *stop) {
     XCTAssertLessThan(idx, 3U);
     XCTAssertLessThan(idx, 3U);
     seenKeys[idx] = aKey;
     seenKeys[idx] = aKey;
     seenObjects[idx] = aObject;
     seenObjects[idx] = aObject;
@@ -3426,7 +3426,7 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
   // Stopping the enumeration.
   // Stopping the enumeration.
   idx = 0;
   idx = 0;
-  [dict enumerateKeysAndObjectsUsingBlock:^(uint64_t aKey, id aObject, BOOL *stop) {
+  [dict enumerateKeysAndObjectsUsingBlock:^(uint64_t aKey, NSString* aObject, BOOL *stop) {
     #pragma unused(aKey, aObject)
     #pragma unused(aKey, aObject)
     if (idx == 1) *stop = YES;
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     XCTAssertNotEqual(idx, 2U);
@@ -3438,30 +3438,30 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 - (void)testEquality {
 - (void)testEquality {
   const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
   const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
   const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
   const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
-  const id kObjects1[] = { @"abc", @"def", @"ghi" };
-  const id kObjects2[] = { @"abc", @"jkl", @"ghi" };
-  const id kObjects3[] = { @"abc", @"def", @"ghi", @"jkl" };
-  GPBUInt64ObjectDictionary *dict1 =
+  const NSString* kObjects1[] = { @"abc", @"def", @"ghi" };
+  const NSString* kObjects2[] = { @"abc", @"jkl", @"ghi" };
+  const NSString* kObjects3[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBUInt64ObjectDictionary<NSString*> *dict1 =
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects1
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects1
                                                  forKeys:kKeys1
                                                  forKeys:kKeys1
                                                    count:GPBARRAYSIZE(kObjects1)];
                                                    count:GPBARRAYSIZE(kObjects1)];
   XCTAssertNotNil(dict1);
   XCTAssertNotNil(dict1);
-  GPBUInt64ObjectDictionary *dict1prime =
+  GPBUInt64ObjectDictionary<NSString*> *dict1prime =
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects1
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects1
                                                  forKeys:kKeys1
                                                  forKeys:kKeys1
                                                    count:GPBARRAYSIZE(kObjects1)];
                                                    count:GPBARRAYSIZE(kObjects1)];
   XCTAssertNotNil(dict1prime);
   XCTAssertNotNil(dict1prime);
-  GPBUInt64ObjectDictionary *dict2 =
+  GPBUInt64ObjectDictionary<NSString*> *dict2 =
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects2
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects2
                                                  forKeys:kKeys1
                                                  forKeys:kKeys1
                                                    count:GPBARRAYSIZE(kObjects2)];
                                                    count:GPBARRAYSIZE(kObjects2)];
   XCTAssertNotNil(dict2);
   XCTAssertNotNil(dict2);
-  GPBUInt64ObjectDictionary *dict3 =
+  GPBUInt64ObjectDictionary<NSString*> *dict3 =
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects1
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects1
                                                  forKeys:kKeys2
                                                  forKeys:kKeys2
                                                    count:GPBARRAYSIZE(kObjects1)];
                                                    count:GPBARRAYSIZE(kObjects1)];
   XCTAssertNotNil(dict3);
   XCTAssertNotNil(dict3);
-  GPBUInt64ObjectDictionary *dict4 =
+  GPBUInt64ObjectDictionary<NSString*> *dict4 =
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects3
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects3
                                                  forKeys:kKeys1
                                                  forKeys:kKeys1
                                                    count:GPBARRAYSIZE(kObjects3)];
                                                    count:GPBARRAYSIZE(kObjects3)];
@@ -3491,14 +3491,14 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
 - (void)testCopy {
 - (void)testCopy {
   const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
   const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
-  const id kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
-  GPBUInt64ObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBUInt64ObjectDictionary<NSString*> *dict =
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects
                                                  forKeys:kKeys
                                                  forKeys:kKeys
                                                    count:GPBARRAYSIZE(kObjects)];
                                                    count:GPBARRAYSIZE(kObjects)];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
 
 
-  GPBUInt64ObjectDictionary *dict2 = [dict copy];
+  GPBUInt64ObjectDictionary<NSString*> *dict2 = [dict copy];
   XCTAssertNotNil(dict2);
   XCTAssertNotNil(dict2);
 
 
   // Should be new object but equal.
   // Should be new object but equal.
@@ -3512,14 +3512,14 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
 - (void)testDictionaryFromDictionary {
 - (void)testDictionaryFromDictionary {
   const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
   const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
-  const id kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
-  GPBUInt64ObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBUInt64ObjectDictionary<NSString*> *dict =
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects
                                                  forKeys:kKeys
                                                  forKeys:kKeys
                                                    count:GPBARRAYSIZE(kObjects)];
                                                    count:GPBARRAYSIZE(kObjects)];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
 
 
-  GPBUInt64ObjectDictionary *dict2 =
+  GPBUInt64ObjectDictionary<NSString*> *dict2 =
       [GPBUInt64ObjectDictionary dictionaryWithDictionary:dict];
       [GPBUInt64ObjectDictionary dictionaryWithDictionary:dict];
   XCTAssertNotNil(dict2);
   XCTAssertNotNil(dict2);
 
 
@@ -3530,7 +3530,7 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 }
 }
 
 
 - (void)testAdds {
 - (void)testAdds {
-  GPBUInt64ObjectDictionary *dict = [GPBUInt64ObjectDictionary dictionary];
+  GPBUInt64ObjectDictionary<NSString*> *dict = [GPBUInt64ObjectDictionary dictionary];
   XCTAssertNotNil(dict);
   XCTAssertNotNil(dict);
 
 
   XCTAssertEqual(dict.count, 0U);
   XCTAssertEqual(dict.count, 0U);
@@ -3538,8 +3538,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
   XCTAssertEqual(dict.count, 1U);
   XCTAssertEqual(dict.count, 1U);
 
 
   const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
   const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
-  const id kObjects[] = { @"def", @"ghi", @"jkl" };
-  GPBUInt64ObjectDictionary *dict2 =
+  const NSString* kObjects[] = { @"def", @"ghi", @"jkl" };
+  GPBUInt64ObjectDictionary<NSString*> *dict2 =
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects
                                                  forKeys:kKeys
                                                  forKeys:kKeys
                                                    count:GPBARRAYSIZE(kObjects)];
                                                    count:GPBARRAYSIZE(kObjects)];
@@ -3556,8 +3556,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
 - (void)testRemove {
 - (void)testRemove {
   const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
   const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
-  const id kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
-  GPBUInt64ObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBUInt64ObjectDictionary<NSString*> *dict =
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects
                                           forKeys:kKeys
                                           forKeys:kKeys
                                             count:GPBARRAYSIZE(kObjects)];
                                             count:GPBARRAYSIZE(kObjects)];
@@ -3597,8 +3597,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
 
 
 - (void)testInplaceMutation {
 - (void)testInplaceMutation {
   const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
   const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
-  const id kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
-  GPBUInt64ObjectDictionary *dict =
+  const NSString* kObjects[] = { @"abc", @"def", @"ghi", @"jkl" };
+  GPBUInt64ObjectDictionary<NSString*> *dict =
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects
                                           forKeys:kKeys
                                           forKeys:kKeys
                                             count:GPBARRAYSIZE(kObjects)];
                                             count:GPBARRAYSIZE(kObjects)];
@@ -3624,8 +3624,8 @@ static BOOL TestingEnum_IsValidValue(int32_t value) {
   XCTAssertEqualObjects([dict objectForKey:34ULL], @"def");
   XCTAssertEqualObjects([dict objectForKey:34ULL], @"def");
 
 
   const uint64_t kKeys2[] = { 32ULL, 33ULL };
   const uint64_t kKeys2[] = { 32ULL, 33ULL };
-  const id kObjects2[] = { @"ghi", @"abc" };
-  GPBUInt64ObjectDictionary *dict2 =
+  const NSString* kObjects2[] = { @"ghi", @"abc" };
+  GPBUInt64ObjectDictionary<NSString*> *dict2 =
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects2
       [[GPBUInt64ObjectDictionary alloc] initWithObjects:kObjects2
                                                  forKeys:kKeys2
                                                  forKeys:kKeys2
                                                    count:GPBARRAYSIZE(kObjects2)];
                                                    count:GPBARRAYSIZE(kObjects2)];

+ 59 - 52
objectivec/Tests/GPBDictionaryTests.pddm

@@ -30,7 +30,7 @@
 
 
 //%PDDM-DEFINE TEST_FOR_POD_KEY(KEY_NAME, KEY_TYPE, KEY1, KEY2, KEY3, KEY4)
 //%PDDM-DEFINE TEST_FOR_POD_KEY(KEY_NAME, KEY_TYPE, KEY1, KEY2, KEY3, KEY4)
 //%TESTS_FOR_POD_VALUES(KEY_NAME, KEY_TYPE, , , KEY1, KEY2, KEY3, KEY4)
 //%TESTS_FOR_POD_VALUES(KEY_NAME, KEY_TYPE, , , KEY1, KEY2, KEY3, KEY4)
-//%TESTS_FOR_POD_KEY_OBJECT_VALUE(KEY_NAME, KEY_TYPE, KEY1, KEY2, KEY3, KEY4, Object, id, @"abc", @"def", @"ghi", @"jkl")
+//%TESTS_FOR_POD_KEY_OBJECT_VALUE(KEY_NAME, KEY_TYPE, KEY1, KEY2, KEY3, KEY4, Object, NSString*, @"abc", @"def", @"ghi", @"jkl")
 
 
 //%PDDM-DEFINE TESTS_FOR_POD_VALUES(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4)
 //%PDDM-DEFINE TESTS_FOR_POD_VALUES(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4)
 //%TEST_HELPERS(KEY_NAME, KEY_TYPE, KisP)
 //%TEST_HELPERS(KEY_NAME, KEY_TYPE, KisP)
@@ -50,6 +50,13 @@
 //%PDDM-DEFINE TESTS_FOR_POD_KEY_OBJECT_VALUE(KEY_NAME, KEY_TYPE, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, VAL1, VAL2, VAL3, VAL4)
 //%PDDM-DEFINE TESTS_FOR_POD_KEY_OBJECT_VALUE(KEY_NAME, KEY_TYPE, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, VAL1, VAL2, VAL3, VAL4)
 //%TESTS_COMMON(KEY_NAME, KEY_TYPE, , , KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, Objects, object, OBJECT, , VAL1, VAL2, VAL3, VAL4)
 //%TESTS_COMMON(KEY_NAME, KEY_TYPE, , , KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, Objects, object, OBJECT, , VAL1, VAL2, VAL3, VAL4)
 
 
+//%PDDM-DEFINE DICTIONARY_CLASS_DECLPOD(KEY_NAME, VALUE_NAME, VALUE_TYPE)
+//%GPB##KEY_NAME##VALUE_NAME##Dictionary
+//%PDDM-DEFINE DICTIONARY_CLASS_DECLEnum(KEY_NAME, VALUE_NAME, VALUE_TYPE)
+//%GPB##KEY_NAME##VALUE_NAME##Dictionary
+//%PDDM-DEFINE DICTIONARY_CLASS_DECLOBJECT(KEY_NAME, VALUE_NAME, VALUE_TYPE)
+//%GPB##KEY_NAME##VALUE_NAME##Dictionary<VALUE_TYPE>
+
 //%PDDM-DEFINE TESTS_COMMON(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, VSUFFIX, VNAME, VHELPER, VACCESSOR, VAL1, VAL2, VAL3, VAL4)
 //%PDDM-DEFINE TESTS_COMMON(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, VSUFFIX, VNAME, VHELPER, VACCESSOR, VAL1, VAL2, VAL3, VAL4)
 //%#pragma mark - KEY_NAME -> VALUE_NAME
 //%#pragma mark - KEY_NAME -> VALUE_NAME
 //%
 //%
@@ -59,7 +66,7 @@
 //%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryTests
 //%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryTests
 //%
 //%
 //%- (void)testEmpty {
 //%- (void)testEmpty {
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
 //%  XCTAssertNotNil(dict);
 //%  XCTAssertNotNil(dict);
 //%  XCTAssertEqual(dict.count, 0U);
 //%  XCTAssertEqual(dict.count, 0U);
 //%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
 //%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
@@ -71,7 +78,7 @@
 //%}
 //%}
 //%
 //%
 //%- (void)testOne {
 //%- (void)testOne {
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWith##VNAME$u##:VAL1 forKey:KEY1];
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWith##VNAME$u##:VAL1 forKey:KEY1];
 //%  XCTAssertNotNil(dict);
 //%  XCTAssertNotNil(dict);
 //%  XCTAssertEqual(dict.count, 1U);
 //%  XCTAssertEqual(dict.count, 1U);
 //%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
 //%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
@@ -86,7 +93,7 @@
 //%- (void)testBasics {
 //%- (void)testBasics {
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3 };
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3 };
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3 };
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3 };
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
@@ -137,27 +144,27 @@
 //%  const VALUE_TYPE k##VNAME$u##s1[] = { VAL1, VAL2, VAL3 };
 //%  const VALUE_TYPE k##VNAME$u##s1[] = { VAL1, VAL2, VAL3 };
 //%  const VALUE_TYPE k##VNAME$u##s2[] = { VAL1, VAL4, VAL3 };
 //%  const VALUE_TYPE k##VNAME$u##s2[] = { VAL1, VAL4, VAL3 };
 //%  const VALUE_TYPE k##VNAME$u##s3[] = { VAL1, VAL2, VAL3, VAL4 };
 //%  const VALUE_TYPE k##VNAME$u##s3[] = { VAL1, VAL2, VAL3, VAL4 };
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1 =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1 =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s1)];
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s1)];
 //%  XCTAssertNotNil(dict1);
 //%  XCTAssertNotNil(dict1);
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1prime =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1prime =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s1)];
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s1)];
 //%  XCTAssertNotNil(dict1prime);
 //%  XCTAssertNotNil(dict1prime);
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s2
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s2
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s2)];
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s2)];
 //%  XCTAssertNotNil(dict2);
 //%  XCTAssertNotNil(dict2);
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict3 =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict3 =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys2
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys2
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s1)];
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s1)];
 //%  XCTAssertNotNil(dict3);
 //%  XCTAssertNotNil(dict3);
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict4 =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict4 =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s3
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s3
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s3)];
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s3)];
@@ -188,13 +195,13 @@
 //%- (void)testCopy {
 //%- (void)testCopy {
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
 //%  XCTAssertNotNil(dict);
 //%  XCTAssertNotNil(dict);
 //%
 //%
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 = [dict copy];
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 = [dict copy];
 //%  XCTAssertNotNil(dict2);
 //%  XCTAssertNotNil(dict2);
 //%
 //%
 //%  // Should be new object but equal.
 //%  // Should be new object but equal.
@@ -209,13 +216,13 @@
 //%- (void)testDictionaryFromDictionary {
 //%- (void)testDictionaryFromDictionary {
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
 //%  XCTAssertNotNil(dict);
 //%  XCTAssertNotNil(dict);
 //%
 //%
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
 //%      [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithDictionary:dict];
 //%      [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithDictionary:dict];
 //%  XCTAssertNotNil(dict2);
 //%  XCTAssertNotNil(dict2);
 //%
 //%
@@ -226,7 +233,7 @@
 //%}
 //%}
 //%
 //%
 //%- (void)testAdds {
 //%- (void)testAdds {
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionary];
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionary];
 //%  XCTAssertNotNil(dict);
 //%  XCTAssertNotNil(dict);
 //%
 //%
 //%  XCTAssertEqual(dict.count, 0U);
 //%  XCTAssertEqual(dict.count, 0U);
@@ -235,7 +242,7 @@
 //%
 //%
 //%  const KEY_TYPE KisP##kKeys[] = { KEY2, KEY3, KEY4 };
 //%  const KEY_TYPE KisP##kKeys[] = { KEY2, KEY3, KEY4 };
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL2, VAL3, VAL4 };
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL2, VAL3, VAL4 };
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
@@ -253,7 +260,7 @@
 //%- (void)testRemove {
 //%- (void)testRemove {
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
 //%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
@@ -294,7 +301,7 @@
 //%- (void)testInplaceMutation {
 //%- (void)testInplaceMutation {
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2, VAL3, VAL4 };
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
 //%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
@@ -321,7 +328,7 @@
 //%
 //%
 //%  const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY3 };
 //%  const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY3 };
 //%  const VALUE_TYPE k##VNAME$u##s2[] = { VAL3, VAL1 };
 //%  const VALUE_TYPE k##VNAME$u##s2[] = { VAL3, VAL1 };
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s2
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s2
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys2
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys2
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s2)];
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s2)];
@@ -353,7 +360,7 @@
 //%- (void)testRawBasics {
 //%- (void)testRawBasics {
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3 };
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3 };
 //%  const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3 };
 //%  const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3 };
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys
@@ -429,31 +436,31 @@
 //%  const VALUE_TYPE kValues1[] = { VAL1, VAL2, VAL3 };  // Unknown
 //%  const VALUE_TYPE kValues1[] = { VAL1, VAL2, VAL3 };  // Unknown
 //%  const VALUE_TYPE kValues2[] = { VAL1, VAL4, VAL3 };  // Unknown
 //%  const VALUE_TYPE kValues2[] = { VAL1, VAL4, VAL3 };  // Unknown
 //%  const VALUE_TYPE kValues3[] = { VAL1, VAL2, VAL3, VAL4 };  // Unknowns
 //%  const VALUE_TYPE kValues3[] = { VAL1, VAL2, VAL3, VAL4 };  // Unknowns
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1 =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1 =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues1
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues1
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys1
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys1
 //%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues1)];
 //%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues1)];
 //%  XCTAssertNotNil(dict1);
 //%  XCTAssertNotNil(dict1);
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1prime =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1prime =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues1
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues1
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys1
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys1
 //%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues1)];
 //%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues1)];
 //%  XCTAssertNotNil(dict1prime);
 //%  XCTAssertNotNil(dict1prime);
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues2
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues2
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys1
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys1
 //%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues2)];
 //%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues2)];
 //%  XCTAssertNotNil(dict2);
 //%  XCTAssertNotNil(dict2);
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict3 =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict3 =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues1
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues1
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys2
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys2
 //%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues1)];
 //%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues1)];
 //%  XCTAssertNotNil(dict3);
 //%  XCTAssertNotNil(dict3);
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict4 =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict4 =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues3
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues3
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys1
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys1
@@ -485,14 +492,14 @@
 //%- (void)testCopyWithUnknowns {
 //%- (void)testCopyWithUnknowns {
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
 //%  const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };  // Unknown
 //%  const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };  // Unknown
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues)];
 //%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues)];
 //%  XCTAssertNotNil(dict);
 //%  XCTAssertNotNil(dict);
 //%
 //%
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 = [dict copy];
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 = [dict copy];
 //%  XCTAssertNotNil(dict2);
 //%  XCTAssertNotNil(dict2);
 //%
 //%
 //%  // Should be new pointer, but equal objects.
 //%  // Should be new pointer, but equal objects.
@@ -507,14 +514,14 @@
 //%- (void)testDictionaryFromDictionary {
 //%- (void)testDictionaryFromDictionary {
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
 //%  const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };  // Unknowns
 //%  const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };  // Unknowns
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues)];
 //%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues)];
 //%  XCTAssertNotNil(dict);
 //%  XCTAssertNotNil(dict);
 //%
 //%
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
 //%      [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithDictionary:dict];
 //%      [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithDictionary:dict];
 //%  XCTAssertNotNil(dict2);
 //%  XCTAssertNotNil(dict2);
 //%
 //%
@@ -526,7 +533,7 @@
 //%}
 //%}
 //%
 //%
 //%- (void)testUnknownAdds {
 //%- (void)testUnknownAdds {
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
 //%    [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue];
 //%    [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue];
 //%  XCTAssertNotNil(dict);
 //%  XCTAssertNotNil(dict);
 //%
 //%
@@ -539,7 +546,7 @@
 //%
 //%
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY3, KEY4 };
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY3, KEY4 };
 //%  const VALUE_TYPE kValues[] = { VAL1, VAL3, VAL4 };  // Unknown
 //%  const VALUE_TYPE kValues[] = { VAL1, VAL3, VAL4 };  // Unknown
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
 //%           KEY_NAME$S VALUE_NAME$S                        forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                        forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                          count:GPBARRAYSIZE(kValues)];
 //%           KEY_NAME$S VALUE_NAME$S                          count:GPBARRAYSIZE(kValues)];
@@ -559,7 +566,7 @@
 //%- (void)testUnknownRemove {
 //%- (void)testUnknownRemove {
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
 //%  const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };  // Unknowns
 //%  const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };  // Unknowns
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys
@@ -601,7 +608,7 @@
 //%- (void)testInplaceMutationUnknowns {
 //%- (void)testInplaceMutationUnknowns {
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
 //%  const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };  // Unknowns
 //%  const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };  // Unknowns
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys
@@ -637,7 +644,7 @@
 //%
 //%
 //%  const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY3 };
 //%  const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY3 };
 //%  const VALUE_TYPE kValues2[] = { VAL3, VAL2 };  // Unknown
 //%  const VALUE_TYPE kValues2[] = { VAL3, VAL2 };  // Unknown
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues2
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues2
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys2
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys2
@@ -657,14 +664,14 @@
 //%- (void)testCopyUnknowns {
 //%- (void)testCopyUnknowns {
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
 //%  const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
 //%  const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues
 //%           KEY_NAME$S VALUE_NAME$S                                  rawValues:kValues
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                                    forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues)];
 //%           KEY_NAME$S VALUE_NAME$S                                      count:GPBARRAYSIZE(kValues)];
 //%  XCTAssertNotNil(dict);
 //%  XCTAssertNotNil(dict);
 //%
 //%
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 = [dict copy];
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 = [dict copy];
 //%  XCTAssertNotNil(dict2);
 //%  XCTAssertNotNil(dict2);
 //%
 //%
 //%  // Should be new pointer, but equal objects.
 //%  // Should be new pointer, but equal objects.
@@ -782,7 +789,7 @@
 //%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryTests
 //%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryTests
 //%
 //%
 //%- (void)testEmpty {
 //%- (void)testEmpty {
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
 //%  XCTAssertNotNil(dict);
 //%  XCTAssertNotNil(dict);
 //%  XCTAssertEqual(dict.count, 0U);
 //%  XCTAssertEqual(dict.count, 0U);
 //%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
 //%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
@@ -794,7 +801,7 @@
 //%}
 //%}
 //%
 //%
 //%- (void)testOne {
 //%- (void)testOne {
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWith##VNAME$u##:VAL1 forKey:KEY1];
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWith##VNAME$u##:VAL1 forKey:KEY1];
 //%  XCTAssertNotNil(dict);
 //%  XCTAssertNotNil(dict);
 //%  XCTAssertEqual(dict.count, 1U);
 //%  XCTAssertEqual(dict.count, 1U);
 //%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
 //%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(dict, VNAME, KEY1, VAL1)
@@ -809,7 +816,7 @@
 //%- (void)testBasics {
 //%- (void)testBasics {
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
@@ -858,27 +865,27 @@
 //%  const VALUE_TYPE k##VNAME$u##s1[] = { VAL1, VAL2 };
 //%  const VALUE_TYPE k##VNAME$u##s1[] = { VAL1, VAL2 };
 //%  const VALUE_TYPE k##VNAME$u##s2[] = { VAL2, VAL1 };
 //%  const VALUE_TYPE k##VNAME$u##s2[] = { VAL2, VAL1 };
 //%  const VALUE_TYPE k##VNAME$u##s3[] = { VAL2 };
 //%  const VALUE_TYPE k##VNAME$u##s3[] = { VAL2 };
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1 =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1 =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s1)];
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s1)];
 //%  XCTAssertNotNil(dict1);
 //%  XCTAssertNotNil(dict1);
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1prime =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict1prime =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s1)];
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s1)];
 //%  XCTAssertNotNil(dict1prime);
 //%  XCTAssertNotNil(dict1prime);
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s2
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s2
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s2)];
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s2)];
 //%  XCTAssertNotNil(dict2);
 //%  XCTAssertNotNil(dict2);
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict3 =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict3 =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s1
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys2
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys2
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s1)];
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s1)];
 //%  XCTAssertNotNil(dict3);
 //%  XCTAssertNotNil(dict3);
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict4 =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict4 =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s3
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s3
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys1
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s3)];
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s3)];
@@ -909,13 +916,13 @@
 //%- (void)testCopy {
 //%- (void)testCopy {
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
 //%  XCTAssertNotNil(dict);
 //%  XCTAssertNotNil(dict);
 //%
 //%
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 = [dict copy];
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 = [dict copy];
 //%  XCTAssertNotNil(dict2);
 //%  XCTAssertNotNil(dict2);
 //%
 //%
 //%  // Should be new object but equal.
 //%  // Should be new object but equal.
@@ -930,13 +937,13 @@
 //%- (void)testDictionaryFromDictionary {
 //%- (void)testDictionaryFromDictionary {
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
 //%  XCTAssertNotNil(dict);
 //%  XCTAssertNotNil(dict);
 //%
 //%
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
 //%      [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithDictionary:dict];
 //%      [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithDictionary:dict];
 //%  XCTAssertNotNil(dict2);
 //%  XCTAssertNotNil(dict2);
 //%
 //%
@@ -947,7 +954,7 @@
 //%}
 //%}
 //%
 //%
 //%- (void)testAdds {
 //%- (void)testAdds {
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionary];
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionary];
 //%  XCTAssertNotNil(dict);
 //%  XCTAssertNotNil(dict);
 //%
 //%
 //%  XCTAssertEqual(dict.count, 0U);
 //%  XCTAssertEqual(dict.count, 0U);
@@ -956,7 +963,7 @@
 //%
 //%
 //%  const KEY_TYPE KisP##kKeys[] = { KEY2 };
 //%  const KEY_TYPE KisP##kKeys[] = { KEY2 };
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL2 };
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL2 };
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
@@ -972,7 +979,7 @@
 //%- (void)testRemove {
 //%- (void)testRemove {
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2};
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2};
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
 //%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
@@ -1000,7 +1007,7 @@
 //%- (void)testInplaceMutation {
 //%- (void)testInplaceMutation {
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
 //%  const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
 //%  const VALUE_TYPE k##VNAME$u##s[] = { VAL1, VAL2 };
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s
 //%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##  forKeys:kKeys
 //%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
 //%           KEY_NAME$S VALUE_NAME$S          ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s)];
@@ -1021,7 +1028,7 @@
 //%
 //%
 //%  const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1 };
 //%  const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1 };
 //%  const VALUE_TYPE k##VNAME$u##s2[] = { VAL2, VAL1 };
 //%  const VALUE_TYPE k##VNAME$u##s2[] = { VAL2, VAL1 };
-//%  GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//%  DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s2
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWith##VNAME$u##s:k##VNAME$u##s2
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys2
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##  forKeys:kKeys2
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s2)];
 //%           KEY_NAME$S VALUE_NAME$S                 ##VNAME$S##    count:GPBARRAYSIZE(k##VNAME$u##s2)];

+ 7 - 8
objectivec/google/protobuf/Api.pbobjc.h

@@ -11,6 +11,9 @@
 
 
 CF_EXTERN_C_BEGIN
 CF_EXTERN_C_BEGIN
 
 
+@class GPBMethod;
+@class GPBMixin;
+@class GPBOption;
 @class GPBSourceContext;
 @class GPBSourceContext;
 GPB_ENUM_FWD_DECLARE(GPBSyntax);
 GPB_ENUM_FWD_DECLARE(GPBSyntax);
 
 
@@ -47,13 +50,11 @@ typedef GPB_ENUM(GPBApi_FieldNumber) {
 @property(nonatomic, readwrite, copy, null_resettable) NSString *name;
 @property(nonatomic, readwrite, copy, null_resettable) NSString *name;
 
 
 // The methods of this api, in unspecified order.
 // The methods of this api, in unspecified order.
-// |methodsArray| contains |GPBMethod|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *methodsArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBMethod*> *methodsArray;
 @property(nonatomic, readonly) NSUInteger methodsArray_Count;
 @property(nonatomic, readonly) NSUInteger methodsArray_Count;
 
 
 // Any metadata attached to the API.
 // Any metadata attached to the API.
-// |optionsArray| contains |GPBOption|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
 @property(nonatomic, readonly) NSUInteger optionsArray_Count;
 @property(nonatomic, readonly) NSUInteger optionsArray_Count;
 
 
 // A version string for this api. If specified, must have the form
 // A version string for this api. If specified, must have the form
@@ -84,8 +85,7 @@ typedef GPB_ENUM(GPBApi_FieldNumber) {
 @property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext;
 @property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext;
 
 
 // Included APIs. See [Mixin][].
 // Included APIs. See [Mixin][].
-// |mixinsArray| contains |GPBMixin|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *mixinsArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBMixin*> *mixinsArray;
 @property(nonatomic, readonly) NSUInteger mixinsArray_Count;
 @property(nonatomic, readonly) NSUInteger mixinsArray_Count;
 
 
 // The source syntax of the service.
 // The source syntax of the service.
@@ -127,8 +127,7 @@ typedef GPB_ENUM(GPBMethod_FieldNumber) {
 @property(nonatomic, readwrite) BOOL responseStreaming;
 @property(nonatomic, readwrite) BOOL responseStreaming;
 
 
 // Any metadata attached to the method.
 // Any metadata attached to the method.
-// |optionsArray| contains |GPBOption|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
 @property(nonatomic, readonly) NSUInteger optionsArray_Count;
 @property(nonatomic, readonly) NSUInteger optionsArray_Count;
 
 
 // The source syntax of this method.
 // The source syntax of this method.

+ 41 - 54
objectivec/google/protobuf/Descriptor.pbobjc.h

@@ -11,14 +11,28 @@
 
 
 CF_EXTERN_C_BEGIN
 CF_EXTERN_C_BEGIN
 
 
+@class GPBDescriptorProto;
+@class GPBDescriptorProto_ExtensionRange;
+@class GPBDescriptorProto_ReservedRange;
+@class GPBEnumDescriptorProto;
 @class GPBEnumOptions;
 @class GPBEnumOptions;
+@class GPBEnumValueDescriptorProto;
 @class GPBEnumValueOptions;
 @class GPBEnumValueOptions;
+@class GPBFieldDescriptorProto;
 @class GPBFieldOptions;
 @class GPBFieldOptions;
+@class GPBFileDescriptorProto;
 @class GPBFileOptions;
 @class GPBFileOptions;
+@class GPBGeneratedCodeInfo_Annotation;
 @class GPBMessageOptions;
 @class GPBMessageOptions;
+@class GPBMethodDescriptorProto;
 @class GPBMethodOptions;
 @class GPBMethodOptions;
+@class GPBOneofDescriptorProto;
+@class GPBServiceDescriptorProto;
 @class GPBServiceOptions;
 @class GPBServiceOptions;
 @class GPBSourceCodeInfo;
 @class GPBSourceCodeInfo;
+@class GPBSourceCodeInfo_Location;
+@class GPBUninterpretedOption;
+@class GPBUninterpretedOption_NamePart;
 
 
 NS_ASSUME_NONNULL_BEGIN
 NS_ASSUME_NONNULL_BEGIN
 
 
@@ -151,8 +165,7 @@ typedef GPB_ENUM(GPBFileDescriptorSet_FieldNumber) {
 // files it parses.
 // files it parses.
 @interface GPBFileDescriptorSet : GPBMessage
 @interface GPBFileDescriptorSet : GPBMessage
 
 
-// |fileArray| contains |GPBFileDescriptorProto|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *fileArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBFileDescriptorProto*> *fileArray;
 @property(nonatomic, readonly) NSUInteger fileArray_Count;
 @property(nonatomic, readonly) NSUInteger fileArray_Count;
 
 
 @end
 @end
@@ -186,8 +199,7 @@ typedef GPB_ENUM(GPBFileDescriptorProto_FieldNumber) {
 @property(nonatomic, readwrite, copy, null_resettable) NSString *package;
 @property(nonatomic, readwrite, copy, null_resettable) NSString *package;
 
 
 // Names of files imported by this file.
 // Names of files imported by this file.
-// |dependencyArray| contains |NSString|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *dependencyArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<NSString*> *dependencyArray;
 @property(nonatomic, readonly) NSUInteger dependencyArray_Count;
 @property(nonatomic, readonly) NSUInteger dependencyArray_Count;
 
 
 // Indexes of the public imported files in the dependency list above.
 // Indexes of the public imported files in the dependency list above.
@@ -200,20 +212,16 @@ typedef GPB_ENUM(GPBFileDescriptorProto_FieldNumber) {
 @property(nonatomic, readonly) NSUInteger weakDependencyArray_Count;
 @property(nonatomic, readonly) NSUInteger weakDependencyArray_Count;
 
 
 // All top-level definitions in this file.
 // All top-level definitions in this file.
-// |messageTypeArray| contains |GPBDescriptorProto|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *messageTypeArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBDescriptorProto*> *messageTypeArray;
 @property(nonatomic, readonly) NSUInteger messageTypeArray_Count;
 @property(nonatomic, readonly) NSUInteger messageTypeArray_Count;
 
 
-// |enumTypeArray| contains |GPBEnumDescriptorProto|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *enumTypeArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBEnumDescriptorProto*> *enumTypeArray;
 @property(nonatomic, readonly) NSUInteger enumTypeArray_Count;
 @property(nonatomic, readonly) NSUInteger enumTypeArray_Count;
 
 
-// |serviceArray| contains |GPBServiceDescriptorProto|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *serviceArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBServiceDescriptorProto*> *serviceArray;
 @property(nonatomic, readonly) NSUInteger serviceArray_Count;
 @property(nonatomic, readonly) NSUInteger serviceArray_Count;
 
 
-// |extensionArray| contains |GPBFieldDescriptorProto|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *extensionArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBFieldDescriptorProto*> *extensionArray;
 @property(nonatomic, readonly) NSUInteger extensionArray_Count;
 @property(nonatomic, readonly) NSUInteger extensionArray_Count;
 
 
 @property(nonatomic, readwrite) BOOL hasOptions;
 @property(nonatomic, readwrite) BOOL hasOptions;
@@ -254,41 +262,33 @@ typedef GPB_ENUM(GPBDescriptorProto_FieldNumber) {
 @property(nonatomic, readwrite) BOOL hasName;
 @property(nonatomic, readwrite) BOOL hasName;
 @property(nonatomic, readwrite, copy, null_resettable) NSString *name;
 @property(nonatomic, readwrite, copy, null_resettable) NSString *name;
 
 
-// |fieldArray| contains |GPBFieldDescriptorProto|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *fieldArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBFieldDescriptorProto*> *fieldArray;
 @property(nonatomic, readonly) NSUInteger fieldArray_Count;
 @property(nonatomic, readonly) NSUInteger fieldArray_Count;
 
 
-// |extensionArray| contains |GPBFieldDescriptorProto|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *extensionArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBFieldDescriptorProto*> *extensionArray;
 @property(nonatomic, readonly) NSUInteger extensionArray_Count;
 @property(nonatomic, readonly) NSUInteger extensionArray_Count;
 
 
-// |nestedTypeArray| contains |GPBDescriptorProto|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *nestedTypeArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBDescriptorProto*> *nestedTypeArray;
 @property(nonatomic, readonly) NSUInteger nestedTypeArray_Count;
 @property(nonatomic, readonly) NSUInteger nestedTypeArray_Count;
 
 
-// |enumTypeArray| contains |GPBEnumDescriptorProto|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *enumTypeArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBEnumDescriptorProto*> *enumTypeArray;
 @property(nonatomic, readonly) NSUInteger enumTypeArray_Count;
 @property(nonatomic, readonly) NSUInteger enumTypeArray_Count;
 
 
-// |extensionRangeArray| contains |GPBDescriptorProto_ExtensionRange|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *extensionRangeArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBDescriptorProto_ExtensionRange*> *extensionRangeArray;
 @property(nonatomic, readonly) NSUInteger extensionRangeArray_Count;
 @property(nonatomic, readonly) NSUInteger extensionRangeArray_Count;
 
 
-// |oneofDeclArray| contains |GPBOneofDescriptorProto|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *oneofDeclArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOneofDescriptorProto*> *oneofDeclArray;
 @property(nonatomic, readonly) NSUInteger oneofDeclArray_Count;
 @property(nonatomic, readonly) NSUInteger oneofDeclArray_Count;
 
 
 @property(nonatomic, readwrite) BOOL hasOptions;
 @property(nonatomic, readwrite) BOOL hasOptions;
 @property(nonatomic, readwrite, strong, null_resettable) GPBMessageOptions *options;
 @property(nonatomic, readwrite, strong, null_resettable) GPBMessageOptions *options;
 
 
-// |reservedRangeArray| contains |GPBDescriptorProto_ReservedRange|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *reservedRangeArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBDescriptorProto_ReservedRange*> *reservedRangeArray;
 @property(nonatomic, readonly) NSUInteger reservedRangeArray_Count;
 @property(nonatomic, readonly) NSUInteger reservedRangeArray_Count;
 
 
 // Reserved field names, which may not be used by fields in the same message.
 // Reserved field names, which may not be used by fields in the same message.
 // A given name may only be reserved once.
 // A given name may only be reserved once.
-// |reservedNameArray| contains |NSString|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *reservedNameArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<NSString*> *reservedNameArray;
 @property(nonatomic, readonly) NSUInteger reservedNameArray_Count;
 @property(nonatomic, readonly) NSUInteger reservedNameArray_Count;
 
 
 @end
 @end
@@ -430,8 +430,7 @@ typedef GPB_ENUM(GPBEnumDescriptorProto_FieldNumber) {
 @property(nonatomic, readwrite) BOOL hasName;
 @property(nonatomic, readwrite) BOOL hasName;
 @property(nonatomic, readwrite, copy, null_resettable) NSString *name;
 @property(nonatomic, readwrite, copy, null_resettable) NSString *name;
 
 
-// |valueArray| contains |GPBEnumValueDescriptorProto|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *valueArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBEnumValueDescriptorProto*> *valueArray;
 @property(nonatomic, readonly) NSUInteger valueArray_Count;
 @property(nonatomic, readonly) NSUInteger valueArray_Count;
 
 
 @property(nonatomic, readwrite) BOOL hasOptions;
 @property(nonatomic, readwrite) BOOL hasOptions;
@@ -475,8 +474,7 @@ typedef GPB_ENUM(GPBServiceDescriptorProto_FieldNumber) {
 @property(nonatomic, readwrite) BOOL hasName;
 @property(nonatomic, readwrite) BOOL hasName;
 @property(nonatomic, readwrite, copy, null_resettable) NSString *name;
 @property(nonatomic, readwrite, copy, null_resettable) NSString *name;
 
 
-// |methodArray| contains |GPBMethodDescriptorProto|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *methodArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBMethodDescriptorProto*> *methodArray;
 @property(nonatomic, readonly) NSUInteger methodArray_Count;
 @property(nonatomic, readonly) NSUInteger methodArray_Count;
 
 
 @property(nonatomic, readwrite) BOOL hasOptions;
 @property(nonatomic, readwrite) BOOL hasOptions;
@@ -650,8 +648,7 @@ typedef GPB_ENUM(GPBFileOptions_FieldNumber) {
 @property(nonatomic, readwrite) BOOL javananoUseDeprecatedPackage;
 @property(nonatomic, readwrite) BOOL javananoUseDeprecatedPackage;
 
 
 // The parser stores options it doesn't recognize here. See above.
 // The parser stores options it doesn't recognize here. See above.
-// |uninterpretedOptionArray| contains |GPBUninterpretedOption|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *uninterpretedOptionArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBUninterpretedOption*> *uninterpretedOptionArray;
 @property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count;
 @property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count;
 
 
 @end
 @end
@@ -727,8 +724,7 @@ typedef GPB_ENUM(GPBMessageOptions_FieldNumber) {
 @property(nonatomic, readwrite) BOOL mapEntry;
 @property(nonatomic, readwrite) BOOL mapEntry;
 
 
 // The parser stores options it doesn't recognize here. See above.
 // The parser stores options it doesn't recognize here. See above.
-// |uninterpretedOptionArray| contains |GPBUninterpretedOption|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *uninterpretedOptionArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBUninterpretedOption*> *uninterpretedOptionArray;
 @property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count;
 @property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count;
 
 
 @end
 @end
@@ -817,8 +813,7 @@ typedef GPB_ENUM(GPBFieldOptions_FieldNumber) {
 @property(nonatomic, readwrite) BOOL weak;
 @property(nonatomic, readwrite) BOOL weak;
 
 
 // The parser stores options it doesn't recognize here. See above.
 // The parser stores options it doesn't recognize here. See above.
-// |uninterpretedOptionArray| contains |GPBUninterpretedOption|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *uninterpretedOptionArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBUninterpretedOption*> *uninterpretedOptionArray;
 @property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count;
 @property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count;
 
 
 @end
 @end
@@ -846,8 +841,7 @@ typedef GPB_ENUM(GPBEnumOptions_FieldNumber) {
 @property(nonatomic, readwrite) BOOL deprecated;
 @property(nonatomic, readwrite) BOOL deprecated;
 
 
 // The parser stores options it doesn't recognize here. See above.
 // The parser stores options it doesn't recognize here. See above.
-// |uninterpretedOptionArray| contains |GPBUninterpretedOption|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *uninterpretedOptionArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBUninterpretedOption*> *uninterpretedOptionArray;
 @property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count;
 @property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count;
 
 
 @end
 @end
@@ -869,8 +863,7 @@ typedef GPB_ENUM(GPBEnumValueOptions_FieldNumber) {
 @property(nonatomic, readwrite) BOOL deprecated;
 @property(nonatomic, readwrite) BOOL deprecated;
 
 
 // The parser stores options it doesn't recognize here. See above.
 // The parser stores options it doesn't recognize here. See above.
-// |uninterpretedOptionArray| contains |GPBUninterpretedOption|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *uninterpretedOptionArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBUninterpretedOption*> *uninterpretedOptionArray;
 @property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count;
 @property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count;
 
 
 @end
 @end
@@ -892,8 +885,7 @@ typedef GPB_ENUM(GPBServiceOptions_FieldNumber) {
 @property(nonatomic, readwrite) BOOL deprecated;
 @property(nonatomic, readwrite) BOOL deprecated;
 
 
 // The parser stores options it doesn't recognize here. See above.
 // The parser stores options it doesn't recognize here. See above.
-// |uninterpretedOptionArray| contains |GPBUninterpretedOption|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *uninterpretedOptionArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBUninterpretedOption*> *uninterpretedOptionArray;
 @property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count;
 @property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count;
 
 
 @end
 @end
@@ -915,8 +907,7 @@ typedef GPB_ENUM(GPBMethodOptions_FieldNumber) {
 @property(nonatomic, readwrite) BOOL deprecated;
 @property(nonatomic, readwrite) BOOL deprecated;
 
 
 // The parser stores options it doesn't recognize here. See above.
 // The parser stores options it doesn't recognize here. See above.
-// |uninterpretedOptionArray| contains |GPBUninterpretedOption|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *uninterpretedOptionArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBUninterpretedOption*> *uninterpretedOptionArray;
 @property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count;
 @property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count;
 
 
 @end
 @end
@@ -941,8 +932,7 @@ typedef GPB_ENUM(GPBUninterpretedOption_FieldNumber) {
 // in them.
 // in them.
 @interface GPBUninterpretedOption : GPBMessage
 @interface GPBUninterpretedOption : GPBMessage
 
 
-// |nameArray| contains |GPBUninterpretedOption_NamePart|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *nameArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBUninterpretedOption_NamePart*> *nameArray;
 @property(nonatomic, readonly) NSUInteger nameArray_Count;
 @property(nonatomic, readonly) NSUInteger nameArray_Count;
 
 
 // The value of the uninterpreted option, in whatever type the tokenizer
 // The value of the uninterpreted option, in whatever type the tokenizer
@@ -1042,8 +1032,7 @@ typedef GPB_ENUM(GPBSourceCodeInfo_FieldNumber) {
 // - Code which tries to interpret locations should probably be designed to
 // - Code which tries to interpret locations should probably be designed to
 //   ignore those that it doesn't understand, as more types of locations could
 //   ignore those that it doesn't understand, as more types of locations could
 //   be recorded in the future.
 //   be recorded in the future.
-// |locationArray| contains |GPBSourceCodeInfo_Location|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *locationArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBSourceCodeInfo_Location*> *locationArray;
 @property(nonatomic, readonly) NSUInteger locationArray_Count;
 @property(nonatomic, readonly) NSUInteger locationArray_Count;
 
 
 @end
 @end
@@ -1147,8 +1136,7 @@ typedef GPB_ENUM(GPBSourceCodeInfo_Location_FieldNumber) {
 @property(nonatomic, readwrite) BOOL hasTrailingComments;
 @property(nonatomic, readwrite) BOOL hasTrailingComments;
 @property(nonatomic, readwrite, copy, null_resettable) NSString *trailingComments;
 @property(nonatomic, readwrite, copy, null_resettable) NSString *trailingComments;
 
 
-// |leadingDetachedCommentsArray| contains |NSString|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *leadingDetachedCommentsArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<NSString*> *leadingDetachedCommentsArray;
 @property(nonatomic, readonly) NSUInteger leadingDetachedCommentsArray_Count;
 @property(nonatomic, readonly) NSUInteger leadingDetachedCommentsArray_Count;
 
 
 @end
 @end
@@ -1166,8 +1154,7 @@ typedef GPB_ENUM(GPBGeneratedCodeInfo_FieldNumber) {
 
 
 // An Annotation connects some span of text in generated code to an element
 // An Annotation connects some span of text in generated code to an element
 // of its generating .proto file.
 // of its generating .proto file.
-// |annotationArray| contains |GPBGeneratedCodeInfo_Annotation|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *annotationArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBGeneratedCodeInfo_Annotation*> *annotationArray;
 @property(nonatomic, readonly) NSUInteger annotationArray_Count;
 @property(nonatomic, readonly) NSUInteger annotationArray_Count;
 
 
 @end
 @end

+ 1 - 2
objectivec/google/protobuf/FieldMask.pbobjc.h

@@ -155,8 +155,7 @@ typedef GPB_ENUM(GPBFieldMask_FieldNumber) {
 @interface GPBFieldMask : GPBMessage
 @interface GPBFieldMask : GPBMessage
 
 
 // The set of field mask paths.
 // The set of field mask paths.
-// |pathsArray| contains |NSString|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *pathsArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<NSString*> *pathsArray;
 @property(nonatomic, readonly) NSUInteger pathsArray_Count;
 @property(nonatomic, readonly) NSUInteger pathsArray_Count;
 
 
 @end
 @end

+ 3 - 4
objectivec/google/protobuf/Struct.pbobjc.h

@@ -13,6 +13,7 @@ CF_EXTERN_C_BEGIN
 
 
 @class GPBListValue;
 @class GPBListValue;
 @class GPBStruct;
 @class GPBStruct;
+@class GPBValue;
 
 
 NS_ASSUME_NONNULL_BEGIN
 NS_ASSUME_NONNULL_BEGIN
 
 
@@ -60,8 +61,7 @@ typedef GPB_ENUM(GPBStruct_FieldNumber) {
 @interface GPBStruct : GPBMessage
 @interface GPBStruct : GPBMessage
 
 
 // Map of dynamically typed values.
 // Map of dynamically typed values.
-// |fields| values are |GPBValue|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableDictionary *fields;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableDictionary<NSString*, GPBValue*> *fields;
 @property(nonatomic, readonly) NSUInteger fields_Count;
 @property(nonatomic, readonly) NSUInteger fields_Count;
 
 
 @end
 @end
@@ -135,8 +135,7 @@ typedef GPB_ENUM(GPBListValue_FieldNumber) {
 @interface GPBListValue : GPBMessage
 @interface GPBListValue : GPBMessage
 
 
 // Repeated field of dynamically typed values.
 // Repeated field of dynamically typed values.
-// |valuesArray| contains |GPBValue|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *valuesArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBValue*> *valuesArray;
 @property(nonatomic, readonly) NSUInteger valuesArray_Count;
 @property(nonatomic, readonly) NSUInteger valuesArray_Count;
 
 
 @end
 @end

+ 10 - 14
objectivec/google/protobuf/Type.pbobjc.h

@@ -12,6 +12,9 @@
 CF_EXTERN_C_BEGIN
 CF_EXTERN_C_BEGIN
 
 
 @class GPBAny;
 @class GPBAny;
+@class GPBEnumValue;
+@class GPBField;
+@class GPBOption;
 @class GPBSourceContext;
 @class GPBSourceContext;
 
 
 NS_ASSUME_NONNULL_BEGIN
 NS_ASSUME_NONNULL_BEGIN
@@ -150,18 +153,15 @@ typedef GPB_ENUM(GPBType_FieldNumber) {
 @property(nonatomic, readwrite, copy, null_resettable) NSString *name;
 @property(nonatomic, readwrite, copy, null_resettable) NSString *name;
 
 
 // The list of fields.
 // The list of fields.
-// |fieldsArray| contains |GPBField|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *fieldsArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBField*> *fieldsArray;
 @property(nonatomic, readonly) NSUInteger fieldsArray_Count;
 @property(nonatomic, readonly) NSUInteger fieldsArray_Count;
 
 
 // The list of types appearing in `oneof` definitions in this type.
 // The list of types appearing in `oneof` definitions in this type.
-// |oneofsArray| contains |NSString|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *oneofsArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<NSString*> *oneofsArray;
 @property(nonatomic, readonly) NSUInteger oneofsArray_Count;
 @property(nonatomic, readonly) NSUInteger oneofsArray_Count;
 
 
 // The protocol buffer options.
 // The protocol buffer options.
-// |optionsArray| contains |GPBOption|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
 @property(nonatomic, readonly) NSUInteger optionsArray_Count;
 @property(nonatomic, readonly) NSUInteger optionsArray_Count;
 
 
 // The source context.
 // The source context.
@@ -218,8 +218,7 @@ typedef GPB_ENUM(GPBField_FieldNumber) {
 @property(nonatomic, readwrite) BOOL packed;
 @property(nonatomic, readwrite) BOOL packed;
 
 
 // The protocol buffer options.
 // The protocol buffer options.
-// |optionsArray| contains |GPBOption|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
 @property(nonatomic, readonly) NSUInteger optionsArray_Count;
 @property(nonatomic, readonly) NSUInteger optionsArray_Count;
 
 
 // The field JSON name.
 // The field JSON name.
@@ -253,13 +252,11 @@ typedef GPB_ENUM(GPBEnum_FieldNumber) {
 @property(nonatomic, readwrite, copy, null_resettable) NSString *name;
 @property(nonatomic, readwrite, copy, null_resettable) NSString *name;
 
 
 // Enum value definitions.
 // Enum value definitions.
-// |enumvalueArray| contains |GPBEnumValue|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *enumvalueArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBEnumValue*> *enumvalueArray;
 @property(nonatomic, readonly) NSUInteger enumvalueArray_Count;
 @property(nonatomic, readonly) NSUInteger enumvalueArray_Count;
 
 
 // Protocol buffer options.
 // Protocol buffer options.
-// |optionsArray| contains |GPBOption|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
 @property(nonatomic, readonly) NSUInteger optionsArray_Count;
 @property(nonatomic, readonly) NSUInteger optionsArray_Count;
 
 
 // The source context.
 // The source context.
@@ -292,8 +289,7 @@ typedef GPB_ENUM(GPBEnumValue_FieldNumber) {
 @property(nonatomic, readwrite) int32_t number;
 @property(nonatomic, readwrite) int32_t number;
 
 
 // Protocol buffer options.
 // Protocol buffer options.
-// |optionsArray| contains |GPBOption|
-@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray;
+@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
 @property(nonatomic, readonly) NSUInteger optionsArray_Count;
 @property(nonatomic, readonly) NSUInteger optionsArray_Count;
 
 
 @end
 @end

+ 1 - 1
src/google/protobuf/compiler/main.cc

@@ -78,7 +78,7 @@ int main(int argc, char* argv[]) {
 
 
   // Objective C
   // Objective C
   google::protobuf::compiler::objectivec::ObjectiveCGenerator objc_generator;
   google::protobuf::compiler::objectivec::ObjectiveCGenerator objc_generator;
-  cli.RegisterGenerator("--objc_out", &objc_generator,
+  cli.RegisterGenerator("--objc_out", "--objc_opt", &objc_generator,
                         "Generate Objective C header and source.");
                         "Generate Objective C header and source.");
 
 
   // JavaScript
   // JavaScript

+ 13 - 4
src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc

@@ -44,6 +44,7 @@ namespace compiler {
 namespace objectivec {
 namespace objectivec {
 
 
 namespace {
 namespace {
+
 void SetEnumVariables(const FieldDescriptor* descriptor,
 void SetEnumVariables(const FieldDescriptor* descriptor,
                       map<string, string>* variables) {
                       map<string, string>* variables) {
   string type = EnumName(descriptor->enum_type());
   string type = EnumName(descriptor->enum_type());
@@ -63,8 +64,9 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
 }
 }
 }  // namespace
 }  // namespace
 
 
-EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor)
-    : SingleFieldGenerator(descriptor) {
+EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
+                                       const Options& options)
+    : SingleFieldGenerator(descriptor, options) {
   SetEnumVariables(descriptor, &variables_);
   SetEnumVariables(descriptor, &variables_);
 }
 }
 
 
@@ -112,6 +114,7 @@ void EnumFieldGenerator::GenerateCFunctionImplementations(
 
 
 void EnumFieldGenerator::DetermineForwardDeclarations(
 void EnumFieldGenerator::DetermineForwardDeclarations(
     set<string>* fwd_decls) const {
     set<string>* fwd_decls) const {
+  SingleFieldGenerator::DetermineForwardDeclarations(fwd_decls);
   // If it is an enum defined in a different file, then we'll need a forward
   // If it is an enum defined in a different file, then we'll need a forward
   // declaration for it.  When it is in our file, all the enums are output
   // declaration for it.  When it is in our file, all the enums are output
   // before the message, so it will be declared before it is needed.
   // before the message, so it will be declared before it is needed.
@@ -123,14 +126,20 @@ void EnumFieldGenerator::DetermineForwardDeclarations(
 }
 }
 
 
 RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
 RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
-    const FieldDescriptor* descriptor)
-    : RepeatedFieldGenerator(descriptor) {
+    const FieldDescriptor* descriptor, const Options& options)
+    : RepeatedFieldGenerator(descriptor, options) {
   SetEnumVariables(descriptor, &variables_);
   SetEnumVariables(descriptor, &variables_);
   variables_["array_storage_type"] = "GPBEnumArray";
   variables_["array_storage_type"] = "GPBEnumArray";
 }
 }
 
 
 RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
 RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
 
 
+void RepeatedEnumFieldGenerator::FinishInitialization(void) {
+  RepeatedFieldGenerator::FinishInitialization();
+  variables_["array_comment"] =
+      "// |" + variables_["name"] + "| contains |" + variables_["storage_type"] + "|\n";
+}
+
 void RepeatedEnumFieldGenerator::GenerateFieldDescriptionTypeSpecific(
 void RepeatedEnumFieldGenerator::GenerateFieldDescriptionTypeSpecific(
     io::Printer* printer) const {
     io::Printer* printer) const {
   printer->Print(
   printer->Print(

+ 8 - 4
src/google/protobuf/compiler/objectivec/objectivec_enum_field.h

@@ -41,7 +41,8 @@ namespace compiler {
 namespace objectivec {
 namespace objectivec {
 
 
 class EnumFieldGenerator : public SingleFieldGenerator {
 class EnumFieldGenerator : public SingleFieldGenerator {
-  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
 
 
  public:
  public:
   virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
   virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
@@ -50,7 +51,7 @@ class EnumFieldGenerator : public SingleFieldGenerator {
   virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
   virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
 
 
  protected:
  protected:
-  explicit EnumFieldGenerator(const FieldDescriptor* descriptor);
+  EnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
   virtual ~EnumFieldGenerator();
   virtual ~EnumFieldGenerator();
 
 
  private:
  private:
@@ -58,13 +59,16 @@ class EnumFieldGenerator : public SingleFieldGenerator {
 };
 };
 
 
 class RepeatedEnumFieldGenerator : public RepeatedFieldGenerator {
 class RepeatedEnumFieldGenerator : public RepeatedFieldGenerator {
-  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
 
 
  public:
  public:
+  virtual void FinishInitialization();
   virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
   virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
 
 
  protected:
  protected:
-  RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor);
+  RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+                             const Options& options);
   virtual ~RepeatedEnumFieldGenerator();
   virtual ~RepeatedEnumFieldGenerator();
 
 
  private:
  private:

+ 34 - 26
src/google/protobuf/compiler/objectivec/objectivec_field.cc

@@ -45,6 +45,7 @@ namespace compiler {
 namespace objectivec {
 namespace objectivec {
 
 
 namespace {
 namespace {
+
 void SetCommonFieldVariables(const FieldDescriptor* descriptor,
 void SetCommonFieldVariables(const FieldDescriptor* descriptor,
                              map<string, string>* variables) {
                              map<string, string>* variables) {
   string camel_case_name = FieldName(descriptor);
   string camel_case_name = FieldName(descriptor);
@@ -117,39 +118,40 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
 
 
 }  // namespace
 }  // namespace
 
 
-FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) {
+FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                     const Options& options) {
   FieldGenerator* result = NULL;
   FieldGenerator* result = NULL;
   if (field->is_repeated()) {
   if (field->is_repeated()) {
     switch (GetObjectiveCType(field)) {
     switch (GetObjectiveCType(field)) {
       case OBJECTIVECTYPE_MESSAGE: {
       case OBJECTIVECTYPE_MESSAGE: {
         if (field->is_map()) {
         if (field->is_map()) {
-          result = new MapFieldGenerator(field);
+          result = new MapFieldGenerator(field, options);
         } else {
         } else {
-          result = new RepeatedMessageFieldGenerator(field);
+          result = new RepeatedMessageFieldGenerator(field, options);
         }
         }
         break;
         break;
       }
       }
       case OBJECTIVECTYPE_ENUM:
       case OBJECTIVECTYPE_ENUM:
-        result = new RepeatedEnumFieldGenerator(field);
+        result = new RepeatedEnumFieldGenerator(field, options);
         break;
         break;
       default:
       default:
-        result = new RepeatedPrimitiveFieldGenerator(field);
+        result = new RepeatedPrimitiveFieldGenerator(field, options);
         break;
         break;
     }
     }
   } else {
   } else {
     switch (GetObjectiveCType(field)) {
     switch (GetObjectiveCType(field)) {
       case OBJECTIVECTYPE_MESSAGE: {
       case OBJECTIVECTYPE_MESSAGE: {
-        result = new MessageFieldGenerator(field);
+        result = new MessageFieldGenerator(field, options);
         break;
         break;
       }
       }
       case OBJECTIVECTYPE_ENUM:
       case OBJECTIVECTYPE_ENUM:
-        result = new EnumFieldGenerator(field);
+        result = new EnumFieldGenerator(field, options);
         break;
         break;
       default:
       default:
         if (IsReferenceType(field)) {
         if (IsReferenceType(field)) {
-          result = new PrimitiveObjFieldGenerator(field);
+          result = new PrimitiveObjFieldGenerator(field, options);
         } else {
         } else {
-          result = new PrimitiveFieldGenerator(field);
+          result = new PrimitiveFieldGenerator(field, options);
         }
         }
         break;
         break;
     }
     }
@@ -158,8 +160,8 @@ FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) {
   return result;
   return result;
 }
 }
 
 
-
-FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor)
+FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor,
+                               const Options& options)
     : descriptor_(descriptor) {
     : descriptor_(descriptor) {
   SetCommonFieldVariables(descriptor, &variables_);
   SetCommonFieldVariables(descriptor, &variables_);
 }
 }
@@ -252,9 +254,9 @@ void FieldGenerator::FinishInitialization(void) {
   }
   }
 }
 }
 
 
-SingleFieldGenerator::SingleFieldGenerator(
-    const FieldDescriptor* descriptor)
-    : FieldGenerator(descriptor) {
+SingleFieldGenerator::SingleFieldGenerator(const FieldDescriptor* descriptor,
+                                           const Options& options)
+    : FieldGenerator(descriptor, options) {
   // Nothing
   // Nothing
 }
 }
 
 
@@ -300,9 +302,9 @@ bool SingleFieldGenerator::WantsHasProperty(void) const {
   return false;
   return false;
 }
 }
 
 
-ObjCObjFieldGenerator::ObjCObjFieldGenerator(
-    const FieldDescriptor* descriptor)
-    : SingleFieldGenerator(descriptor) {
+ObjCObjFieldGenerator::ObjCObjFieldGenerator(const FieldDescriptor* descriptor,
+                                             const Options& options)
+    : SingleFieldGenerator(descriptor, options) {
   variables_["property_storage_attribute"] = "strong";
   variables_["property_storage_attribute"] = "strong";
   if (IsRetainedName(variables_["name"])) {
   if (IsRetainedName(variables_["name"])) {
     variables_["storage_attribute"] = " NS_RETURNS_NOT_RETAINED";
     variables_["storage_attribute"] = " NS_RETURNS_NOT_RETAINED";
@@ -342,18 +344,21 @@ void ObjCObjFieldGenerator::GeneratePropertyDeclaration(
 }
 }
 
 
 RepeatedFieldGenerator::RepeatedFieldGenerator(
 RepeatedFieldGenerator::RepeatedFieldGenerator(
-    const FieldDescriptor* descriptor)
-    : ObjCObjFieldGenerator(descriptor) {
+    const FieldDescriptor* descriptor, const Options& options)
+    : ObjCObjFieldGenerator(descriptor, options) {
   // Repeated fields don't use the has index.
   // Repeated fields don't use the has index.
   variables_["has_index"] = "GPBNoHasBit";
   variables_["has_index"] = "GPBNoHasBit";
+  // Default to no comment and let the cases needing it fill it in.
+  variables_["array_comment"] = "";
 }
 }
 
 
 RepeatedFieldGenerator::~RepeatedFieldGenerator() {}
 RepeatedFieldGenerator::~RepeatedFieldGenerator() {}
 
 
 void RepeatedFieldGenerator::FinishInitialization(void) {
 void RepeatedFieldGenerator::FinishInitialization(void) {
   FieldGenerator::FinishInitialization();
   FieldGenerator::FinishInitialization();
-  variables_["array_comment"] =
-      "// |" + variables_["name"] + "| contains |" + variables_["storage_type"] + "|\n";
+  if (variables_.find("array_property_type") == variables_.end()) {
+    variables_["array_property_type"] = variable("array_storage_type");
+  }
 }
 }
 
 
 void RepeatedFieldGenerator::GenerateFieldStorageDeclaration(
 void RepeatedFieldGenerator::GenerateFieldStorageDeclaration(
@@ -379,13 +384,13 @@ void RepeatedFieldGenerator::GeneratePropertyDeclaration(
       variables_,
       variables_,
       "$comments$"
       "$comments$"
       "$array_comment$"
       "$array_comment$"
-      "@property(nonatomic, readwrite, strong, null_resettable) $array_storage_type$ *$name$$storage_attribute$;\n"
+      "@property(nonatomic, readwrite, strong, null_resettable) $array_property_type$ *$name$$storage_attribute$;\n"
       "@property(nonatomic, readonly) NSUInteger $name$_Count;\n");
       "@property(nonatomic, readonly) NSUInteger $name$_Count;\n");
   if (IsInitName(variables_.find("name")->second)) {
   if (IsInitName(variables_.find("name")->second)) {
     // If property name starts with init we need to annotate it to get past ARC.
     // If property name starts with init we need to annotate it to get past ARC.
     // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
     // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
     printer->Print(variables_,
     printer->Print(variables_,
-                   "- ($array_storage_type$ *)$name$ GPB_METHOD_FAMILY_NONE;\n");
+                   "- ($array_property_type$ *)$name$ GPB_METHOD_FAMILY_NONE;\n");
   }
   }
   printer->Print("\n");
   printer->Print("\n");
 }
 }
@@ -395,7 +400,8 @@ bool RepeatedFieldGenerator::WantsHasProperty(void) const {
   return false;
   return false;
 }
 }
 
 
-FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
+FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
+                                     const Options& options)
     : descriptor_(descriptor),
     : descriptor_(descriptor),
       field_generators_(
       field_generators_(
           new scoped_ptr<FieldGenerator>[descriptor->field_count()]),
           new scoped_ptr<FieldGenerator>[descriptor->field_count()]),
@@ -403,10 +409,12 @@ FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
           new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) {
           new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) {
   // Construct all the FieldGenerators.
   // Construct all the FieldGenerators.
   for (int i = 0; i < descriptor->field_count(); i++) {
   for (int i = 0; i < descriptor->field_count(); i++) {
-    field_generators_[i].reset(FieldGenerator::Make(descriptor->field(i)));
+    field_generators_[i].reset(
+        FieldGenerator::Make(descriptor->field(i), options));
   }
   }
   for (int i = 0; i < descriptor->extension_count(); i++) {
   for (int i = 0; i < descriptor->extension_count(); i++) {
-    extension_generators_[i].reset(FieldGenerator::Make(descriptor->extension(i)));
+    extension_generators_[i].reset(
+        FieldGenerator::Make(descriptor->extension(i), options));
   }
   }
 }
 }
 
 

+ 19 - 9
src/google/protobuf/compiler/objectivec/objectivec_field.h

@@ -49,24 +49,31 @@ namespace objectivec {
 
 
 class FieldGenerator {
 class FieldGenerator {
  public:
  public:
-  static FieldGenerator* Make(const FieldDescriptor* field);
+  static FieldGenerator* Make(const FieldDescriptor* field,
+                              const Options& options);
 
 
   virtual ~FieldGenerator();
   virtual ~FieldGenerator();
 
 
+  // Exposed for subclasses to fill in.
   virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const = 0;
   virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const = 0;
   virtual void GeneratePropertyDeclaration(io::Printer* printer) const = 0;
   virtual void GeneratePropertyDeclaration(io::Printer* printer) const = 0;
-
   virtual void GeneratePropertyImplementation(io::Printer* printer) const = 0;
   virtual void GeneratePropertyImplementation(io::Printer* printer) const = 0;
 
 
-  virtual void GenerateFieldDescription(io::Printer* printer) const;
+  // Called by GenerateFieldDescription, exposed for classes that need custom
+  // generation.
   virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
   virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
-  virtual void GenerateFieldNumberConstant(io::Printer* printer) const;
 
 
+  // Exposed for subclasses to extend, base does nothing.
   virtual void GenerateCFunctionDeclarations(io::Printer* printer) const;
   virtual void GenerateCFunctionDeclarations(io::Printer* printer) const;
   virtual void GenerateCFunctionImplementations(io::Printer* printer) const;
   virtual void GenerateCFunctionImplementations(io::Printer* printer) const;
 
 
+  // Exposed for subclasses, should always call it on the parent class also.
   virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
   virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
 
 
+  // Used during generation, not intended to be extended by subclasses.
+  void GenerateFieldDescription(io::Printer* printer) const;
+  void GenerateFieldNumberConstant(io::Printer* printer) const;
+
   void SetOneofIndexBase(int index_base);
   void SetOneofIndexBase(int index_base);
 
 
   string variable(const char* key) const {
   string variable(const char* key) const {
@@ -81,7 +88,7 @@ class FieldGenerator {
   string raw_field_name() const { return variable("raw_field_name"); }
   string raw_field_name() const { return variable("raw_field_name"); }
 
 
  protected:
  protected:
-  explicit FieldGenerator(const FieldDescriptor* descriptor);
+  FieldGenerator(const FieldDescriptor* descriptor, const Options& options);
 
 
   virtual void FinishInitialization(void);
   virtual void FinishInitialization(void);
   virtual bool WantsHasProperty(void) const = 0;
   virtual bool WantsHasProperty(void) const = 0;
@@ -103,7 +110,8 @@ class SingleFieldGenerator : public FieldGenerator {
   virtual void GeneratePropertyImplementation(io::Printer* printer) const;
   virtual void GeneratePropertyImplementation(io::Printer* printer) const;
 
 
  protected:
  protected:
-  explicit SingleFieldGenerator(const FieldDescriptor* descriptor);
+  SingleFieldGenerator(const FieldDescriptor* descriptor,
+                       const Options& options);
   virtual bool WantsHasProperty(void) const;
   virtual bool WantsHasProperty(void) const;
 
 
  private:
  private:
@@ -119,7 +127,8 @@ class ObjCObjFieldGenerator : public SingleFieldGenerator {
   virtual void GeneratePropertyDeclaration(io::Printer* printer) const;
   virtual void GeneratePropertyDeclaration(io::Printer* printer) const;
 
 
  protected:
  protected:
-  explicit ObjCObjFieldGenerator(const FieldDescriptor* descriptor);
+  ObjCObjFieldGenerator(const FieldDescriptor* descriptor,
+                        const Options& options);
 
 
  private:
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjCObjFieldGenerator);
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjCObjFieldGenerator);
@@ -135,7 +144,8 @@ class RepeatedFieldGenerator : public ObjCObjFieldGenerator {
   virtual void GeneratePropertyImplementation(io::Printer* printer) const;
   virtual void GeneratePropertyImplementation(io::Printer* printer) const;
 
 
  protected:
  protected:
-  explicit RepeatedFieldGenerator(const FieldDescriptor* descriptor);
+  RepeatedFieldGenerator(const FieldDescriptor* descriptor,
+                         const Options& options);
   virtual void FinishInitialization(void);
   virtual void FinishInitialization(void);
   virtual bool WantsHasProperty(void) const;
   virtual bool WantsHasProperty(void) const;
 
 
@@ -146,7 +156,7 @@ class RepeatedFieldGenerator : public ObjCObjFieldGenerator {
 // Convenience class which constructs FieldGenerators for a Descriptor.
 // Convenience class which constructs FieldGenerators for a Descriptor.
 class FieldGeneratorMap {
 class FieldGeneratorMap {
  public:
  public:
-  explicit FieldGeneratorMap(const Descriptor* descriptor);
+  FieldGeneratorMap(const Descriptor* descriptor, const Options& options);
   ~FieldGeneratorMap();
   ~FieldGeneratorMap();
 
 
   const FieldGenerator& get(const FieldDescriptor* field) const;
   const FieldGenerator& get(const FieldDescriptor* field) const;

+ 6 - 4
src/google/protobuf/compiler/objectivec/objectivec_file.cc

@@ -50,17 +50,18 @@ const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30000;
 namespace compiler {
 namespace compiler {
 namespace objectivec {
 namespace objectivec {
 
 
-FileGenerator::FileGenerator(const FileDescriptor *file)
+FileGenerator::FileGenerator(const FileDescriptor *file, const Options& options)
     : file_(file),
     : file_(file),
       root_class_name_(FileClassName(file)),
       root_class_name_(FileClassName(file)),
-      is_public_dep_(false) {
+      is_public_dep_(false),
+      options_(options) {
   for (int i = 0; i < file_->enum_type_count(); i++) {
   for (int i = 0; i < file_->enum_type_count(); i++) {
     EnumGenerator *generator = new EnumGenerator(file_->enum_type(i));
     EnumGenerator *generator = new EnumGenerator(file_->enum_type(i));
     enum_generators_.push_back(generator);
     enum_generators_.push_back(generator);
   }
   }
   for (int i = 0; i < file_->message_type_count(); i++) {
   for (int i = 0; i < file_->message_type_count(); i++) {
     MessageGenerator *generator =
     MessageGenerator *generator =
-        new MessageGenerator(root_class_name_, file_->message_type(i));
+        new MessageGenerator(root_class_name_, file_->message_type(i), options_);
     message_generators_.push_back(generator);
     message_generators_.push_back(generator);
   }
   }
   for (int i = 0; i < file_->extension_count(); i++) {
   for (int i = 0; i < file_->extension_count(); i++) {
@@ -352,7 +353,8 @@ const vector<FileGenerator *> &FileGenerator::DependencyGenerators() {
       public_import_names.insert(file_->public_dependency(i)->name());
       public_import_names.insert(file_->public_dependency(i)->name());
     }
     }
     for (int i = 0; i < file_->dependency_count(); i++) {
     for (int i = 0; i < file_->dependency_count(); i++) {
-      FileGenerator *generator = new FileGenerator(file_->dependency(i));
+      FileGenerator *generator =
+          new FileGenerator(file_->dependency(i), options_);
       const string& name = file_->dependency(i)->name();
       const string& name = file_->dependency(i)->name();
       bool public_import = (public_import_names.count(name) != 0);
       bool public_import = (public_import_names.count(name) != 0);
       generator->SetIsPublicDependency(public_import);
       generator->SetIsPublicDependency(public_import);

+ 3 - 1
src/google/protobuf/compiler/objectivec/objectivec_file.h

@@ -55,7 +55,7 @@ class MessageGenerator;
 
 
 class FileGenerator {
 class FileGenerator {
  public:
  public:
-  explicit FileGenerator(const FileDescriptor* file);
+  FileGenerator(const FileDescriptor* file, const Options& options);
   ~FileGenerator();
   ~FileGenerator();
 
 
   void GenerateSource(io::Printer* printer);
   void GenerateSource(io::Printer* printer);
@@ -84,6 +84,8 @@ class FileGenerator {
   vector<ExtensionGenerator*> extension_generators_;
   vector<ExtensionGenerator*> extension_generators_;
   bool is_public_dep_;
   bool is_public_dep_;
 
 
+  const Options options_;
+
   const vector<FileGenerator*>& DependencyGenerators();
   const vector<FileGenerator*>& DependencyGenerators();
 
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);

+ 15 - 5
src/google/protobuf/compiler/objectivec/objectivec_generator.cc

@@ -49,21 +49,31 @@ bool ObjectiveCGenerator::Generate(const FileDescriptor* file,
                                    const string& parameter,
                                    const string& parameter,
                                    OutputDirectory* output_directory,
                                    OutputDirectory* output_directory,
                                    string* error) const {
                                    string* error) const {
-  // ObjC doesn't have any options at the moment, error if passed one.
+  // -----------------------------------------------------------------
+  // Parse generator options.
+
+  Options generation_options;
+
   vector<pair<string, string> > options;
   vector<pair<string, string> > options;
   ParseGeneratorParameter(parameter, &options);
   ParseGeneratorParameter(parameter, &options);
   for (int i = 0; i < options.size(); i++) {
   for (int i = 0; i < options.size(); i++) {
-    *error = "error:: Unknown generator option: " + options[i].first;
-    return false;
+    if (options[i].first == "expected_prefixes_path") {
+      generation_options.expected_prefixes_path = options[i].second;
+    } else {
+      *error = "error: Unknown generator option: " + options[i].first;
+      return false;
+    }
   }
   }
 
 
+  // -----------------------------------------------------------------
+
   // Validate the objc prefix/package pairing.
   // Validate the objc prefix/package pairing.
-  if (!ValidateObjCClassPrefix(file, error)) {
+  if (!ValidateObjCClassPrefix(file, generation_options, error)) {
     // *error will have been filled in.
     // *error will have been filled in.
     return false;
     return false;
   }
   }
 
 
-  FileGenerator file_generator(file);
+  FileGenerator file_generator(file, generation_options);
   string filepath = FilePath(file);
   string filepath = FilePath(file);
 
 
   // Generate header.
   // Generate header.

+ 29 - 19
src/google/protobuf/compiler/objectivec/objectivec_helpers.cc

@@ -58,6 +58,14 @@ namespace protobuf {
 namespace compiler {
 namespace compiler {
 namespace objectivec {
 namespace objectivec {
 
 
+Options::Options() {
+  // Default is the value of the env for the package prefixes.
+  const char* file_path = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES");
+  if (file_path) {
+    expected_prefixes_path = file_path;
+  }
+}
+
 namespace {
 namespace {
 
 
 hash_set<string> MakeWordsMap(const char* const words[], size_t num_words) {
 hash_set<string> MakeWordsMap(const char* const words[], size_t num_words) {
@@ -890,26 +898,26 @@ bool Parser::ParseLoop() {
   return true;
   return true;
 }
 }
 
 
-bool LoadExpectedPackagePrefixes(map<string, string>* prefix_map,
-                                 string* out_expect_file_path,
+bool LoadExpectedPackagePrefixes(const Options &generation_options,
+                                 map<string, string>* prefix_map,
                                  string* out_error) {
                                  string* out_error) {
-  const char* file_path = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES");
-  if (file_path == NULL) {
+  if (generation_options.expected_prefixes_path.empty()) {
     return true;
     return true;
   }
   }
 
 
   int fd;
   int fd;
   do {
   do {
-    fd = open(file_path, O_RDONLY);
+    fd = open(generation_options.expected_prefixes_path.c_str(), O_RDONLY);
   } while (fd < 0 && errno == EINTR);
   } while (fd < 0 && errno == EINTR);
   if (fd < 0) {
   if (fd < 0) {
     *out_error =
     *out_error =
-        string(file_path) + ":0:0: error: Unable to open." + strerror(errno);
+        string("error: Unable to open \"") +
+        generation_options.expected_prefixes_path +
+        "\", " + strerror(errno);
     return false;
     return false;
   }
   }
   io::FileInputStream file_stream(fd);
   io::FileInputStream file_stream(fd);
   file_stream.SetCloseOnDelete(true);
   file_stream.SetCloseOnDelete(true);
-  *out_expect_file_path = file_path;
 
 
   Parser parser(prefix_map);
   Parser parser(prefix_map);
   const void* buf;
   const void* buf;
@@ -920,8 +928,9 @@ bool LoadExpectedPackagePrefixes(map<string, string>* prefix_map,
     }
     }
 
 
     if (!parser.ParseChunk(StringPiece(static_cast<const char*>(buf), buf_len))) {
     if (!parser.ParseChunk(StringPiece(static_cast<const char*>(buf), buf_len))) {
-      *out_error = string(file_path) + ":" + SimpleItoa(parser.last_line()) +
-                   ":0: error: " + parser.error_str();
+      *out_error =
+          string("error: ") + generation_options.expected_prefixes_path +
+          " Line " + SimpleItoa(parser.last_line()) + ", " + parser.error_str();
       return false;
       return false;
     }
     }
   }
   }
@@ -930,7 +939,9 @@ bool LoadExpectedPackagePrefixes(map<string, string>* prefix_map,
 
 
 }  // namespace
 }  // namespace
 
 
-bool ValidateObjCClassPrefix(const FileDescriptor* file, string* out_error) {
+bool ValidateObjCClassPrefix(const FileDescriptor* file,
+                             const Options& generation_options,
+                             string* out_error) {
   const string prefix = file->options().objc_class_prefix();
   const string prefix = file->options().objc_class_prefix();
   const string package = file->package();
   const string package = file->package();
 
 
@@ -939,11 +950,10 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file, string* out_error) {
 
 
   // Load any expected package prefixes to validate against those.
   // Load any expected package prefixes to validate against those.
   map<string, string> expected_package_prefixes;
   map<string, string> expected_package_prefixes;
-  string expect_file_path;
-  if (!LoadExpectedPackagePrefixes(&expected_package_prefixes,
-                                   &expect_file_path, out_error)) {
-    // Any error, clear the entries that were read.
-    expected_package_prefixes.clear();
+  if (!LoadExpectedPackagePrefixes(generation_options,
+                                   &expected_package_prefixes,
+                                   out_error)) {
+    return false;
   }
   }
 
 
   // Check: Error - See if there was an expected prefix for the package and
   // Check: Error - See if there was an expected prefix for the package and
@@ -957,7 +967,7 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file, string* out_error) {
       return true;
       return true;
     } else {
     } else {
       // ...it didn't match!
       // ...it didn't match!
-      *out_error = "protoc:0: error: Expected 'option objc_class_prefix = \"" +
+      *out_error = "error: Expected 'option objc_class_prefix = \"" +
                    package_match->second + "\";' in '" + file->name() + "'";
                    package_match->second + "\";' in '" + file->name() + "'";
       if (prefix.length()) {
       if (prefix.length()) {
         *out_error += "; but found '" + prefix + "' instead";
         *out_error += "; but found '" + prefix + "' instead";
@@ -980,11 +990,11 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file, string* out_error) {
        i != expected_package_prefixes.end(); ++i) {
        i != expected_package_prefixes.end(); ++i) {
     if (i->second == prefix) {
     if (i->second == prefix) {
       *out_error =
       *out_error =
-          "protoc:0: error: Found 'option objc_class_prefix = \"" + prefix +
+          "error: Found 'option objc_class_prefix = \"" + prefix +
           "\";' in '" + file->name() +
           "\";' in '" + file->name() +
           "'; that prefix is already used for 'package " + i->first +
           "'; that prefix is already used for 'package " + i->first +
           ";'. It can only be reused by listing it in the expected file (" +
           ";'. It can only be reused by listing it in the expected file (" +
-          expect_file_path + ").";
+          generation_options.expected_prefixes_path + ").";
       return false;  // Only report first usage of the prefix.
       return false;  // Only report first usage of the prefix.
     }
     }
   }
   }
@@ -1017,7 +1027,7 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file, string* out_error) {
          << "protoc:0: warning: Found unexpected 'option objc_class_prefix = \""
          << "protoc:0: warning: Found unexpected 'option objc_class_prefix = \""
          << prefix << "\";' in '" << file->name() << "';"
          << prefix << "\";' in '" << file->name() << "';"
          << " consider adding it to the expected prefixes file ("
          << " consider adding it to the expected prefixes file ("
-         << expect_file_path << ")." << endl;
+         << generation_options.expected_prefixes_path << ")." << endl;
     cerr.flush();
     cerr.flush();
   }
   }
 
 

+ 9 - 1
src/google/protobuf/compiler/objectivec/objectivec_helpers.h

@@ -42,6 +42,12 @@ namespace protobuf {
 namespace compiler {
 namespace compiler {
 namespace objectivec {
 namespace objectivec {
 
 
+// Generator options (see objectivec_generator.cc for a description of each):
+struct Options {
+  Options();
+  string expected_prefixes_path;
+};
+
 // Strips ".proto" or ".protodevel" from the end of a filename.
 // Strips ".proto" or ".protodevel" from the end of a filename.
 string StripProto(const string& filename);
 string StripProto(const string& filename);
 
 
@@ -145,7 +151,9 @@ string BuildCommentsString(const SourceLocation& location);
 // Checks the prefix for a given file and outputs any warnings needed, if
 // Checks the prefix for a given file and outputs any warnings needed, if
 // there are flat out errors, then out_error is filled in and the result is
 // there are flat out errors, then out_error is filled in and the result is
 // false.
 // false.
-bool ValidateObjCClassPrefix(const FileDescriptor* file, string *out_error);
+bool ValidateObjCClassPrefix(const FileDescriptor* file,
+                             const Options& generation_options,
+                             string* out_error);
 
 
 // Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform
 // Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform
 // the input into the expected output.
 // the input into the expected output.

+ 35 - 16
src/google/protobuf/compiler/objectivec/objectivec_map_field.cc

@@ -84,13 +84,14 @@ const char* MapEntryTypeName(const FieldDescriptor* descriptor, bool isKey) {
 
 
 }  // namespace
 }  // namespace
 
 
-MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor)
-    : RepeatedFieldGenerator(descriptor) {
+MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
+                                     const Options& options)
+    : RepeatedFieldGenerator(descriptor, options) {
   const FieldDescriptor* key_descriptor =
   const FieldDescriptor* key_descriptor =
       descriptor->message_type()->FindFieldByName("key");
       descriptor->message_type()->FindFieldByName("key");
   const FieldDescriptor* value_descriptor =
   const FieldDescriptor* value_descriptor =
       descriptor->message_type()->FindFieldByName("value");
       descriptor->message_type()->FindFieldByName("value");
-  value_field_generator_.reset(FieldGenerator::Make(value_descriptor));
+  value_field_generator_.reset(FieldGenerator::Make(value_descriptor, options));
 
 
   // Pull over some variables_ from the value.
   // Pull over some variables_ from the value.
   variables_["field_type"] = value_field_generator_->variable("field_type");
   variables_["field_type"] = value_field_generator_->variable("field_type");
@@ -117,16 +118,27 @@ MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor)
   variables_["fieldflags"] = BuildFlagsString(field_flags);
   variables_["fieldflags"] = BuildFlagsString(field_flags);
 
 
   ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor);
   ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor);
-  if ((GetObjectiveCType(key_descriptor) == OBJECTIVECTYPE_STRING) &&
+  const bool value_is_object_type =
       ((value_objc_type == OBJECTIVECTYPE_STRING) ||
       ((value_objc_type == OBJECTIVECTYPE_STRING) ||
        (value_objc_type == OBJECTIVECTYPE_DATA) ||
        (value_objc_type == OBJECTIVECTYPE_DATA) ||
-       (value_objc_type == OBJECTIVECTYPE_MESSAGE))) {
+       (value_objc_type == OBJECTIVECTYPE_MESSAGE));
+  if ((GetObjectiveCType(key_descriptor) == OBJECTIVECTYPE_STRING) &&
+      value_is_object_type) {
     variables_["array_storage_type"] = "NSMutableDictionary";
     variables_["array_storage_type"] = "NSMutableDictionary";
+    variables_["array_property_type"] =
+        "NSMutableDictionary<NSString*, " +
+        value_field_generator_->variable("storage_type") + "*>";
   } else {
   } else {
-    string base_name = MapEntryTypeName(key_descriptor, true);
-    base_name += MapEntryTypeName(value_descriptor, false);
-    base_name += "Dictionary";
-    variables_["array_storage_type"] = "GPB" + base_name;
+    string class_name("GPB");
+    class_name += MapEntryTypeName(key_descriptor, true);
+    class_name += MapEntryTypeName(value_descriptor, false);
+    class_name += "Dictionary";
+    variables_["array_storage_type"] = class_name;
+    if (value_is_object_type) {
+      variables_["array_property_type"] =
+          class_name + "<" +
+          value_field_generator_->variable("storage_type") + "*>";
+    }
   }
   }
 }
 }
 
 
@@ -138,15 +150,9 @@ void MapFieldGenerator::FinishInitialization(void) {
   // values in the map are.
   // values in the map are.
   const FieldDescriptor* value_descriptor =
   const FieldDescriptor* value_descriptor =
       descriptor_->message_type()->FindFieldByName("value");
       descriptor_->message_type()->FindFieldByName("value");
-  ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor);
-  if ((value_objc_type == OBJECTIVECTYPE_MESSAGE) ||
-      (value_objc_type == OBJECTIVECTYPE_DATA) ||
-      (value_objc_type == OBJECTIVECTYPE_STRING) ||
-      (value_objc_type == OBJECTIVECTYPE_ENUM)) {
+  if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_ENUM) {
     variables_["array_comment"] =
     variables_["array_comment"] =
         "// |" + variables_["name"] + "| values are |" + value_field_generator_->variable("storage_type") + "|\n";
         "// |" + variables_["name"] + "| values are |" + value_field_generator_->variable("storage_type") + "|\n";
-  } else {
-    variables_["array_comment"] = "";
   }
   }
 }
 }
 
 
@@ -157,6 +163,19 @@ void MapFieldGenerator::GenerateFieldDescriptionTypeSpecific(
   value_field_generator_->GenerateFieldDescriptionTypeSpecific(printer);
   value_field_generator_->GenerateFieldDescriptionTypeSpecific(printer);
 }
 }
 
 
+void MapFieldGenerator::DetermineForwardDeclarations(
+    set<string>* fwd_decls) const {
+  RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls);
+  const FieldDescriptor* value_descriptor =
+      descriptor_->message_type()->FindFieldByName("value");
+  if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_MESSAGE) {
+    const string& value_storage_type =
+        value_field_generator_->variable("storage_type");
+    fwd_decls->insert("@class " + value_storage_type);
+  }
+}
+
+
 }  // namespace objectivec
 }  // namespace objectivec
 }  // namespace compiler
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace protobuf

+ 6 - 2
src/google/protobuf/compiler/objectivec/objectivec_map_field.h

@@ -41,18 +41,22 @@ namespace compiler {
 namespace objectivec {
 namespace objectivec {
 
 
 class MapFieldGenerator : public RepeatedFieldGenerator {
 class MapFieldGenerator : public RepeatedFieldGenerator {
-  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
 
 
  public:
  public:
   virtual void FinishInitialization(void);
   virtual void FinishInitialization(void);
   virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
   virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
 
 
  protected:
  protected:
-  explicit MapFieldGenerator(const FieldDescriptor* descriptor);
+  MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
   virtual ~MapFieldGenerator();
   virtual ~MapFieldGenerator();
 
 
+  virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
+
  private:
  private:
   scoped_ptr<FieldGenerator> value_field_generator_;
   scoped_ptr<FieldGenerator> value_field_generator_;
+
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
 };
 };
 
 

+ 6 - 8
src/google/protobuf/compiler/objectivec/objectivec_message.cc

@@ -174,10 +174,11 @@ const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) {
 }  // namespace
 }  // namespace
 
 
 MessageGenerator::MessageGenerator(const string& root_classname,
 MessageGenerator::MessageGenerator(const string& root_classname,
-                                   const Descriptor* descriptor)
+                                   const Descriptor* descriptor,
+                                   const Options& options)
     : root_classname_(root_classname),
     : root_classname_(root_classname),
       descriptor_(descriptor),
       descriptor_(descriptor),
-      field_generators_(descriptor),
+      field_generators_(descriptor, options),
       class_name_(ClassName(descriptor_)) {
       class_name_(ClassName(descriptor_)) {
   for (int i = 0; i < descriptor_->extension_count(); i++) {
   for (int i = 0; i < descriptor_->extension_count(); i++) {
     extension_generators_.push_back(
     extension_generators_.push_back(
@@ -196,7 +197,9 @@ MessageGenerator::MessageGenerator(const string& root_classname,
 
 
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
     MessageGenerator* generator =
     MessageGenerator* generator =
-        new MessageGenerator(root_classname_, descriptor_->nested_type(i));
+        new MessageGenerator(root_classname_,
+                             descriptor_->nested_type(i),
+                             options);
     nested_message_generators_.push_back(generator);
     nested_message_generators_.push_back(generator);
   }
   }
 }
 }
@@ -230,11 +233,6 @@ void MessageGenerator::DetermineForwardDeclarations(set<string>* fwd_decls) {
   if (!IsMapEntryMessage(descriptor_)) {
   if (!IsMapEntryMessage(descriptor_)) {
     for (int i = 0; i < descriptor_->field_count(); i++) {
     for (int i = 0; i < descriptor_->field_count(); i++) {
       const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
       const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
-      // If it is a the field is repeated, the type will be and *Array, and we
-      // don't need any forward decl.
-      if (fieldDescriptor->is_repeated()) {
-        continue;
-      }
       field_generators_.get(fieldDescriptor)
       field_generators_.get(fieldDescriptor)
           .DetermineForwardDeclarations(fwd_decls);
           .DetermineForwardDeclarations(fwd_decls);
     }
     }

+ 3 - 1
src/google/protobuf/compiler/objectivec/objectivec_message.h

@@ -54,7 +54,9 @@ class EnumGenerator;
 
 
 class MessageGenerator {
 class MessageGenerator {
  public:
  public:
-  MessageGenerator(const string& root_classname, const Descriptor* descriptor);
+  MessageGenerator(const string& root_classname,
+                   const Descriptor* descriptor,
+                   const Options& options);
   ~MessageGenerator();
   ~MessageGenerator();
 
 
   void GenerateStaticVariablesInitialization(io::Printer* printer);
   void GenerateStaticVariablesInitialization(io::Printer* printer);

+ 16 - 4
src/google/protobuf/compiler/objectivec/objectivec_message_field.cc

@@ -58,8 +58,9 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
 
 
 }  // namespace
 }  // namespace
 
 
-MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor)
-    : ObjCObjFieldGenerator(descriptor) {
+MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
+                                             const Options& options)
+    : ObjCObjFieldGenerator(descriptor, options) {
   SetMessageVariables(descriptor, &variables_);
   SetMessageVariables(descriptor, &variables_);
 }
 }
 
 
@@ -67,6 +68,7 @@ MessageFieldGenerator::~MessageFieldGenerator() {}
 
 
 void MessageFieldGenerator::DetermineForwardDeclarations(
 void MessageFieldGenerator::DetermineForwardDeclarations(
     set<string>* fwd_decls) const {
     set<string>* fwd_decls) const {
+  ObjCObjFieldGenerator::DetermineForwardDeclarations(fwd_decls);
   // Class name is already in "storage_type".
   // Class name is already in "storage_type".
   fwd_decls->insert("@class " + variable("storage_type"));
   fwd_decls->insert("@class " + variable("storage_type"));
 }
 }
@@ -82,14 +84,24 @@ bool MessageFieldGenerator::WantsHasProperty(void) const {
 }
 }
 
 
 RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
 RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
-    const FieldDescriptor* descriptor)
-    : RepeatedFieldGenerator(descriptor) {
+    const FieldDescriptor* descriptor, const Options& options)
+    : RepeatedFieldGenerator(descriptor, options) {
   SetMessageVariables(descriptor, &variables_);
   SetMessageVariables(descriptor, &variables_);
   variables_["array_storage_type"] = "NSMutableArray";
   variables_["array_storage_type"] = "NSMutableArray";
+  variables_["array_property_type"] =
+      "NSMutableArray<" + variables_["storage_type"] + "*>";
 }
 }
 
 
 RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
 RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
 
 
+void RepeatedMessageFieldGenerator::DetermineForwardDeclarations(
+    set<string>* fwd_decls) const {
+  RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls);
+  // Class name is already in "storage_type".
+  fwd_decls->insert("@class " + variable("storage_type"));
+}
+
+
 }  // namespace objectivec
 }  // namespace objectivec
 }  // namespace compiler
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace protobuf

+ 11 - 4
src/google/protobuf/compiler/objectivec/objectivec_message_field.h

@@ -41,10 +41,12 @@ namespace compiler {
 namespace objectivec {
 namespace objectivec {
 
 
 class MessageFieldGenerator : public ObjCObjFieldGenerator {
 class MessageFieldGenerator : public ObjCObjFieldGenerator {
-  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
 
 
  protected:
  protected:
-  explicit MessageFieldGenerator(const FieldDescriptor* descriptor);
+  MessageFieldGenerator(const FieldDescriptor* descriptor,
+                        const Options& options);
   virtual ~MessageFieldGenerator();
   virtual ~MessageFieldGenerator();
   virtual bool WantsHasProperty(void) const;
   virtual bool WantsHasProperty(void) const;
 
 
@@ -56,12 +58,17 @@ class MessageFieldGenerator : public ObjCObjFieldGenerator {
 };
 };
 
 
 class RepeatedMessageFieldGenerator : public RepeatedFieldGenerator {
 class RepeatedMessageFieldGenerator : public RepeatedFieldGenerator {
-  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
 
 
  protected:
  protected:
-  explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor);
+  RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+                                const Options& options);
   virtual ~RepeatedMessageFieldGenerator();
   virtual ~RepeatedMessageFieldGenerator();
 
 
+ public:
+  virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
+
  private:
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
 };
 };

+ 11 - 16
src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc

@@ -74,7 +74,7 @@ const char* PrimitiveTypeName(const FieldDescriptor* descriptor) {
     case OBJECTIVECTYPE_ENUM:
     case OBJECTIVECTYPE_ENUM:
       return "int32_t";
       return "int32_t";
     case OBJECTIVECTYPE_MESSAGE:
     case OBJECTIVECTYPE_MESSAGE:
-      return NULL;
+      return NULL;  // Messages go through objectivec_message_field.cc|h.
   }
   }
 
 
   // Some compilers report reaching end of function even though all cases of
   // Some compilers report reaching end of function even though all cases of
@@ -107,7 +107,8 @@ const char* PrimitiveArrayTypeName(const FieldDescriptor* descriptor) {
     case OBJECTIVECTYPE_ENUM:
     case OBJECTIVECTYPE_ENUM:
       return "Enum";
       return "Enum";
     case OBJECTIVECTYPE_MESSAGE:
     case OBJECTIVECTYPE_MESSAGE:
-      return "";  // Want NSArray
+      // Want NSArray (but goes through objectivec_message_field.cc|h).
+      return "";
   }
   }
 
 
   // Some compilers report reaching end of function even though all cases of
   // Some compilers report reaching end of function even though all cases of
@@ -126,16 +127,16 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
 }  // namespace
 }  // namespace
 
 
 PrimitiveFieldGenerator::PrimitiveFieldGenerator(
 PrimitiveFieldGenerator::PrimitiveFieldGenerator(
-    const FieldDescriptor* descriptor)
-    : SingleFieldGenerator(descriptor) {
+    const FieldDescriptor* descriptor, const Options& options)
+    : SingleFieldGenerator(descriptor, options) {
   SetPrimitiveVariables(descriptor, &variables_);
   SetPrimitiveVariables(descriptor, &variables_);
 }
 }
 
 
 PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
 PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
 
 
 PrimitiveObjFieldGenerator::PrimitiveObjFieldGenerator(
 PrimitiveObjFieldGenerator::PrimitiveObjFieldGenerator(
-    const FieldDescriptor* descriptor)
-    : ObjCObjFieldGenerator(descriptor) {
+    const FieldDescriptor* descriptor, const Options& options)
+    : ObjCObjFieldGenerator(descriptor, options) {
   SetPrimitiveVariables(descriptor, &variables_);
   SetPrimitiveVariables(descriptor, &variables_);
   variables_["property_storage_attribute"] = "copy";
   variables_["property_storage_attribute"] = "copy";
 }
 }
@@ -143,8 +144,8 @@ PrimitiveObjFieldGenerator::PrimitiveObjFieldGenerator(
 PrimitiveObjFieldGenerator::~PrimitiveObjFieldGenerator() {}
 PrimitiveObjFieldGenerator::~PrimitiveObjFieldGenerator() {}
 
 
 RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
 RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
-    const FieldDescriptor* descriptor)
-    : RepeatedFieldGenerator(descriptor) {
+    const FieldDescriptor* descriptor, const Options& options)
+    : RepeatedFieldGenerator(descriptor, options) {
   SetPrimitiveVariables(descriptor, &variables_);
   SetPrimitiveVariables(descriptor, &variables_);
 
 
   string base_name = PrimitiveArrayTypeName(descriptor);
   string base_name = PrimitiveArrayTypeName(descriptor);
@@ -152,19 +153,13 @@ RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
     variables_["array_storage_type"] = "GPB" + base_name + "Array";
     variables_["array_storage_type"] = "GPB" + base_name + "Array";
   } else {
   } else {
     variables_["array_storage_type"] = "NSMutableArray";
     variables_["array_storage_type"] = "NSMutableArray";
+    variables_["array_property_type"] =
+        "NSMutableArray<" + variables_["storage_type"] + "*>";
   }
   }
 }
 }
 
 
 RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
 RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
 
 
-void RepeatedPrimitiveFieldGenerator::FinishInitialization(void) {
-  RepeatedFieldGenerator::FinishInitialization();
-  if (IsPrimitiveType(descriptor_)) {
-    // No comment needed for primitive types.
-    variables_["array_comment"] = "";
-  }
-}
-
 }  // namespace objectivec
 }  // namespace objectivec
 }  // namespace compiler
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace protobuf

+ 12 - 7
src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h

@@ -41,10 +41,12 @@ namespace compiler {
 namespace objectivec {
 namespace objectivec {
 
 
 class PrimitiveFieldGenerator : public SingleFieldGenerator {
 class PrimitiveFieldGenerator : public SingleFieldGenerator {
-  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
 
 
  protected:
  protected:
-  explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor);
+  PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                          const Options& options);
   virtual ~PrimitiveFieldGenerator();
   virtual ~PrimitiveFieldGenerator();
 
 
  private:
  private:
@@ -52,10 +54,12 @@ class PrimitiveFieldGenerator : public SingleFieldGenerator {
 };
 };
 
 
 class PrimitiveObjFieldGenerator : public ObjCObjFieldGenerator {
 class PrimitiveObjFieldGenerator : public ObjCObjFieldGenerator {
-  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
 
 
  protected:
  protected:
-  explicit PrimitiveObjFieldGenerator(const FieldDescriptor* descriptor);
+  PrimitiveObjFieldGenerator(const FieldDescriptor* descriptor,
+                             const Options& options);
   virtual ~PrimitiveObjFieldGenerator();
   virtual ~PrimitiveObjFieldGenerator();
 
 
  private:
  private:
@@ -63,12 +67,13 @@ class PrimitiveObjFieldGenerator : public ObjCObjFieldGenerator {
 };
 };
 
 
 class RepeatedPrimitiveFieldGenerator : public RepeatedFieldGenerator {
 class RepeatedPrimitiveFieldGenerator : public RepeatedFieldGenerator {
-  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+                                              const Options& options);
 
 
  protected:
  protected:
-  explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor);
+  RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+                                  const Options& options);
   virtual ~RepeatedPrimitiveFieldGenerator();
   virtual ~RepeatedPrimitiveFieldGenerator();
-  virtual void FinishInitialization(void);
 
 
  private:
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);