From 74956e1c1589ef473cf229fdf81d4045953a3f38 Mon Sep 17 00:00:00 2001 From: Dave MacLachlan Date: Tue, 17 Dec 2019 17:32:09 -0800 Subject: [PATCH] Use references to Objective C classes instead of looking classes up by name. This should reduce binary size slightly, small performance improvement, and improve linkage by forcing references to all used classes. Note that this maintains backwards compatibility for sources generated by older protoc for the time being. If you want the benefits you will need to recompile your protos with the newer protoc. --- Makefile.am | 1 + objectivec/GPBDescriptor.m | 98 +++++++---- objectivec/GPBDescriptor_PackagePrivate.h | 41 ++++- objectivec/GPBRuntimeTypes.h | 7 + .../project.pbxproj | 5 + .../project.pbxproj | 7 + .../project.pbxproj | 5 + objectivec/Tests/GPBMessageTests+ClassNames.m | 164 ++++++++++++++++++ objectivec/google/protobuf/Any.pbobjc.m | 6 +- objectivec/google/protobuf/Api.pbobjc.m | 46 +++-- objectivec/google/protobuf/Duration.pbobjc.m | 6 +- objectivec/google/protobuf/Empty.pbobjc.m | 2 +- objectivec/google/protobuf/FieldMask.pbobjc.m | 4 +- .../google/protobuf/SourceContext.pbobjc.m | 4 +- objectivec/google/protobuf/Struct.pbobjc.m | 31 ++-- objectivec/google/protobuf/Timestamp.pbobjc.m | 6 +- objectivec/google/protobuf/Type.pbobjc.m | 67 ++++--- objectivec/google/protobuf/Wrappers.pbobjc.m | 36 ++-- .../objectivec/objectivec_extension.cc | 30 +++- .../objectivec/objectivec_extension.h | 1 + .../compiler/objectivec/objectivec_field.cc | 9 +- .../compiler/objectivec/objectivec_field.h | 1 + .../compiler/objectivec/objectivec_file.cc | 36 +++- .../compiler/objectivec/objectivec_helpers.cc | 13 ++ .../compiler/objectivec/objectivec_helpers.h | 9 + .../objectivec/objectivec_map_field.cc | 12 ++ .../objectivec/objectivec_map_field.h | 1 + .../compiler/objectivec/objectivec_message.cc | 42 ++++- .../compiler/objectivec/objectivec_message.h | 1 + .../objectivec/objectivec_message_field.cc | 16 +- .../objectivec/objectivec_message_field.h | 2 + 31 files changed, 554 insertions(+), 155 deletions(-) create mode 100644 objectivec/Tests/GPBMessageTests+ClassNames.m diff --git a/Makefile.am b/Makefile.am index cca346e9ca03..079ac7062bd7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -687,6 +687,7 @@ objectivec_EXTRA_DIST= \ objectivec/Tests/GPBDictionaryTests.m \ objectivec/Tests/GPBDictionaryTests.pddm \ objectivec/Tests/GPBExtensionRegistryTest.m \ + objectivec/Tests/GPBMessageTests+ClassNames.m \ objectivec/Tests/GPBMessageTests+Merge.m \ objectivec/Tests/GPBMessageTests+Runtime.m \ objectivec/Tests/GPBMessageTests+Serialization.m \ diff --git a/objectivec/GPBDescriptor.m b/objectivec/GPBDescriptor.m index 41bf5adbcb67..130f1b96a83f 100644 --- a/objectivec/GPBDescriptor.m +++ b/objectivec/GPBDescriptor.m @@ -44,7 +44,7 @@ // The addresses of these variables are used as keys for objc_getAssociatedObject. static const char kTextFormatExtraValueKey = 0; -static const char kParentClassNameValueKey = 0; +static const char kParentClassValueKey = 0; static const char kClassNameSuffixKey = 0; // Utility function to generate selectors on the fly. @@ -126,6 +126,8 @@ @implementation GPBDescriptor { GPBFileSyntax syntax = file.syntax; BOOL fieldsIncludeDefault = (flags & GPBDescriptorInitializationFlag_FieldsWithDefault) != 0; + BOOL usesClassRefs = + (flags & GPBDescriptorInitializationFlag_UsesClassRefs) != 0; void *desc; for (uint32_t i = 0; i < fieldCount; ++i) { @@ -143,6 +145,7 @@ @implementation GPBDescriptor { GPBFieldDescriptor *fieldDescriptor = [[GPBFieldDescriptor alloc] initWithFieldDescription:desc includesDefault:fieldsIncludeDefault + usesClassRefs:usesClassRefs syntax:syntax]; [fields addObject:fieldDescriptor]; [fieldDescriptor release]; @@ -217,15 +220,19 @@ - (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)co extensionRangesCount_ = count; } +- (void)setupContainingMessageClass:(Class)messageClass { + objc_setAssociatedObject(self, &kParentClassValueKey, + messageClass, + OBJC_ASSOCIATION_ASSIGN); +} + - (void)setupContainingMessageClassName:(const char *)msgClassName { // Note: Only fetch the class here, can't send messages to it because // that could cause cycles back to this class within +initialize if // two messages have each other in fields (i.e. - they build a graph). - NSAssert(objc_getClass(msgClassName), @"Class %s not defined", msgClassName); - NSValue *parentNameValue = [NSValue valueWithPointer:msgClassName]; - objc_setAssociatedObject(self, &kParentClassNameValueKey, - parentNameValue, - OBJC_ASSOCIATION_RETAIN_NONATOMIC); + Class clazz = objc_getClass(msgClassName); + NSAssert(clazz, @"Class %s not defined", msgClassName); + [self setupContainingMessageClass:clazz]; } - (void)setupMessageClassNameSuffix:(NSString *)suffix { @@ -241,14 +248,7 @@ - (NSString *)name { } - (GPBDescriptor *)containingType { - NSValue *parentNameValue = - objc_getAssociatedObject(self, &kParentClassNameValueKey); - if (!parentNameValue) { - return nil; - } - const char *parentName = [parentNameValue pointerValue]; - Class parentClass = objc_getClass(parentName); - NSAssert(parentClass, @"Class %s not defined", parentName); + Class parentClass = objc_getAssociatedObject(self, &kParentClassValueKey); return [parentClass descriptor]; } @@ -487,6 +487,7 @@ - (instancetype)init { - (instancetype)initWithFieldDescription:(void *)description includesDefault:(BOOL)includesDefault + usesClassRefs:(BOOL)usesClassRefs syntax:(GPBFileSyntax)syntax { if ((self = [super init])) { GPBMessageFieldDescription *coreDesc; @@ -524,12 +525,17 @@ - (instancetype)initWithFieldDescription:(void *)description // Extra type specific data. if (isMessage) { - const char *className = coreDesc->dataTypeSpecific.className; // Note: Only fetch the class here, can't send messages to it because // that could cause cycles back to this class within +initialize if // two messages have each other in fields (i.e. - they build a graph). - msgClass_ = objc_getClass(className); - NSAssert(msgClass_, @"Class %s not defined", className); + if (usesClassRefs) { + msgClass_ = coreDesc->dataTypeSpecific.clazz; + } else { + // Backwards compatibility for sources generated with older protoc. + const char *className = coreDesc->dataTypeSpecific.className; + msgClass_ = objc_getClass(className); + NSAssert(msgClass_, @"Class %s not defined", className); + } } else if (dataType == GPBDataTypeEnum) { if ((coreDesc->flags & GPBFieldHasEnumDescriptor) != 0) { enumHandling_.enumDescriptor_ = @@ -561,6 +567,15 @@ - (instancetype)initWithFieldDescription:(void *)description return self; } +- (instancetype)initWithFieldDescription:(void *)description + includesDefault:(BOOL)includesDefault + syntax:(GPBFileSyntax)syntax { + return [self initWithFieldDescription:description + includesDefault:includesDefault + usesClassRefs:NO + syntax:syntax]; +} + - (void)dealloc { if (description_->dataType == GPBDataTypeBytes && !(description_->flags & GPBFieldRepeated)) { @@ -957,33 +972,32 @@ @implementation GPBExtensionDescriptor { GPBGenericValue defaultValue_; } -@synthesize containingMessageClass = containingMessageClass_; - -- (instancetype)initWithExtensionDescription: - (GPBExtensionDescription *)description { +- (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc + usesClassRefs:(BOOL)usesClassRefs { if ((self = [super init])) { - description_ = description; - -#if defined(DEBUG) && DEBUG - const char *className = description->messageOrGroupClassName; - if (className) { - NSAssert(objc_lookUpClass(className) != Nil, - @"Class %s not defined", className); - } -#endif + description_ = desc; + if (!usesClassRefs) { + // Legacy without class ref support. + const char *className = description_->messageOrGroupClass.name; + if (className) { + Class clazz = objc_lookUpClass(className); + NSAssert(clazz != Nil, @"Class %s not defined", className); + description_->messageOrGroupClass.clazz = clazz; + } - if (description->extendedClass) { - Class containingClass = objc_lookUpClass(description->extendedClass); - NSAssert(containingClass, @"Class %s not defined", - description->extendedClass); - containingMessageClass_ = containingClass; + const char *extendedClassName = description_->extendedClass.name; + if (extendedClassName) { + Class clazz = objc_lookUpClass(extendedClassName); + NSAssert(clazz, @"Class %s not defined", extendedClassName); + description_->extendedClass.clazz = clazz; + } } GPBDataType type = description_->dataType; if (type == GPBDataTypeBytes) { // Data stored as a length prefixed c-string in descriptor records. const uint8_t *bytes = - (const uint8_t *)description->defaultValue.valueData; + (const uint8_t *)description_->defaultValue.valueData; if (bytes) { uint32_t length; memcpy(&length, bytes, sizeof(length)); @@ -998,12 +1012,16 @@ - (instancetype)initWithExtensionDescription: // aren't common, we avoid the hit startup hit and it avoid initialization // order issues. } else { - defaultValue_ = description->defaultValue; + defaultValue_ = description_->defaultValue; } } return self; } +- (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc { + return [self initWithExtensionDescription:desc usesClassRefs:NO]; +} + - (void)dealloc { if ((description_->dataType == GPBDataTypeBytes) && !GPBExtensionIsRepeated(description_)) { @@ -1055,7 +1073,11 @@ - (BOOL)isPackable { } - (Class)msgClass { - return objc_getClass(description_->messageOrGroupClassName); + return description_->messageOrGroupClass.clazz; +} + +- (Class)containingMessageClass { + return description_->extendedClass.clazz; } - (GPBEnumDescriptor *)enumDescriptor { diff --git a/objectivec/GPBDescriptor_PackagePrivate.h b/objectivec/GPBDescriptor_PackagePrivate.h index 452b3f8e7ecc..09c1202a0747 100644 --- a/objectivec/GPBDescriptor_PackagePrivate.h +++ b/objectivec/GPBDescriptor_PackagePrivate.h @@ -80,7 +80,11 @@ typedef struct GPBMessageFieldDescription { // Name of ivar. const char *name; union { - const char *className; // Name for message class. + // className is deprecated and will be removed in favor of clazz. + // kept around right now for backwards compatibility. + // clazz is used iff GPBDescriptorInitializationFlag_UsesClassRefs is set. + char *className; // Name of the class of the message. + Class clazz; // Class of the message. // For enums only: If EnumDescriptors are compiled in, it will be that, // otherwise it will be the verifier. GPBEnumDescriptorFunc enumDescFunc; @@ -123,8 +127,14 @@ typedef NS_OPTIONS(uint8_t, GPBExtensionOptions) { typedef struct GPBExtensionDescription { GPBGenericValue defaultValue; const char *singletonName; - const char *extendedClass; - const char *messageOrGroupClassName; + union { + const char *name; + Class clazz; + } extendedClass; + union { + const char *name; + Class clazz; + } messageOrGroupClass; GPBEnumDescriptorFunc enumDescriptorFunc; int32_t fieldNumber; GPBDataType dataType; @@ -135,6 +145,11 @@ typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) { GPBDescriptorInitializationFlag_None = 0, GPBDescriptorInitializationFlag_FieldsWithDefault = 1 << 0, GPBDescriptorInitializationFlag_WireFormat = 1 << 1, + + // This is used as a stopgap as we move from using class names to class + // references. The runtime needs to support both until we allow a + // breaking change in the runtime. + GPBDescriptorInitializationFlag_UsesClassRefs = 1 << 2, }; @interface GPBDescriptor () { @@ -168,9 +183,12 @@ typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) { firstHasIndex:(int32_t)firstHasIndex; - (void)setupExtraTextInfo:(const char *)extraTextFormatInfo; - (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)count; -- (void)setupContainingMessageClassName:(const char *)msgClassName; +- (void)setupContainingMessageClass:(Class)msgClass; - (void)setupMessageClassNameSuffix:(NSString *)suffix; +// Deprecated. Use setupContainingMessageClass instead. +- (void)setupContainingMessageClassName:(const char *)msgClassName; + @end @interface GPBFileDescriptor () @@ -206,7 +224,15 @@ typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) { // description has to be long lived, it is held as a raw pointer. - (instancetype)initWithFieldDescription:(void *)description includesDefault:(BOOL)includesDefault + usesClassRefs:(BOOL)usesClassRefs syntax:(GPBFileSyntax)syntax; + +// Deprecated. Equivalent to calling above with `usesClassRefs = NO`. +- (instancetype)initWithFieldDescription:(void *)description + includesDefault:(BOOL)includesDefault + syntax:(GPBFileSyntax)syntax; + + @end @interface GPBEnumDescriptor () @@ -246,8 +272,11 @@ typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) { @property(nonatomic, readonly) GPBWireFormat alternateWireType; // description has to be long lived, it is held as a raw pointer. -- (instancetype)initWithExtensionDescription: - (GPBExtensionDescription *)description; +- (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc + usesClassRefs:(BOOL)usesClassRefs; +// Deprecated. Calls above with `usesClassRefs = NO` +- (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc; + - (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)other; @end diff --git a/objectivec/GPBRuntimeTypes.h b/objectivec/GPBRuntimeTypes.h index 81480548fea5..b269f1de1123 100644 --- a/objectivec/GPBRuntimeTypes.h +++ b/objectivec/GPBRuntimeTypes.h @@ -142,3 +142,10 @@ typedef struct GPBExtensionRange { /** Exclusive. */ uint32_t end; } GPBExtensionRange; + +/** + A type to represent a reference to an Objective C class. + This is actually an `objc_class` but the runtime headers will not allow us to + reference `objc_class`. +*/ +typedef struct GPBObjcClassReference GPBObjcClassReference; diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj index 9b0af314fd0e..6bc4d322e348 100644 --- a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj +++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj @@ -35,6 +35,7 @@ 8BBEA4BB147C729200C4ADB7 /* libProtocolBuffers.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */; }; 8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */; }; 8BF8193514A0DDA600A2C982 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + 8BFF9D1A23AD582300E63E32 /* GPBMessageTests+ClassNames.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BFF9D1923AD582200E63E32 /* GPBMessageTests+ClassNames.m */; }; F401DC2D1A8D444600FCC765 /* GPBArray.m in Sources */ = {isa = PBXBuildFile; fileRef = F401DC2B1A8D444600FCC765 /* GPBArray.m */; }; F401DC331A8E5C0200FCC765 /* GPBArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F401DC321A8E5C0200FCC765 /* GPBArrayTests.m */; }; F40EE4AB206BF8B90071091A /* GPBCompileTest01.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE488206BF8B00071091A /* GPBCompileTest01.m */; }; @@ -181,6 +182,7 @@ 8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_enormous_descriptor.proto; path = ../../src/google/protobuf/unittest_enormous_descriptor.proto; sourceTree = ""; }; 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos.m; sourceTree = ""; }; 8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRuntimeTypes.h; sourceTree = ""; }; + 8BFF9D1923AD582200E63E32 /* GPBMessageTests+ClassNames.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+ClassNames.m"; sourceTree = ""; }; F401DC2A1A8D444600FCC765 /* GPBArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBArray.h; sourceTree = ""; }; F401DC2B1A8D444600FCC765 /* GPBArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArray.m; sourceTree = ""; }; F401DC321A8E5C0200FCC765 /* GPBArrayTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArrayTests.m; sourceTree = ""; }; @@ -485,6 +487,7 @@ 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */, F4487C821AAF6AB300531423 /* GPBMessageTests+Merge.m */, F4487C741AADF7F500531423 /* GPBMessageTests+Runtime.m */, + 8BFF9D1923AD582200E63E32 /* GPBMessageTests+ClassNames.m */, F4487C7E1AAF62CD00531423 /* GPBMessageTests+Serialization.m */, F4B51B1D1BBC610700744318 /* GPBObjectiveCPlusPlusTest.mm */, F41C175C1833D3310064ED4D /* GPBPerfTests.m */, @@ -656,6 +659,7 @@ developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( + English, en, ); mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; @@ -770,6 +774,7 @@ 8B4248BB1A8C256A00BC1EC6 /* GPBSwiftTests.swift in Sources */, F40EE50C206C06640071091A /* GPBCompileTest25.m in Sources */, F4584D821ECCB52A00803AB6 /* GPBExtensionRegistryTest.m in Sources */, + 8BFF9D1A23AD582300E63E32 /* GPBMessageTests+ClassNames.m in Sources */, 5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */, F4487C751AADF7F500531423 /* GPBMessageTests+Runtime.m in Sources */, F40EE4AC206BF8B90071091A /* GPBCompileTest02.m in Sources */, diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj index 9f1d825c6fd6..1b60be25a423 100644 --- a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj +++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj @@ -36,6 +36,7 @@ 8BBEA4BB147C729200C4ADB7 /* libProtocolBuffers.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */; }; 8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */; }; 8BF8193514A0DDA600A2C982 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + 8BFF9D1C23AD593C00E63E32 /* GPBMessageTests+ClassNames.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BFF9D1B23AD593B00E63E32 /* GPBMessageTests+ClassNames.m */; }; F401DC351A8E5C6F00FCC765 /* GPBArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */; }; F40EE4F0206BF91E0071091A /* GPBCompileTest01.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CD206BF9170071091A /* GPBCompileTest01.m */; }; F40EE4F1206BF91E0071091A /* GPBCompileTest02.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4C6206BF9170071091A /* GPBCompileTest02.m */; }; @@ -183,6 +184,7 @@ 8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_enormous_descriptor.proto; path = ../../src/google/protobuf/unittest_enormous_descriptor.proto; sourceTree = ""; }; 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos.m; sourceTree = ""; }; 8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRuntimeTypes.h; sourceTree = ""; }; + 8BFF9D1B23AD593B00E63E32 /* GPBMessageTests+ClassNames.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+ClassNames.m"; sourceTree = ""; }; F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArrayTests.m; sourceTree = ""; }; F40EE4C2206BF9160071091A /* GPBCompileTest08.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest08.m; sourceTree = ""; }; F40EE4C3206BF9160071091A /* GPBCompileTest04.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest04.m; sourceTree = ""; }; @@ -491,6 +493,7 @@ 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */, F4487C841AAF6AC500531423 /* GPBMessageTests+Merge.m */, F4487C761AADF84900531423 /* GPBMessageTests+Runtime.m */, + 8BFF9D1B23AD593B00E63E32 /* GPBMessageTests+ClassNames.m */, F4487C801AAF62FC00531423 /* GPBMessageTests+Serialization.m */, F4B51B1B1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm */, F41C175C1833D3310064ED4D /* GPBPerfTests.m */, @@ -663,6 +666,7 @@ developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( + English, en, ); mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; @@ -777,6 +781,7 @@ 8B4248B41A8BD96E00BC1EC6 /* GPBSwiftTests.swift in Sources */, F40EE512206C068D0071091A /* GPBCompileTest25.m in Sources */, F4584D831ECCB53600803AB6 /* GPBExtensionRegistryTest.m in Sources */, + 8BFF9D1C23AD593C00E63E32 /* GPBMessageTests+ClassNames.m in Sources */, 5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */, F4487C771AADF84900531423 /* GPBMessageTests+Runtime.m in Sources */, F40EE4F1206BF91E0071091A /* GPBCompileTest02.m in Sources */, @@ -851,6 +856,7 @@ buildSettings = { CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_WEAK = YES; + ENABLE_BITCODE = YES; FRAMEWORK_SEARCH_PATHS = ( "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", "$(inherited)", @@ -883,6 +889,7 @@ buildSettings = { CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_WEAK = YES; + ENABLE_BITCODE = YES; FRAMEWORK_SEARCH_PATHS = ( "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", "$(inherited)", diff --git a/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj index c40c2aaa15a7..3962083c18fd 100644 --- a/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj +++ b/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj @@ -36,6 +36,7 @@ 8BBEA4BB147C729200C4ADB7 /* libProtocolBuffers.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */; }; 8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */; }; 8BF8193514A0DDA600A2C982 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + 8BFF9D1E23AD599400E63E32 /* GPBMessageTests+ClassNames.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BFF9D1D23AD599400E63E32 /* GPBMessageTests+ClassNames.m */; }; F401DC351A8E5C6F00FCC765 /* GPBArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */; }; F40EE4F0206BF91E0071091A /* GPBCompileTest01.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CD206BF9170071091A /* GPBCompileTest01.m */; }; F40EE4F1206BF91E0071091A /* GPBCompileTest02.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4C6206BF9170071091A /* GPBCompileTest02.m */; }; @@ -183,6 +184,7 @@ 8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_enormous_descriptor.proto; path = ../../src/google/protobuf/unittest_enormous_descriptor.proto; sourceTree = ""; }; 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos.m; sourceTree = ""; }; 8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRuntimeTypes.h; sourceTree = ""; }; + 8BFF9D1D23AD599400E63E32 /* GPBMessageTests+ClassNames.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+ClassNames.m"; sourceTree = ""; }; F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArrayTests.m; sourceTree = ""; }; F40EE4C2206BF9160071091A /* GPBCompileTest08.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest08.m; sourceTree = ""; }; F40EE4C3206BF9160071091A /* GPBCompileTest04.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest04.m; sourceTree = ""; }; @@ -491,6 +493,7 @@ 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */, F4487C841AAF6AC500531423 /* GPBMessageTests+Merge.m */, F4487C761AADF84900531423 /* GPBMessageTests+Runtime.m */, + 8BFF9D1D23AD599400E63E32 /* GPBMessageTests+ClassNames.m */, F4487C801AAF62FC00531423 /* GPBMessageTests+Serialization.m */, F4B51B1B1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm */, F41C175C1833D3310064ED4D /* GPBPerfTests.m */, @@ -663,6 +666,7 @@ developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( + English, en, ); mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; @@ -777,6 +781,7 @@ 8B4248B41A8BD96E00BC1EC6 /* GPBSwiftTests.swift in Sources */, F40EE512206C068D0071091A /* GPBCompileTest25.m in Sources */, F4584D831ECCB53600803AB6 /* GPBExtensionRegistryTest.m in Sources */, + 8BFF9D1E23AD599400E63E32 /* GPBMessageTests+ClassNames.m in Sources */, 5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */, F4487C771AADF84900531423 /* GPBMessageTests+Runtime.m in Sources */, F40EE4F1206BF91E0071091A /* GPBCompileTest02.m in Sources */, diff --git a/objectivec/Tests/GPBMessageTests+ClassNames.m b/objectivec/Tests/GPBMessageTests+ClassNames.m new file mode 100644 index 000000000000..31d15b534a76 --- /dev/null +++ b/objectivec/Tests/GPBMessageTests+ClassNames.m @@ -0,0 +1,164 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBTestUtilities.h" + +#import + +#import "GPBDescriptor_PackagePrivate.h" +#import "GPBExtensionRegistry.h" +#import "GPBMessage.h" +#import "GPBRootObject_PackagePrivate.h" + +// Support classes for tests using old class name (vs classrefs) interfaces. +@interface MessageLackingClazzRoot : GPBRootObject +@end + +@interface MessageLackingClazzRoot (DynamicMethods) ++ (GPBExtensionDescriptor *)ext1; +@end + +@interface MessageLackingClazz : GPBMessage +@property(copy, nonatomic) NSString *foo; +@end + +@implementation MessageLackingClazz + +@dynamic foo; + +typedef struct MessageLackingClazz_storage_ { + uint32_t _has_storage_[1]; + NSString *foo; +} MessageLackingClazz_storage_; + ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "foo", + .dataTypeSpecific.className = "NSString", + .number = 1, + .hasIndex = 0, + .offset = (uint32_t)offsetof(MessageLackingClazz_storage_, foo), + .flags = (GPBFieldFlags)(GPBFieldOptional), + .dataType = GPBDataTypeMessage, + }, + }; + GPBFileDescriptor *desc = + [[[GPBFileDescriptor alloc] initWithPackage:@"test" + objcPrefix:@"TEST" + syntax:GPBFileSyntaxProto3] autorelease]; + + // GPBDescriptorInitializationFlag_UsesClassRefs intentionally not set here + descriptor = + [GPBDescriptor allocDescriptorForClass:[MessageLackingClazz class] + rootClass:[MessageLackingClazzRoot class] + file:desc + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(MessageLackingClazz_storage_) + flags:GPBDescriptorInitializationFlag_None]; + [descriptor setupContainingMessageClassName:"MessageLackingClazz"]; + } + return descriptor; +} +@end + +@implementation MessageLackingClazzRoot + ++ (GPBExtensionRegistry*)extensionRegistry { + // This is called by +initialize so there is no need to worry + // about thread safety and initialization of registry. + static GPBExtensionRegistry* registry = nil; + if (!registry) { + registry = [[GPBExtensionRegistry alloc] init]; + static GPBExtensionDescription descriptions[] = { + { + .defaultValue.valueMessage = NULL, + .singletonName = "MessageLackingClazzRoot_ext1", + .extendedClass.name = "MessageLackingClazz", + .messageOrGroupClass.name = "MessageLackingClazz", + .enumDescriptorFunc = NULL, + .fieldNumber = 1, + .dataType = GPBDataTypeMessage, + // GPBExtensionUsesClazz Intentionally not set + .options = 0, + }, + }; + for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) { + // Intentionall using `-initWithExtensionDescription:` and not ` + // -initWithExtensionDescription:usesClassRefs:` to test backwards + // compatibility + GPBExtensionDescriptor *extension = + [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]]; + [registry addExtension:extension]; + [self globallyRegisterExtension:extension]; + [extension release]; + } + // None of the imports (direct or indirect) defined extensions, so no need to add + // them to this registry. + } + return registry; +} +@end + +@interface MessageClassNameTests : GPBTestCase +@end + +@implementation MessageClassNameTests + +- (void)testClassNameSupported { + // This tests backwards compatibility to make sure we support older sources + // that use class names instead of references. + GPBDescriptor *desc = [MessageLackingClazz descriptor]; + GPBFieldDescriptor *fieldDesc = [desc fieldWithName:@"foo"]; + XCTAssertEqualObjects(fieldDesc.msgClass, [NSString class]); +} + +- (void)testSetupContainingMessageClassNameSupported { + // This tests backwards compatibility to make sure we support older sources + // that use class names instead of references. + GPBDescriptor *desc = [MessageLackingClazz descriptor]; + GPBDescriptor *container = [desc containingType]; + XCTAssertEqualObjects(container.messageClass, [MessageLackingClazz class]); +} + +- (void)testExtensionsNameSupported { + // This tests backwards compatibility to make sure we support older sources + // that use class names instead of references. + GPBExtensionDescriptor *desc = [MessageLackingClazzRoot ext1]; + Class containerClass = [desc containingMessageClass]; + XCTAssertEqualObjects(containerClass, [MessageLackingClazz class]); + Class msgClass = [desc msgClass]; + XCTAssertEqualObjects(msgClass, [MessageLackingClazz class]); +} + +@end diff --git a/objectivec/google/protobuf/Any.pbobjc.m b/objectivec/google/protobuf/Any.pbobjc.m index f1e815fd120f..d396e8422a46 100644 --- a/objectivec/google/protobuf/Any.pbobjc.m +++ b/objectivec/google/protobuf/Any.pbobjc.m @@ -68,7 +68,7 @@ + (GPBDescriptor *)descriptor { static GPBMessageFieldDescription fields[] = { { .name = "typeURL", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBAny_FieldNumber_TypeURL, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBAny__storage_, typeURL), @@ -77,7 +77,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "value", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBAny_FieldNumber_Value, .hasIndex = 1, .offset = (uint32_t)offsetof(GPBAny__storage_, value), @@ -92,7 +92,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBAny__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS static const char *extraTextFormatInfo = "\001\001\004\241!!\000"; diff --git a/objectivec/google/protobuf/Api.pbobjc.m b/objectivec/google/protobuf/Api.pbobjc.m index 410239996174..1463f0dc9de4 100644 --- a/objectivec/google/protobuf/Api.pbobjc.m +++ b/objectivec/google/protobuf/Api.pbobjc.m @@ -26,6 +26,18 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" +#pragma clang diagnostic ignored "-Wdollar-in-identifier-extension" + +#pragma mark - Objective C Class references +// This somewhat arcane code forces linkage of classes from static archives by +// adding a concrete reference to the classes. +// We don't use `[Foo class]` because we need a static value for our initializer. +// This also has the added benefit of reducing size in that we don't have to +// encode the class names and look them up at runtime. +extern const GPBObjcClassReference OBJC_CLASS_$_GPBMethod; +extern const GPBObjcClassReference OBJC_CLASS_$_GPBMixin; +extern const GPBObjcClassReference OBJC_CLASS_$_GPBOption; +extern const GPBObjcClassReference OBJC_CLASS_$_GPBSourceContext; #pragma mark - GPBApiRoot @@ -82,7 +94,7 @@ + (GPBDescriptor *)descriptor { static GPBMessageFieldDescription fields[] = { { .name = "name", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBApi_FieldNumber_Name, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBApi__storage_, name), @@ -91,7 +103,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "methodsArray", - .dataTypeSpecific.className = GPBStringifySymbol(GPBMethod), + .dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBMethod), .number = GPBApi_FieldNumber_MethodsArray, .hasIndex = GPBNoHasBit, .offset = (uint32_t)offsetof(GPBApi__storage_, methodsArray), @@ -100,7 +112,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "optionsArray", - .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), + .dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBOption), .number = GPBApi_FieldNumber_OptionsArray, .hasIndex = GPBNoHasBit, .offset = (uint32_t)offsetof(GPBApi__storage_, optionsArray), @@ -109,7 +121,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "version", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBApi_FieldNumber_Version, .hasIndex = 1, .offset = (uint32_t)offsetof(GPBApi__storage_, version), @@ -118,7 +130,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "sourceContext", - .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext), + .dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBSourceContext), .number = GPBApi_FieldNumber_SourceContext, .hasIndex = 2, .offset = (uint32_t)offsetof(GPBApi__storage_, sourceContext), @@ -127,7 +139,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "mixinsArray", - .dataTypeSpecific.className = GPBStringifySymbol(GPBMixin), + .dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBMixin), .number = GPBApi_FieldNumber_MixinsArray, .hasIndex = GPBNoHasBit, .offset = (uint32_t)offsetof(GPBApi__storage_, mixinsArray), @@ -151,7 +163,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBApi__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -203,7 +215,7 @@ + (GPBDescriptor *)descriptor { static GPBMessageFieldDescription fields[] = { { .name = "name", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBMethod_FieldNumber_Name, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBMethod__storage_, name), @@ -212,7 +224,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "requestTypeURL", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBMethod_FieldNumber_RequestTypeURL, .hasIndex = 1, .offset = (uint32_t)offsetof(GPBMethod__storage_, requestTypeURL), @@ -221,7 +233,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "requestStreaming", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBMethod_FieldNumber_RequestStreaming, .hasIndex = 2, .offset = 3, // Stored in _has_storage_ to save space. @@ -230,7 +242,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "responseTypeURL", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBMethod_FieldNumber_ResponseTypeURL, .hasIndex = 4, .offset = (uint32_t)offsetof(GPBMethod__storage_, responseTypeURL), @@ -239,7 +251,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "responseStreaming", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBMethod_FieldNumber_ResponseStreaming, .hasIndex = 5, .offset = 6, // Stored in _has_storage_ to save space. @@ -248,7 +260,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "optionsArray", - .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), + .dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBOption), .number = GPBMethod_FieldNumber_OptionsArray, .hasIndex = GPBNoHasBit, .offset = (uint32_t)offsetof(GPBMethod__storage_, optionsArray), @@ -272,7 +284,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBMethod__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS static const char *extraTextFormatInfo = "\002\002\007\244\241!!\000\004\010\244\241!!\000"; @@ -321,7 +333,7 @@ + (GPBDescriptor *)descriptor { static GPBMessageFieldDescription fields[] = { { .name = "name", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBMixin_FieldNumber_Name, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBMixin__storage_, name), @@ -330,7 +342,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "root", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBMixin_FieldNumber_Root, .hasIndex = 1, .offset = (uint32_t)offsetof(GPBMixin__storage_, root), @@ -345,7 +357,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBMixin__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG diff --git a/objectivec/google/protobuf/Duration.pbobjc.m b/objectivec/google/protobuf/Duration.pbobjc.m index 1b718a12e7a6..5d1134bdad08 100644 --- a/objectivec/google/protobuf/Duration.pbobjc.m +++ b/objectivec/google/protobuf/Duration.pbobjc.m @@ -68,7 +68,7 @@ + (GPBDescriptor *)descriptor { static GPBMessageFieldDescription fields[] = { { .name = "seconds", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBDuration_FieldNumber_Seconds, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBDuration__storage_, seconds), @@ -77,7 +77,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "nanos", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBDuration_FieldNumber_Nanos, .hasIndex = 1, .offset = (uint32_t)offsetof(GPBDuration__storage_, nanos), @@ -92,7 +92,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBDuration__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG diff --git a/objectivec/google/protobuf/Empty.pbobjc.m b/objectivec/google/protobuf/Empty.pbobjc.m index 4cb0f12c353d..9738b0a6b356 100644 --- a/objectivec/google/protobuf/Empty.pbobjc.m +++ b/objectivec/google/protobuf/Empty.pbobjc.m @@ -68,7 +68,7 @@ + (GPBDescriptor *)descriptor { fields:NULL fieldCount:0 storageSize:sizeof(GPBEmpty__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG diff --git a/objectivec/google/protobuf/FieldMask.pbobjc.m b/objectivec/google/protobuf/FieldMask.pbobjc.m index 2e6b2eef7c75..4d72efbd2c32 100644 --- a/objectivec/google/protobuf/FieldMask.pbobjc.m +++ b/objectivec/google/protobuf/FieldMask.pbobjc.m @@ -66,7 +66,7 @@ + (GPBDescriptor *)descriptor { static GPBMessageFieldDescription fields[] = { { .name = "pathsArray", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBFieldMask_FieldNumber_PathsArray, .hasIndex = GPBNoHasBit, .offset = (uint32_t)offsetof(GPBFieldMask__storage_, pathsArray), @@ -81,7 +81,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBFieldMask__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG diff --git a/objectivec/google/protobuf/SourceContext.pbobjc.m b/objectivec/google/protobuf/SourceContext.pbobjc.m index c955f2b4fae6..d425cc85b3be 100644 --- a/objectivec/google/protobuf/SourceContext.pbobjc.m +++ b/objectivec/google/protobuf/SourceContext.pbobjc.m @@ -66,7 +66,7 @@ + (GPBDescriptor *)descriptor { static GPBMessageFieldDescription fields[] = { { .name = "fileName", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBSourceContext_FieldNumber_FileName, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBSourceContext__storage_, fileName), @@ -81,7 +81,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBSourceContext__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG diff --git a/objectivec/google/protobuf/Struct.pbobjc.m b/objectivec/google/protobuf/Struct.pbobjc.m index 3873f5a0338c..e8e181b25431 100644 --- a/objectivec/google/protobuf/Struct.pbobjc.m +++ b/objectivec/google/protobuf/Struct.pbobjc.m @@ -25,6 +25,17 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" #pragma clang diagnostic ignored "-Wdirect-ivar-access" +#pragma clang diagnostic ignored "-Wdollar-in-identifier-extension" + +#pragma mark - Objective C Class references +// This somewhat arcane code forces linkage of classes from static archives by +// adding a concrete reference to the classes. +// We don't use `[Foo class]` because we need a static value for our initializer. +// This also has the added benefit of reducing size in that we don't have to +// encode the class names and look them up at runtime. +extern const GPBObjcClassReference OBJC_CLASS_$_GPBListValue; +extern const GPBObjcClassReference OBJC_CLASS_$_GPBStruct; +extern const GPBObjcClassReference OBJC_CLASS_$_GPBValue; #pragma mark - GPBStructRoot @@ -102,7 +113,7 @@ + (GPBDescriptor *)descriptor { static GPBMessageFieldDescription fields[] = { { .name = "fields", - .dataTypeSpecific.className = GPBStringifySymbol(GPBValue), + .dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBValue), .number = GPBStruct_FieldNumber_Fields, .hasIndex = GPBNoHasBit, .offset = (uint32_t)offsetof(GPBStruct__storage_, fields), @@ -117,7 +128,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBStruct__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -166,7 +177,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "numberValue", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBValue_FieldNumber_NumberValue, .hasIndex = -1, .offset = (uint32_t)offsetof(GPBValue__storage_, numberValue), @@ -175,7 +186,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "stringValue", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBValue_FieldNumber_StringValue, .hasIndex = -1, .offset = (uint32_t)offsetof(GPBValue__storage_, stringValue), @@ -184,7 +195,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "boolValue", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBValue_FieldNumber_BoolValue, .hasIndex = -1, .offset = 0, // Stored in _has_storage_ to save space. @@ -193,7 +204,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "structValue", - .dataTypeSpecific.className = GPBStringifySymbol(GPBStruct), + .dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBStruct), .number = GPBValue_FieldNumber_StructValue, .hasIndex = -1, .offset = (uint32_t)offsetof(GPBValue__storage_, structValue), @@ -202,7 +213,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "listValue", - .dataTypeSpecific.className = GPBStringifySymbol(GPBListValue), + .dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBListValue), .number = GPBValue_FieldNumber_ListValue, .hasIndex = -1, .offset = (uint32_t)offsetof(GPBValue__storage_, listValue), @@ -217,7 +228,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBValue__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; static const char *oneofs[] = { "kind", }; @@ -270,7 +281,7 @@ + (GPBDescriptor *)descriptor { static GPBMessageFieldDescription fields[] = { { .name = "valuesArray", - .dataTypeSpecific.className = GPBStringifySymbol(GPBValue), + .dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBValue), .number = GPBListValue_FieldNumber_ValuesArray, .hasIndex = GPBNoHasBit, .offset = (uint32_t)offsetof(GPBListValue__storage_, valuesArray), @@ -285,7 +296,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBListValue__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG diff --git a/objectivec/google/protobuf/Timestamp.pbobjc.m b/objectivec/google/protobuf/Timestamp.pbobjc.m index 05eb3a5d295d..6368885df018 100644 --- a/objectivec/google/protobuf/Timestamp.pbobjc.m +++ b/objectivec/google/protobuf/Timestamp.pbobjc.m @@ -68,7 +68,7 @@ + (GPBDescriptor *)descriptor { static GPBMessageFieldDescription fields[] = { { .name = "seconds", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBTimestamp_FieldNumber_Seconds, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBTimestamp__storage_, seconds), @@ -77,7 +77,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "nanos", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBTimestamp_FieldNumber_Nanos, .hasIndex = 1, .offset = (uint32_t)offsetof(GPBTimestamp__storage_, nanos), @@ -92,7 +92,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBTimestamp__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG diff --git a/objectivec/google/protobuf/Type.pbobjc.m b/objectivec/google/protobuf/Type.pbobjc.m index 7451edc6e21d..0c48e6b31219 100644 --- a/objectivec/google/protobuf/Type.pbobjc.m +++ b/objectivec/google/protobuf/Type.pbobjc.m @@ -28,6 +28,19 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" +#pragma clang diagnostic ignored "-Wdollar-in-identifier-extension" + +#pragma mark - Objective C Class references +// This somewhat arcane code forces linkage of classes from static archives by +// adding a concrete reference to the classes. +// We don't use `[Foo class]` because we need a static value for our initializer. +// This also has the added benefit of reducing size in that we don't have to +// encode the class names and look them up at runtime. +extern const GPBObjcClassReference OBJC_CLASS_$_GPBAny; +extern const GPBObjcClassReference OBJC_CLASS_$_GPBEnumValue; +extern const GPBObjcClassReference OBJC_CLASS_$_GPBField; +extern const GPBObjcClassReference OBJC_CLASS_$_GPBOption; +extern const GPBObjcClassReference OBJC_CLASS_$_GPBSourceContext; #pragma mark - GPBTypeRoot @@ -117,7 +130,7 @@ + (GPBDescriptor *)descriptor { static GPBMessageFieldDescription fields[] = { { .name = "name", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBType_FieldNumber_Name, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBType__storage_, name), @@ -126,7 +139,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "fieldsArray", - .dataTypeSpecific.className = GPBStringifySymbol(GPBField), + .dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBField), .number = GPBType_FieldNumber_FieldsArray, .hasIndex = GPBNoHasBit, .offset = (uint32_t)offsetof(GPBType__storage_, fieldsArray), @@ -135,7 +148,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "oneofsArray", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBType_FieldNumber_OneofsArray, .hasIndex = GPBNoHasBit, .offset = (uint32_t)offsetof(GPBType__storage_, oneofsArray), @@ -144,7 +157,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "optionsArray", - .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), + .dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBOption), .number = GPBType_FieldNumber_OptionsArray, .hasIndex = GPBNoHasBit, .offset = (uint32_t)offsetof(GPBType__storage_, optionsArray), @@ -153,7 +166,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "sourceContext", - .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext), + .dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBSourceContext), .number = GPBType_FieldNumber_SourceContext, .hasIndex = 1, .offset = (uint32_t)offsetof(GPBType__storage_, sourceContext), @@ -177,7 +190,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBType__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -254,7 +267,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "number", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBField_FieldNumber_Number, .hasIndex = 2, .offset = (uint32_t)offsetof(GPBField__storage_, number), @@ -263,7 +276,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "name", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBField_FieldNumber_Name, .hasIndex = 3, .offset = (uint32_t)offsetof(GPBField__storage_, name), @@ -272,7 +285,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "typeURL", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBField_FieldNumber_TypeURL, .hasIndex = 4, .offset = (uint32_t)offsetof(GPBField__storage_, typeURL), @@ -281,7 +294,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "oneofIndex", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBField_FieldNumber_OneofIndex, .hasIndex = 5, .offset = (uint32_t)offsetof(GPBField__storage_, oneofIndex), @@ -290,7 +303,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "packed", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBField_FieldNumber_Packed, .hasIndex = 6, .offset = 7, // Stored in _has_storage_ to save space. @@ -299,7 +312,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "optionsArray", - .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), + .dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBOption), .number = GPBField_FieldNumber_OptionsArray, .hasIndex = GPBNoHasBit, .offset = (uint32_t)offsetof(GPBField__storage_, optionsArray), @@ -308,7 +321,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "jsonName", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBField_FieldNumber_JsonName, .hasIndex = 8, .offset = (uint32_t)offsetof(GPBField__storage_, jsonName), @@ -317,7 +330,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "defaultValue", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBField_FieldNumber_DefaultValue, .hasIndex = 9, .offset = (uint32_t)offsetof(GPBField__storage_, defaultValue), @@ -332,7 +345,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBField__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS static const char *extraTextFormatInfo = "\001\006\004\241!!\000"; @@ -513,7 +526,7 @@ + (GPBDescriptor *)descriptor { static GPBMessageFieldDescription fields[] = { { .name = "name", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBEnum_FieldNumber_Name, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBEnum__storage_, name), @@ -522,7 +535,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "enumvalueArray", - .dataTypeSpecific.className = GPBStringifySymbol(GPBEnumValue), + .dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBEnumValue), .number = GPBEnum_FieldNumber_EnumvalueArray, .hasIndex = GPBNoHasBit, .offset = (uint32_t)offsetof(GPBEnum__storage_, enumvalueArray), @@ -531,7 +544,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "optionsArray", - .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), + .dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBOption), .number = GPBEnum_FieldNumber_OptionsArray, .hasIndex = GPBNoHasBit, .offset = (uint32_t)offsetof(GPBEnum__storage_, optionsArray), @@ -540,7 +553,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "sourceContext", - .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext), + .dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBSourceContext), .number = GPBEnum_FieldNumber_SourceContext, .hasIndex = 1, .offset = (uint32_t)offsetof(GPBEnum__storage_, sourceContext), @@ -564,7 +577,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBEnum__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -610,7 +623,7 @@ + (GPBDescriptor *)descriptor { static GPBMessageFieldDescription fields[] = { { .name = "name", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBEnumValue_FieldNumber_Name, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBEnumValue__storage_, name), @@ -619,7 +632,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "number", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBEnumValue_FieldNumber_Number, .hasIndex = 1, .offset = (uint32_t)offsetof(GPBEnumValue__storage_, number), @@ -628,7 +641,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "optionsArray", - .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), + .dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBOption), .number = GPBEnumValue_FieldNumber_OptionsArray, .hasIndex = GPBNoHasBit, .offset = (uint32_t)offsetof(GPBEnumValue__storage_, optionsArray), @@ -643,7 +656,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBEnumValue__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -675,7 +688,7 @@ + (GPBDescriptor *)descriptor { static GPBMessageFieldDescription fields[] = { { .name = "name", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBOption_FieldNumber_Name, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBOption__storage_, name), @@ -684,7 +697,7 @@ + (GPBDescriptor *)descriptor { }, { .name = "value", - .dataTypeSpecific.className = GPBStringifySymbol(GPBAny), + .dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBAny), .number = GPBOption_FieldNumber_Value, .hasIndex = 1, .offset = (uint32_t)offsetof(GPBOption__storage_, value), @@ -699,7 +712,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBOption__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG diff --git a/objectivec/google/protobuf/Wrappers.pbobjc.m b/objectivec/google/protobuf/Wrappers.pbobjc.m index f91d345041ea..19bca6f5c468 100644 --- a/objectivec/google/protobuf/Wrappers.pbobjc.m +++ b/objectivec/google/protobuf/Wrappers.pbobjc.m @@ -66,7 +66,7 @@ + (GPBDescriptor *)descriptor { static GPBMessageFieldDescription fields[] = { { .name = "value", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBDoubleValue_FieldNumber_Value, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBDoubleValue__storage_, value), @@ -81,7 +81,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBDoubleValue__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -111,7 +111,7 @@ + (GPBDescriptor *)descriptor { static GPBMessageFieldDescription fields[] = { { .name = "value", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBFloatValue_FieldNumber_Value, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBFloatValue__storage_, value), @@ -126,7 +126,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBFloatValue__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -156,7 +156,7 @@ + (GPBDescriptor *)descriptor { static GPBMessageFieldDescription fields[] = { { .name = "value", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBInt64Value_FieldNumber_Value, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBInt64Value__storage_, value), @@ -171,7 +171,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBInt64Value__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -201,7 +201,7 @@ + (GPBDescriptor *)descriptor { static GPBMessageFieldDescription fields[] = { { .name = "value", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBUInt64Value_FieldNumber_Value, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBUInt64Value__storage_, value), @@ -216,7 +216,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBUInt64Value__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -246,7 +246,7 @@ + (GPBDescriptor *)descriptor { static GPBMessageFieldDescription fields[] = { { .name = "value", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBInt32Value_FieldNumber_Value, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBInt32Value__storage_, value), @@ -261,7 +261,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBInt32Value__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -291,7 +291,7 @@ + (GPBDescriptor *)descriptor { static GPBMessageFieldDescription fields[] = { { .name = "value", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBUInt32Value_FieldNumber_Value, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBUInt32Value__storage_, value), @@ -306,7 +306,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBUInt32Value__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -335,7 +335,7 @@ + (GPBDescriptor *)descriptor { static GPBMessageFieldDescription fields[] = { { .name = "value", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBBoolValue_FieldNumber_Value, .hasIndex = 0, .offset = 1, // Stored in _has_storage_ to save space. @@ -350,7 +350,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBBoolValue__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -380,7 +380,7 @@ + (GPBDescriptor *)descriptor { static GPBMessageFieldDescription fields[] = { { .name = "value", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBStringValue_FieldNumber_Value, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBStringValue__storage_, value), @@ -395,7 +395,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBStringValue__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -425,7 +425,7 @@ + (GPBDescriptor *)descriptor { static GPBMessageFieldDescription fields[] = { { .name = "value", - .dataTypeSpecific.className = NULL, + .dataTypeSpecific.clazz = Nil, .number = GPBBytesValue_FieldNumber_Value, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBBytesValue__storage_, value), @@ -440,7 +440,7 @@ + (GPBDescriptor *)descriptor { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBBytesValue__storage_) - flags:GPBDescriptorInitializationFlag_None]; + flags:GPBDescriptorInitializationFlag_UsesClassRefs]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc index bf65de3be268..a67d1a2ebab9 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc @@ -84,24 +84,24 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization( io::Printer* printer) { std::map vars; vars["root_class_and_method_name"] = root_class_and_method_name_; - vars["extended_type"] = ClassName(descriptor_->containing_type()); + const string containing_type = ClassName(descriptor_->containing_type()); + vars["extended_type"] = ObjCClassSymbolReference(containing_type); vars["number"] = StrCat(descriptor_->number()); std::vector options; if (descriptor_->is_repeated()) options.push_back("GPBExtensionRepeated"); if (descriptor_->is_packed()) options.push_back("GPBExtensionPacked"); - if (descriptor_->containing_type()->options().message_set_wire_format()) + if (descriptor_->containing_type()->options().message_set_wire_format()) { options.push_back("GPBExtensionSetWireFormat"); - + } vars["options"] = BuildFlagsString(FLAGTYPE_EXTENSION, options); ObjectiveCType objc_type = GetObjectiveCType(descriptor_); - string singular_type; if (objc_type == OBJECTIVECTYPE_MESSAGE) { - vars["type"] = string("GPBStringifySymbol(") + - ClassName(descriptor_->message_type()) + ")"; + std::string message_type = ClassName(descriptor_->message_type()); + vars["type"] = ObjCClassSymbolReference(message_type); } else { - vars["type"] = "NULL"; + vars["type"] = "Nil"; } vars["default_name"] = GPBGenericValueFieldName(descriptor_); @@ -124,8 +124,8 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization( "{\n" " .defaultValue.$default_name$ = $default$,\n" " .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n" - " .extendedClass = GPBStringifySymbol($extended_type$),\n" - " .messageOrGroupClassName = $type$,\n" + " .extendedClass.clazz = $extended_type$,\n" + " .messageOrGroupClass.clazz = $type$,\n" " .enumDescriptorFunc = $enum_desc_func_name$,\n" " .fieldNumber = $number$,\n" " .dataType = $extension_type$,\n" @@ -133,11 +133,23 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization( "},\n"); } +void ExtensionGenerator::DetermineObjectiveCClassDefinitions( + std::set* fwd_decls) { + string extended_type = ClassName(descriptor_->containing_type()); + fwd_decls->insert(ObjCClassSymbolDefinition(extended_type)); + ObjectiveCType objc_type = GetObjectiveCType(descriptor_); + if (objc_type == OBJECTIVECTYPE_MESSAGE) { + string message_type = ClassName(descriptor_->message_type()); + fwd_decls->insert(ObjCClassSymbolDefinition(message_type)); + } +} + void ExtensionGenerator::GenerateRegistrationSource(io::Printer* printer) { printer->Print( "[registry addExtension:$root_class_and_method_name$];\n", "root_class_and_method_name", root_class_and_method_name_); } + } // namespace objectivec } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.h b/src/google/protobuf/compiler/objectivec/objectivec_extension.h index d49a4f1cc2a6..1bc19d818770 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_extension.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.h @@ -51,6 +51,7 @@ class ExtensionGenerator { void GenerateMembersHeader(io::Printer* printer); void GenerateStaticVariablesInitialization(io::Printer* printer); void GenerateRegistrationSource(io::Printer* printer); + void DetermineObjectiveCClassDefinitions(std::set* fwd_decls); private: string method_name_; diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc index 19be007bfb89..829f4258f980 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc @@ -97,8 +97,8 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, (*variables)["default"] = DefaultValue(descriptor); (*variables)["default_name"] = GPBGenericValueFieldName(descriptor); - (*variables)["dataTypeSpecific_name"] = "className"; - (*variables)["dataTypeSpecific_value"] = "NULL"; + (*variables)["dataTypeSpecific_name"] = "clazz"; + (*variables)["dataTypeSpecific_value"] = "Nil"; (*variables)["storage_offset_value"] = "(uint32_t)offsetof(" + classname + "__storage_, " + camel_case_name + ")"; @@ -181,6 +181,11 @@ void FieldGenerator::DetermineForwardDeclarations( // Nothing } +void FieldGenerator::DetermineObjectiveCClassDefinitions( + std::set* fwd_decls) const { + // Nothing +} + void FieldGenerator::GenerateFieldDescription( io::Printer* printer, bool include_default) const { // Printed in the same order as the structure decl. diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.h b/src/google/protobuf/compiler/objectivec/objectivec_field.h index 24465d0a36f0..68c470a50b43 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_field.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_field.h @@ -66,6 +66,7 @@ class FieldGenerator { // Exposed for subclasses, should always call it on the parent class also. virtual void DetermineForwardDeclarations(std::set* fwd_decls) const; + virtual void DetermineObjectiveCClassDefinitions(std::set* fwd_decls) const; // Used during generation, not intended to be extended by subclasses. void GenerateFieldDescription( diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc index 7bc585e9bafe..369b3be6a2df 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc @@ -398,10 +398,20 @@ void FileGenerator::GenerateSource(io::Printer *printer) { } } + std::set fwd_decls; + for (const auto& generator : message_generators_) { + generator->DetermineObjectiveCClassDefinitions(&fwd_decls); + } + for (const auto& generator : extension_generators_) { + generator->DetermineObjectiveCClassDefinitions(&fwd_decls); + } + // Note: // deprecated-declarations suppression is only needed if some place in this // proto file is something deprecated or if it references something from // another file that is deprecated. + // dollar-in-identifier-extension is needed because we use references to + // objc class names that have $ in identifiers. printer->Print( "// @@protoc_insertion_point(imports)\n" "\n" @@ -414,9 +424,28 @@ void FileGenerator::GenerateSource(io::Printer *printer) { printer->Print( "#pragma clang diagnostic ignored \"-Wdirect-ivar-access\"\n"); } - + if (fwd_decls.size() > 0) { + printer->Print( + "#pragma clang diagnostic ignored \"-Wdollar-in-identifier-extension\"\n"); + } + printer->Print( + "\n"); + if (fwd_decls.size() > 0) { + printer->Print( + "#pragma mark - Objective C Class references\n" + "// This somewhat arcane code forces linkage of classes from static archives by\n" + "// adding a concrete reference to the classes.\n" + "// We don't use `[Foo class]` because we need a static value for our initializer.\n" + "// This also has the added benefit of reducing size in that we don't have to\n" + "// encode the class names and look them up at runtime.\n"); + } + for (const auto& i : fwd_decls) { + printer->Print("$value$\n", "value", i); + } + if (fwd_decls.size() > 0) { + printer->Print("\n"); + } printer->Print( - "\n" "#pragma mark - $root_class_name$\n" "\n" "@implementation $root_class_name$\n\n", @@ -454,7 +483,8 @@ void FileGenerator::GenerateSource(io::Printer *printer) { "};\n" "for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n" " GPBExtensionDescriptor *extension =\n" - " [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]];\n" + " [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]\n" + " usesClassRefs:YES];\n" " [registry addExtension:extension];\n" " [self globallyRegisterExtension:extension];\n" " [extension release];\n" diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc index 09a808bf405c..97bc75be9659 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc @@ -585,6 +585,19 @@ string OneofNameCapitalized(const OneofDescriptor* descriptor) { return result; } +static string ObjCClassSymbolName(const string& class_name) { + return string("OBJC_CLASS_$_") + class_name; +} + +string ObjCClassSymbolReference(const string& class_name) { + return "((__bridge Class)&" + ObjCClassSymbolName(class_name) + ")"; +} + +string ObjCClassSymbolDefinition(const string& class_name) { + const string &ref = ObjCClassSymbolName(class_name); + return "extern const GPBObjcClassReference " + ref + ";"; +} + string UnCamelCaseFieldName(const string& name, const FieldDescriptor* field) { string worker(name); if (HasSuffixString(worker, "_p")) { diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h index 98ec7db8fbc6..5334addc51d1 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h @@ -118,6 +118,15 @@ string PROTOC_EXPORT OneofEnumName(const OneofDescriptor* descriptor); string PROTOC_EXPORT OneofName(const OneofDescriptor* descriptor); string PROTOC_EXPORT OneofNameCapitalized(const OneofDescriptor* descriptor); +// Returns a symbol that can be used in C code to refer to an Objective C +// class without initializing the class. +string PROTOC_EXPORT ObjCClassSymbolReference(const string& className); + +// Defines a symbol that can be used in C code to refer to an Objective C +// class without initializing the class. Use a corresponding +// ObjCClassSymbolReference to reference it. +string PROTOC_EXPORT ObjCClassSymbolDefinition(const string& className); + inline bool HasFieldPresence(const FileDescriptor* file) { return file->syntax() != FileDescriptor::SYNTAX_PROTO3; } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc index 6abad8bd0061..55e5bf9da649 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc @@ -112,6 +112,7 @@ MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor, if (value_field_flags.find("GPBFieldHasEnumDescriptor") != string::npos) { field_flags.push_back("GPBFieldHasEnumDescriptor"); } + variables_["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags); ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor); @@ -170,6 +171,17 @@ void MapFieldGenerator::DetermineForwardDeclarations( } } +void MapFieldGenerator::DetermineObjectiveCClassDefinitions( + std::set* fwd_decls) const { + // Class name is already in "storage_type". + const FieldDescriptor* value_descriptor = + descriptor_->message_type()->FindFieldByName("value"); + if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_MESSAGE) { + fwd_decls->insert(ObjCClassSymbolDefinition( + value_field_generator_->variable("storage_type"))); + } +} + } // namespace objectivec } // namespace compiler diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h index c3085019ee3b..da18d579f556 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h @@ -54,6 +54,7 @@ class MapFieldGenerator : public RepeatedFieldGenerator { MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options); virtual ~MapFieldGenerator(); + virtual void DetermineObjectiveCClassDefinitions(std::set* fwd_decls) const; virtual void DetermineForwardDeclarations(std::set* fwd_decls) const; private: diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc index 6731e37a77fe..af13c145a849 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc @@ -234,6 +234,30 @@ void MessageGenerator::DetermineForwardDeclarations(std::set* fwd_decls) } } +void MessageGenerator::DetermineObjectiveCClassDefinitions(std::set* fwd_decls) { + if (!IsMapEntryMessage(descriptor_)) { + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* fieldDescriptor = descriptor_->field(i); + field_generators_.get(fieldDescriptor) + .DetermineObjectiveCClassDefinitions(fwd_decls); + } + } + + for (const auto& generator : extension_generators_) { + generator->DetermineObjectiveCClassDefinitions(fwd_decls); + } + + for (const auto& generator : nested_message_generators_) { + generator->DetermineObjectiveCClassDefinitions(fwd_decls); + } + + const Descriptor* containing_descriptor = descriptor_->containing_type(); + if (containing_descriptor != NULL) { + string containing_class = ClassName(containing_descriptor); + fwd_decls->insert(ObjCClassSymbolDefinition(containing_class)); + } +} + bool MessageGenerator::IncludesOneOfDefinition() const { if (!oneof_generators_.empty()) { return true; @@ -457,11 +481,11 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { field_description_type = "GPBMessageFieldDescription"; } if (has_fields) { - printer->Print( - " static $field_description_type$ fields[] = {\n", - "field_description_type", field_description_type); printer->Indent(); printer->Indent(); + printer->Print( + "static $field_description_type$ fields[] = {\n", + "field_description_type", field_description_type); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); ++i) { const FieldGenerator& field_generator = @@ -474,10 +498,10 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { } } printer->Outdent(); + printer->Print( + "};\n"); printer->Outdent(); printer->Outdent(); - printer->Print( - " };\n"); } std::map vars; @@ -492,6 +516,7 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { } std::vector init_flags; + init_flags.push_back("GPBDescriptorInitializationFlag_UsesClassRefs"); if (need_defaults) { init_flags.push_back("GPBDescriptorInitializationFlag_FieldsWithDefault"); } @@ -556,10 +581,11 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { " count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n"); } if (descriptor_->containing_type() != NULL) { - string parent_class_name = ClassName(descriptor_->containing_type()); + string containing_class = ClassName(descriptor_->containing_type()); + string parent_class_ref = ObjCClassSymbolReference(containing_class); printer->Print( - " [localDescriptor setupContainingMessageClassName:GPBStringifySymbol($parent_name$)];\n", - "parent_name", parent_class_name); + " [localDescriptor setupContainingMessageClass:$parent_class_ref$];\n", + "parent_class_ref", parent_class_ref); } string suffix_added; ClassName(descriptor_, &suffix_added); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.h b/src/google/protobuf/compiler/objectivec/objectivec_message.h index 55eda0b8efe9..138e62020638 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_message.h @@ -63,6 +63,7 @@ class MessageGenerator { void GenerateMessageHeader(io::Printer* printer); void GenerateSource(io::Printer* printer); void GenerateExtensionRegistrationSource(io::Printer* printer); + void DetermineObjectiveCClassDefinitions(std::set* fwd_decls); void DetermineForwardDeclarations(std::set* fwd_decls); // Checks if the message or a nested message includes a oneof definition. diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc index 8a0299e7c2ad..93b75571c2a6 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc @@ -46,13 +46,14 @@ namespace { void SetMessageVariables(const FieldDescriptor* descriptor, std::map* variables) { const string& message_type = ClassName(descriptor->message_type()); + const string& containing_class = ClassName(descriptor->containing_type()); (*variables)["type"] = message_type; - (*variables)["containing_class"] = ClassName(descriptor->containing_type()); + (*variables)["containing_class"] = containing_class; (*variables)["storage_type"] = message_type; (*variables)["group_or_message"] = (descriptor->type() == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message"; - - (*variables)["dataTypeSpecific_value"] = "GPBStringifySymbol(" + message_type + ")"; + (*variables)["dataTypeSpecific_value"] = + ObjCClassSymbolReference(message_type); } } // namespace @@ -72,6 +73,11 @@ void MessageFieldGenerator::DetermineForwardDeclarations( fwd_decls->insert("@class " + variable("storage_type")); } +void MessageFieldGenerator::DetermineObjectiveCClassDefinitions( + std::set* fwd_decls) const { + fwd_decls->insert(ObjCClassSymbolDefinition(variable("storage_type"))); +} + bool MessageFieldGenerator::WantsHasProperty(void) const { if (descriptor_->containing_oneof() != NULL) { // If in a oneof, it uses the oneofcase instead of a has bit. @@ -100,6 +106,10 @@ void RepeatedMessageFieldGenerator::DetermineForwardDeclarations( fwd_decls->insert("@class " + variable("storage_type")); } +void RepeatedMessageFieldGenerator::DetermineObjectiveCClassDefinitions( + std::set* fwd_decls) const { + fwd_decls->insert(ObjCClassSymbolDefinition(variable("storage_type"))); +} } // namespace objectivec } // namespace compiler diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h index 98d457942e23..692f94c02614 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h @@ -56,6 +56,7 @@ class MessageFieldGenerator : public ObjCObjFieldGenerator { public: virtual void DetermineForwardDeclarations(std::set* fwd_decls) const; + virtual void DetermineObjectiveCClassDefinitions(std::set* fwd_decls) const; }; class RepeatedMessageFieldGenerator : public RepeatedFieldGenerator { @@ -72,6 +73,7 @@ class RepeatedMessageFieldGenerator : public RepeatedFieldGenerator { public: virtual void DetermineForwardDeclarations(std::set* fwd_decls) const; + virtual void DetermineObjectiveCClassDefinitions(std::set* fwd_decls) const; }; } // namespace objectivec